oleaut32: Always search external references in GetRefTypeInfo.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob69269f2d3a3c3c168fc76500bae18125745c2f80
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
63 #include "winerror.h"
64 #include "windef.h"
65 #include "winbase.h"
66 #include "winnls.h"
67 #include "winreg.h"
68 #include "winuser.h"
69 #include "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);
104 /****************************************************************************
105 * FromLExxx
107 * Takes p_iVal (which is in little endian) and returns it
108 * in the host machine's byte order.
110 #ifdef WORDS_BIGENDIAN
111 static WORD FromLEWord(WORD p_iVal)
113 return (((p_iVal & 0x00FF) << 8) |
114 ((p_iVal & 0xFF00) >> 8));
118 static DWORD FromLEDWord(DWORD p_iVal)
120 return (((p_iVal & 0x000000FF) << 24) |
121 ((p_iVal & 0x0000FF00) << 8) |
122 ((p_iVal & 0x00FF0000) >> 8) |
123 ((p_iVal & 0xFF000000) >> 24));
125 #else
126 #define FromLEWord(X) (X)
127 #define FromLEDWord(X) (X)
128 #endif
130 #define DISPATCH_HREF_OFFSET 0x01000000
131 #define DISPATCH_HREF_MASK 0xff000000
133 /****************************************************************************
134 * FromLExxx
136 * Fix byte order in any structure if necessary
138 #ifdef WORDS_BIGENDIAN
139 static void FromLEWords(void *p_Val, int p_iSize)
141 WORD *Val = p_Val;
143 p_iSize /= sizeof(WORD);
145 while (p_iSize) {
146 *Val = FromLEWord(*Val);
147 Val++;
148 p_iSize--;
153 static void FromLEDWords(void *p_Val, int p_iSize)
155 DWORD *Val = p_Val;
157 p_iSize /= sizeof(DWORD);
159 while (p_iSize) {
160 *Val = FromLEDWord(*Val);
161 Val++;
162 p_iSize--;
165 #else
166 #define FromLEWords(X,Y) /*nothing*/
167 #define FromLEDWords(X,Y) /*nothing*/
168 #endif
171 * Find a typelib key which matches a requested maj.min version.
173 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
175 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
176 WCHAR buffer[60];
177 char key_name[16];
178 DWORD len, i;
179 INT best_maj = -1, best_min = -1;
180 HKEY hkey;
182 memcpy( buffer, typelibW, sizeof(typelibW) );
183 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
185 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
186 return FALSE;
188 len = sizeof(key_name);
189 i = 0;
190 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
192 INT v_maj, v_min;
194 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
196 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
198 if (*wMaj == 0xffff && *wMin == 0xffff)
200 if (v_maj > best_maj) best_maj = v_maj;
201 if (v_min > best_min) best_min = v_min;
203 else if (*wMaj == v_maj)
205 best_maj = v_maj;
207 if (*wMin == v_min)
209 best_min = v_min;
210 break; /* exact match */
212 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
215 len = sizeof(key_name);
217 RegCloseKey( hkey );
219 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
221 if (*wMaj == 0xffff && *wMin == 0xffff)
223 if (best_maj >= 0 && best_min >= 0)
225 *wMaj = best_maj;
226 *wMin = best_min;
227 return TRUE;
231 if (*wMaj == best_maj && best_min >= 0)
233 *wMin = best_min;
234 return TRUE;
236 return FALSE;
239 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
240 /* buffer must be at least 60 characters long */
241 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
243 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
244 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
246 memcpy( buffer, TypelibW, sizeof(TypelibW) );
247 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
248 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
249 return buffer;
252 /* get the path of an interface key, in the form "Interface\\<guid>" */
253 /* buffer must be at least 50 characters long */
254 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
256 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
258 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
259 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
260 return buffer;
263 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
264 /* buffer must be at least 16 characters long */
265 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
267 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
268 static const WCHAR win16W[] = {'w','i','n','1','6',0};
269 static const WCHAR win32W[] = {'w','i','n','3','2',0};
270 static const WCHAR win64W[] = {'w','i','n','6','4',0};
272 sprintfW( buffer, LcidFormatW, lcid );
273 switch(syskind)
275 case SYS_WIN16: strcatW( buffer, win16W ); break;
276 case SYS_WIN32: strcatW( buffer, win32W ); break;
277 case SYS_WIN64: strcatW( buffer, win64W ); break;
278 default:
279 TRACE("Typelib is for unsupported syskind %i\n", syskind);
280 return NULL;
282 return buffer;
285 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
288 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
289 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
290 SYSKIND syskind, LCID lcid, LPBSTR path )
292 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
293 LCID myLCID = lcid;
294 HKEY hkey;
295 WCHAR buffer[60];
296 WCHAR Path[MAX_PATH];
297 LONG res;
299 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
301 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
302 get_typelib_key( guid, wMaj, wMin, buffer );
304 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
305 if (res == ERROR_FILE_NOT_FOUND)
307 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
308 return TYPE_E_LIBNOTREGISTERED;
310 else if (res != ERROR_SUCCESS)
312 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
313 return TYPE_E_REGISTRYACCESS;
316 while (hr != S_OK)
318 LONG dwPathLen = sizeof(Path);
320 get_lcid_subkey( myLCID, syskind, buffer );
322 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
324 if (!lcid)
325 break;
326 else if (myLCID == lcid)
328 /* try with sub-langid */
329 myLCID = SUBLANGID(lcid);
331 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
333 /* try with system langid */
334 myLCID = 0;
336 else
338 break;
341 else
343 *path = SysAllocString( Path );
344 hr = S_OK;
347 RegCloseKey( hkey );
348 TRACE_(typelib)("-- 0x%08x\n", hr);
349 return hr;
352 /****************************************************************************
353 * QueryPathOfRegTypeLib [OLEAUT32.164]
355 * Gets the path to a registered type library.
357 * PARAMS
358 * guid [I] referenced guid
359 * wMaj [I] major version
360 * wMin [I] minor version
361 * lcid [I] locale id
362 * path [O] path of typelib
364 * RETURNS
365 * Success: S_OK.
366 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
367 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
368 * opened.
370 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
372 #ifdef _WIN64
373 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
374 if(SUCCEEDED(hres))
375 return hres;
376 #endif
377 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
380 /******************************************************************************
381 * CreateTypeLib [OLEAUT32.160] creates a typelib
383 * RETURNS
384 * Success: S_OK
385 * Failure: Status
387 HRESULT WINAPI CreateTypeLib(
388 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
390 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
391 return E_FAIL;
394 /******************************************************************************
395 * LoadTypeLib [OLEAUT32.161]
397 * Loads a type library
399 * PARAMS
400 * szFile [I] Name of file to load from.
401 * pptLib [O] Pointer that receives ITypeLib object on success.
403 * RETURNS
404 * Success: S_OK
405 * Failure: Status
407 * SEE
408 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
410 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
412 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
413 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
416 /******************************************************************************
417 * LoadTypeLibEx [OLEAUT32.183]
419 * Loads and optionally registers a type library
421 * RETURNS
422 * Success: S_OK
423 * Failure: Status
425 HRESULT WINAPI LoadTypeLibEx(
426 LPCOLESTR szFile, /* [in] Name of file to load from */
427 REGKIND regkind, /* [in] Specify kind of registration */
428 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
430 WCHAR szPath[MAX_PATH+1];
431 HRESULT res;
433 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
435 *pptLib = NULL;
437 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
439 if (SUCCEEDED(res))
440 switch(regkind)
442 case REGKIND_DEFAULT:
443 /* don't register typelibs supplied with full path. Experimentation confirms the following */
444 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
445 (szFile[0] && (szFile[1] == ':'))) break;
446 /* else fall-through */
448 case REGKIND_REGISTER:
449 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
451 ITypeLib_Release(*pptLib);
452 *pptLib = 0;
454 break;
455 case REGKIND_NONE:
456 break;
459 TRACE(" returns %08x\n",res);
460 return res;
463 /******************************************************************************
464 * LoadRegTypeLib [OLEAUT32.162]
466 * Loads a registered type library.
468 * PARAMS
469 * rguid [I] GUID of the registered type library.
470 * wVerMajor [I] major version.
471 * wVerMinor [I] minor version.
472 * lcid [I] locale ID.
473 * ppTLib [O] pointer that receives an ITypeLib object on success.
475 * RETURNS
476 * Success: S_OK.
477 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
478 * LoadTypeLib.
480 HRESULT WINAPI LoadRegTypeLib(
481 REFGUID rguid,
482 WORD wVerMajor,
483 WORD wVerMinor,
484 LCID lcid,
485 ITypeLib **ppTLib)
487 BSTR bstr=NULL;
488 HRESULT res;
490 *ppTLib = NULL;
492 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
494 if(SUCCEEDED(res))
496 res= LoadTypeLib(bstr, ppTLib);
497 SysFreeString(bstr);
500 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
502 return res;
506 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
507 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
508 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
509 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
510 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
511 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
513 /******************************************************************************
514 * RegisterTypeLib [OLEAUT32.163]
515 * Adds information about a type library to the System Registry
516 * NOTES
517 * Docs: ITypeLib FAR * ptlib
518 * Docs: OLECHAR FAR* szFullPath
519 * Docs: OLECHAR FAR* szHelpDir
521 * RETURNS
522 * Success: S_OK
523 * Failure: Status
525 HRESULT WINAPI RegisterTypeLib(
526 ITypeLib * ptlib, /* [in] Pointer to the library*/
527 OLECHAR * szFullPath, /* [in] full Path of the library*/
528 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
529 may be NULL*/
531 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
532 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
533 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
534 HRESULT res;
535 TLIBATTR *attr;
536 WCHAR keyName[60];
537 WCHAR tmp[16];
538 HKEY key, subKey;
539 UINT types, tidx;
540 TYPEKIND kind;
541 DWORD disposition;
543 if (ptlib == NULL || szFullPath == NULL)
544 return E_INVALIDARG;
546 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
547 return E_FAIL;
549 #ifdef _WIN64
550 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
551 #else
552 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
553 #endif
555 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
557 res = S_OK;
558 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
559 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
561 LPOLESTR doc;
563 /* Set the human-readable name of the typelib */
564 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
565 res = E_FAIL;
566 else if (doc)
568 if (RegSetValueExW(key, NULL, 0, REG_SZ,
569 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
570 res = E_FAIL;
572 SysFreeString(doc);
575 /* Make up the name of the typelib path subkey */
576 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
578 /* Create the typelib path subkey */
579 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
580 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
582 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
583 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
584 res = E_FAIL;
586 RegCloseKey(subKey);
588 else
589 res = E_FAIL;
591 /* Create the flags subkey */
592 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
593 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
595 /* FIXME: is %u correct? */
596 static const WCHAR formatW[] = {'%','u',0};
597 WCHAR buf[20];
598 sprintfW(buf, formatW, attr->wLibFlags);
599 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
600 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
601 res = E_FAIL;
603 RegCloseKey(subKey);
605 else
606 res = E_FAIL;
608 /* create the helpdir subkey */
609 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
610 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
612 BOOL freeHelpDir = FALSE;
613 OLECHAR* pIndexStr;
615 /* if we created a new key, and helpDir was null, set the helpdir
616 to the directory which contains the typelib. However,
617 if we just opened an existing key, we leave the helpdir alone */
618 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
619 szHelpDir = SysAllocString(szFullPath);
620 pIndexStr = strrchrW(szHelpDir, '\\');
621 if (pIndexStr) {
622 *pIndexStr = 0;
624 freeHelpDir = TRUE;
627 /* if we have an szHelpDir, set it! */
628 if (szHelpDir != NULL) {
629 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
630 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
631 res = E_FAIL;
635 /* tidy up */
636 if (freeHelpDir) SysFreeString(szHelpDir);
637 RegCloseKey(subKey);
639 } else {
640 res = E_FAIL;
643 RegCloseKey(key);
645 else
646 res = E_FAIL;
648 /* register OLE Automation-compatible interfaces for this typelib */
649 types = ITypeLib_GetTypeInfoCount(ptlib);
650 for (tidx=0; tidx<types; tidx++) {
651 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
652 LPOLESTR name = NULL;
653 ITypeInfo *tinfo = NULL;
655 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
657 switch (kind) {
658 case TKIND_INTERFACE:
659 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
660 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
661 break;
663 case TKIND_DISPATCH:
664 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
665 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
666 break;
668 default:
669 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
670 break;
673 if (tinfo) {
674 TYPEATTR *tattr = NULL;
675 ITypeInfo_GetTypeAttr(tinfo, &tattr);
677 if (tattr) {
678 TRACE_(typelib)("guid=%s, flags=%04x (",
679 debugstr_guid(&tattr->guid),
680 tattr->wTypeFlags);
682 if (TRACE_ON(typelib)) {
683 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
684 XX(FAPPOBJECT);
685 XX(FCANCREATE);
686 XX(FLICENSED);
687 XX(FPREDECLID);
688 XX(FHIDDEN);
689 XX(FCONTROL);
690 XX(FDUAL);
691 XX(FNONEXTENSIBLE);
692 XX(FOLEAUTOMATION);
693 XX(FRESTRICTED);
694 XX(FAGGREGATABLE);
695 XX(FREPLACEABLE);
696 XX(FDISPATCHABLE);
697 XX(FREVERSEBIND);
698 XX(FPROXY);
699 #undef XX
700 MESSAGE("\n");
703 /* Register all dispinterfaces (which includes dual interfaces) and
704 oleautomation interfaces */
705 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
706 kind == TKIND_DISPATCH)
708 /* register interface<->typelib coupling */
709 get_interface_key( &tattr->guid, keyName );
710 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
711 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
713 if (name)
714 RegSetValueExW(key, NULL, 0, REG_SZ,
715 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
717 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (const BYTE *)PSOA, sizeof PSOA);
721 RegCloseKey(subKey);
724 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
726 RegSetValueExW(subKey, NULL, 0, REG_SZ,
727 (const BYTE *)PSOA, sizeof PSOA);
728 RegCloseKey(subKey);
731 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
732 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
734 WCHAR buffer[40];
735 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
736 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
738 StringFromGUID2(&attr->guid, buffer, 40);
739 RegSetValueExW(subKey, NULL, 0, REG_SZ,
740 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
741 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
742 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
743 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
744 RegCloseKey(subKey);
747 RegCloseKey(key);
751 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
754 ITypeInfo_Release(tinfo);
757 SysFreeString(name);
761 ITypeLib_ReleaseTLibAttr(ptlib, attr);
763 return res;
767 /******************************************************************************
768 * UnRegisterTypeLib [OLEAUT32.186]
769 * Removes information about a type library from the System Registry
770 * NOTES
772 * RETURNS
773 * Success: S_OK
774 * Failure: Status
776 HRESULT WINAPI UnRegisterTypeLib(
777 REFGUID libid, /* [in] Guid of the library */
778 WORD wVerMajor, /* [in] major version */
779 WORD wVerMinor, /* [in] minor version */
780 LCID lcid, /* [in] locale id */
781 SYSKIND syskind)
783 BSTR tlibPath = NULL;
784 DWORD tmpLength;
785 WCHAR keyName[60];
786 WCHAR subKeyName[50];
787 int result = S_OK;
788 DWORD i = 0;
789 BOOL deleteOtherStuff;
790 HKEY key = NULL;
791 HKEY subKey = NULL;
792 TYPEATTR* typeAttr = NULL;
793 TYPEKIND kind;
794 ITypeInfo* typeInfo = NULL;
795 ITypeLib* typeLib = NULL;
796 int numTypes;
798 TRACE("(IID: %s)\n",debugstr_guid(libid));
800 /* Create the path to the key */
801 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
803 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
805 TRACE("Unsupported syskind %i\n", syskind);
806 result = E_INVALIDARG;
807 goto end;
810 /* get the path to the typelib on disk */
811 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
812 result = E_INVALIDARG;
813 goto end;
816 /* Try and open the key to the type library. */
817 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
818 result = E_INVALIDARG;
819 goto end;
822 /* Try and load the type library */
823 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
824 result = TYPE_E_INVALIDSTATE;
825 goto end;
828 /* remove any types registered with this typelib */
829 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
830 for (i=0; i<numTypes; i++) {
831 /* get the kind of type */
832 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
833 goto enddeleteloop;
836 /* skip non-interfaces, and get type info for the type */
837 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
838 goto enddeleteloop;
840 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
841 goto enddeleteloop;
843 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
844 goto enddeleteloop;
847 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
848 kind == TKIND_DISPATCH)
850 /* the path to the type */
851 get_interface_key( &typeAttr->guid, subKeyName );
853 /* Delete its bits */
854 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
855 goto enddeleteloop;
857 RegDeleteKeyW(subKey, ProxyStubClsidW);
858 RegDeleteKeyW(subKey, ProxyStubClsid32W);
859 RegDeleteKeyW(subKey, TypeLibW);
860 RegCloseKey(subKey);
861 subKey = NULL;
862 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
865 enddeleteloop:
866 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
867 typeAttr = NULL;
868 if (typeInfo) ITypeInfo_Release(typeInfo);
869 typeInfo = NULL;
872 /* Now, delete the type library path subkey */
873 get_lcid_subkey( lcid, syskind, subKeyName );
874 RegDeleteKeyW(key, subKeyName);
875 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
876 RegDeleteKeyW(key, subKeyName);
878 /* check if there is anything besides the FLAGS/HELPDIR keys.
879 If there is, we don't delete them */
880 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
881 deleteOtherStuff = TRUE;
882 i = 0;
883 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
884 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
886 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
887 if (!strcmpW(subKeyName, FLAGSW)) continue;
888 if (!strcmpW(subKeyName, HELPDIRW)) continue;
889 deleteOtherStuff = FALSE;
890 break;
893 /* only delete the other parts of the key if we're absolutely sure */
894 if (deleteOtherStuff) {
895 RegDeleteKeyW(key, FLAGSW);
896 RegDeleteKeyW(key, HELPDIRW);
897 RegCloseKey(key);
898 key = NULL;
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
901 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
902 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
905 end:
906 SysFreeString(tlibPath);
907 if (typeLib) ITypeLib_Release(typeLib);
908 if (subKey) RegCloseKey(subKey);
909 if (key) RegCloseKey(key);
910 return result;
913 /******************************************************************************
914 * RegisterTypeLibForUser [OLEAUT32.442]
915 * Adds information about a type library to the user registry
916 * NOTES
917 * Docs: ITypeLib FAR * ptlib
918 * Docs: OLECHAR FAR* szFullPath
919 * Docs: OLECHAR FAR* szHelpDir
921 * RETURNS
922 * Success: S_OK
923 * Failure: Status
925 HRESULT WINAPI RegisterTypeLibForUser(
926 ITypeLib * ptlib, /* [in] Pointer to the library*/
927 OLECHAR * szFullPath, /* [in] full Path of the library*/
928 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
929 may be NULL*/
931 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
932 debugstr_w(szFullPath), debugstr_w(szHelpDir));
933 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
936 /******************************************************************************
937 * UnRegisterTypeLibForUser [OLEAUT32.443]
938 * Removes information about a type library from the user registry
940 * RETURNS
941 * Success: S_OK
942 * Failure: Status
944 HRESULT WINAPI UnRegisterTypeLibForUser(
945 REFGUID libid, /* [in] GUID of the library */
946 WORD wVerMajor, /* [in] major version */
947 WORD wVerMinor, /* [in] minor version */
948 LCID lcid, /* [in] locale id */
949 SYSKIND syskind)
951 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
952 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
953 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
956 /*======================= ITypeLib implementation =======================*/
958 typedef struct tagTLBGuid {
959 GUID guid;
960 UINT offset;
961 struct list entry;
962 } TLBGuid;
964 typedef struct tagTLBCustData
966 TLBGuid *guid;
967 VARIANT data;
968 struct list entry;
969 } TLBCustData;
971 /* data structure for import typelibs */
972 typedef struct tagTLBImpLib
974 int offset; /* offset in the file (MSFT)
975 offset in nametable (SLTG)
976 just used to identify library while reading
977 data from file */
978 TLBGuid *guid; /* libid */
979 BSTR name; /* name */
981 LCID lcid; /* lcid of imported typelib */
983 WORD wVersionMajor; /* major version number */
984 WORD wVersionMinor; /* minor version number */
986 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
987 NULL if not yet loaded */
988 struct list entry;
989 } TLBImpLib;
991 typedef struct tagTLBString {
992 BSTR str;
993 UINT offset;
994 struct list entry;
995 } TLBString;
997 /* internal ITypeLib data */
998 typedef struct tagITypeLibImpl
1000 ITypeLib2 ITypeLib2_iface;
1001 ITypeComp ITypeComp_iface;
1002 ICreateTypeLib2 ICreateTypeLib2_iface;
1003 LONG ref;
1004 TLBGuid *guid;
1005 LCID lcid;
1006 SYSKIND syskind;
1007 WORD ver_major;
1008 WORD ver_minor;
1009 WORD libflags;
1010 LCID set_lcid;
1012 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1013 * exported to the application as a UNICODE string.
1015 struct list string_list;
1016 struct list name_list;
1017 struct list guid_list;
1019 const TLBString *Name;
1020 const TLBString *DocString;
1021 const TLBString *HelpFile;
1022 const TLBString *HelpStringDll;
1023 DWORD dwHelpContext;
1024 int TypeInfoCount; /* nr of typeinfo's in librarry */
1025 struct tagITypeInfoImpl **typeinfos;
1026 struct list custdata_list;
1027 struct list implib_list;
1028 int ctTypeDesc; /* number of items in type desc array */
1029 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1030 library. Only used while reading MSFT
1031 typelibs */
1032 struct list ref_list; /* list of ref types in this typelib */
1033 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1036 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1037 struct list entry;
1038 WCHAR *path;
1039 INT index;
1040 } ITypeLibImpl;
1042 static const ITypeLib2Vtbl tlbvt;
1043 static const ITypeCompVtbl tlbtcvt;
1044 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1046 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1048 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1051 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1053 return impl_from_ITypeLib2((ITypeLib2*)iface);
1056 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1058 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1061 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1063 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1066 /* ITypeLib methods */
1067 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1068 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1070 /*======================= ITypeInfo implementation =======================*/
1072 /* data for referenced types */
1073 typedef struct tagTLBRefType
1075 INT index; /* Type index for internal ref or for external ref
1076 it the format is SLTG. -2 indicates to
1077 use guid */
1079 TYPEKIND tkind;
1080 TLBGuid *guid; /* guid of the referenced type */
1081 /* if index == TLB_REF_USE_GUID */
1083 HREFTYPE reference; /* The href of this ref */
1084 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1085 TLB_REF_INTERNAL for internal refs
1086 TLB_REF_NOT_FOUND for broken refs */
1088 struct list entry;
1089 } TLBRefType;
1091 #define TLB_REF_USE_GUID -2
1093 #define TLB_REF_INTERNAL (void*)-2
1094 #define TLB_REF_NOT_FOUND (void*)-1
1096 /* internal Parameter data */
1097 typedef struct tagTLBParDesc
1099 const TLBString *Name;
1100 struct list custdata_list;
1101 } TLBParDesc;
1103 /* internal Function data */
1104 typedef struct tagTLBFuncDesc
1106 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1107 const TLBString *Name; /* the name of this function */
1108 TLBParDesc *pParamDesc; /* array with param names and custom data */
1109 int helpcontext;
1110 int HelpStringContext;
1111 const TLBString *HelpString;
1112 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1113 struct list custdata_list;
1114 } TLBFuncDesc;
1116 /* internal Variable data */
1117 typedef struct tagTLBVarDesc
1119 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1120 const TLBString *Name; /* the name of this variable */
1121 int HelpContext;
1122 int HelpStringContext;
1123 const TLBString *HelpString;
1124 struct list custdata_list;
1125 } TLBVarDesc;
1127 /* internal implemented interface data */
1128 typedef struct tagTLBImplType
1130 HREFTYPE hRef; /* hRef of interface */
1131 int implflags; /* IMPLFLAG_*s */
1132 struct list custdata_list;
1133 } TLBImplType;
1135 /* internal TypeInfo data */
1136 typedef struct tagITypeInfoImpl
1138 ITypeInfo2 ITypeInfo2_iface;
1139 ITypeComp ITypeComp_iface;
1140 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1141 LONG ref;
1142 BOOL not_attached_to_typelib;
1143 BOOL needs_layout;
1145 TLBGuid *guid;
1146 LCID lcid;
1147 MEMBERID memidConstructor;
1148 MEMBERID memidDestructor;
1149 LPOLESTR lpstrSchema;
1150 ULONG cbSizeInstance;
1151 TYPEKIND typekind;
1152 WORD cFuncs;
1153 WORD cVars;
1154 WORD cImplTypes;
1155 WORD cbSizeVft;
1156 WORD cbAlignment;
1157 WORD wTypeFlags;
1158 WORD wMajorVerNum;
1159 WORD wMinorVerNum;
1160 TYPEDESC tdescAlias;
1161 IDLDESC idldescType;
1163 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1164 int index; /* index in this typelib; */
1165 HREFTYPE hreftype; /* hreftype for app object binding */
1166 /* type libs seem to store the doc strings in ascii
1167 * so why should we do it in unicode?
1169 const TLBString *Name;
1170 const TLBString *DocString;
1171 const TLBString *DllName;
1172 const TLBString *Schema;
1173 DWORD dwHelpContext;
1174 DWORD dwHelpStringContext;
1176 /* functions */
1177 TLBFuncDesc *funcdescs;
1179 /* variables */
1180 TLBVarDesc *vardescs;
1182 /* Implemented Interfaces */
1183 TLBImplType *impltypes;
1185 struct list custdata_list;
1186 } ITypeInfoImpl;
1188 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1190 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1193 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1195 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1198 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1200 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1203 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1205 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1208 static const ITypeInfo2Vtbl tinfvt;
1209 static const ITypeCompVtbl tcompvt;
1210 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1212 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1213 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1215 typedef struct tagTLBContext
1217 unsigned int oStart; /* start of TLB in file */
1218 unsigned int pos; /* current pos */
1219 unsigned int length; /* total length */
1220 void *mapping; /* memory mapping */
1221 MSFT_SegDir * pTblDir;
1222 ITypeLibImpl* pLibInfo;
1223 } TLBContext;
1226 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1228 static inline BSTR TLB_get_bstr(const TLBString *str)
1230 return str != NULL ? str->str : NULL;
1233 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1235 if(!str)
1236 return 1;
1237 return memcmp(left, str->str, len);
1240 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1242 return guid != NULL ? &guid->guid : NULL;
1245 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1247 return guid != NULL ? &guid->guid : &GUID_NULL;
1251 debug
1253 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1254 if (pTD->vt & VT_RESERVED)
1255 szVarType += strlen(strcpy(szVarType, "reserved | "));
1256 if (pTD->vt & VT_BYREF)
1257 szVarType += strlen(strcpy(szVarType, "ref to "));
1258 if (pTD->vt & VT_ARRAY)
1259 szVarType += strlen(strcpy(szVarType, "array of "));
1260 if (pTD->vt & VT_VECTOR)
1261 szVarType += strlen(strcpy(szVarType, "vector of "));
1262 switch(pTD->vt & VT_TYPEMASK) {
1263 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1264 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1265 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1266 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1267 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1268 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1269 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1270 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1271 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1272 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1273 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1274 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1275 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1276 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1277 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1278 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1279 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1280 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1281 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1282 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1283 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1284 pTD->u.hreftype); break;
1285 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1286 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1287 case VT_PTR: sprintf(szVarType, "ptr to ");
1288 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1289 break;
1290 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1291 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1292 break;
1293 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1294 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1295 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1296 break;
1298 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1302 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1303 char buf[200];
1304 USHORT flags = edesc->u.paramdesc.wParamFlags;
1305 dump_TypeDesc(&edesc->tdesc,buf);
1306 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1307 MESSAGE("\t\tu.paramdesc.wParamFlags");
1308 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1309 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1310 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1311 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1312 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1313 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1314 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1315 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1316 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1318 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1319 int i;
1320 MESSAGE("memid is %08x\n",funcdesc->memid);
1321 for (i=0;i<funcdesc->cParams;i++) {
1322 MESSAGE("Param %d:\n",i);
1323 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1325 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1326 switch (funcdesc->funckind) {
1327 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1328 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1329 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1330 case FUNC_STATIC: MESSAGE("static");break;
1331 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1332 default: MESSAGE("unknown");break;
1334 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1335 switch (funcdesc->invkind) {
1336 case INVOKE_FUNC: MESSAGE("func");break;
1337 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1338 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1339 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1341 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1342 switch (funcdesc->callconv) {
1343 case CC_CDECL: MESSAGE("cdecl");break;
1344 case CC_PASCAL: MESSAGE("pascal");break;
1345 case CC_STDCALL: MESSAGE("stdcall");break;
1346 case CC_SYSCALL: MESSAGE("syscall");break;
1347 default:break;
1349 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1350 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1351 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1353 MESSAGE("\telemdescFunc (return value type):\n");
1354 dump_ELEMDESC(&funcdesc->elemdescFunc);
1357 static const char * const typekind_desc[] =
1359 "TKIND_ENUM",
1360 "TKIND_RECORD",
1361 "TKIND_MODULE",
1362 "TKIND_INTERFACE",
1363 "TKIND_DISPATCH",
1364 "TKIND_COCLASS",
1365 "TKIND_ALIAS",
1366 "TKIND_UNION",
1367 "TKIND_MAX"
1370 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1372 int i;
1373 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1374 for (i=0;i<pfd->funcdesc.cParams;i++)
1375 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1378 dump_FUNCDESC(&(pfd->funcdesc));
1380 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1381 if(pfd->Entry == NULL)
1382 MESSAGE("\tentry: (null)\n");
1383 else if(pfd->Entry == (void*)-1)
1384 MESSAGE("\tentry: invalid\n");
1385 else if(IS_INTRESOURCE(pfd->Entry))
1386 MESSAGE("\tentry: %p\n", pfd->Entry);
1387 else
1388 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1390 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1392 while (n)
1394 dump_TLBFuncDescOne(pfd);
1395 ++pfd;
1396 --n;
1399 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1401 while (n)
1403 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1404 ++pvd;
1405 --n;
1409 static void dump_TLBImpLib(const TLBImpLib *import)
1411 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1412 debugstr_w(import->name));
1413 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1414 import->wVersionMinor, import->lcid, import->offset);
1417 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1419 TLBRefType *ref;
1421 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1423 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1424 if(ref->index == -1)
1425 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1426 else
1427 TRACE_(typelib)("type no: %d\n", ref->index);
1429 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1431 TRACE_(typelib)("in lib\n");
1432 dump_TLBImpLib(ref->pImpTLInfo);
1437 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1439 if(!impl)
1440 return;
1441 while (n) {
1442 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1443 impl->hRef, impl->implflags);
1444 ++impl;
1445 --n;
1449 static void dump_Variant(const VARIANT * pvar)
1451 SYSTEMTIME st;
1453 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1455 if (pvar)
1457 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1458 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1460 TRACE(",%p", V_BYREF(pvar));
1462 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1464 TRACE(",%p", V_ARRAY(pvar));
1466 else switch (V_TYPE(pvar))
1468 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1469 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1470 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1471 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1472 case VT_INT:
1473 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1474 case VT_UINT:
1475 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1476 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1477 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1478 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1479 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1480 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1481 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1482 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1483 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1484 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1485 V_CY(pvar).s.Lo); break;
1486 case VT_DATE:
1487 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1488 TRACE(",<invalid>");
1489 else
1490 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1491 st.wHour, st.wMinute, st.wSecond);
1492 break;
1493 case VT_ERROR:
1494 case VT_VOID:
1495 case VT_USERDEFINED:
1496 case VT_EMPTY:
1497 case VT_NULL: break;
1498 default: TRACE(",?"); break;
1501 TRACE("}\n");
1504 static void dump_DispParms(const DISPPARAMS * pdp)
1506 unsigned int index;
1508 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1510 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1512 TRACE("named args:\n");
1513 for (index = 0; index < pdp->cNamedArgs; index++)
1514 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1517 if (pdp->cArgs && pdp->rgvarg)
1519 TRACE("args:\n");
1520 for (index = 0; index < pdp->cArgs; index++)
1521 dump_Variant( &pdp->rgvarg[index] );
1525 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1527 TRACE("%p ref=%u\n", pty, pty->ref);
1528 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1529 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1530 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1531 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1532 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1533 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1534 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1535 if (TRACE_ON(ole))
1536 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1537 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1538 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1541 static void dump_VARDESC(const VARDESC *v)
1543 MESSAGE("memid %d\n",v->memid);
1544 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1545 MESSAGE("oInst %d\n",v->u.oInst);
1546 dump_ELEMDESC(&(v->elemdescVar));
1547 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1548 MESSAGE("varkind %d\n",v->varkind);
1551 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1553 /* VT_LPWSTR is largest type that, may appear in type description */
1554 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1555 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1556 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1557 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1558 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1559 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1560 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1561 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1564 static void TLB_abort(void)
1566 DebugBreak();
1569 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1571 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1572 if (!ret) ERR("cannot allocate memory\n");
1573 return ret;
1576 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1578 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1579 if (!ret) ERR("cannot allocate memory\n");
1580 return ret;
1583 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1585 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1588 void heap_free(void *ptr)
1590 HeapFree(GetProcessHeap(), 0, ptr);
1593 /* returns the size required for a deep copy of a typedesc into a
1594 * flat buffer */
1595 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1597 SIZE_T size = 0;
1599 if (alloc_initial_space)
1600 size += sizeof(TYPEDESC);
1602 switch (tdesc->vt)
1604 case VT_PTR:
1605 case VT_SAFEARRAY:
1606 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1607 break;
1608 case VT_CARRAY:
1609 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1610 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1611 break;
1613 return size;
1616 /* deep copy a typedesc into a flat buffer */
1617 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1619 if (!dest)
1621 dest = buffer;
1622 buffer = (char *)buffer + sizeof(TYPEDESC);
1625 *dest = *src;
1627 switch (src->vt)
1629 case VT_PTR:
1630 case VT_SAFEARRAY:
1631 dest->u.lptdesc = buffer;
1632 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1633 break;
1634 case VT_CARRAY:
1635 dest->u.lpadesc = buffer;
1636 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1637 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1638 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1639 break;
1641 return buffer;
1644 /* free custom data allocated by MSFT_CustData */
1645 static inline void TLB_FreeCustData(struct list *custdata_list)
1647 TLBCustData *cd, *cdn;
1648 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1650 list_remove(&cd->entry);
1651 VariantClear(&cd->data);
1652 heap_free(cd);
1656 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1658 DWORD len;
1659 BSTR ret;
1661 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1662 ret = SysAllocStringLen(NULL, len - 1);
1663 if (!ret) return ret;
1664 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1665 return ret;
1668 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1669 UINT n, MEMBERID memid)
1671 while(n){
1672 if(funcdescs->funcdesc.memid == memid)
1673 return funcdescs;
1674 ++funcdescs;
1675 --n;
1677 return NULL;
1680 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1681 UINT n, const OLECHAR *name)
1683 while(n){
1684 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1685 return funcdescs;
1686 ++funcdescs;
1687 --n;
1689 return NULL;
1692 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1693 UINT n, MEMBERID memid)
1695 while(n){
1696 if(vardescs->vardesc.memid == memid)
1697 return vardescs;
1698 ++vardescs;
1699 --n;
1701 return NULL;
1704 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1705 UINT n, const OLECHAR *name)
1707 while(n){
1708 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1709 return vardescs;
1710 ++vardescs;
1711 --n;
1713 return NULL;
1716 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1718 TLBCustData *cust_data;
1719 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1720 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1721 return cust_data;
1722 return NULL;
1725 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1726 UINT n, const OLECHAR *name)
1728 while(n){
1729 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1730 return *typeinfos;
1731 ++typeinfos;
1732 --n;
1734 return NULL;
1737 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1739 list_init(&var_desc->custdata_list);
1742 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1744 TLBVarDesc *ret;
1746 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1747 if(!ret)
1748 return NULL;
1750 while(n){
1751 TLBVarDesc_Constructor(&ret[n-1]);
1752 --n;
1755 return ret;
1758 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1760 TLBParDesc *ret;
1762 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1763 if(!ret)
1764 return NULL;
1766 while(n){
1767 list_init(&ret[n-1].custdata_list);
1768 --n;
1771 return ret;
1774 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1776 list_init(&func_desc->custdata_list);
1779 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1781 TLBFuncDesc *ret;
1783 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1784 if(!ret)
1785 return NULL;
1787 while(n){
1788 TLBFuncDesc_Constructor(&ret[n-1]);
1789 --n;
1792 return ret;
1795 static void TLBImplType_Constructor(TLBImplType *impl)
1797 list_init(&impl->custdata_list);
1800 static TLBImplType *TLBImplType_Alloc(UINT n)
1802 TLBImplType *ret;
1804 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1805 if(!ret)
1806 return NULL;
1808 while(n){
1809 TLBImplType_Constructor(&ret[n-1]);
1810 --n;
1813 return ret;
1816 static TLBGuid *TLB_append_guid(struct list *guid_list, const GUID *new_guid)
1818 TLBGuid *guid;
1820 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1821 if (IsEqualGUID(&guid->guid, new_guid))
1822 return guid;
1825 guid = heap_alloc(sizeof(TLBGuid));
1826 if (!guid)
1827 return NULL;
1829 memcpy(&guid->guid, new_guid, sizeof(GUID));
1831 list_add_tail(guid_list, &guid->entry);
1833 return guid;
1836 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1838 TLBCustData *cust_data;
1840 switch(V_VT(var)){
1841 case VT_I4:
1842 case VT_R4:
1843 case VT_UI4:
1844 case VT_INT:
1845 case VT_UINT:
1846 case VT_HRESULT:
1847 case VT_BSTR:
1848 break;
1849 default:
1850 return DISP_E_BADVARTYPE;
1853 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1855 if (!cust_data) {
1856 cust_data = heap_alloc(sizeof(TLBCustData));
1857 if (!cust_data)
1858 return E_OUTOFMEMORY;
1860 cust_data->guid = tlbguid;
1861 VariantInit(&cust_data->data);
1863 list_add_tail(custdata_list, &cust_data->entry);
1864 }else
1865 VariantClear(&cust_data->data);
1867 return VariantCopy(&cust_data->data, var);
1870 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1872 TLBString *str;
1874 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1875 if (strcmpW(str->str, new_str) == 0)
1876 return str;
1879 str = heap_alloc(sizeof(TLBString));
1880 if (!str)
1881 return NULL;
1883 str->str = SysAllocString(new_str);
1884 if (!str->str) {
1885 heap_free(str);
1886 return NULL;
1889 list_add_tail(string_list, &str->entry);
1891 return str;
1894 /**********************************************************************
1896 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1898 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1900 return pcx->pos;
1903 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1905 if (where != DO_NOT_SEEK)
1907 where += pcx->oStart;
1908 if (where > pcx->length)
1910 /* FIXME */
1911 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1912 TLB_abort();
1914 pcx->pos = where;
1918 /* read function */
1919 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1921 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1922 pcx->pos, count, pcx->oStart, pcx->length, where);
1924 MSFT_Seek(pcx, where);
1925 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1926 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1927 pcx->pos += count;
1928 return count;
1931 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1932 LONG where )
1934 DWORD ret;
1936 ret = MSFT_Read(buffer, count, pcx, where);
1937 FromLEDWords(buffer, ret);
1939 return ret;
1942 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1943 LONG where )
1945 DWORD ret;
1947 ret = MSFT_Read(buffer, count, pcx, where);
1948 FromLEWords(buffer, ret);
1950 return ret;
1953 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
1955 TLBGuid *guid;
1956 MSFT_GuidEntry entry;
1957 int offs = 0;
1959 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
1960 while (1) {
1961 if (offs >= pcx->pTblDir->pGuidTab.length)
1962 return S_OK;
1964 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
1966 guid = heap_alloc(sizeof(TLBGuid));
1968 guid->offset = offs;
1969 guid->guid = entry.guid;
1971 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
1973 offs += sizeof(MSFT_GuidEntry);
1977 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
1979 TLBGuid *ret;
1981 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
1982 if(ret->offset == offset){
1983 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
1984 return ret;
1988 return NULL;
1991 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1993 MSFT_NameIntro niName;
1995 if (offset < 0)
1997 ERR_(typelib)("bad offset %d\n", offset);
1998 return -1;
2001 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2002 pcx->pTblDir->pNametab.offset+offset);
2004 return niName.hreftype;
2007 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2009 char *string;
2010 MSFT_NameIntro intro;
2011 INT16 len_piece;
2012 int offs = 0, lengthInChars;
2014 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2015 while (1) {
2016 TLBString *tlbstr;
2018 if (offs >= pcx->pTblDir->pNametab.length)
2019 return S_OK;
2021 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2022 intro.namelen &= 0xFF;
2023 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2024 if(len_piece % 4)
2025 len_piece = (len_piece + 4) & ~0x3;
2026 if(len_piece < 8)
2027 len_piece = 8;
2029 string = heap_alloc(len_piece + 1);
2030 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2031 string[intro.namelen] = '\0';
2033 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2034 string, -1, NULL, 0);
2035 if (!lengthInChars) {
2036 heap_free(string);
2037 return E_UNEXPECTED;
2040 tlbstr = heap_alloc(sizeof(TLBString));
2042 tlbstr->offset = offs;
2043 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2044 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2046 heap_free(string);
2048 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2050 offs += len_piece;
2054 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2056 TLBString *tlbstr;
2058 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2059 if (tlbstr->offset == offset) {
2060 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2061 return tlbstr;
2065 return NULL;
2068 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2070 TLBString *tlbstr;
2072 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2073 if (tlbstr->offset == offset) {
2074 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2075 return tlbstr;
2079 return NULL;
2083 * read a value and fill a VARIANT structure
2085 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2087 int size;
2089 TRACE_(typelib)("\n");
2091 if(offset <0) { /* data are packed in here */
2092 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2093 V_I4(pVar) = offset & 0x3ffffff;
2094 return;
2096 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2097 pcx->pTblDir->pCustData.offset + offset );
2098 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2099 switch (V_VT(pVar)){
2100 case VT_EMPTY: /* FIXME: is this right? */
2101 case VT_NULL: /* FIXME: is this right? */
2102 case VT_I2 : /* this should not happen */
2103 case VT_I4 :
2104 case VT_R4 :
2105 case VT_ERROR :
2106 case VT_BOOL :
2107 case VT_I1 :
2108 case VT_UI1 :
2109 case VT_UI2 :
2110 case VT_UI4 :
2111 case VT_INT :
2112 case VT_UINT :
2113 case VT_VOID : /* FIXME: is this right? */
2114 case VT_HRESULT :
2115 size=4; break;
2116 case VT_R8 :
2117 case VT_CY :
2118 case VT_DATE :
2119 case VT_I8 :
2120 case VT_UI8 :
2121 case VT_DECIMAL : /* FIXME: is this right? */
2122 case VT_FILETIME :
2123 size=8;break;
2124 /* pointer types with known behaviour */
2125 case VT_BSTR :{
2126 char * ptr;
2127 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2128 if(size < 0) {
2129 char next;
2130 DWORD origPos = MSFT_Tell(pcx), nullPos;
2132 do {
2133 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
2134 } while (next);
2135 nullPos = MSFT_Tell(pcx);
2136 size = nullPos - origPos;
2137 MSFT_Seek(pcx, origPos);
2139 ptr = heap_alloc_zero(size);/* allocate temp buffer */
2140 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
2141 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2142 /* FIXME: do we need a AtoW conversion here? */
2143 V_UNION(pVar, bstrVal[size])='\0';
2144 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2145 heap_free(ptr);
2147 size=-4; break;
2148 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2149 case VT_DISPATCH :
2150 case VT_VARIANT :
2151 case VT_UNKNOWN :
2152 case VT_PTR :
2153 case VT_SAFEARRAY :
2154 case VT_CARRAY :
2155 case VT_USERDEFINED :
2156 case VT_LPSTR :
2157 case VT_LPWSTR :
2158 case VT_BLOB :
2159 case VT_STREAM :
2160 case VT_STORAGE :
2161 case VT_STREAMED_OBJECT :
2162 case VT_STORED_OBJECT :
2163 case VT_BLOB_OBJECT :
2164 case VT_CF :
2165 case VT_CLSID :
2166 default:
2167 size=0;
2168 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2169 V_VT(pVar));
2172 if(size>0) /* (big|small) endian correct? */
2173 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2174 return;
2177 * create a linked list with custom data
2179 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2181 MSFT_CDGuid entry;
2182 TLBCustData* pNew;
2183 int count=0;
2185 TRACE_(typelib)("\n");
2187 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2189 while(offset >=0){
2190 count++;
2191 pNew=heap_alloc_zero(sizeof(TLBCustData));
2192 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2193 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2194 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2195 list_add_head(custdata_list, &pNew->entry);
2196 offset = entry.next;
2198 return count;
2201 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
2202 ITypeInfoImpl *pTI)
2204 if(type <0)
2205 pTd->vt=type & VT_TYPEMASK;
2206 else
2207 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2209 if(pTd->vt == VT_USERDEFINED)
2210 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
2212 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2215 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
2217 /* resolve referenced type if any */
2218 while (lpTypeDesc)
2220 switch (lpTypeDesc->vt)
2222 case VT_PTR:
2223 lpTypeDesc = lpTypeDesc->u.lptdesc;
2224 break;
2226 case VT_CARRAY:
2227 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
2228 break;
2230 case VT_USERDEFINED:
2231 MSFT_DoRefType(pcx, pTI->pTypeLib,
2232 lpTypeDesc->u.hreftype);
2234 lpTypeDesc = NULL;
2235 break;
2237 default:
2238 lpTypeDesc = NULL;
2243 static int TLB_is_propgetput(INVOKEKIND invkind)
2245 return (invkind == INVOKE_PROPERTYGET ||
2246 invkind == INVOKE_PROPERTYPUT ||
2247 invkind == INVOKE_PROPERTYPUTREF);
2250 static void
2251 MSFT_DoFuncs(TLBContext* pcx,
2252 ITypeInfoImpl* pTI,
2253 int cFuncs,
2254 int cVars,
2255 int offset,
2256 TLBFuncDesc** pptfd)
2259 * member information is stored in a data structure at offset
2260 * indicated by the memoffset field of the typeinfo structure
2261 * There are several distinctive parts.
2262 * The first part starts with a field that holds the total length
2263 * of this (first) part excluding this field. Then follow the records,
2264 * for each member there is one record.
2266 * The first entry is always the length of the record (including this
2267 * length word).
2268 * The rest of the record depends on the type of the member. If there is
2269 * a field indicating the member type (function, variable, interface, etc)
2270 * I have not found it yet. At this time we depend on the information
2271 * in the type info and the usual order how things are stored.
2273 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2274 * for each member;
2276 * Third is an equal sized array with file offsets to the name entry
2277 * of each member.
2279 * The fourth and last (?) part is an array with offsets to the records
2280 * in the first part of this file segment.
2283 int infolen, nameoffset, reclength, i;
2284 int recoffset = offset + sizeof(INT);
2286 char *recbuf = heap_alloc(0xffff);
2287 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2288 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2290 TRACE_(typelib)("\n");
2292 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2294 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2295 ptfd = *pptfd;
2296 for ( i = 0; i < cFuncs ; i++ )
2298 int optional;
2300 /* name, eventually add to a hash table */
2301 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2302 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2304 /* read the function information record */
2305 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2307 reclength &= 0xffff;
2309 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2311 /* size without argument data */
2312 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2313 if (pFuncRec->FKCCIC & 0x1000)
2314 optional -= pFuncRec->nrargs * sizeof(INT);
2316 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2317 ptfd->helpcontext = pFuncRec->HelpContext;
2319 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2320 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2322 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2324 if (pFuncRec->FKCCIC & 0x2000 )
2326 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2327 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2328 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2330 else
2331 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2333 else
2334 ptfd->Entry = (TLBString*)-1;
2336 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2337 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2339 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2340 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2342 /* fill the FuncDesc Structure */
2343 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2344 offset + infolen + ( i + 1) * sizeof(INT));
2346 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2347 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2348 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2349 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2350 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2351 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2352 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2354 /* nameoffset is sometimes -1 on the second half of a propget/propput
2355 * pair of functions */
2356 if ((nameoffset == -1) && (i > 0) &&
2357 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2358 TLB_is_propgetput(ptfd->funcdesc.invkind))
2359 ptfd->Name = ptfd_prev->Name;
2360 else
2361 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2363 MSFT_GetTdesc(pcx,
2364 pFuncRec->DataType,
2365 &ptfd->funcdesc.elemdescFunc.tdesc,
2366 pTI);
2367 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2369 /* do the parameters/arguments */
2370 if(pFuncRec->nrargs)
2372 int j = 0;
2373 MSFT_ParameterInfo paraminfo;
2375 ptfd->funcdesc.lprgelemdescParam =
2376 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2378 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2380 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2381 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2383 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2385 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2387 MSFT_GetTdesc(pcx,
2388 paraminfo.DataType,
2389 &elemdesc->tdesc,
2390 pTI);
2392 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2394 /* name */
2395 if (paraminfo.oName != -1)
2396 ptfd->pParamDesc[j].Name =
2397 MSFT_ReadName( pcx, paraminfo.oName );
2398 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2400 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2402 /* default value */
2403 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2404 (pFuncRec->FKCCIC & 0x1000) )
2406 INT* pInt = (INT *)((char *)pFuncRec +
2407 reclength -
2408 (pFuncRec->nrargs * 4) * sizeof(INT) );
2410 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2412 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2413 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2415 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2416 pInt[j], pcx);
2418 else
2419 elemdesc->u.paramdesc.pparamdescex = NULL;
2421 /* custom info */
2422 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2423 j*sizeof(pFuncRec->oArgCustData[0])) &&
2424 pFuncRec->FKCCIC & 0x80 )
2426 MSFT_CustData(pcx,
2427 pFuncRec->oArgCustData[j],
2428 &ptfd->pParamDesc[j].custdata_list);
2431 /* SEEK value = jump to offset,
2432 * from there jump to the end of record,
2433 * go back by (j-1) arguments
2435 MSFT_ReadLEDWords( &paraminfo ,
2436 sizeof(MSFT_ParameterInfo), pcx,
2437 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2438 * sizeof(MSFT_ParameterInfo)));
2442 /* scode is not used: archaic win16 stuff FIXME: right? */
2443 ptfd->funcdesc.cScodes = 0 ;
2444 ptfd->funcdesc.lprgscode = NULL ;
2446 ptfd_prev = ptfd;
2447 ++ptfd;
2448 recoffset += reclength;
2450 heap_free(recbuf);
2453 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2454 int cVars, int offset, TLBVarDesc ** pptvd)
2456 int infolen, nameoffset, reclength;
2457 char recbuf[256];
2458 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2459 TLBVarDesc *ptvd;
2460 int i;
2461 int recoffset;
2463 TRACE_(typelib)("\n");
2465 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2466 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2467 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2468 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2469 recoffset += offset+sizeof(INT);
2470 for(i=0;i<cVars;i++, ++ptvd){
2471 /* name, eventually add to a hash table */
2472 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2473 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2474 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2475 /* read the variable information record */
2476 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2477 reclength &= 0xff;
2478 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2480 /* optional data */
2481 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2482 ptvd->HelpContext = pVarRec->HelpContext;
2484 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2485 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2487 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2488 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2490 /* fill the VarDesc Structure */
2491 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2492 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2493 ptvd->vardesc.varkind = pVarRec->VarKind;
2494 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2495 MSFT_GetTdesc(pcx, pVarRec->DataType,
2496 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2497 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2498 if(pVarRec->VarKind == VAR_CONST ){
2499 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2500 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2501 pVarRec->OffsValue, pcx);
2502 } else
2503 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2504 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2505 recoffset += reclength;
2509 /* fill in data for a hreftype (offset). When the referenced type is contained
2510 * in the typelib, it's just an (file) offset in the type info base dir.
2511 * If comes from import, it's an offset+1 in the ImpInfo table
2512 * */
2513 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2514 int offset)
2516 TLBRefType *ref;
2518 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2520 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2522 if(ref->reference == offset) return;
2525 ref = heap_alloc_zero(sizeof(TLBRefType));
2526 list_add_tail(&pTL->ref_list, &ref->entry);
2528 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2529 /* external typelib */
2530 MSFT_ImpInfo impinfo;
2531 TLBImpLib *pImpLib;
2533 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2535 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2536 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2538 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2539 if(pImpLib->offset==impinfo.oImpFile)
2540 break;
2542 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2543 ref->reference = offset & (~0x3);
2544 ref->pImpTLInfo = pImpLib;
2545 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2546 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2547 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2548 ref->index = TLB_REF_USE_GUID;
2549 } else
2550 ref->index = impinfo.oGuid;
2551 }else{
2552 ERR("Cannot find a reference\n");
2553 ref->reference = -1;
2554 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2556 }else{
2557 /* in this typelib */
2558 ref->index = MSFT_HREFTYPE_INDEX(offset);
2559 ref->reference = offset;
2560 ref->pImpTLInfo = TLB_REF_INTERNAL;
2564 /* process Implemented Interfaces of a com class */
2565 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2566 int offset)
2568 int i;
2569 MSFT_RefRecord refrec;
2570 TLBImplType *pImpl;
2572 TRACE_(typelib)("\n");
2574 pTI->impltypes = TLBImplType_Alloc(count);
2575 pImpl = pTI->impltypes;
2576 for(i=0;i<count;i++){
2577 if(offset<0) break; /* paranoia */
2578 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2579 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2580 pImpl->hRef = refrec.reftype;
2581 pImpl->implflags=refrec.flags;
2582 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2583 offset=refrec.onext;
2584 ++pImpl;
2588 * process a typeinfo record
2590 static ITypeInfoImpl * MSFT_DoTypeInfo(
2591 TLBContext *pcx,
2592 int count,
2593 ITypeLibImpl * pLibInfo)
2595 MSFT_TypeInfoBase tiBase;
2596 ITypeInfoImpl *ptiRet;
2598 TRACE_(typelib)("count=%u\n", count);
2600 ptiRet = ITypeInfoImpl_Constructor();
2601 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2602 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2604 /* this is where we are coming from */
2605 ptiRet->pTypeLib = pLibInfo;
2606 ptiRet->index=count;
2608 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2609 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2610 ptiRet->lpstrSchema=NULL; /* reserved */
2611 ptiRet->cbSizeInstance=tiBase.size;
2612 ptiRet->typekind=tiBase.typekind & 0xF;
2613 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2614 ptiRet->cVars=HIWORD(tiBase.cElement);
2615 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2616 ptiRet->wTypeFlags=tiBase.flags;
2617 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2618 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2619 ptiRet->cImplTypes=tiBase.cImplTypes;
2620 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2621 if(ptiRet->typekind == TKIND_ALIAS)
2622 MSFT_GetTdesc(pcx, tiBase.datatype1,
2623 &ptiRet->tdescAlias, ptiRet);
2625 /* FIXME: */
2626 /* IDLDESC idldescType; *//* never saw this one != zero */
2628 /* name, eventually add to a hash table */
2629 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2630 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2631 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2632 /* help info */
2633 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2634 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2635 ptiRet->dwHelpContext=tiBase.helpcontext;
2637 if (ptiRet->typekind == TKIND_MODULE)
2638 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2640 /* note: InfoType's Help file and HelpStringDll come from the containing
2641 * library. Further HelpString and Docstring appear to be the same thing :(
2643 /* functions */
2644 if(ptiRet->cFuncs >0 )
2645 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2646 ptiRet->cVars,
2647 tiBase.memoffset, &ptiRet->funcdescs);
2648 /* variables */
2649 if(ptiRet->cVars >0 )
2650 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2651 ptiRet->cVars,
2652 tiBase.memoffset, &ptiRet->vardescs);
2653 if(ptiRet->cImplTypes >0 ) {
2654 switch(ptiRet->typekind)
2656 case TKIND_COCLASS:
2657 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2658 tiBase.datatype1);
2659 break;
2660 case TKIND_DISPATCH:
2661 /* This is not -1 when the interface is a non-base dual interface or
2662 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2663 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2664 not this interface.
2667 if (tiBase.datatype1 != -1)
2669 ptiRet->impltypes = TLBImplType_Alloc(1);
2670 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2671 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2673 break;
2674 default:
2675 ptiRet->impltypes = TLBImplType_Alloc(1);
2676 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2677 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2678 break;
2681 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2683 TRACE_(typelib)("%s guid: %s kind:%s\n",
2684 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2685 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2686 typekind_desc[ptiRet->typekind]);
2687 if (TRACE_ON(typelib))
2688 dump_TypeInfo(ptiRet);
2690 return ptiRet;
2693 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2695 char *string;
2696 INT16 len_str, len_piece;
2697 int offs = 0, lengthInChars;
2699 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2700 while (1) {
2701 TLBString *tlbstr;
2703 if (offs >= pcx->pTblDir->pStringtab.length)
2704 return S_OK;
2706 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2707 len_piece = len_str + sizeof(INT16);
2708 if(len_piece % 4)
2709 len_piece = (len_piece + 4) & ~0x3;
2710 if(len_piece < 8)
2711 len_piece = 8;
2713 string = heap_alloc(len_piece + 1);
2714 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2715 string[len_str] = '\0';
2717 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2718 string, -1, NULL, 0);
2719 if (!lengthInChars) {
2720 heap_free(string);
2721 return E_UNEXPECTED;
2724 tlbstr = heap_alloc(sizeof(TLBString));
2726 tlbstr->offset = offs;
2727 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2728 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2730 heap_free(string);
2732 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2734 offs += len_piece;
2738 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2739 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2740 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2741 * tradeoff here.
2743 static struct list tlb_cache = LIST_INIT(tlb_cache);
2744 static CRITICAL_SECTION cache_section;
2745 static CRITICAL_SECTION_DEBUG cache_section_debug =
2747 0, 0, &cache_section,
2748 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2749 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2751 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2754 typedef struct TLB_PEFile
2756 IUnknown IUnknown_iface;
2757 LONG refs;
2758 HMODULE dll;
2759 HRSRC typelib_resource;
2760 HGLOBAL typelib_global;
2761 LPVOID typelib_base;
2762 } TLB_PEFile;
2764 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2766 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2769 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2771 if (IsEqualIID(riid, &IID_IUnknown))
2773 *ppv = iface;
2774 IUnknown_AddRef(iface);
2775 return S_OK;
2777 *ppv = NULL;
2778 return E_NOINTERFACE;
2781 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2783 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2784 return InterlockedIncrement(&This->refs);
2787 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2789 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2790 ULONG refs = InterlockedDecrement(&This->refs);
2791 if (!refs)
2793 if (This->typelib_global)
2794 FreeResource(This->typelib_global);
2795 if (This->dll)
2796 FreeLibrary(This->dll);
2797 heap_free(This);
2799 return refs;
2802 static const IUnknownVtbl TLB_PEFile_Vtable =
2804 TLB_PEFile_QueryInterface,
2805 TLB_PEFile_AddRef,
2806 TLB_PEFile_Release
2809 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2811 TLB_PEFile *This;
2812 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2814 This = heap_alloc(sizeof(TLB_PEFile));
2815 if (!This)
2816 return E_OUTOFMEMORY;
2818 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2819 This->refs = 1;
2820 This->dll = NULL;
2821 This->typelib_resource = NULL;
2822 This->typelib_global = NULL;
2823 This->typelib_base = NULL;
2825 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2826 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2828 if (This->dll)
2830 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2831 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2832 if (This->typelib_resource)
2834 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2835 if (This->typelib_global)
2837 This->typelib_base = LockResource(This->typelib_global);
2839 if (This->typelib_base)
2841 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2842 *ppBase = This->typelib_base;
2843 *ppFile = &This->IUnknown_iface;
2844 return S_OK;
2849 TRACE("No TYPELIB resource found\n");
2850 hr = E_FAIL;
2853 TLB_PEFile_Release(&This->IUnknown_iface);
2854 return hr;
2857 typedef struct TLB_NEFile
2859 IUnknown IUnknown_iface;
2860 LONG refs;
2861 LPVOID typelib_base;
2862 } TLB_NEFile;
2864 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2866 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2869 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2871 if (IsEqualIID(riid, &IID_IUnknown))
2873 *ppv = iface;
2874 IUnknown_AddRef(iface);
2875 return S_OK;
2877 *ppv = NULL;
2878 return E_NOINTERFACE;
2881 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2883 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2884 return InterlockedIncrement(&This->refs);
2887 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2889 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2890 ULONG refs = InterlockedDecrement(&This->refs);
2891 if (!refs)
2893 heap_free(This->typelib_base);
2894 heap_free(This);
2896 return refs;
2899 static const IUnknownVtbl TLB_NEFile_Vtable =
2901 TLB_NEFile_QueryInterface,
2902 TLB_NEFile_AddRef,
2903 TLB_NEFile_Release
2906 /***********************************************************************
2907 * read_xx_header [internal]
2909 static int read_xx_header( HFILE lzfd )
2911 IMAGE_DOS_HEADER mzh;
2912 char magic[3];
2914 LZSeek( lzfd, 0, SEEK_SET );
2915 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2916 return 0;
2917 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2918 return 0;
2920 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2921 if ( 2 != LZRead( lzfd, magic, 2 ) )
2922 return 0;
2924 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2926 if ( magic[0] == 'N' && magic[1] == 'E' )
2927 return IMAGE_OS2_SIGNATURE;
2928 if ( magic[0] == 'P' && magic[1] == 'E' )
2929 return IMAGE_NT_SIGNATURE;
2931 magic[2] = '\0';
2932 WARN("Can't handle %s files.\n", magic );
2933 return 0;
2937 /***********************************************************************
2938 * find_ne_resource [internal]
2940 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2941 DWORD *resLen, DWORD *resOff )
2943 IMAGE_OS2_HEADER nehd;
2944 NE_TYPEINFO *typeInfo;
2945 NE_NAMEINFO *nameInfo;
2946 DWORD nehdoffset;
2947 LPBYTE resTab;
2948 DWORD resTabSize;
2949 int count;
2951 /* Read in NE header */
2952 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2953 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2955 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2956 if ( !resTabSize )
2958 TRACE("No resources in NE dll\n" );
2959 return FALSE;
2962 /* Read in resource table */
2963 resTab = heap_alloc( resTabSize );
2964 if ( !resTab ) return FALSE;
2966 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2967 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2969 heap_free( resTab );
2970 return FALSE;
2973 /* Find resource */
2974 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2976 if (!IS_INTRESOURCE(typeid)) /* named type */
2978 BYTE len = strlen( typeid );
2979 while (typeInfo->type_id)
2981 if (!(typeInfo->type_id & 0x8000))
2983 BYTE *p = resTab + typeInfo->type_id;
2984 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2986 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2987 typeInfo->count * sizeof(NE_NAMEINFO));
2990 else /* numeric type id */
2992 WORD id = LOWORD(typeid) | 0x8000;
2993 while (typeInfo->type_id)
2995 if (typeInfo->type_id == id) goto found_type;
2996 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2997 typeInfo->count * sizeof(NE_NAMEINFO));
3000 TRACE("No typeid entry found for %p\n", typeid );
3001 heap_free( resTab );
3002 return FALSE;
3004 found_type:
3005 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3007 if (!IS_INTRESOURCE(resid)) /* named resource */
3009 BYTE len = strlen( resid );
3010 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3012 BYTE *p = resTab + nameInfo->id;
3013 if (nameInfo->id & 0x8000) continue;
3014 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3017 else /* numeric resource id */
3019 WORD id = LOWORD(resid) | 0x8000;
3020 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3021 if (nameInfo->id == id) goto found_name;
3023 TRACE("No resid entry found for %p\n", typeid );
3024 heap_free( resTab );
3025 return FALSE;
3027 found_name:
3028 /* Return resource data */
3029 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3030 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3032 heap_free( resTab );
3033 return TRUE;
3036 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3038 HFILE lzfd = -1;
3039 OFSTRUCT ofs;
3040 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3041 TLB_NEFile *This;
3043 This = heap_alloc(sizeof(TLB_NEFile));
3044 if (!This) return E_OUTOFMEMORY;
3046 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3047 This->refs = 1;
3048 This->typelib_base = NULL;
3050 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3051 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3053 DWORD reslen, offset;
3054 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3056 This->typelib_base = heap_alloc(reslen);
3057 if( !This->typelib_base )
3058 hr = E_OUTOFMEMORY;
3059 else
3061 LZSeek( lzfd, offset, SEEK_SET );
3062 reslen = LZRead( lzfd, This->typelib_base, reslen );
3063 LZClose( lzfd );
3064 *ppBase = This->typelib_base;
3065 *pdwTLBLength = reslen;
3066 *ppFile = &This->IUnknown_iface;
3067 return S_OK;
3072 if( lzfd >= 0) LZClose( lzfd );
3073 TLB_NEFile_Release(&This->IUnknown_iface);
3074 return hr;
3077 typedef struct TLB_Mapping
3079 IUnknown IUnknown_iface;
3080 LONG refs;
3081 HANDLE file;
3082 HANDLE mapping;
3083 LPVOID typelib_base;
3084 } TLB_Mapping;
3086 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3088 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3091 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3093 if (IsEqualIID(riid, &IID_IUnknown))
3095 *ppv = iface;
3096 IUnknown_AddRef(iface);
3097 return S_OK;
3099 *ppv = NULL;
3100 return E_NOINTERFACE;
3103 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3105 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3106 return InterlockedIncrement(&This->refs);
3109 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3111 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3112 ULONG refs = InterlockedDecrement(&This->refs);
3113 if (!refs)
3115 if (This->typelib_base)
3116 UnmapViewOfFile(This->typelib_base);
3117 if (This->mapping)
3118 CloseHandle(This->mapping);
3119 if (This->file != INVALID_HANDLE_VALUE)
3120 CloseHandle(This->file);
3121 heap_free(This);
3123 return refs;
3126 static const IUnknownVtbl TLB_Mapping_Vtable =
3128 TLB_Mapping_QueryInterface,
3129 TLB_Mapping_AddRef,
3130 TLB_Mapping_Release
3133 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3135 TLB_Mapping *This;
3137 This = heap_alloc(sizeof(TLB_Mapping));
3138 if (!This)
3139 return E_OUTOFMEMORY;
3141 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3142 This->refs = 1;
3143 This->file = INVALID_HANDLE_VALUE;
3144 This->mapping = NULL;
3145 This->typelib_base = NULL;
3147 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3148 if (INVALID_HANDLE_VALUE != This->file)
3150 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3151 if (This->mapping)
3153 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3154 if(This->typelib_base)
3156 /* retrieve file size */
3157 *pdwTLBLength = GetFileSize(This->file, NULL);
3158 *ppBase = This->typelib_base;
3159 *ppFile = &This->IUnknown_iface;
3160 return S_OK;
3165 IUnknown_Release(&This->IUnknown_iface);
3166 return TYPE_E_CANTLOADLIBRARY;
3169 /****************************************************************************
3170 * TLB_ReadTypeLib
3172 * find the type of the typelib file and map the typelib resource into
3173 * the memory
3176 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3177 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3179 ITypeLibImpl *entry;
3180 HRESULT ret;
3181 INT index = 1;
3182 LPWSTR index_str, file = (LPWSTR)pszFileName;
3183 LPVOID pBase = NULL;
3184 DWORD dwTLBLength = 0;
3185 IUnknown *pFile = NULL;
3187 *ppTypeLib = NULL;
3189 index_str = strrchrW(pszFileName, '\\');
3190 if(index_str && *++index_str != '\0')
3192 LPWSTR end_ptr;
3193 LONG idx = strtolW(index_str, &end_ptr, 10);
3194 if(*end_ptr == '\0')
3196 int str_len = index_str - pszFileName - 1;
3197 index = idx;
3198 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3199 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3200 file[str_len] = 0;
3204 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3206 if(strchrW(file, '\\'))
3208 lstrcpyW(pszPath, file);
3210 else
3212 int len = GetSystemDirectoryW(pszPath, cchPath);
3213 pszPath[len] = '\\';
3214 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3218 if(file != pszFileName) heap_free(file);
3220 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3222 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3223 EnterCriticalSection(&cache_section);
3224 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3226 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3228 TRACE("cache hit\n");
3229 *ppTypeLib = &entry->ITypeLib2_iface;
3230 ITypeLib2_AddRef(*ppTypeLib);
3231 LeaveCriticalSection(&cache_section);
3232 return S_OK;
3235 LeaveCriticalSection(&cache_section);
3237 /* now actually load and parse the typelib */
3239 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3240 if (ret == TYPE_E_CANTLOADLIBRARY)
3241 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3242 if (ret == TYPE_E_CANTLOADLIBRARY)
3243 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3244 if (SUCCEEDED(ret))
3246 if (dwTLBLength >= 4)
3248 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3249 if (dwSignature == MSFT_SIGNATURE)
3250 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3251 else if (dwSignature == SLTG_SIGNATURE)
3252 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3253 else
3255 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3256 ret = TYPE_E_CANTLOADLIBRARY;
3259 else
3260 ret = TYPE_E_CANTLOADLIBRARY;
3261 IUnknown_Release(pFile);
3264 if(*ppTypeLib) {
3265 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3267 TRACE("adding to cache\n");
3268 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3269 lstrcpyW(impl->path, pszPath);
3270 /* We should really canonicalise the path here. */
3271 impl->index = index;
3273 /* FIXME: check if it has added already in the meantime */
3274 EnterCriticalSection(&cache_section);
3275 list_add_head(&tlb_cache, &impl->entry);
3276 LeaveCriticalSection(&cache_section);
3277 ret = S_OK;
3279 else
3281 if(ret != E_FAIL)
3282 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3284 ret = TYPE_E_CANTLOADLIBRARY;
3288 return ret;
3291 /*================== ITypeLib(2) Methods ===================================*/
3293 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3295 ITypeLibImpl* pTypeLibImpl;
3297 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3298 if (!pTypeLibImpl) return NULL;
3300 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3301 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3302 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3303 pTypeLibImpl->ref = 1;
3305 list_init(&pTypeLibImpl->implib_list);
3306 list_init(&pTypeLibImpl->custdata_list);
3307 list_init(&pTypeLibImpl->name_list);
3308 list_init(&pTypeLibImpl->string_list);
3309 list_init(&pTypeLibImpl->guid_list);
3310 list_init(&pTypeLibImpl->ref_list);
3311 pTypeLibImpl->dispatch_href = -1;
3313 return pTypeLibImpl;
3316 /****************************************************************************
3317 * ITypeLib2_Constructor_MSFT
3319 * loading an MSFT typelib from an in-memory image
3321 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3323 TLBContext cx;
3324 LONG lPSegDir;
3325 MSFT_Header tlbHeader;
3326 MSFT_SegDir tlbSegDir;
3327 ITypeLibImpl * pTypeLibImpl;
3329 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3331 pTypeLibImpl = TypeLibImpl_Constructor();
3332 if (!pTypeLibImpl) return NULL;
3334 /* get pointer to beginning of typelib data */
3335 cx.pos = 0;
3336 cx.oStart=0;
3337 cx.mapping = pLib;
3338 cx.pLibInfo = pTypeLibImpl;
3339 cx.length = dwTLBLength;
3341 /* read header */
3342 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3343 TRACE_(typelib)("header:\n");
3344 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3345 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3346 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3347 return NULL;
3349 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3351 /* there is a small amount of information here until the next important
3352 * part:
3353 * the segment directory . Try to calculate the amount of data */
3354 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3356 /* now read the segment directory */
3357 TRACE("read segment directory (at %d)\n",lPSegDir);
3358 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3359 cx.pTblDir = &tlbSegDir;
3361 /* just check two entries */
3362 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3364 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3365 heap_free(pTypeLibImpl);
3366 return NULL;
3369 MSFT_ReadAllNames(&cx);
3370 MSFT_ReadAllStrings(&cx);
3371 MSFT_ReadAllGuids(&cx);
3373 /* now fill our internal data */
3374 /* TLIBATTR fields */
3375 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3377 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3378 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3379 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3380 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3382 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3383 pTypeLibImpl->lcid = tlbHeader.lcid;
3385 /* name, eventually add to a hash table */
3386 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3388 /* help info */
3389 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3390 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3392 if( tlbHeader.varflags & HELPDLLFLAG)
3394 int offset;
3395 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3396 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3399 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3401 /* custom data */
3402 if(tlbHeader.CustomDataOffset >= 0)
3404 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3407 /* fill in type descriptions */
3408 if(tlbSegDir.pTypdescTab.length > 0)
3410 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3411 INT16 td[4];
3412 pTypeLibImpl->ctTypeDesc = cTD;
3413 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3414 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3415 for(i=0; i<cTD; )
3417 /* FIXME: add several sanity checks here */
3418 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3419 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3421 /* FIXME: check safearray */
3422 if(td[3] < 0)
3423 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3424 else
3425 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3427 else if(td[0] == VT_CARRAY)
3429 /* array descr table here */
3430 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3432 else if(td[0] == VT_USERDEFINED)
3434 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3436 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3439 /* second time around to fill the array subscript info */
3440 for(i=0;i<cTD;i++)
3442 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3443 if(tlbSegDir.pArrayDescriptions.offset>0)
3445 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3446 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3448 if(td[1]<0)
3449 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3450 else
3451 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3453 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3455 for(j = 0; j<td[2]; j++)
3457 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3458 sizeof(INT), &cx, DO_NOT_SEEK);
3459 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3460 sizeof(INT), &cx, DO_NOT_SEEK);
3463 else
3465 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3466 ERR("didn't find array description data\n");
3471 /* imported type libs */
3472 if(tlbSegDir.pImpFiles.offset>0)
3474 TLBImpLib *pImpLib;
3475 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3476 UINT16 size;
3478 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3480 char *name;
3482 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3483 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3484 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3486 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3487 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3488 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3489 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3491 size >>= 2;
3492 name = heap_alloc_zero(size+1);
3493 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3494 pImpLib->name = TLB_MultiByteToBSTR(name);
3495 heap_free(name);
3497 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3498 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3500 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3504 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3505 if(pTypeLibImpl->dispatch_href != -1)
3506 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3508 /* type infos */
3509 if(tlbHeader.nrtypeinfos >= 0 )
3511 ITypeInfoImpl **ppTI;
3512 int i;
3514 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3516 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3518 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3520 ++ppTI;
3521 (pTypeLibImpl->TypeInfoCount)++;
3525 TRACE("(%p)\n", pTypeLibImpl);
3526 return &pTypeLibImpl->ITypeLib2_iface;
3530 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3532 char b[3];
3533 int i;
3534 short s;
3536 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3537 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3538 return FALSE;
3541 guid->Data4[0] = s >> 8;
3542 guid->Data4[1] = s & 0xff;
3544 b[2] = '\0';
3545 for(i = 0; i < 6; i++) {
3546 memcpy(b, str + 24 + 2 * i, 2);
3547 guid->Data4[i + 2] = strtol(b, NULL, 16);
3549 return TRUE;
3552 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3554 WORD bytelen;
3555 DWORD len;
3556 BSTR tmp_str;
3558 *pStr = NULL;
3559 bytelen = *(const WORD*)ptr;
3560 if(bytelen == 0xffff) return 2;
3562 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3563 tmp_str = SysAllocStringLen(NULL, len);
3564 if (*tmp_str) {
3565 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3566 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3567 SysFreeString(tmp_str);
3569 return bytelen + 2;
3572 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3574 WORD bytelen;
3576 *str = NULL;
3577 bytelen = *(const WORD*)ptr;
3578 if(bytelen == 0xffff) return 2;
3579 *str = heap_alloc(bytelen + 1);
3580 memcpy(*str, ptr + 2, bytelen);
3581 (*str)[bytelen] = '\0';
3582 return bytelen + 2;
3585 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3587 BSTR tmp_str;
3588 TLBString *tlbstr;
3590 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3591 if (tlbstr->offset == offset)
3592 return tlbstr;
3595 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3596 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3597 SysFreeString(tmp_str);
3599 return tlbstr;
3602 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3604 char *ptr = pLibBlk;
3605 WORD w;
3607 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3608 FIXME("libblk magic = %04x\n", w);
3609 return 0;
3612 ptr += 6;
3613 if((w = *(WORD*)ptr) != 0xffff) {
3614 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3615 ptr += w;
3617 ptr += 2;
3619 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3621 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3623 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3624 ptr += 4;
3626 pTypeLibImpl->syskind = *(WORD*)ptr;
3627 ptr += 2;
3629 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3630 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3631 else
3632 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3633 ptr += 2;
3635 ptr += 4; /* skip res12 */
3637 pTypeLibImpl->libflags = *(WORD*)ptr;
3638 ptr += 2;
3640 pTypeLibImpl->ver_major = *(WORD*)ptr;
3641 ptr += 2;
3643 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3644 ptr += 2;
3646 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr);
3647 ptr += sizeof(GUID);
3649 return ptr - (char*)pLibBlk;
3652 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3653 typedef struct
3655 unsigned int num;
3656 HREFTYPE refs[1];
3657 } sltg_ref_lookup_t;
3659 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3660 HREFTYPE *typelib_ref)
3662 if(table && typeinfo_ref < table->num)
3664 *typelib_ref = table->refs[typeinfo_ref];
3665 return S_OK;
3668 ERR_(typelib)("Unable to find reference\n");
3669 *typelib_ref = -1;
3670 return E_FAIL;
3673 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3675 BOOL done = FALSE;
3677 while(!done) {
3678 if((*pType & 0xe00) == 0xe00) {
3679 pTD->vt = VT_PTR;
3680 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3681 pTD = pTD->u.lptdesc;
3683 switch(*pType & 0x3f) {
3684 case VT_PTR:
3685 pTD->vt = VT_PTR;
3686 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3687 pTD = pTD->u.lptdesc;
3688 break;
3690 case VT_USERDEFINED:
3691 pTD->vt = VT_USERDEFINED;
3692 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3693 done = TRUE;
3694 break;
3696 case VT_CARRAY:
3698 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3699 array */
3701 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3703 pTD->vt = VT_CARRAY;
3704 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3705 pTD->u.lpadesc->cDims = pSA->cDims;
3706 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3707 pSA->cDims * sizeof(SAFEARRAYBOUND));
3709 pTD = &pTD->u.lpadesc->tdescElem;
3710 break;
3713 case VT_SAFEARRAY:
3715 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3716 useful? */
3718 pType++;
3719 pTD->vt = VT_SAFEARRAY;
3720 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3721 pTD = pTD->u.lptdesc;
3722 break;
3724 default:
3725 pTD->vt = *pType & 0x3f;
3726 done = TRUE;
3727 break;
3729 pType++;
3731 return pType;
3734 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3735 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3737 /* Handle [in/out] first */
3738 if((*pType & 0xc000) == 0xc000)
3739 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3740 else if(*pType & 0x8000)
3741 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3742 else if(*pType & 0x4000)
3743 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3744 else
3745 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3747 if(*pType & 0x2000)
3748 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3750 if(*pType & 0x80)
3751 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3753 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3757 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3758 char *pNameTable)
3760 unsigned int ref;
3761 char *name;
3762 TLBRefType *ref_type;
3763 sltg_ref_lookup_t *table;
3764 HREFTYPE typelib_ref;
3766 if(pRef->magic != SLTG_REF_MAGIC) {
3767 FIXME("Ref magic = %x\n", pRef->magic);
3768 return NULL;
3770 name = ( (char*)pRef->names + pRef->number);
3772 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3773 table->num = pRef->number >> 3;
3775 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3777 /* We don't want the first href to be 0 */
3778 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3780 for(ref = 0; ref < pRef->number >> 3; ref++) {
3781 char *refname;
3782 unsigned int lib_offs, type_num;
3784 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3786 name += SLTG_ReadStringA(name, &refname);
3787 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3788 FIXME_(typelib)("Can't sscanf ref\n");
3789 if(lib_offs != 0xffff) {
3790 TLBImpLib *import;
3792 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3793 if(import->offset == lib_offs)
3794 break;
3796 if(&import->entry == &pTL->implib_list) {
3797 char fname[MAX_PATH+1];
3798 int len;
3799 GUID tmpguid;
3801 import = heap_alloc_zero(sizeof(*import));
3802 import->offset = lib_offs;
3803 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3804 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid);
3805 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3806 &import->wVersionMajor,
3807 &import->wVersionMinor,
3808 &import->lcid, fname) != 4) {
3809 FIXME_(typelib)("can't sscanf ref %s\n",
3810 pNameTable + lib_offs + 40);
3812 len = strlen(fname);
3813 if(fname[len-1] != '#')
3814 FIXME("fname = %s\n", fname);
3815 fname[len-1] = '\0';
3816 import->name = TLB_MultiByteToBSTR(fname);
3817 list_add_tail(&pTL->implib_list, &import->entry);
3819 ref_type->pImpTLInfo = import;
3821 /* Store a reference to IDispatch */
3822 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3823 pTL->dispatch_href = typelib_ref;
3825 } else { /* internal ref */
3826 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3828 ref_type->reference = typelib_ref;
3829 ref_type->index = type_num;
3831 heap_free(refname);
3832 list_add_tail(&pTL->ref_list, &ref_type->entry);
3834 table->refs[ref] = typelib_ref;
3835 typelib_ref += 4;
3837 if((BYTE)*name != SLTG_REF_MAGIC)
3838 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3839 dump_TLBRefType(pTL);
3840 return table;
3843 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3844 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3846 SLTG_ImplInfo *info;
3847 TLBImplType *pImplType;
3848 /* I don't really get this structure, usually it's 0x16 bytes
3849 long, but iuser.tlb contains some that are 0x18 bytes long.
3850 That's ok because we can use the next ptr to jump to the next
3851 one. But how do we know the length of the last one? The WORD
3852 at offs 0x8 might be the clue. For now I'm just assuming that
3853 the last one is the regular 0x16 bytes. */
3855 info = (SLTG_ImplInfo*)pBlk;
3856 while(1){
3857 pTI->cImplTypes++;
3858 if(info->next == 0xffff)
3859 break;
3860 info = (SLTG_ImplInfo*)(pBlk + info->next);
3863 info = (SLTG_ImplInfo*)pBlk;
3864 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
3865 pImplType = pTI->impltypes;
3866 while(1) {
3867 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3868 pImplType->implflags = info->impltypeflags;
3869 ++pImplType;
3871 if(info->next == 0xffff)
3872 break;
3873 if(OneOnly)
3874 FIXME_(typelib)("Interface inheriting more than one interface\n");
3875 info = (SLTG_ImplInfo*)(pBlk + info->next);
3877 info++; /* see comment at top of function */
3878 return (char*)info;
3881 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3882 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3884 TLBVarDesc *pVarDesc;
3885 const TLBString *prevName = NULL;
3886 SLTG_Variable *pItem;
3887 unsigned short i;
3888 WORD *pType;
3890 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
3892 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3893 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3895 pVarDesc->vardesc.memid = pItem->memid;
3897 if (pItem->magic != SLTG_VAR_MAGIC &&
3898 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3899 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3900 return;
3903 if (pItem->name == 0xfffe)
3904 pVarDesc->Name = prevName;
3905 else
3906 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
3908 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
3909 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3910 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3912 if(pItem->flags & 0x02)
3913 pType = &pItem->type;
3914 else
3915 pType = (WORD*)(pBlk + pItem->type);
3917 if (pItem->flags & ~0xda)
3918 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3920 SLTG_DoElem(pType, pBlk,
3921 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3923 if (TRACE_ON(typelib)) {
3924 char buf[300];
3925 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3926 TRACE_(typelib)("elemdescVar: %s\n", buf);
3929 if (pItem->flags & 0x40) {
3930 TRACE_(typelib)("VAR_DISPATCH\n");
3931 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3933 else if (pItem->flags & 0x10) {
3934 TRACE_(typelib)("VAR_CONST\n");
3935 pVarDesc->vardesc.varkind = VAR_CONST;
3936 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3937 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3938 if (pItem->flags & 0x08)
3939 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3940 else {
3941 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3943 case VT_LPSTR:
3944 case VT_LPWSTR:
3945 case VT_BSTR:
3947 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3948 BSTR str;
3949 TRACE_(typelib)("len = %u\n", len);
3950 if (len == 0xffff) {
3951 str = NULL;
3952 } else {
3953 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3954 str = SysAllocStringLen(NULL, alloc_len);
3955 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3957 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3958 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3959 break;
3961 case VT_I2:
3962 case VT_UI2:
3963 case VT_I4:
3964 case VT_UI4:
3965 case VT_INT:
3966 case VT_UINT:
3967 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3968 *(INT*)(pBlk + pItem->byte_offs);
3969 break;
3970 default:
3971 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3975 else {
3976 TRACE_(typelib)("VAR_PERINSTANCE\n");
3977 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3978 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3981 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3982 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3984 if (pItem->flags & 0x80)
3985 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3987 prevName = pVarDesc->Name;
3989 pTI->cVars = cVars;
3992 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3993 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3995 SLTG_Function *pFunc;
3996 unsigned short i;
3997 TLBFuncDesc *pFuncDesc;
3999 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4001 pFuncDesc = pTI->funcdescs;
4002 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4003 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4005 int param;
4006 WORD *pType, *pArg;
4008 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4009 case SLTG_FUNCTION_MAGIC:
4010 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4011 break;
4012 case SLTG_DISPATCH_FUNCTION_MAGIC:
4013 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4014 break;
4015 case SLTG_STATIC_FUNCTION_MAGIC:
4016 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4017 break;
4018 default:
4019 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4020 continue;
4022 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4024 pFuncDesc->funcdesc.memid = pFunc->dispid;
4025 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4026 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4027 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4028 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4029 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4031 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4032 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4034 if(pFunc->retnextopt & 0x80)
4035 pType = &pFunc->rettype;
4036 else
4037 pType = (WORD*)(pBlk + pFunc->rettype);
4039 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4041 pFuncDesc->funcdesc.lprgelemdescParam =
4042 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4043 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4045 pArg = (WORD*)(pBlk + pFunc->arg_off);
4047 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4048 char *paramName = pNameTable + *pArg;
4049 BOOL HaveOffs;
4050 /* If arg type follows then paramName points to the 2nd
4051 letter of the name, else the next WORD is an offset to
4052 the arg type and paramName points to the first letter.
4053 So let's take one char off paramName and see if we're
4054 pointing at an alpha-numeric char. However if *pArg is
4055 0xffff or 0xfffe then the param has no name, the former
4056 meaning that the next WORD is the type, the latter
4057 meaning that the next WORD is an offset to the type. */
4059 HaveOffs = FALSE;
4060 if(*pArg == 0xffff)
4061 paramName = NULL;
4062 else if(*pArg == 0xfffe) {
4063 paramName = NULL;
4064 HaveOffs = TRUE;
4066 else if(paramName[-1] && !isalnum(paramName[-1]))
4067 HaveOffs = TRUE;
4069 pArg++;
4071 if(HaveOffs) { /* the next word is an offset to type */
4072 pType = (WORD*)(pBlk + *pArg);
4073 SLTG_DoElem(pType, pBlk,
4074 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4075 pArg++;
4076 } else {
4077 if(paramName)
4078 paramName--;
4079 pArg = SLTG_DoElem(pArg, pBlk,
4080 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4083 /* Are we an optional param ? */
4084 if(pFuncDesc->funcdesc.cParams - param <=
4085 pFuncDesc->funcdesc.cParamsOpt)
4086 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4088 if(paramName) {
4089 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4090 paramName - pNameTable, pTI->pTypeLib);
4091 } else {
4092 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4096 pTI->cFuncs = cFuncs;
4099 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4100 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4101 SLTG_TypeInfoTail *pTITail)
4103 char *pFirstItem;
4104 sltg_ref_lookup_t *ref_lookup = NULL;
4106 if(pTIHeader->href_table != 0xffffffff) {
4107 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4108 pNameTable);
4111 pFirstItem = pBlk;
4113 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4114 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4116 heap_free(ref_lookup);
4120 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4121 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4122 const SLTG_TypeInfoTail *pTITail)
4124 char *pFirstItem;
4125 sltg_ref_lookup_t *ref_lookup = NULL;
4127 if(pTIHeader->href_table != 0xffffffff) {
4128 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4129 pNameTable);
4132 pFirstItem = pBlk;
4134 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4135 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4138 if (pTITail->funcs_off != 0xffff)
4139 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4141 heap_free(ref_lookup);
4143 if (TRACE_ON(typelib))
4144 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4147 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4148 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4149 const SLTG_TypeInfoTail *pTITail)
4151 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4154 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4155 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4156 const SLTG_TypeInfoTail *pTITail)
4158 WORD *pType;
4159 sltg_ref_lookup_t *ref_lookup = NULL;
4161 if (pTITail->simple_alias) {
4162 /* if simple alias, no more processing required */
4163 pTI->tdescAlias.vt = pTITail->tdescalias_vt;
4164 return;
4167 if(pTIHeader->href_table != 0xffffffff) {
4168 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4169 pNameTable);
4172 /* otherwise it is an offset to a type */
4173 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4175 SLTG_DoType(pType, pBlk, &pTI->tdescAlias, ref_lookup);
4177 heap_free(ref_lookup);
4180 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4181 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4182 const SLTG_TypeInfoTail *pTITail)
4184 sltg_ref_lookup_t *ref_lookup = NULL;
4185 if (pTIHeader->href_table != 0xffffffff)
4186 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4187 pNameTable);
4189 if (pTITail->vars_off != 0xffff)
4190 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4192 if (pTITail->funcs_off != 0xffff)
4193 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4195 if (pTITail->impls_off != 0xffff)
4196 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4198 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4199 * of dispinterface functions including the IDispatch ones, so
4200 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4201 pTI->cbSizeVft = pTI->cFuncs * sizeof(void *);
4203 heap_free(ref_lookup);
4204 if (TRACE_ON(typelib))
4205 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4208 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4209 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4210 const SLTG_TypeInfoTail *pTITail)
4212 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4215 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4216 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4217 const SLTG_TypeInfoTail *pTITail)
4219 sltg_ref_lookup_t *ref_lookup = NULL;
4220 if (pTIHeader->href_table != 0xffffffff)
4221 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4222 pNameTable);
4224 if (pTITail->vars_off != 0xffff)
4225 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4227 if (pTITail->funcs_off != 0xffff)
4228 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4229 heap_free(ref_lookup);
4230 if (TRACE_ON(typelib))
4231 dump_TypeInfo(pTI);
4234 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4235 manageable copy of it into this */
4236 typedef struct {
4237 WORD small_no;
4238 char *index_name;
4239 char *other_name;
4240 WORD res1a;
4241 WORD name_offs;
4242 WORD more_bytes;
4243 char *extra;
4244 WORD res20;
4245 DWORD helpcontext;
4246 WORD res26;
4247 GUID uuid;
4248 } SLTG_InternalOtherTypeInfo;
4250 /****************************************************************************
4251 * ITypeLib2_Constructor_SLTG
4253 * loading a SLTG typelib from an in-memory image
4255 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4257 ITypeLibImpl *pTypeLibImpl;
4258 SLTG_Header *pHeader;
4259 SLTG_BlkEntry *pBlkEntry;
4260 SLTG_Magic *pMagic;
4261 SLTG_Index *pIndex;
4262 SLTG_Pad9 *pPad9;
4263 LPVOID pBlk, pFirstBlk;
4264 SLTG_LibBlk *pLibBlk;
4265 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4266 char *pAfterOTIBlks = NULL;
4267 char *pNameTable, *ptr;
4268 int i;
4269 DWORD len, order;
4270 ITypeInfoImpl **ppTypeInfoImpl;
4272 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4275 pTypeLibImpl = TypeLibImpl_Constructor();
4276 if (!pTypeLibImpl) return NULL;
4278 pHeader = pLib;
4280 TRACE_(typelib)("header:\n");
4281 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4282 pHeader->nrOfFileBlks );
4283 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4284 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4285 pHeader->SLTG_magic);
4286 return NULL;
4289 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4290 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4292 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4293 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4295 /* Next we have a magic block */
4296 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4298 /* Let's see if we're still in sync */
4299 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4300 sizeof(SLTG_COMPOBJ_MAGIC))) {
4301 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4302 return NULL;
4304 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4305 sizeof(SLTG_DIR_MAGIC))) {
4306 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4307 return NULL;
4310 pIndex = (SLTG_Index*)(pMagic+1);
4312 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4314 pFirstBlk = pPad9 + 1;
4316 /* We'll set up a ptr to the main library block, which is the last one. */
4318 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4319 pBlkEntry[order].next != 0;
4320 order = pBlkEntry[order].next - 1, i++) {
4321 pBlk = (char*)pBlk + pBlkEntry[order].len;
4323 pLibBlk = pBlk;
4325 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4327 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4328 interspersed */
4330 len += 0x40;
4332 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4334 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4337 ptr = (char*)pLibBlk + len;
4339 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4340 WORD w, extra;
4341 len = 0;
4343 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4345 w = *(WORD*)(ptr + 2);
4346 if(w != 0xffff) {
4347 len += w;
4348 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4349 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4350 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4352 w = *(WORD*)(ptr + 4 + len);
4353 if(w != 0xffff) {
4354 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4355 len += w;
4356 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4357 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4358 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4360 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4361 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4362 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4363 if(extra) {
4364 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4365 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4366 len += extra;
4368 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4369 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4370 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4371 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4372 len += sizeof(SLTG_OtherTypeInfo);
4373 ptr += len;
4376 pAfterOTIBlks = ptr;
4378 /* Skip this WORD and get the next DWORD */
4379 len = *(DWORD*)(pAfterOTIBlks + 2);
4381 /* Now add this to pLibBLk look at what we're pointing at and
4382 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4383 dust and we should be pointing at the beginning of the name
4384 table */
4386 pNameTable = (char*)pLibBlk + len;
4388 switch(*(WORD*)pNameTable) {
4389 case 0xffff:
4390 break;
4391 case 0x0200:
4392 pNameTable += 0x20;
4393 break;
4394 default:
4395 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4396 break;
4399 pNameTable += 0x216;
4401 pNameTable += 2;
4403 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4405 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4408 /* Hopefully we now have enough ptrs set up to actually read in
4409 some TypeInfos. It's not clear which order to do them in, so
4410 I'll just follow the links along the BlkEntry chain and read
4411 them in the order in which they are in the file */
4413 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4414 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4416 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4417 pBlkEntry[order].next != 0;
4418 order = pBlkEntry[order].next - 1, i++) {
4420 SLTG_TypeInfoHeader *pTIHeader;
4421 SLTG_TypeInfoTail *pTITail;
4422 SLTG_MemberHeader *pMemHeader;
4424 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4425 FIXME_(typelib)("Index strings don't match\n");
4426 heap_free(pOtherTypeInfoBlks);
4427 return NULL;
4430 pTIHeader = pBlk;
4431 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4432 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4433 heap_free(pOtherTypeInfoBlks);
4434 return NULL;
4436 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4437 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4438 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4440 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4441 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4442 (*ppTypeInfoImpl)->index = i;
4443 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4444 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4445 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid);
4446 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4447 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4448 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4449 (*ppTypeInfoImpl)->wTypeFlags =
4450 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4452 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4453 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4455 if((pTIHeader->typeflags1 & 7) != 2)
4456 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4457 if(pTIHeader->typeflags3 != 2)
4458 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4460 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4461 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4462 typekind_desc[pTIHeader->typekind],
4463 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4464 (*ppTypeInfoImpl)->wTypeFlags);
4466 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4468 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4470 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4471 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4472 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4474 switch(pTIHeader->typekind) {
4475 case TKIND_ENUM:
4476 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4477 pTIHeader, pTITail);
4478 break;
4480 case TKIND_RECORD:
4481 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4482 pTIHeader, pTITail);
4483 break;
4485 case TKIND_INTERFACE:
4486 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4487 pTIHeader, pTITail);
4488 break;
4490 case TKIND_COCLASS:
4491 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4492 pTIHeader, pTITail);
4493 break;
4495 case TKIND_ALIAS:
4496 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4497 pTIHeader, pTITail);
4498 break;
4500 case TKIND_DISPATCH:
4501 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4502 pTIHeader, pTITail);
4503 break;
4505 case TKIND_MODULE:
4506 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4507 pTIHeader, pTITail);
4508 break;
4510 default:
4511 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4512 break;
4516 /* could get cFuncs, cVars and cImplTypes from here
4517 but we've already set those */
4518 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4519 X(06);
4520 X(16);
4521 X(18);
4522 X(1a);
4523 X(1e);
4524 X(24);
4525 X(26);
4526 X(2a);
4527 X(2c);
4528 X(2e);
4529 X(30);
4530 X(32);
4531 X(34);
4532 #undef X
4533 ++ppTypeInfoImpl;
4534 pBlk = (char*)pBlk + pBlkEntry[order].len;
4537 if(i != pTypeLibImpl->TypeInfoCount) {
4538 FIXME("Somehow processed %d TypeInfos\n", i);
4539 heap_free(pOtherTypeInfoBlks);
4540 return NULL;
4543 heap_free(pOtherTypeInfoBlks);
4544 return &pTypeLibImpl->ITypeLib2_iface;
4547 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4549 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4551 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4553 if(IsEqualIID(riid, &IID_IUnknown) ||
4554 IsEqualIID(riid,&IID_ITypeLib)||
4555 IsEqualIID(riid,&IID_ITypeLib2))
4557 *ppv = &This->ITypeLib2_iface;
4559 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4560 IsEqualIID(riid, &IID_ICreateTypeLib2))
4562 *ppv = &This->ICreateTypeLib2_iface;
4564 else
4566 *ppv = NULL;
4567 TRACE("-- Interface: E_NOINTERFACE\n");
4568 return E_NOINTERFACE;
4571 IUnknown_AddRef((IUnknown*)*ppv);
4572 return S_OK;
4575 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4577 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4578 ULONG ref = InterlockedIncrement(&This->ref);
4580 TRACE("(%p) ref=%u\n", This, ref);
4582 return ref;
4585 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4587 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4588 ULONG ref = InterlockedDecrement(&This->ref);
4590 TRACE("(%p) ref=%u\n",This, ref);
4592 if (!ref)
4594 TLBImpLib *pImpLib, *pImpLibNext;
4595 TLBRefType *ref_type;
4596 TLBString *tlbstr, *tlbstr_next;
4597 void *cursor2;
4598 int i;
4600 /* remove cache entry */
4601 if(This->path)
4603 TRACE("removing from cache list\n");
4604 EnterCriticalSection(&cache_section);
4605 if(This->entry.next)
4606 list_remove(&This->entry);
4607 LeaveCriticalSection(&cache_section);
4608 heap_free(This->path);
4610 TRACE(" destroying ITypeLib(%p)\n",This);
4612 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4613 list_remove(&tlbstr->entry);
4614 heap_free(tlbstr);
4617 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4618 list_remove(&tlbstr->entry);
4619 heap_free(tlbstr);
4622 TLB_FreeCustData(&This->custdata_list);
4624 for (i = 0; i < This->ctTypeDesc; i++)
4625 if (This->pTypeDesc[i].vt == VT_CARRAY)
4626 heap_free(This->pTypeDesc[i].u.lpadesc);
4628 heap_free(This->pTypeDesc);
4630 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4632 if (pImpLib->pImpTypeLib)
4633 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4634 SysFreeString(pImpLib->name);
4636 list_remove(&pImpLib->entry);
4637 heap_free(pImpLib);
4640 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4642 list_remove(&ref_type->entry);
4643 heap_free(ref_type);
4646 for (i = 0; i < This->TypeInfoCount; ++i)
4647 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4648 heap_free(This->typeinfos);
4649 heap_free(This);
4650 return 0;
4653 return ref;
4656 /* ITypeLib::GetTypeInfoCount
4658 * Returns the number of type descriptions in the type library
4660 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4662 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4663 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4664 return This->TypeInfoCount;
4667 /* ITypeLib::GetTypeInfo
4669 * retrieves the specified type description in the library.
4671 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4672 ITypeLib2 *iface,
4673 UINT index,
4674 ITypeInfo **ppTInfo)
4676 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4678 TRACE("%p %u %p\n", This, index, ppTInfo);
4680 if(!ppTInfo)
4681 return E_INVALIDARG;
4683 if(index >= This->TypeInfoCount)
4684 return TYPE_E_ELEMENTNOTFOUND;
4686 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4687 ITypeInfo_AddRef(*ppTInfo);
4689 return S_OK;
4693 /* ITypeLibs::GetTypeInfoType
4695 * Retrieves the type of a type description.
4697 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4698 ITypeLib2 *iface,
4699 UINT index,
4700 TYPEKIND *pTKind)
4702 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4704 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4706 if(!pTKind)
4707 return E_INVALIDARG;
4709 if(index >= This->TypeInfoCount)
4710 return TYPE_E_ELEMENTNOTFOUND;
4712 *pTKind = This->typeinfos[index]->typekind;
4714 return S_OK;
4717 /* ITypeLib::GetTypeInfoOfGuid
4719 * Retrieves the type description that corresponds to the specified GUID.
4722 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4723 ITypeLib2 *iface,
4724 REFGUID guid,
4725 ITypeInfo **ppTInfo)
4727 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4728 int i;
4730 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4732 for(i = 0; i < This->TypeInfoCount; ++i){
4733 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4734 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4735 ITypeInfo_AddRef(*ppTInfo);
4736 return S_OK;
4740 return TYPE_E_ELEMENTNOTFOUND;
4743 /* ITypeLib::GetLibAttr
4745 * Retrieves the structure that contains the library's attributes.
4748 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4749 ITypeLib2 *iface,
4750 LPTLIBATTR *attr)
4752 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4754 TRACE("(%p, %p)\n", This, attr);
4756 if (!attr) return E_INVALIDARG;
4758 *attr = heap_alloc(sizeof(**attr));
4759 if (!*attr) return E_OUTOFMEMORY;
4761 (*attr)->guid = *TLB_get_guid_null(This->guid);
4762 (*attr)->lcid = This->set_lcid;
4763 (*attr)->syskind = This->syskind;
4764 (*attr)->wMajorVerNum = This->ver_major;
4765 (*attr)->wMinorVerNum = This->ver_minor;
4766 (*attr)->wLibFlags = This->libflags;
4768 return S_OK;
4771 /* ITypeLib::GetTypeComp
4773 * Enables a client compiler to bind to a library's types, variables,
4774 * constants, and global functions.
4777 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4778 ITypeLib2 *iface,
4779 ITypeComp **ppTComp)
4781 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4783 TRACE("(%p)->(%p)\n",This,ppTComp);
4784 *ppTComp = &This->ITypeComp_iface;
4785 ITypeComp_AddRef(*ppTComp);
4787 return S_OK;
4790 /* ITypeLib::GetDocumentation
4792 * Retrieves the library's documentation string, the complete Help file name
4793 * and path, and the context identifier for the library Help topic in the Help
4794 * file.
4796 * On a successful return all non-null BSTR pointers will have been set,
4797 * possibly to NULL.
4799 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4800 ITypeLib2 *iface,
4801 INT index,
4802 BSTR *pBstrName,
4803 BSTR *pBstrDocString,
4804 DWORD *pdwHelpContext,
4805 BSTR *pBstrHelpFile)
4807 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4808 HRESULT result = E_INVALIDARG;
4809 ITypeInfo *pTInfo;
4811 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4812 This, index,
4813 pBstrName, pBstrDocString,
4814 pdwHelpContext, pBstrHelpFile);
4816 if(index<0)
4818 /* documentation for the typelib */
4819 if(pBstrName)
4821 if (This->Name)
4823 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4824 goto memerr1;
4826 else
4827 *pBstrName = NULL;
4829 if(pBstrDocString)
4831 if (This->DocString)
4833 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4834 goto memerr2;
4836 else
4837 *pBstrDocString = NULL;
4839 if(pdwHelpContext)
4841 *pdwHelpContext = This->dwHelpContext;
4843 if(pBstrHelpFile)
4845 if (This->HelpFile)
4847 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4848 goto memerr3;
4850 else
4851 *pBstrHelpFile = NULL;
4854 result = S_OK;
4856 else
4858 /* for a typeinfo */
4859 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4861 if(SUCCEEDED(result))
4863 result = ITypeInfo_GetDocumentation(pTInfo,
4864 MEMBERID_NIL,
4865 pBstrName,
4866 pBstrDocString,
4867 pdwHelpContext, pBstrHelpFile);
4869 ITypeInfo_Release(pTInfo);
4872 return result;
4873 memerr3:
4874 if (pBstrDocString) SysFreeString (*pBstrDocString);
4875 memerr2:
4876 if (pBstrName) SysFreeString (*pBstrName);
4877 memerr1:
4878 return STG_E_INSUFFICIENTMEMORY;
4881 /* ITypeLib::IsName
4883 * Indicates whether a passed-in string contains the name of a type or member
4884 * described in the library.
4887 static HRESULT WINAPI ITypeLib2_fnIsName(
4888 ITypeLib2 *iface,
4889 LPOLESTR szNameBuf,
4890 ULONG lHashVal,
4891 BOOL *pfName)
4893 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4894 int tic;
4895 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4897 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4898 pfName);
4900 *pfName=TRUE;
4901 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4902 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4903 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4904 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4905 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4906 int pc;
4907 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4908 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
4909 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
4910 goto ITypeLib2_fnIsName_exit;
4913 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
4914 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4915 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4919 *pfName=FALSE;
4921 ITypeLib2_fnIsName_exit:
4922 TRACE("(%p)slow! search for %s: %s found!\n", This,
4923 debugstr_w(szNameBuf), *pfName?"NOT":"");
4925 return S_OK;
4928 /* ITypeLib::FindName
4930 * Finds occurrences of a type description in a type library. This may be used
4931 * to quickly verify that a name exists in a type library.
4934 static HRESULT WINAPI ITypeLib2_fnFindName(
4935 ITypeLib2 *iface,
4936 LPOLESTR name,
4937 ULONG hash,
4938 ITypeInfo **ppTInfo,
4939 MEMBERID *memid,
4940 UINT16 *found)
4942 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4943 int tic;
4944 UINT count = 0;
4945 UINT len;
4947 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4949 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4950 return E_INVALIDARG;
4952 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4953 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4954 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4955 TLBVarDesc *var;
4956 UINT fdc;
4958 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4959 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4960 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4961 int pc;
4963 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4964 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4965 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
4966 goto ITypeLib2_fnFindName_exit;
4970 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
4971 if (var)
4972 goto ITypeLib2_fnFindName_exit;
4974 continue;
4975 ITypeLib2_fnFindName_exit:
4976 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4977 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4978 count++;
4980 TRACE("found %d typeinfos\n", count);
4982 *found = count;
4984 return S_OK;
4987 /* ITypeLib::ReleaseTLibAttr
4989 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4992 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4993 ITypeLib2 *iface,
4994 TLIBATTR *pTLibAttr)
4996 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4997 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4998 heap_free(pTLibAttr);
5001 /* ITypeLib2::GetCustData
5003 * gets the custom data
5005 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5006 ITypeLib2 * iface,
5007 REFGUID guid,
5008 VARIANT *pVarVal)
5010 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5011 TLBCustData *pCData;
5013 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5015 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5016 if(!pCData)
5017 return TYPE_E_ELEMENTNOTFOUND;
5019 VariantInit(pVarVal);
5020 VariantCopy(pVarVal, &pCData->data);
5022 return S_OK;
5025 /* ITypeLib2::GetLibStatistics
5027 * Returns statistics about a type library that are required for efficient
5028 * sizing of hash tables.
5031 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5032 ITypeLib2 * iface,
5033 ULONG *pcUniqueNames,
5034 ULONG *pcchUniqueNames)
5036 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5038 FIXME("(%p): stub!\n", This);
5040 if(pcUniqueNames) *pcUniqueNames=1;
5041 if(pcchUniqueNames) *pcchUniqueNames=1;
5042 return S_OK;
5045 /* ITypeLib2::GetDocumentation2
5047 * Retrieves the library's documentation string, the complete Help file name
5048 * and path, the localization context to use, and the context ID for the
5049 * library Help topic in the Help file.
5052 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5053 ITypeLib2 * iface,
5054 INT index,
5055 LCID lcid,
5056 BSTR *pbstrHelpString,
5057 DWORD *pdwHelpStringContext,
5058 BSTR *pbstrHelpStringDll)
5060 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5061 HRESULT result;
5062 ITypeInfo *pTInfo;
5064 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5066 /* the help string should be obtained from the helpstringdll,
5067 * using the _DLLGetDocumentation function, based on the supplied
5068 * lcid. Nice to do sometime...
5070 if(index<0)
5072 /* documentation for the typelib */
5073 if(pbstrHelpString)
5074 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5075 if(pdwHelpStringContext)
5076 *pdwHelpStringContext=This->dwHelpContext;
5077 if(pbstrHelpStringDll)
5078 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5080 result = S_OK;
5082 else
5084 /* for a typeinfo */
5085 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5087 if(SUCCEEDED(result))
5089 ITypeInfo2 * pTInfo2;
5090 result = ITypeInfo_QueryInterface(pTInfo,
5091 &IID_ITypeInfo2,
5092 (LPVOID*) &pTInfo2);
5094 if(SUCCEEDED(result))
5096 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5097 MEMBERID_NIL,
5098 lcid,
5099 pbstrHelpString,
5100 pdwHelpStringContext,
5101 pbstrHelpStringDll);
5103 ITypeInfo2_Release(pTInfo2);
5106 ITypeInfo_Release(pTInfo);
5109 return result;
5112 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5114 TLBCustData *pCData;
5115 unsigned int ct;
5116 CUSTDATAITEM *cdi;
5118 ct = list_count(custdata_list);
5120 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5121 if(!pCustData->prgCustData)
5122 return E_OUTOFMEMORY;
5124 pCustData->cCustData = ct;
5126 cdi = pCustData->prgCustData;
5127 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5128 cdi->guid = *TLB_get_guid_null(pCData->guid);
5129 VariantCopy(&cdi->varValue, &pCData->data);
5130 ++cdi;
5133 return S_OK;
5137 /* ITypeLib2::GetAllCustData
5139 * Gets all custom data items for the library.
5142 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5143 ITypeLib2 * iface,
5144 CUSTDATA *pCustData)
5146 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5147 TRACE("(%p)->(%p)\n", This, pCustData);
5148 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5151 static const ITypeLib2Vtbl tlbvt = {
5152 ITypeLib2_fnQueryInterface,
5153 ITypeLib2_fnAddRef,
5154 ITypeLib2_fnRelease,
5155 ITypeLib2_fnGetTypeInfoCount,
5156 ITypeLib2_fnGetTypeInfo,
5157 ITypeLib2_fnGetTypeInfoType,
5158 ITypeLib2_fnGetTypeInfoOfGuid,
5159 ITypeLib2_fnGetLibAttr,
5160 ITypeLib2_fnGetTypeComp,
5161 ITypeLib2_fnGetDocumentation,
5162 ITypeLib2_fnIsName,
5163 ITypeLib2_fnFindName,
5164 ITypeLib2_fnReleaseTLibAttr,
5166 ITypeLib2_fnGetCustData,
5167 ITypeLib2_fnGetLibStatistics,
5168 ITypeLib2_fnGetDocumentation2,
5169 ITypeLib2_fnGetAllCustData
5173 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5175 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5177 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5180 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5182 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5184 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5187 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5189 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5191 return ITypeLib2_Release(&This->ITypeLib2_iface);
5194 static HRESULT WINAPI ITypeLibComp_fnBind(
5195 ITypeComp * iface,
5196 OLECHAR * szName,
5197 ULONG lHash,
5198 WORD wFlags,
5199 ITypeInfo ** ppTInfo,
5200 DESCKIND * pDescKind,
5201 BINDPTR * pBindPtr)
5203 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5204 int typemismatch=0, i;
5206 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5208 *pDescKind = DESCKIND_NONE;
5209 pBindPtr->lptcomp = NULL;
5210 *ppTInfo = NULL;
5212 for(i = 0; i < This->TypeInfoCount; ++i){
5213 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5214 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5216 /* FIXME: check wFlags here? */
5217 /* FIXME: we should use a hash table to look this info up using lHash
5218 * instead of an O(n) search */
5219 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5220 (pTypeInfo->typekind == TKIND_MODULE))
5222 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5224 *pDescKind = DESCKIND_TYPECOMP;
5225 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5226 ITypeComp_AddRef(pBindPtr->lptcomp);
5227 TRACE("module or enum: %s\n", debugstr_w(szName));
5228 return S_OK;
5232 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5233 (pTypeInfo->typekind == TKIND_ENUM))
5235 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5236 HRESULT hr;
5238 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5239 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5241 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5242 return S_OK;
5244 else if (hr == TYPE_E_TYPEMISMATCH)
5245 typemismatch = 1;
5248 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5249 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5251 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5252 HRESULT hr;
5253 ITypeInfo *subtypeinfo;
5254 BINDPTR subbindptr;
5255 DESCKIND subdesckind;
5257 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5258 &subtypeinfo, &subdesckind, &subbindptr);
5259 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5261 TYPEDESC tdesc_appobject;
5262 const VARDESC vardesc_appobject =
5264 -2, /* memid */
5265 NULL, /* lpstrSchema */
5267 0 /* oInst */
5270 /* ELEMDESC */
5272 /* TYPEDESC */
5274 &tdesc_appobject
5276 VT_PTR
5279 0, /* wVarFlags */
5280 VAR_STATIC /* varkind */
5283 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5284 tdesc_appobject.vt = VT_USERDEFINED;
5286 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5288 /* cleanup things filled in by Bind call so we can put our
5289 * application object data in there instead */
5290 switch (subdesckind)
5292 case DESCKIND_FUNCDESC:
5293 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5294 break;
5295 case DESCKIND_VARDESC:
5296 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5297 break;
5298 default:
5299 break;
5301 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5303 if (pTypeInfo->hreftype == -1)
5304 FIXME("no hreftype for interface %p\n", pTypeInfo);
5306 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5307 if (FAILED(hr))
5308 return hr;
5310 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5311 *ppTInfo = (ITypeInfo *)pTypeInfo;
5312 ITypeInfo_AddRef(*ppTInfo);
5313 return S_OK;
5315 else if (hr == TYPE_E_TYPEMISMATCH)
5316 typemismatch = 1;
5320 if (typemismatch)
5322 TRACE("type mismatch %s\n", debugstr_w(szName));
5323 return TYPE_E_TYPEMISMATCH;
5325 else
5327 TRACE("name not found %s\n", debugstr_w(szName));
5328 return S_OK;
5332 static HRESULT WINAPI ITypeLibComp_fnBindType(
5333 ITypeComp * iface,
5334 OLECHAR * szName,
5335 ULONG lHash,
5336 ITypeInfo ** ppTInfo,
5337 ITypeComp ** ppTComp)
5339 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5340 ITypeInfoImpl *info;
5342 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5344 if(!szName || !ppTInfo || !ppTComp)
5345 return E_INVALIDARG;
5347 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5348 if(!info){
5349 *ppTInfo = NULL;
5350 *ppTComp = NULL;
5351 return S_OK;
5354 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5355 ITypeInfo_AddRef(*ppTInfo);
5356 *ppTComp = &info->ITypeComp_iface;
5357 ITypeComp_AddRef(*ppTComp);
5359 return S_OK;
5362 static const ITypeCompVtbl tlbtcvt =
5365 ITypeLibComp_fnQueryInterface,
5366 ITypeLibComp_fnAddRef,
5367 ITypeLibComp_fnRelease,
5369 ITypeLibComp_fnBind,
5370 ITypeLibComp_fnBindType
5373 /*================== ITypeInfo(2) Methods ===================================*/
5374 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5376 ITypeInfoImpl *pTypeInfoImpl;
5378 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5379 if (pTypeInfoImpl)
5381 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5382 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5383 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5384 pTypeInfoImpl->ref = 0;
5385 pTypeInfoImpl->hreftype = -1;
5386 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5387 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5388 list_init(&pTypeInfoImpl->custdata_list);
5390 TRACE("(%p)\n", pTypeInfoImpl);
5391 return pTypeInfoImpl;
5394 /* ITypeInfo::QueryInterface
5396 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5397 ITypeInfo2 *iface,
5398 REFIID riid,
5399 VOID **ppvObject)
5401 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5403 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5405 *ppvObject=NULL;
5406 if(IsEqualIID(riid, &IID_IUnknown) ||
5407 IsEqualIID(riid,&IID_ITypeInfo)||
5408 IsEqualIID(riid,&IID_ITypeInfo2))
5409 *ppvObject = This;
5410 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5411 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5412 *ppvObject = &This->ICreateTypeInfo2_iface;
5414 if(*ppvObject){
5415 ITypeInfo2_AddRef(iface);
5416 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5417 return S_OK;
5419 TRACE("-- Interface: E_NOINTERFACE\n");
5420 return E_NOINTERFACE;
5423 /* ITypeInfo::AddRef
5425 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5427 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5428 ULONG ref = InterlockedIncrement(&This->ref);
5430 TRACE("(%p)->ref is %u\n",This, ref);
5432 if (ref == 1 /* incremented from 0 */)
5433 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5435 return ref;
5438 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5440 UINT i;
5442 TRACE("destroying ITypeInfo(%p)\n",This);
5444 for (i = 0; i < This->cFuncs; ++i)
5446 int j;
5447 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5448 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5450 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5451 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5453 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5454 heap_free(elemdesc->u.paramdesc.pparamdescex);
5456 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5458 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5459 heap_free(pFInfo->pParamDesc);
5460 TLB_FreeCustData(&pFInfo->custdata_list);
5462 heap_free(This->funcdescs);
5464 for(i = 0; i < This->cVars; ++i)
5466 TLBVarDesc *pVInfo = &This->vardescs[i];
5467 if (pVInfo->vardesc.varkind == VAR_CONST)
5469 VariantClear(pVInfo->vardesc.u.lpvarValue);
5470 heap_free(pVInfo->vardesc.u.lpvarValue);
5472 TLB_FreeCustData(&pVInfo->custdata_list);
5474 heap_free(This->vardescs);
5476 if(This->impltypes){
5477 for (i = 0; i < This->cImplTypes; ++i){
5478 TLBImplType *pImpl = &This->impltypes[i];
5479 TLB_FreeCustData(&pImpl->custdata_list);
5481 heap_free(This->impltypes);
5484 TLB_FreeCustData(&This->custdata_list);
5486 heap_free(This);
5489 /* ITypeInfo::Release
5491 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5493 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5494 ULONG ref = InterlockedDecrement(&This->ref);
5496 TRACE("(%p)->(%u)\n",This, ref);
5498 if (!ref)
5500 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5501 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5502 if (not_attached_to_typelib)
5503 heap_free(This);
5504 /* otherwise This will be freed when typelib is freed */
5507 return ref;
5510 /* ITypeInfo::GetTypeAttr
5512 * Retrieves a TYPEATTR structure that contains the attributes of the type
5513 * description.
5516 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5517 LPTYPEATTR *ppTypeAttr)
5519 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5520 SIZE_T size;
5522 TRACE("(%p)\n",This);
5524 size = sizeof(**ppTypeAttr);
5525 if (This->typekind == TKIND_ALIAS)
5526 size += TLB_SizeTypeDesc(&This->tdescAlias, FALSE);
5528 *ppTypeAttr = heap_alloc(size);
5529 if (!*ppTypeAttr)
5530 return E_OUTOFMEMORY;
5532 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5533 (*ppTypeAttr)->lcid = This->lcid;
5534 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5535 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5536 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5537 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5538 (*ppTypeAttr)->typekind = This->typekind;
5539 (*ppTypeAttr)->cFuncs = This->cFuncs;
5540 (*ppTypeAttr)->cVars = This->cVars;
5541 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5542 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5543 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5544 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5545 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5546 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5547 (*ppTypeAttr)->tdescAlias = This->tdescAlias;
5548 (*ppTypeAttr)->idldescType = This->idldescType;
5550 if (This->typekind == TKIND_ALIAS)
5551 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5552 &This->tdescAlias, *ppTypeAttr + 1);
5554 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5555 /* This should include all the inherited funcs */
5556 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5557 /* This is always the size of IDispatch's vtbl */
5558 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5559 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5561 return S_OK;
5564 /* ITypeInfo::GetTypeComp
5566 * Retrieves the ITypeComp interface for the type description, which enables a
5567 * client compiler to bind to the type description's members.
5570 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5571 ITypeComp * *ppTComp)
5573 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5575 TRACE("(%p)->(%p)\n", This, ppTComp);
5577 *ppTComp = &This->ITypeComp_iface;
5578 ITypeComp_AddRef(*ppTComp);
5579 return S_OK;
5582 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5584 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5585 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5586 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5587 return size;
5590 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5592 *dest = *src;
5593 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5594 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5596 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5597 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5598 *buffer += sizeof(PARAMDESCEX);
5599 *pparamdescex_dest = *pparamdescex_src;
5600 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5601 VariantInit(&pparamdescex_dest->varDefaultValue);
5602 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5603 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5605 else
5606 dest->u.paramdesc.pparamdescex = NULL;
5607 return S_OK;
5610 static HRESULT TLB_SanitizeBSTR(BSTR str)
5612 UINT len = SysStringLen(str), i;
5613 for (i = 0; i < len; ++i)
5614 if (str[i] > 0x7f)
5615 str[i] = '?';
5616 return S_OK;
5619 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5621 if (V_VT(var) == VT_INT)
5622 return VariantChangeType(var, var, 0, VT_I4);
5623 else if (V_VT(var) == VT_UINT)
5624 return VariantChangeType(var, var, 0, VT_UI4);
5625 else if (V_VT(var) == VT_BSTR)
5626 return TLB_SanitizeBSTR(V_BSTR(var));
5628 return S_OK;
5631 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5633 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5634 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5637 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5639 FUNCDESC *dest;
5640 char *buffer;
5641 SIZE_T size = sizeof(*src);
5642 SHORT i;
5643 HRESULT hr;
5645 size += sizeof(*src->lprgscode) * src->cScodes;
5646 size += TLB_SizeElemDesc(&src->elemdescFunc);
5647 for (i = 0; i < src->cParams; i++)
5649 size += sizeof(ELEMDESC);
5650 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5653 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5654 if (!dest) return E_OUTOFMEMORY;
5656 *dest = *src;
5657 if (dispinterface) /* overwrite funckind */
5658 dest->funckind = FUNC_DISPATCH;
5659 buffer = (char *)(dest + 1);
5661 dest->oVft = dest->oVft & 0xFFFC;
5663 if (dest->cScodes) {
5664 dest->lprgscode = (SCODE *)buffer;
5665 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5666 buffer += sizeof(*src->lprgscode) * src->cScodes;
5667 } else
5668 dest->lprgscode = NULL;
5670 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5671 if (FAILED(hr))
5673 SysFreeString((BSTR)dest);
5674 return hr;
5677 if (dest->cParams) {
5678 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5679 buffer += sizeof(ELEMDESC) * src->cParams;
5680 for (i = 0; i < src->cParams; i++)
5682 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5683 if (FAILED(hr))
5684 break;
5686 if (FAILED(hr))
5688 /* undo the above actions */
5689 for (i = i - 1; i >= 0; i--)
5690 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5691 TLB_FreeElemDesc(&dest->elemdescFunc);
5692 SysFreeString((BSTR)dest);
5693 return hr;
5695 } else
5696 dest->lprgelemdescParam = NULL;
5698 /* special treatment for dispinterfaces: this makes functions appear
5699 * to return their [retval] value when it is really returning an
5700 * HRESULT */
5701 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5703 if (dest->cParams &&
5704 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5706 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5707 if (elemdesc->tdesc.vt != VT_PTR)
5709 ERR("elemdesc should have started with VT_PTR instead of:\n");
5710 if (ERR_ON(ole))
5711 dump_ELEMDESC(elemdesc);
5712 return E_UNEXPECTED;
5715 /* copy last parameter to the return value. we are using a flat
5716 * buffer so there is no danger of leaking memory in
5717 * elemdescFunc */
5718 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5720 /* remove the last parameter */
5721 dest->cParams--;
5723 else
5724 /* otherwise this function is made to appear to have no return
5725 * value */
5726 dest->elemdescFunc.tdesc.vt = VT_VOID;
5730 *dest_ptr = dest;
5731 return S_OK;
5734 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5736 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5738 if (index >= This->cFuncs)
5739 return TYPE_E_ELEMENTNOTFOUND;
5741 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5742 return S_OK;
5745 /* internal function to make the inherited interfaces' methods appear
5746 * part of the interface */
5747 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5748 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5750 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5751 HRESULT hr;
5752 UINT implemented_funcs = 0;
5754 if (funcs)
5755 *funcs = 0;
5756 else
5757 *hrefoffset = DISPATCH_HREF_OFFSET;
5759 if(This->impltypes)
5761 ITypeInfo *pSubTypeInfo;
5762 UINT sub_funcs;
5764 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5765 if (FAILED(hr))
5766 return hr;
5768 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5769 index,
5770 ppFuncDesc,
5771 &sub_funcs, hrefoffset);
5772 implemented_funcs += sub_funcs;
5773 ITypeInfo_Release(pSubTypeInfo);
5774 if (SUCCEEDED(hr))
5775 return hr;
5776 *hrefoffset += DISPATCH_HREF_OFFSET;
5779 if (funcs)
5780 *funcs = implemented_funcs + This->cFuncs;
5781 else
5782 *hrefoffset = 0;
5784 if (index < implemented_funcs)
5785 return E_INVALIDARG;
5786 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5787 ppFuncDesc);
5790 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5792 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5793 while (TRUE)
5795 switch (pTypeDesc->vt)
5797 case VT_USERDEFINED:
5798 pTypeDesc->u.hreftype += hrefoffset;
5799 return;
5800 case VT_PTR:
5801 case VT_SAFEARRAY:
5802 pTypeDesc = pTypeDesc->u.lptdesc;
5803 break;
5804 case VT_CARRAY:
5805 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5806 break;
5807 default:
5808 return;
5813 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5815 SHORT i;
5816 for (i = 0; i < pFuncDesc->cParams; i++)
5817 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5818 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5821 /* ITypeInfo::GetFuncDesc
5823 * Retrieves the FUNCDESC structure that contains information about a
5824 * specified function.
5827 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5828 LPFUNCDESC *ppFuncDesc)
5830 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5831 const FUNCDESC *internal_funcdesc;
5832 HRESULT hr;
5833 UINT hrefoffset = 0;
5835 TRACE("(%p) index %d\n", This, index);
5837 if (!ppFuncDesc)
5838 return E_INVALIDARG;
5840 if (This->needs_layout)
5841 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5843 if (This->typekind == TKIND_DISPATCH)
5844 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5845 &internal_funcdesc, NULL,
5846 &hrefoffset);
5847 else
5848 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5849 &internal_funcdesc);
5850 if (FAILED(hr))
5852 WARN("description for function %d not found\n", index);
5853 return hr;
5856 hr = TLB_AllocAndInitFuncDesc(
5857 internal_funcdesc,
5858 ppFuncDesc,
5859 This->typekind == TKIND_DISPATCH);
5861 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
5862 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5864 TRACE("-- 0x%08x\n", hr);
5865 return hr;
5868 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5870 VARDESC *dest;
5871 char *buffer;
5872 SIZE_T size = sizeof(*src);
5873 HRESULT hr;
5875 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5876 if (src->varkind == VAR_CONST)
5877 size += sizeof(VARIANT);
5878 size += TLB_SizeElemDesc(&src->elemdescVar);
5880 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5881 if (!dest) return E_OUTOFMEMORY;
5883 *dest = *src;
5884 buffer = (char *)(dest + 1);
5885 if (src->lpstrSchema)
5887 int len;
5888 dest->lpstrSchema = (LPOLESTR)buffer;
5889 len = strlenW(src->lpstrSchema);
5890 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5891 buffer += (len + 1) * sizeof(WCHAR);
5894 if (src->varkind == VAR_CONST)
5896 HRESULT hr;
5898 dest->u.lpvarValue = (VARIANT *)buffer;
5899 *dest->u.lpvarValue = *src->u.lpvarValue;
5900 buffer += sizeof(VARIANT);
5901 VariantInit(dest->u.lpvarValue);
5902 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5903 if (FAILED(hr))
5905 SysFreeString((BSTR)dest);
5906 return hr;
5909 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5910 if (FAILED(hr))
5912 if (src->varkind == VAR_CONST)
5913 VariantClear(dest->u.lpvarValue);
5914 SysFreeString((BSTR)dest);
5915 return hr;
5917 *dest_ptr = dest;
5918 return S_OK;
5921 /* ITypeInfo::GetVarDesc
5923 * Retrieves a VARDESC structure that describes the specified variable.
5926 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5927 LPVARDESC *ppVarDesc)
5929 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5930 const TLBVarDesc *pVDesc = &This->vardescs[index];
5932 TRACE("(%p) index %d\n", This, index);
5934 if(index >= This->cVars)
5935 return TYPE_E_ELEMENTNOTFOUND;
5937 if (This->needs_layout)
5938 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5940 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5943 /* ITypeInfo_GetNames
5945 * Retrieves the variable with the specified member ID (or the name of the
5946 * property or method and its parameters) that correspond to the specified
5947 * function ID.
5949 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5950 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5952 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5953 const TLBFuncDesc *pFDesc;
5954 const TLBVarDesc *pVDesc;
5955 int i;
5956 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5958 if(!rgBstrNames)
5959 return E_INVALIDARG;
5961 *pcNames = 0;
5963 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
5964 if(pFDesc)
5966 if(!cMaxNames || !pFDesc->Name)
5967 return S_OK;
5969 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
5970 ++(*pcNames);
5972 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
5973 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
5974 return S_OK;
5975 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
5976 ++(*pcNames);
5978 return S_OK;
5981 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
5982 if(pVDesc)
5984 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
5985 *pcNames=1;
5987 else
5989 if(This->impltypes &&
5990 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
5991 /* recursive search */
5992 ITypeInfo *pTInfo;
5993 HRESULT result;
5994 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5995 if(SUCCEEDED(result))
5997 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5998 ITypeInfo_Release(pTInfo);
5999 return result;
6001 WARN("Could not search inherited interface!\n");
6003 else
6005 WARN("no names found\n");
6007 *pcNames=0;
6008 return TYPE_E_ELEMENTNOTFOUND;
6010 return S_OK;
6014 /* ITypeInfo::GetRefTypeOfImplType
6016 * If a type description describes a COM class, it retrieves the type
6017 * description of the implemented interface types. For an interface,
6018 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6019 * if any exist.
6022 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6023 ITypeInfo2 *iface,
6024 UINT index,
6025 HREFTYPE *pRefType)
6027 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6028 HRESULT hr = S_OK;
6030 TRACE("(%p) index %d\n", This, index);
6031 if (TRACE_ON(ole)) dump_TypeInfo(This);
6033 if(index==(UINT)-1)
6035 /* only valid on dual interfaces;
6036 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6039 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6041 *pRefType = -2;
6043 else
6045 hr = TYPE_E_ELEMENTNOTFOUND;
6048 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6050 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6051 *pRefType = This->pTypeLib->dispatch_href;
6053 else
6055 if(index >= This->cImplTypes)
6056 hr = TYPE_E_ELEMENTNOTFOUND;
6057 else
6058 *pRefType = This->impltypes[index].hRef;
6061 if(TRACE_ON(ole))
6063 if(SUCCEEDED(hr))
6064 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6065 else
6066 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6069 return hr;
6072 /* ITypeInfo::GetImplTypeFlags
6074 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6075 * or base interface in a type description.
6077 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6078 UINT index, INT *pImplTypeFlags)
6080 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6082 TRACE("(%p) index %d\n", This, index);
6084 if(!pImplTypeFlags)
6085 return E_INVALIDARG;
6087 if(This->typekind == TKIND_DISPATCH && index == 0){
6088 *pImplTypeFlags = 0;
6089 return S_OK;
6092 if(index >= This->cImplTypes)
6093 return TYPE_E_ELEMENTNOTFOUND;
6095 *pImplTypeFlags = This->impltypes[index].implflags;
6097 return S_OK;
6100 /* GetIDsOfNames
6101 * Maps between member names and member IDs, and parameter names and
6102 * parameter IDs.
6104 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6105 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6107 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6108 const TLBVarDesc *pVDesc;
6109 HRESULT ret=S_OK;
6110 UINT i, fdc;
6112 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6113 cNames);
6115 /* init out parameters in case of failure */
6116 for (i = 0; i < cNames; i++)
6117 pMemId[i] = MEMBERID_NIL;
6119 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6120 int j;
6121 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6122 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6123 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6124 for(i=1; i < cNames; i++){
6125 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6126 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6127 break;
6128 if( j<pFDesc->funcdesc.cParams)
6129 pMemId[i]=j;
6130 else
6131 ret=DISP_E_UNKNOWNNAME;
6133 TRACE("-- 0x%08x\n", ret);
6134 return ret;
6137 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6138 if(pVDesc){
6139 if(cNames)
6140 *pMemId = pVDesc->vardesc.memid;
6141 return ret;
6143 /* not found, see if it can be found in an inherited interface */
6144 if(This->impltypes) {
6145 /* recursive search */
6146 ITypeInfo *pTInfo;
6147 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6148 if(SUCCEEDED(ret)){
6149 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6150 ITypeInfo_Release(pTInfo);
6151 return ret;
6153 WARN("Could not search inherited interface!\n");
6154 } else
6155 WARN("no names found\n");
6156 return DISP_E_UNKNOWNNAME;
6160 #ifdef __i386__
6162 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6163 __ASM_GLOBAL_FUNC( call_method,
6164 "pushl %ebp\n\t"
6165 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6166 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6167 "movl %esp,%ebp\n\t"
6168 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6169 "pushl %esi\n\t"
6170 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6171 "pushl %edi\n\t"
6172 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6173 "movl 12(%ebp),%edx\n\t"
6174 "movl %esp,%edi\n\t"
6175 "shll $2,%edx\n\t"
6176 "jz 1f\n\t"
6177 "subl %edx,%edi\n\t"
6178 "andl $~15,%edi\n\t"
6179 "movl %edi,%esp\n\t"
6180 "movl 12(%ebp),%ecx\n\t"
6181 "movl 16(%ebp),%esi\n\t"
6182 "cld\n\t"
6183 "rep; movsl\n"
6184 "1:\tcall *8(%ebp)\n\t"
6185 "subl %esp,%edi\n\t"
6186 "movl 20(%ebp),%ecx\n\t"
6187 "movl %edi,(%ecx)\n\t"
6188 "leal -8(%ebp),%esp\n\t"
6189 "popl %edi\n\t"
6190 __ASM_CFI(".cfi_same_value %edi\n\t")
6191 "popl %esi\n\t"
6192 __ASM_CFI(".cfi_same_value %esi\n\t")
6193 "popl %ebp\n\t"
6194 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6195 __ASM_CFI(".cfi_same_value %ebp\n\t")
6196 "ret" )
6198 /* same function but returning floating point */
6199 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6201 /* ITypeInfo::Invoke
6203 * Invokes a method, or accesses a property of an object, that implements the
6204 * interface described by the type description.
6206 DWORD
6207 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6208 DWORD res;
6209 int stack_offset;
6211 if (TRACE_ON(ole)) {
6212 int i;
6213 TRACE("Calling %p(",func);
6214 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6215 if (nrargs > 30) TRACE("...");
6216 TRACE(")\n");
6219 switch (callconv) {
6220 case CC_STDCALL:
6221 case CC_CDECL:
6222 res = call_method( func, nrargs, args, &stack_offset );
6223 break;
6224 default:
6225 FIXME("unsupported calling convention %d\n",callconv);
6226 res = -1;
6227 break;
6229 TRACE("returns %08x\n",res);
6230 return res;
6233 #elif defined(__x86_64__)
6235 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6236 __ASM_GLOBAL_FUNC( call_method,
6237 "pushq %rbp\n\t"
6238 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6239 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6240 "movq %rsp,%rbp\n\t"
6241 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6242 "pushq %rsi\n\t"
6243 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6244 "pushq %rdi\n\t"
6245 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6246 "movq %rcx,%rax\n\t"
6247 "movq $4,%rcx\n\t"
6248 "cmp %rcx,%rdx\n\t"
6249 "cmovgq %rdx,%rcx\n\t"
6250 "leaq 0(,%rcx,8),%rdx\n\t"
6251 "subq %rdx,%rsp\n\t"
6252 "andq $~15,%rsp\n\t"
6253 "movq %rsp,%rdi\n\t"
6254 "movq %r8,%rsi\n\t"
6255 "rep; movsq\n\t"
6256 "movq 0(%rsp),%rcx\n\t"
6257 "movq 8(%rsp),%rdx\n\t"
6258 "movq 16(%rsp),%r8\n\t"
6259 "movq 24(%rsp),%r9\n\t"
6260 "movq %rcx,%xmm0\n\t"
6261 "movq %rdx,%xmm1\n\t"
6262 "movq %r8,%xmm2\n\t"
6263 "movq %r9,%xmm3\n\t"
6264 "callq *%rax\n\t"
6265 "leaq -16(%rbp),%rsp\n\t"
6266 "popq %rdi\n\t"
6267 __ASM_CFI(".cfi_same_value %rdi\n\t")
6268 "popq %rsi\n\t"
6269 __ASM_CFI(".cfi_same_value %rsi\n\t")
6270 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6271 "popq %rbp\n\t"
6272 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6273 __ASM_CFI(".cfi_same_value %rbp\n\t")
6274 "ret")
6276 /* same function but returning floating point */
6277 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6279 #endif /* __x86_64__ */
6281 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6283 HRESULT hr = S_OK;
6284 ITypeInfo *tinfo2 = NULL;
6285 TYPEATTR *tattr = NULL;
6287 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6288 if (hr)
6290 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6291 "hr = 0x%08x\n",
6292 tdesc->u.hreftype, hr);
6293 return hr;
6295 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6296 if (hr)
6298 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6299 ITypeInfo_Release(tinfo2);
6300 return hr;
6303 switch (tattr->typekind)
6305 case TKIND_ENUM:
6306 *vt |= VT_I4;
6307 break;
6309 case TKIND_ALIAS:
6310 tdesc = &tattr->tdescAlias;
6311 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6312 break;
6314 case TKIND_INTERFACE:
6315 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6316 *vt |= VT_DISPATCH;
6317 else
6318 *vt |= VT_UNKNOWN;
6319 break;
6321 case TKIND_DISPATCH:
6322 *vt |= VT_DISPATCH;
6323 break;
6325 case TKIND_COCLASS:
6326 *vt |= VT_DISPATCH;
6327 break;
6329 case TKIND_RECORD:
6330 FIXME("TKIND_RECORD unhandled.\n");
6331 hr = E_NOTIMPL;
6332 break;
6334 case TKIND_UNION:
6335 FIXME("TKIND_UNION unhandled.\n");
6336 hr = E_NOTIMPL;
6337 break;
6339 default:
6340 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6341 hr = E_NOTIMPL;
6342 break;
6344 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6345 ITypeInfo_Release(tinfo2);
6346 return hr;
6349 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6351 HRESULT hr = S_OK;
6353 /* enforce only one level of pointer indirection */
6354 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6356 tdesc = tdesc->u.lptdesc;
6358 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6359 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6360 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6361 if ((tdesc->vt == VT_USERDEFINED) ||
6362 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6364 VARTYPE vt_userdefined = 0;
6365 const TYPEDESC *tdesc_userdefined = tdesc;
6366 if (tdesc->vt == VT_PTR)
6368 vt_userdefined = VT_BYREF;
6369 tdesc_userdefined = tdesc->u.lptdesc;
6371 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6372 if ((hr == S_OK) &&
6373 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6374 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6376 *vt |= vt_userdefined;
6377 return S_OK;
6380 *vt = VT_BYREF;
6383 switch (tdesc->vt)
6385 case VT_HRESULT:
6386 *vt |= VT_ERROR;
6387 break;
6388 case VT_USERDEFINED:
6389 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6390 break;
6391 case VT_VOID:
6392 case VT_CARRAY:
6393 case VT_PTR:
6394 case VT_LPSTR:
6395 case VT_LPWSTR:
6396 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6397 hr = DISP_E_BADVARTYPE;
6398 break;
6399 case VT_SAFEARRAY:
6400 *vt |= VT_ARRAY;
6401 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6402 break;
6403 case VT_INT:
6404 *vt |= VT_I4;
6405 break;
6406 case VT_UINT:
6407 *vt |= VT_UI4;
6408 break;
6409 default:
6410 *vt |= tdesc->vt;
6411 break;
6413 return hr;
6416 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6418 ITypeInfo *tinfo2;
6419 TYPEATTR *tattr;
6420 HRESULT hres;
6422 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6423 if(FAILED(hres))
6424 return hres;
6426 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6427 if(FAILED(hres)) {
6428 ITypeInfo_Release(tinfo2);
6429 return hres;
6432 switch(tattr->typekind) {
6433 case TKIND_ALIAS:
6434 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6435 break;
6437 case TKIND_INTERFACE:
6438 case TKIND_DISPATCH:
6439 *guid = tattr->guid;
6440 break;
6442 default:
6443 ERR("Unexpected typekind %d\n", tattr->typekind);
6444 hres = E_UNEXPECTED;
6447 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6448 ITypeInfo_Release(tinfo2);
6449 return hres;
6452 /***********************************************************************
6453 * DispCallFunc (OLEAUT32.@)
6455 * Invokes a function of the specified calling convention, passing the
6456 * specified arguments and returns the result.
6458 * PARAMS
6459 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6460 * oVft [I] The offset in the vtable. See notes.
6461 * cc [I] Calling convention of the function to call.
6462 * vtReturn [I] The return type of the function.
6463 * cActuals [I] Number of parameters.
6464 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6465 * prgpvarg [I] The arguments to pass.
6466 * pvargResult [O] The return value of the function. Can be NULL.
6468 * RETURNS
6469 * Success: S_OK.
6470 * Failure: HRESULT code.
6472 * NOTES
6473 * The HRESULT return value of this function is not affected by the return
6474 * value of the user supplied function, which is returned in pvargResult.
6476 * If pvInstance is NULL then a non-object function is to be called and oVft
6477 * is the address of the function to call.
6479 * The cc parameter can be one of the following values:
6480 *|CC_FASTCALL
6481 *|CC_CDECL
6482 *|CC_PASCAL
6483 *|CC_STDCALL
6484 *|CC_FPFASTCALL
6485 *|CC_SYSCALL
6486 *|CC_MPWCDECL
6487 *|CC_MPWPASCAL
6490 HRESULT WINAPI
6491 DispCallFunc(
6492 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6493 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6495 #ifdef __i386__
6496 int argspos, stack_offset;
6497 void *func;
6498 UINT i;
6499 DWORD *args;
6501 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6502 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6503 pvargResult, V_VT(pvargResult));
6505 if (cc != CC_STDCALL && cc != CC_CDECL)
6507 FIXME("unsupported calling convention %d\n",cc);
6508 return E_INVALIDARG;
6511 /* maximum size for an argument is sizeof(VARIANT) */
6512 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6514 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6515 argspos = 1;
6516 if (pvInstance)
6518 const FARPROC *vtable = *(FARPROC **)pvInstance;
6519 func = vtable[oVft/sizeof(void *)];
6520 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6522 else func = (void *)oVft;
6524 for (i = 0; i < cActuals; i++)
6526 VARIANT *arg = prgpvarg[i];
6528 switch (prgvt[i])
6530 case VT_EMPTY:
6531 break;
6532 case VT_I8:
6533 case VT_UI8:
6534 case VT_R8:
6535 case VT_DATE:
6536 case VT_CY:
6537 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6538 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6539 break;
6540 case VT_DECIMAL:
6541 case VT_VARIANT:
6542 memcpy( &args[argspos], arg, sizeof(*arg) );
6543 argspos += sizeof(*arg) / sizeof(DWORD);
6544 break;
6545 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6546 args[argspos++] = V_BOOL(arg);
6547 break;
6548 default:
6549 args[argspos++] = V_UI4(arg);
6550 break;
6552 TRACE("arg %u: type %d\n",i,prgvt[i]);
6553 dump_Variant(arg);
6556 switch (vtReturn)
6558 case VT_EMPTY:
6559 call_method( func, argspos - 1, args + 1, &stack_offset );
6560 break;
6561 case VT_R4:
6562 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6563 break;
6564 case VT_R8:
6565 case VT_DATE:
6566 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6567 break;
6568 case VT_DECIMAL:
6569 case VT_VARIANT:
6570 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6571 call_method( func, argspos, args, &stack_offset );
6572 break;
6573 case VT_I8:
6574 case VT_UI8:
6575 case VT_CY:
6576 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6577 break;
6578 case VT_HRESULT:
6579 WARN("invalid return type %u\n", vtReturn);
6580 heap_free( args );
6581 return E_INVALIDARG;
6582 default:
6583 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6584 break;
6586 heap_free( args );
6587 if (stack_offset && cc == CC_STDCALL)
6589 WARN( "stack pointer off by %d\n", stack_offset );
6590 return DISP_E_BADCALLEE;
6592 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6593 TRACE("retval: "); dump_Variant(pvargResult);
6594 return S_OK;
6596 #elif defined(__x86_64__)
6597 int argspos;
6598 UINT i;
6599 DWORD_PTR *args;
6600 void *func;
6602 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6603 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6604 pvargResult, V_VT(pvargResult));
6606 if (cc != CC_STDCALL && cc != CC_CDECL)
6608 FIXME("unsupported calling convention %d\n",cc);
6609 return E_INVALIDARG;
6612 /* maximum size for an argument is sizeof(DWORD_PTR) */
6613 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6615 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6616 argspos = 1;
6617 if (pvInstance)
6619 const FARPROC *vtable = *(FARPROC **)pvInstance;
6620 func = vtable[oVft/sizeof(void *)];
6621 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6623 else func = (void *)oVft;
6625 for (i = 0; i < cActuals; i++)
6627 VARIANT *arg = prgpvarg[i];
6629 switch (prgvt[i])
6631 case VT_DECIMAL:
6632 case VT_VARIANT:
6633 args[argspos++] = (ULONG_PTR)arg;
6634 break;
6635 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6636 args[argspos++] = V_BOOL(arg);
6637 break;
6638 default:
6639 args[argspos++] = V_UI8(arg);
6640 break;
6642 TRACE("arg %u: type %d\n",i,prgvt[i]);
6643 dump_Variant(arg);
6646 switch (vtReturn)
6648 case VT_R4:
6649 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6650 break;
6651 case VT_R8:
6652 case VT_DATE:
6653 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6654 break;
6655 case VT_DECIMAL:
6656 case VT_VARIANT:
6657 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6658 call_method( func, argspos, args );
6659 break;
6660 case VT_HRESULT:
6661 WARN("invalid return type %u\n", vtReturn);
6662 heap_free( args );
6663 return E_INVALIDARG;
6664 default:
6665 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6666 break;
6668 heap_free( args );
6669 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6670 TRACE("retval: "); dump_Variant(pvargResult);
6671 return S_OK;
6673 #else
6674 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6675 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6676 return E_NOTIMPL;
6677 #endif
6680 static inline BOOL func_restricted( const FUNCDESC *desc )
6682 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6685 #define INVBUF_ELEMENT_SIZE \
6686 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6687 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6688 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6689 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6690 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6691 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6692 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6693 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6695 static HRESULT WINAPI ITypeInfo_fnInvoke(
6696 ITypeInfo2 *iface,
6697 VOID *pIUnk,
6698 MEMBERID memid,
6699 UINT16 wFlags,
6700 DISPPARAMS *pDispParams,
6701 VARIANT *pVarResult,
6702 EXCEPINFO *pExcepInfo,
6703 UINT *pArgErr)
6705 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6706 int i;
6707 unsigned int var_index;
6708 TYPEKIND type_kind;
6709 HRESULT hres;
6710 const TLBFuncDesc *pFuncInfo;
6711 UINT fdc;
6713 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6714 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6717 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6718 return DISP_E_MEMBERNOTFOUND;
6720 if (!pDispParams)
6722 ERR("NULL pDispParams not allowed\n");
6723 return E_INVALIDARG;
6726 dump_DispParms(pDispParams);
6728 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6730 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6731 pDispParams->cNamedArgs, pDispParams->cArgs);
6732 return E_INVALIDARG;
6735 /* we do this instead of using GetFuncDesc since it will return a fake
6736 * FUNCDESC for dispinterfaces and we want the real function description */
6737 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6738 pFuncInfo = &This->funcdescs[fdc];
6739 if ((memid == pFuncInfo->funcdesc.memid) &&
6740 (wFlags & pFuncInfo->funcdesc.invkind) &&
6741 !func_restricted( &pFuncInfo->funcdesc ))
6742 break;
6745 if (fdc < This->cFuncs) {
6746 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6748 if (TRACE_ON(ole))
6750 TRACE("invoking:\n");
6751 dump_TLBFuncDescOne(pFuncInfo);
6754 switch (func_desc->funckind) {
6755 case FUNC_PUREVIRTUAL:
6756 case FUNC_VIRTUAL: {
6757 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6758 VARIANT varresult;
6759 VARIANT retval; /* pointer for storing byref retvals in */
6760 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6761 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6762 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6763 UINT cNamedArgs = pDispParams->cNamedArgs;
6764 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6765 UINT vargs_converted=0;
6767 hres = S_OK;
6769 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6771 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6773 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6774 hres = DISP_E_PARAMNOTFOUND;
6775 goto func_fail;
6779 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6781 ERR("functions with the vararg attribute do not support named arguments\n");
6782 hres = DISP_E_NONAMEDARGS;
6783 goto func_fail;
6786 for (i = 0; i < func_desc->cParams; i++)
6788 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6789 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6790 if (FAILED(hres))
6791 goto func_fail;
6794 TRACE("changing args\n");
6795 for (i = 0; i < func_desc->cParams; i++)
6797 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6798 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6799 VARIANTARG *src_arg;
6801 if (wParamFlags & PARAMFLAG_FLCID)
6803 VARIANTARG *arg;
6804 arg = prgpvarg[i] = &rgvarg[i];
6805 V_VT(arg) = VT_I4;
6806 V_I4(arg) = This->pTypeLib->lcid;
6807 continue;
6810 src_arg = NULL;
6812 if (cNamedArgs)
6814 USHORT j;
6815 for (j = 0; j < cNamedArgs; j++)
6816 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6818 src_arg = &pDispParams->rgvarg[j];
6819 break;
6823 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6825 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6826 vargs_converted++;
6829 if (wParamFlags & PARAMFLAG_FRETVAL)
6831 /* under most conditions the caller is not allowed to
6832 * pass in a dispparam arg in the index of what would be
6833 * the retval parameter. however, there is an exception
6834 * where the extra parameter is used in an extra
6835 * IDispatch::Invoke below */
6836 if ((i < pDispParams->cArgs) &&
6837 ((func_desc->cParams != 1) || !pVarResult ||
6838 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6840 hres = DISP_E_BADPARAMCOUNT;
6841 break;
6844 /* note: this check is placed so that if the caller passes
6845 * in a VARIANTARG for the retval we just ignore it, like
6846 * native does */
6847 if (i == func_desc->cParams - 1)
6849 VARIANTARG *arg;
6850 arg = prgpvarg[i] = &rgvarg[i];
6851 memset(arg, 0, sizeof(*arg));
6852 V_VT(arg) = rgvt[i];
6853 memset(&retval, 0, sizeof(retval));
6854 V_BYREF(arg) = &retval;
6856 else
6858 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6859 hres = E_UNEXPECTED;
6860 break;
6863 else if (src_arg)
6865 dump_Variant(src_arg);
6867 if(rgvt[i]!=V_VT(src_arg))
6869 if (rgvt[i] == VT_VARIANT)
6870 hres = VariantCopy(&rgvarg[i], src_arg);
6871 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6873 if (rgvt[i] == V_VT(src_arg))
6874 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6875 else
6877 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6878 if (wParamFlags & PARAMFLAG_FIN)
6879 hres = VariantCopy(&missing_arg[i], src_arg);
6880 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6882 V_VT(&rgvarg[i]) = rgvt[i];
6884 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6886 SAFEARRAY *a;
6887 SAFEARRAYBOUND bound;
6888 VARIANT *v;
6889 LONG j;
6890 bound.lLbound = 0;
6891 bound.cElements = pDispParams->cArgs-i;
6892 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6894 ERR("SafeArrayCreate failed\n");
6895 break;
6897 hres = SafeArrayAccessData(a, (LPVOID)&v);
6898 if (hres != S_OK)
6900 ERR("SafeArrayAccessData failed with %x\n", hres);
6901 SafeArrayDestroy(a);
6902 break;
6904 for (j = 0; j < bound.cElements; j++)
6905 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6906 hres = SafeArrayUnaccessData(a);
6907 if (hres != S_OK)
6909 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6910 SafeArrayDestroy(a);
6911 break;
6913 V_ARRAY(&rgvarg[i]) = a;
6914 V_VT(&rgvarg[i]) = rgvt[i];
6916 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6918 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6919 if (wParamFlags & PARAMFLAG_FIN)
6920 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6921 else
6922 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6923 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6924 V_VT(&rgvarg[i]) = rgvt[i];
6926 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6928 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6929 V_VT(&rgvarg[i]) = rgvt[i];
6931 else
6933 /* FIXME: this doesn't work for VT_BYREF arguments if
6934 * they are not the same type as in the paramdesc */
6935 V_VT(&rgvarg[i]) = V_VT(src_arg);
6936 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6937 V_VT(&rgvarg[i]) = rgvt[i];
6940 if (FAILED(hres))
6942 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6943 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6944 debugstr_VT(src_arg), debugstr_VF(src_arg));
6945 break;
6947 prgpvarg[i] = &rgvarg[i];
6949 else
6951 prgpvarg[i] = src_arg;
6954 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6955 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6956 && V_UNKNOWN(prgpvarg[i])) {
6957 IUnknown *userdefined_iface;
6958 GUID guid;
6960 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6961 if(FAILED(hres))
6962 break;
6964 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6965 if(FAILED(hres)) {
6966 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6967 break;
6970 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6971 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6974 else if (wParamFlags & PARAMFLAG_FOPT)
6976 VARIANTARG *arg;
6977 arg = prgpvarg[i] = &rgvarg[i];
6978 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6980 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6981 if (FAILED(hres))
6982 break;
6984 else
6986 VARIANTARG *missing_arg;
6987 /* if the function wants a pointer to a variant then
6988 * set that up, otherwise just pass the VT_ERROR in
6989 * the argument by value */
6990 if (rgvt[i] & VT_BYREF)
6992 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6993 V_VT(arg) = VT_VARIANT | VT_BYREF;
6994 V_VARIANTREF(arg) = missing_arg;
6996 else
6997 missing_arg = arg;
6998 V_VT(missing_arg) = VT_ERROR;
6999 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7002 else
7004 hres = DISP_E_BADPARAMCOUNT;
7005 break;
7008 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7010 /* VT_VOID is a special case for return types, so it is not
7011 * handled in the general function */
7012 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7013 V_VT(&varresult) = VT_EMPTY;
7014 else
7016 V_VT(&varresult) = 0;
7017 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7018 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7021 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7022 V_VT(&varresult), func_desc->cParams, rgvt,
7023 prgpvarg, &varresult);
7025 vargs_converted = 0;
7027 for (i = 0; i < func_desc->cParams; i++)
7029 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7030 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7032 if (wParamFlags & PARAMFLAG_FLCID)
7033 continue;
7034 else if (wParamFlags & PARAMFLAG_FRETVAL)
7036 if (TRACE_ON(ole))
7038 TRACE("[retval] value: ");
7039 dump_Variant(prgpvarg[i]);
7042 if (pVarResult)
7044 VariantInit(pVarResult);
7045 /* deref return value */
7046 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7049 VARIANT_ClearInd(prgpvarg[i]);
7051 else if (vargs_converted < pDispParams->cArgs)
7053 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7054 if (wParamFlags & PARAMFLAG_FOUT)
7056 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7058 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7060 if (FAILED(hres))
7062 ERR("failed to convert param %d to vt %d\n", i,
7063 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7064 break;
7068 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7069 func_desc->cParamsOpt < 0 &&
7070 i == func_desc->cParams-1)
7072 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7073 LONG j, ubound;
7074 VARIANT *v;
7075 hres = SafeArrayGetUBound(a, 1, &ubound);
7076 if (hres != S_OK)
7078 ERR("SafeArrayGetUBound failed with %x\n", hres);
7079 break;
7081 hres = SafeArrayAccessData(a, (LPVOID)&v);
7082 if (hres != S_OK)
7084 ERR("SafeArrayAccessData failed with %x\n", hres);
7085 break;
7087 for (j = 0; j <= ubound; j++)
7088 VariantClear(&v[j]);
7089 hres = SafeArrayUnaccessData(a);
7090 if (hres != S_OK)
7092 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7093 break;
7096 VariantClear(&rgvarg[i]);
7097 vargs_converted++;
7099 else if (wParamFlags & PARAMFLAG_FOPT)
7101 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7102 VariantClear(&rgvarg[i]);
7105 VariantClear(&missing_arg[i]);
7108 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7110 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7111 hres = DISP_E_EXCEPTION;
7112 if (pExcepInfo)
7114 IErrorInfo *pErrorInfo;
7115 pExcepInfo->scode = V_ERROR(&varresult);
7116 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7118 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7119 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7120 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7121 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7123 IErrorInfo_Release(pErrorInfo);
7127 if (V_VT(&varresult) != VT_ERROR)
7129 TRACE("varresult value: ");
7130 dump_Variant(&varresult);
7132 if (pVarResult)
7134 VariantClear(pVarResult);
7135 *pVarResult = varresult;
7137 else
7138 VariantClear(&varresult);
7141 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7142 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7143 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7144 (pDispParams->cArgs != 0))
7146 if (V_VT(pVarResult) == VT_DISPATCH)
7148 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7149 /* Note: not VariantClear; we still need the dispatch
7150 * pointer to be valid */
7151 VariantInit(pVarResult);
7152 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7153 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7154 pDispParams, pVarResult, pExcepInfo, pArgErr);
7155 IDispatch_Release(pDispatch);
7157 else
7159 VariantClear(pVarResult);
7160 hres = DISP_E_NOTACOLLECTION;
7164 func_fail:
7165 heap_free(buffer);
7166 break;
7168 case FUNC_DISPATCH: {
7169 IDispatch *disp;
7171 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7172 if (SUCCEEDED(hres)) {
7173 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7174 hres = IDispatch_Invoke(
7175 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7176 pVarResult,pExcepInfo,pArgErr
7178 if (FAILED(hres))
7179 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7180 IDispatch_Release(disp);
7181 } else
7182 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7183 break;
7185 default:
7186 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7187 hres = E_FAIL;
7188 break;
7191 TRACE("-- 0x%08x\n", hres);
7192 return hres;
7194 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7195 VARDESC *var_desc;
7197 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7198 if(FAILED(hres)) return hres;
7200 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7201 dump_VARDESC(var_desc);
7202 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7203 return E_NOTIMPL;
7206 /* not found, look for it in inherited interfaces */
7207 ITypeInfo2_GetTypeKind(iface, &type_kind);
7208 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7209 if(This->impltypes) {
7210 /* recursive search */
7211 ITypeInfo *pTInfo;
7212 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7213 if(SUCCEEDED(hres)){
7214 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7215 ITypeInfo_Release(pTInfo);
7216 return hres;
7218 WARN("Could not search inherited interface!\n");
7221 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7222 return DISP_E_MEMBERNOTFOUND;
7225 /* ITypeInfo::GetDocumentation
7227 * Retrieves the documentation string, the complete Help file name and path,
7228 * and the context ID for the Help topic for a specified type description.
7230 * (Can be tested by the Visual Basic Editor in Word for instance.)
7232 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7233 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7234 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7236 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7237 const TLBFuncDesc *pFDesc;
7238 const TLBVarDesc *pVDesc;
7239 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7240 " HelpContext(%p) HelpFile(%p)\n",
7241 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7242 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7243 if(pBstrName)
7244 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7245 if(pBstrDocString)
7246 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7247 if(pdwHelpContext)
7248 *pdwHelpContext=This->dwHelpContext;
7249 if(pBstrHelpFile)
7250 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7251 return S_OK;
7252 }else {/* for a member */
7253 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7254 if(pFDesc){
7255 if(pBstrName)
7256 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7257 if(pBstrDocString)
7258 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7259 if(pdwHelpContext)
7260 *pdwHelpContext=pFDesc->helpcontext;
7261 if(pBstrHelpFile)
7262 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7263 return S_OK;
7265 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7266 if(pVDesc){
7267 if(pBstrName)
7268 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7269 if(pBstrDocString)
7270 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7271 if(pdwHelpContext)
7272 *pdwHelpContext=pVDesc->HelpContext;
7273 if(pBstrHelpFile)
7274 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7275 return S_OK;
7279 if(This->impltypes &&
7280 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7281 /* recursive search */
7282 ITypeInfo *pTInfo;
7283 HRESULT result;
7284 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7285 if(SUCCEEDED(result)) {
7286 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7287 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7288 ITypeInfo_Release(pTInfo);
7289 return result;
7291 WARN("Could not search inherited interface!\n");
7294 WARN("member %d not found\n", memid);
7295 return TYPE_E_ELEMENTNOTFOUND;
7298 /* ITypeInfo::GetDllEntry
7300 * Retrieves a description or specification of an entry point for a function
7301 * in a DLL.
7303 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7304 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7305 WORD *pwOrdinal)
7307 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7308 const TLBFuncDesc *pFDesc;
7310 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7312 if (pBstrDllName) *pBstrDllName = NULL;
7313 if (pBstrName) *pBstrName = NULL;
7314 if (pwOrdinal) *pwOrdinal = 0;
7316 if (This->typekind != TKIND_MODULE)
7317 return TYPE_E_BADMODULEKIND;
7319 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7320 if(pFDesc){
7321 dump_TypeInfo(This);
7322 if (TRACE_ON(ole))
7323 dump_TLBFuncDescOne(pFDesc);
7325 if (pBstrDllName)
7326 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7328 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7329 if (pBstrName)
7330 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7331 if (pwOrdinal)
7332 *pwOrdinal = -1;
7333 return S_OK;
7335 if (pBstrName)
7336 *pBstrName = NULL;
7337 if (pwOrdinal)
7338 *pwOrdinal = LOWORD(pFDesc->Entry);
7339 return S_OK;
7341 return TYPE_E_ELEMENTNOTFOUND;
7344 /* internal function to make the inherited interfaces' methods appear
7345 * part of the interface */
7346 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7347 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7349 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7350 HRESULT hr;
7352 TRACE("%p, 0x%x\n", iface, *hRefType);
7354 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7356 ITypeInfo *pSubTypeInfo;
7358 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7359 if (FAILED(hr))
7360 return hr;
7362 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7363 hRefType, ppTInfo);
7364 ITypeInfo_Release(pSubTypeInfo);
7365 if (SUCCEEDED(hr))
7366 return hr;
7368 *hRefType -= DISPATCH_HREF_OFFSET;
7370 if (!(*hRefType & DISPATCH_HREF_MASK))
7371 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7372 else
7373 return E_FAIL;
7376 /* ITypeInfo::GetRefTypeInfo
7378 * If a type description references other type descriptions, it retrieves
7379 * the referenced type descriptions.
7381 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7382 ITypeInfo2 *iface,
7383 HREFTYPE hRefType,
7384 ITypeInfo **ppTInfo)
7386 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7387 HRESULT result = E_FAIL;
7389 if(!ppTInfo)
7390 return E_INVALIDARG;
7392 if ((INT)hRefType < 0) {
7393 ITypeInfoImpl *pTypeInfoImpl;
7395 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7396 !(This->typekind == TKIND_INTERFACE ||
7397 This->typekind == TKIND_DISPATCH))
7398 return TYPE_E_ELEMENTNOTFOUND;
7400 /* when we meet a DUAL typeinfo, we must create the alternate
7401 * version of it.
7403 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7405 *pTypeInfoImpl = *This;
7406 pTypeInfoImpl->ref = 0;
7408 if (This->typekind == TKIND_INTERFACE)
7409 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7410 else
7411 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7413 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7414 /* the AddRef implicitly adds a reference to the parent typelib, which
7415 * stops the copied data from being destroyed until the new typeinfo's
7416 * refcount goes to zero, but we need to signal to the new instance to
7417 * not free its data structures when it is destroyed */
7418 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7420 ITypeInfo_AddRef(*ppTInfo);
7422 result = S_OK;
7423 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7424 (This->typekind == TKIND_DISPATCH))
7426 HREFTYPE href_dispatch = hRefType;
7427 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7428 } else {
7429 TLBRefType *ref_type;
7430 ITypeLib *pTLib = NULL;
7431 UINT i;
7433 if(!(hRefType & 0x1)){
7434 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7436 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7438 result = S_OK;
7439 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7440 ITypeInfo_AddRef(*ppTInfo);
7441 goto end;
7446 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7448 if(ref_type->reference == (hRefType & (~0x3)))
7449 break;
7451 if(&ref_type->entry == &This->pTypeLib->ref_list)
7453 FIXME("Can't find pRefType for ref %x\n", hRefType);
7454 goto end;
7457 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7458 UINT Index;
7459 TRACE("internal reference\n");
7460 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7461 } else {
7462 if(ref_type->pImpTLInfo->pImpTypeLib) {
7463 TRACE("typeinfo in imported typelib that is already loaded\n");
7464 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7465 ITypeLib_AddRef(pTLib);
7466 result = S_OK;
7467 } else {
7468 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7469 result = LoadRegTypeLib( TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7470 ref_type->pImpTLInfo->wVersionMajor,
7471 ref_type->pImpTLInfo->wVersionMinor,
7472 ref_type->pImpTLInfo->lcid,
7473 &pTLib);
7475 if(FAILED(result)) {
7476 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7477 result=LoadTypeLib(libnam, &pTLib);
7478 SysFreeString(libnam);
7480 if(SUCCEEDED(result)) {
7481 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7482 ITypeLib_AddRef(pTLib);
7486 if(SUCCEEDED(result)) {
7487 if(ref_type->index == TLB_REF_USE_GUID)
7488 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7489 else
7490 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7492 if (pTLib != NULL)
7493 ITypeLib_Release(pTLib);
7496 end:
7497 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7498 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7499 return result;
7502 /* ITypeInfo::AddressOfMember
7504 * Retrieves the addresses of static functions or variables, such as those
7505 * defined in a DLL.
7507 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7508 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7510 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7511 HRESULT hr;
7512 BSTR dll, entry;
7513 WORD ordinal;
7514 HMODULE module;
7516 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7518 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7519 if (FAILED(hr))
7520 return hr;
7522 module = LoadLibraryW(dll);
7523 if (!module)
7525 ERR("couldn't load %s\n", debugstr_w(dll));
7526 SysFreeString(dll);
7527 SysFreeString(entry);
7528 return STG_E_FILENOTFOUND;
7530 /* FIXME: store library somewhere where we can free it */
7532 if (entry)
7534 LPSTR entryA;
7535 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7536 entryA = heap_alloc(len);
7537 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7539 *ppv = GetProcAddress(module, entryA);
7540 if (!*ppv)
7541 ERR("function not found %s\n", debugstr_a(entryA));
7543 heap_free(entryA);
7545 else
7547 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7548 if (!*ppv)
7549 ERR("function not found %d\n", ordinal);
7552 SysFreeString(dll);
7553 SysFreeString(entry);
7555 if (!*ppv)
7556 return TYPE_E_DLLFUNCTIONNOTFOUND;
7558 return S_OK;
7561 /* ITypeInfo::CreateInstance
7563 * Creates a new instance of a type that describes a component object class
7564 * (coclass).
7566 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7567 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7569 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7570 HRESULT hr;
7571 TYPEATTR *pTA;
7573 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7575 *ppvObj = NULL;
7577 if(pOuterUnk)
7579 WARN("Not able to aggregate\n");
7580 return CLASS_E_NOAGGREGATION;
7583 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7584 if(FAILED(hr)) return hr;
7586 if(pTA->typekind != TKIND_COCLASS)
7588 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7589 hr = E_INVALIDARG;
7590 goto end;
7593 hr = S_FALSE;
7594 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7596 IUnknown *pUnk;
7597 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7598 TRACE("GetActiveObject rets %08x\n", hr);
7599 if(hr == S_OK)
7601 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7602 IUnknown_Release(pUnk);
7606 if(hr != S_OK)
7607 hr = CoCreateInstance(&pTA->guid, NULL,
7608 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7609 riid, ppvObj);
7611 end:
7612 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7613 return hr;
7616 /* ITypeInfo::GetMops
7618 * Retrieves marshalling information.
7620 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7621 BSTR *pBstrMops)
7623 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7624 FIXME("(%p %d) stub!\n", This, memid);
7625 *pBstrMops = NULL;
7626 return S_OK;
7629 /* ITypeInfo::GetContainingTypeLib
7631 * Retrieves the containing type library and the index of the type description
7632 * within that type library.
7634 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7635 ITypeLib * *ppTLib, UINT *pIndex)
7637 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7639 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7640 if (pIndex) {
7641 *pIndex=This->index;
7642 TRACE("returning pIndex=%d\n", *pIndex);
7645 if (ppTLib) {
7646 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7647 ITypeLib_AddRef(*ppTLib);
7648 TRACE("returning ppTLib=%p\n", *ppTLib);
7651 return S_OK;
7654 /* ITypeInfo::ReleaseTypeAttr
7656 * Releases a TYPEATTR previously returned by Get
7659 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7660 TYPEATTR* pTypeAttr)
7662 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7663 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7664 heap_free(pTypeAttr);
7667 /* ITypeInfo::ReleaseFuncDesc
7669 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7671 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7672 ITypeInfo2 *iface,
7673 FUNCDESC *pFuncDesc)
7675 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7676 SHORT i;
7678 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7680 for (i = 0; i < pFuncDesc->cParams; i++)
7681 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7682 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7684 SysFreeString((BSTR)pFuncDesc);
7687 /* ITypeInfo::ReleaseVarDesc
7689 * Releases a VARDESC previously returned by GetVarDesc.
7691 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7692 VARDESC *pVarDesc)
7694 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7695 TRACE("(%p)->(%p)\n", This, pVarDesc);
7697 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7698 if (pVarDesc->varkind == VAR_CONST)
7699 VariantClear(pVarDesc->u.lpvarValue);
7700 SysFreeString((BSTR)pVarDesc);
7703 /* ITypeInfo2::GetTypeKind
7705 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7708 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7709 TYPEKIND *pTypeKind)
7711 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7712 *pTypeKind=This->typekind;
7713 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7714 return S_OK;
7717 /* ITypeInfo2::GetTypeFlags
7719 * Returns the type flags without any allocations. This returns a DWORD type
7720 * flag, which expands the type flags without growing the TYPEATTR (type
7721 * attribute).
7724 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7726 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7727 *pTypeFlags=This->wTypeFlags;
7728 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7729 return S_OK;
7732 /* ITypeInfo2::GetFuncIndexOfMemId
7733 * Binds to a specific member based on a known DISPID, where the member name
7734 * is not known (for example, when binding to a default member).
7737 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7738 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7740 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7741 UINT fdc;
7742 HRESULT result;
7744 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7745 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7746 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7747 break;
7749 if(fdc < This->cFuncs) {
7750 *pFuncIndex = fdc;
7751 result = S_OK;
7752 } else
7753 result = TYPE_E_ELEMENTNOTFOUND;
7755 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7756 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7757 return result;
7760 /* TypeInfo2::GetVarIndexOfMemId
7762 * Binds to a specific member based on a known DISPID, where the member name
7763 * is not known (for example, when binding to a default member).
7766 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7767 MEMBERID memid, UINT *pVarIndex)
7769 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7770 TLBVarDesc *pVarInfo;
7772 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7774 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7775 if(!pVarInfo)
7776 return TYPE_E_ELEMENTNOTFOUND;
7778 *pVarIndex = (pVarInfo - This->vardescs);
7780 return S_OK;
7783 /* ITypeInfo2::GetCustData
7785 * Gets the custom data
7787 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7788 ITypeInfo2 * iface,
7789 REFGUID guid,
7790 VARIANT *pVarVal)
7792 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7793 TLBCustData *pCData;
7795 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7797 if(!guid || !pVarVal)
7798 return E_INVALIDARG;
7800 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7802 VariantInit( pVarVal);
7803 if (pCData)
7804 VariantCopy( pVarVal, &pCData->data);
7805 else
7806 VariantClear( pVarVal );
7807 return S_OK;
7810 /* ITypeInfo2::GetFuncCustData
7812 * Gets the custom data
7814 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7815 ITypeInfo2 * iface,
7816 UINT index,
7817 REFGUID guid,
7818 VARIANT *pVarVal)
7820 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7821 TLBCustData *pCData;
7822 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7824 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7826 if(index >= This->cFuncs)
7827 return TYPE_E_ELEMENTNOTFOUND;
7829 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7830 if(!pCData)
7831 return TYPE_E_ELEMENTNOTFOUND;
7833 VariantInit(pVarVal);
7834 VariantCopy(pVarVal, &pCData->data);
7836 return S_OK;
7839 /* ITypeInfo2::GetParamCustData
7841 * Gets the custom data
7843 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7844 ITypeInfo2 * iface,
7845 UINT indexFunc,
7846 UINT indexParam,
7847 REFGUID guid,
7848 VARIANT *pVarVal)
7850 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7851 TLBCustData *pCData;
7852 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7854 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7855 debugstr_guid(guid), pVarVal);
7857 if(indexFunc >= This->cFuncs)
7858 return TYPE_E_ELEMENTNOTFOUND;
7860 if(indexParam >= pFDesc->funcdesc.cParams)
7861 return TYPE_E_ELEMENTNOTFOUND;
7863 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7864 if(!pCData)
7865 return TYPE_E_ELEMENTNOTFOUND;
7867 VariantInit(pVarVal);
7868 VariantCopy(pVarVal, &pCData->data);
7870 return S_OK;
7873 /* ITypeInfo2::GetVarCustData
7875 * Gets the custom data
7877 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7878 ITypeInfo2 * iface,
7879 UINT index,
7880 REFGUID guid,
7881 VARIANT *pVarVal)
7883 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7884 TLBCustData *pCData;
7885 TLBVarDesc *pVDesc = &This->vardescs[index];
7887 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7889 if(index >= This->cVars)
7890 return TYPE_E_ELEMENTNOTFOUND;
7892 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7893 if(!pCData)
7894 return TYPE_E_ELEMENTNOTFOUND;
7896 VariantInit(pVarVal);
7897 VariantCopy(pVarVal, &pCData->data);
7899 return S_OK;
7902 /* ITypeInfo2::GetImplCustData
7904 * Gets the custom data
7906 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7907 ITypeInfo2 * iface,
7908 UINT index,
7909 REFGUID guid,
7910 VARIANT *pVarVal)
7912 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7913 TLBCustData *pCData;
7914 TLBImplType *pRDesc = &This->impltypes[index];
7916 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7918 if(index >= This->cImplTypes)
7919 return TYPE_E_ELEMENTNOTFOUND;
7921 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7922 if(!pCData)
7923 return TYPE_E_ELEMENTNOTFOUND;
7925 VariantInit(pVarVal);
7926 VariantCopy(pVarVal, &pCData->data);
7928 return S_OK;
7931 /* ITypeInfo2::GetDocumentation2
7933 * Retrieves the documentation string, the complete Help file name and path,
7934 * the localization context to use, and the context ID for the library Help
7935 * topic in the Help file.
7938 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7939 ITypeInfo2 * iface,
7940 MEMBERID memid,
7941 LCID lcid,
7942 BSTR *pbstrHelpString,
7943 DWORD *pdwHelpStringContext,
7944 BSTR *pbstrHelpStringDll)
7946 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7947 const TLBFuncDesc *pFDesc;
7948 const TLBVarDesc *pVDesc;
7949 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7950 "HelpStringContext(%p) HelpStringDll(%p)\n",
7951 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7952 pbstrHelpStringDll );
7953 /* the help string should be obtained from the helpstringdll,
7954 * using the _DLLGetDocumentation function, based on the supplied
7955 * lcid. Nice to do sometime...
7957 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7958 if(pbstrHelpString)
7959 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
7960 if(pdwHelpStringContext)
7961 *pdwHelpStringContext=This->dwHelpStringContext;
7962 if(pbstrHelpStringDll)
7963 *pbstrHelpStringDll=
7964 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7965 return S_OK;
7966 }else {/* for a member */
7967 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7968 if(pFDesc){
7969 if(pbstrHelpString)
7970 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7971 if(pdwHelpStringContext)
7972 *pdwHelpStringContext=pFDesc->HelpStringContext;
7973 if(pbstrHelpStringDll)
7974 *pbstrHelpStringDll=
7975 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7976 return S_OK;
7978 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7979 if(pVDesc){
7980 if(pbstrHelpString)
7981 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7982 if(pdwHelpStringContext)
7983 *pdwHelpStringContext=pVDesc->HelpStringContext;
7984 if(pbstrHelpStringDll)
7985 *pbstrHelpStringDll=
7986 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7987 return S_OK;
7990 return TYPE_E_ELEMENTNOTFOUND;
7993 /* ITypeInfo2::GetAllCustData
7995 * Gets all custom data items for the Type info.
7998 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7999 ITypeInfo2 * iface,
8000 CUSTDATA *pCustData)
8002 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8004 TRACE("%p %p\n", This, pCustData);
8006 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
8009 /* ITypeInfo2::GetAllFuncCustData
8011 * Gets all custom data items for the specified Function
8014 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8015 ITypeInfo2 * iface,
8016 UINT index,
8017 CUSTDATA *pCustData)
8019 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8020 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8022 TRACE("%p %u %p\n", This, index, pCustData);
8024 if(index >= This->cFuncs)
8025 return TYPE_E_ELEMENTNOTFOUND;
8027 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8030 /* ITypeInfo2::GetAllParamCustData
8032 * Gets all custom data items for the Functions
8035 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8036 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8038 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8039 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8041 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8043 if(indexFunc >= This->cFuncs)
8044 return TYPE_E_ELEMENTNOTFOUND;
8046 if(indexParam >= pFDesc->funcdesc.cParams)
8047 return TYPE_E_ELEMENTNOTFOUND;
8049 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8052 /* ITypeInfo2::GetAllVarCustData
8054 * Gets all custom data items for the specified Variable
8057 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8058 UINT index, CUSTDATA *pCustData)
8060 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8061 TLBVarDesc * pVDesc = &This->vardescs[index];
8063 TRACE("%p %u %p\n", This, index, pCustData);
8065 if(index >= This->cVars)
8066 return TYPE_E_ELEMENTNOTFOUND;
8068 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8071 /* ITypeInfo2::GetAllImplCustData
8073 * Gets all custom data items for the specified implementation type
8076 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8077 ITypeInfo2 * iface,
8078 UINT index,
8079 CUSTDATA *pCustData)
8081 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8082 TLBImplType *pRDesc = &This->impltypes[index];
8084 TRACE("%p %u %p\n", This, index, pCustData);
8086 if(index >= This->cImplTypes)
8087 return TYPE_E_ELEMENTNOTFOUND;
8089 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8092 static const ITypeInfo2Vtbl tinfvt =
8095 ITypeInfo_fnQueryInterface,
8096 ITypeInfo_fnAddRef,
8097 ITypeInfo_fnRelease,
8099 ITypeInfo_fnGetTypeAttr,
8100 ITypeInfo_fnGetTypeComp,
8101 ITypeInfo_fnGetFuncDesc,
8102 ITypeInfo_fnGetVarDesc,
8103 ITypeInfo_fnGetNames,
8104 ITypeInfo_fnGetRefTypeOfImplType,
8105 ITypeInfo_fnGetImplTypeFlags,
8106 ITypeInfo_fnGetIDsOfNames,
8107 ITypeInfo_fnInvoke,
8108 ITypeInfo_fnGetDocumentation,
8109 ITypeInfo_fnGetDllEntry,
8110 ITypeInfo_fnGetRefTypeInfo,
8111 ITypeInfo_fnAddressOfMember,
8112 ITypeInfo_fnCreateInstance,
8113 ITypeInfo_fnGetMops,
8114 ITypeInfo_fnGetContainingTypeLib,
8115 ITypeInfo_fnReleaseTypeAttr,
8116 ITypeInfo_fnReleaseFuncDesc,
8117 ITypeInfo_fnReleaseVarDesc,
8119 ITypeInfo2_fnGetTypeKind,
8120 ITypeInfo2_fnGetTypeFlags,
8121 ITypeInfo2_fnGetFuncIndexOfMemId,
8122 ITypeInfo2_fnGetVarIndexOfMemId,
8123 ITypeInfo2_fnGetCustData,
8124 ITypeInfo2_fnGetFuncCustData,
8125 ITypeInfo2_fnGetParamCustData,
8126 ITypeInfo2_fnGetVarCustData,
8127 ITypeInfo2_fnGetImplTypeCustData,
8128 ITypeInfo2_fnGetDocumentation2,
8129 ITypeInfo2_fnGetAllCustData,
8130 ITypeInfo2_fnGetAllFuncCustData,
8131 ITypeInfo2_fnGetAllParamCustData,
8132 ITypeInfo2_fnGetAllVarCustData,
8133 ITypeInfo2_fnGetAllImplTypeCustData,
8136 /******************************************************************************
8137 * CreateDispTypeInfo [OLEAUT32.31]
8139 * Build type information for an object so it can be called through an
8140 * IDispatch interface.
8142 * RETURNS
8143 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8144 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8146 * NOTES
8147 * This call allows an objects methods to be accessed through IDispatch, by
8148 * building an ITypeInfo object that IDispatch can use to call through.
8150 HRESULT WINAPI CreateDispTypeInfo(
8151 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8152 LCID lcid, /* [I] Locale Id */
8153 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8155 ITypeInfoImpl *pTIClass, *pTIIface;
8156 ITypeLibImpl *pTypeLibImpl;
8157 unsigned int param, func;
8158 TLBFuncDesc *pFuncDesc;
8159 TLBRefType *ref;
8161 TRACE("\n");
8162 pTypeLibImpl = TypeLibImpl_Constructor();
8163 if (!pTypeLibImpl) return E_FAIL;
8165 pTypeLibImpl->TypeInfoCount = 2;
8166 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8168 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8169 pTIIface->pTypeLib = pTypeLibImpl;
8170 pTIIface->index = 0;
8171 pTIIface->Name = NULL;
8172 pTIIface->dwHelpContext = -1;
8173 pTIIface->guid = NULL;
8174 pTIIface->lcid = lcid;
8175 pTIIface->typekind = TKIND_INTERFACE;
8176 pTIIface->wMajorVerNum = 0;
8177 pTIIface->wMinorVerNum = 0;
8178 pTIIface->cbAlignment = 2;
8179 pTIIface->cbSizeInstance = -1;
8180 pTIIface->cbSizeVft = -1;
8181 pTIIface->cFuncs = 0;
8182 pTIIface->cImplTypes = 0;
8183 pTIIface->cVars = 0;
8184 pTIIface->wTypeFlags = 0;
8185 pTIIface->hreftype = 0;
8187 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8188 pFuncDesc = pTIIface->funcdescs;
8189 for(func = 0; func < pidata->cMembers; func++) {
8190 METHODDATA *md = pidata->pmethdata + func;
8191 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8192 pFuncDesc->funcdesc.memid = md->dispid;
8193 pFuncDesc->funcdesc.lprgscode = NULL;
8194 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8195 pFuncDesc->funcdesc.invkind = md->wFlags;
8196 pFuncDesc->funcdesc.callconv = md->cc;
8197 pFuncDesc->funcdesc.cParams = md->cArgs;
8198 pFuncDesc->funcdesc.cParamsOpt = 0;
8199 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8200 pFuncDesc->funcdesc.cScodes = 0;
8201 pFuncDesc->funcdesc.wFuncFlags = 0;
8202 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8203 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8204 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8205 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8206 md->cArgs * sizeof(ELEMDESC));
8207 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8208 for(param = 0; param < md->cArgs; param++) {
8209 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8210 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8212 pFuncDesc->helpcontext = 0;
8213 pFuncDesc->HelpStringContext = 0;
8214 pFuncDesc->HelpString = NULL;
8215 pFuncDesc->Entry = NULL;
8216 list_init(&pFuncDesc->custdata_list);
8217 pTIIface->cFuncs++;
8218 ++pFuncDesc;
8221 dump_TypeInfo(pTIIface);
8223 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8224 pTIClass->pTypeLib = pTypeLibImpl;
8225 pTIClass->index = 1;
8226 pTIClass->Name = NULL;
8227 pTIClass->dwHelpContext = -1;
8228 pTIClass->guid = NULL;
8229 pTIClass->lcid = lcid;
8230 pTIClass->typekind = TKIND_COCLASS;
8231 pTIClass->wMajorVerNum = 0;
8232 pTIClass->wMinorVerNum = 0;
8233 pTIClass->cbAlignment = 2;
8234 pTIClass->cbSizeInstance = -1;
8235 pTIClass->cbSizeVft = -1;
8236 pTIClass->cFuncs = 0;
8237 pTIClass->cImplTypes = 1;
8238 pTIClass->cVars = 0;
8239 pTIClass->wTypeFlags = 0;
8240 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8242 pTIClass->impltypes = TLBImplType_Alloc(1);
8244 ref = heap_alloc_zero(sizeof(*ref));
8245 ref->pImpTLInfo = TLB_REF_INTERNAL;
8246 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8248 dump_TypeInfo(pTIClass);
8250 *pptinfo = (ITypeInfo*)pTIClass;
8252 ITypeInfo_AddRef(*pptinfo);
8253 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8255 return S_OK;
8259 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8261 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8263 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
8266 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8268 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8270 return ITypeInfo_AddRef((ITypeInfo *)This);
8273 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8275 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8277 return ITypeInfo_Release((ITypeInfo *)This);
8280 static HRESULT WINAPI ITypeComp_fnBind(
8281 ITypeComp * iface,
8282 OLECHAR * szName,
8283 ULONG lHash,
8284 WORD wFlags,
8285 ITypeInfo ** ppTInfo,
8286 DESCKIND * pDescKind,
8287 BINDPTR * pBindPtr)
8289 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8290 const TLBFuncDesc *pFDesc;
8291 const TLBVarDesc *pVDesc;
8292 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8293 UINT fdc;
8295 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8297 *pDescKind = DESCKIND_NONE;
8298 pBindPtr->lpfuncdesc = NULL;
8299 *ppTInfo = NULL;
8301 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8302 pFDesc = &This->funcdescs[fdc];
8303 if (!strcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8304 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8305 break;
8306 else
8307 /* name found, but wrong flags */
8308 hr = TYPE_E_TYPEMISMATCH;
8312 if (fdc < This->cFuncs)
8314 HRESULT hr = TLB_AllocAndInitFuncDesc(
8315 &pFDesc->funcdesc,
8316 &pBindPtr->lpfuncdesc,
8317 This->typekind == TKIND_DISPATCH);
8318 if (FAILED(hr))
8319 return hr;
8320 *pDescKind = DESCKIND_FUNCDESC;
8321 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8322 ITypeInfo_AddRef(*ppTInfo);
8323 return S_OK;
8324 } else {
8325 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8326 if(pVDesc){
8327 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8328 if (FAILED(hr))
8329 return hr;
8330 *pDescKind = DESCKIND_VARDESC;
8331 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8332 ITypeInfo_AddRef(*ppTInfo);
8333 return S_OK;
8336 /* FIXME: search each inherited interface, not just the first */
8337 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8338 /* recursive search */
8339 ITypeInfo *pTInfo;
8340 ITypeComp *pTComp;
8341 HRESULT hr;
8342 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8343 if (SUCCEEDED(hr))
8345 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8346 ITypeInfo_Release(pTInfo);
8348 if (SUCCEEDED(hr))
8350 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8351 ITypeComp_Release(pTComp);
8352 return hr;
8354 WARN("Could not search inherited interface!\n");
8356 if (hr == DISP_E_MEMBERNOTFOUND)
8357 hr = S_OK;
8358 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8359 return hr;
8362 static HRESULT WINAPI ITypeComp_fnBindType(
8363 ITypeComp * iface,
8364 OLECHAR * szName,
8365 ULONG lHash,
8366 ITypeInfo ** ppTInfo,
8367 ITypeComp ** ppTComp)
8369 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8371 /* strange behaviour (does nothing) but like the
8372 * original */
8374 if (!ppTInfo || !ppTComp)
8375 return E_POINTER;
8377 *ppTInfo = NULL;
8378 *ppTComp = NULL;
8380 return S_OK;
8383 static const ITypeCompVtbl tcompvt =
8386 ITypeComp_fnQueryInterface,
8387 ITypeComp_fnAddRef,
8388 ITypeComp_fnRelease,
8390 ITypeComp_fnBind,
8391 ITypeComp_fnBindType
8394 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8395 REFIID riid, void **object)
8397 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8399 return ITypeLib2_QueryInterface((ITypeLib2*)This, riid, object);
8402 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8404 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8406 return ITypeLib2_AddRef((ITypeLib2*)This);
8409 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8411 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8413 return ITypeLib2_Release((ITypeLib2*)This);
8416 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8417 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8419 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8420 ITypeInfoImpl *info;
8421 HRESULT hres;
8423 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8425 if (!ctinfo || !name)
8426 return E_INVALIDARG;
8428 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8429 if (info)
8430 return TYPE_E_NAMECONFLICT;
8432 if (This->typeinfos)
8433 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8434 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8435 else
8436 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8438 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8440 info->pTypeLib = This;
8441 info->Name = TLB_append_str(&This->name_list, name);
8442 info->index = This->TypeInfoCount;
8443 info->typekind = kind;
8444 info->cbAlignment = 4;
8446 switch(info->typekind) {
8447 case TKIND_ENUM:
8448 case TKIND_INTERFACE:
8449 case TKIND_DISPATCH:
8450 case TKIND_COCLASS:
8451 info->cbSizeInstance = 4;
8452 break;
8453 case TKIND_RECORD:
8454 case TKIND_UNION:
8455 info->cbSizeInstance = 0;
8456 break;
8457 case TKIND_MODULE:
8458 info->cbSizeInstance = 2;
8459 break;
8460 case TKIND_ALIAS:
8461 info->cbSizeInstance = -0x75;
8462 break;
8463 default:
8464 FIXME("unrecognized typekind %d\n", info->typekind);
8465 info->cbSizeInstance = 0xdeadbeef;
8466 break;
8469 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8470 &IID_ICreateTypeInfo, (void **)ctinfo);
8471 if (FAILED(hres)) {
8472 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8473 return hres;
8476 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8478 ++This->TypeInfoCount;
8480 return S_OK;
8483 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8484 LPOLESTR name)
8486 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8488 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8490 if (!name)
8491 return E_INVALIDARG;
8493 This->Name = TLB_append_str(&This->name_list, name);
8495 return S_OK;
8498 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8499 WORD majorVerNum, WORD minorVerNum)
8501 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8503 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8505 This->ver_major = majorVerNum;
8506 This->ver_minor = minorVerNum;
8508 return S_OK;
8511 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8512 REFGUID guid)
8514 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8516 TRACE("%p %s\n", This, debugstr_guid(guid));
8518 This->guid = TLB_append_guid(&This->guid_list, guid);
8520 return S_OK;
8523 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8524 LPOLESTR doc)
8526 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8528 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8530 if (!doc)
8531 return E_INVALIDARG;
8533 This->DocString = TLB_append_str(&This->string_list, doc);
8535 return S_OK;
8538 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8539 LPOLESTR helpFileName)
8541 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8543 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8545 if (!helpFileName)
8546 return E_INVALIDARG;
8548 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8550 return S_OK;
8553 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8554 DWORD helpContext)
8556 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8558 TRACE("%p %d\n", This, helpContext);
8560 This->dwHelpContext = helpContext;
8562 return S_OK;
8565 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8566 LCID lcid)
8568 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8570 TRACE("%p %x\n", This, lcid);
8572 This->set_lcid = lcid;
8574 return S_OK;
8577 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8578 UINT libFlags)
8580 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8582 TRACE("%p %x\n", This, libFlags);
8584 This->libflags = libFlags;
8586 return S_OK;
8589 typedef struct tagWMSFT_SegContents {
8590 DWORD len;
8591 void *data;
8592 } WMSFT_SegContents;
8594 typedef struct tagWMSFT_TLBFile {
8595 MSFT_Header header;
8596 WMSFT_SegContents typeinfo_seg;
8597 WMSFT_SegContents impfile_seg;
8598 WMSFT_SegContents impinfo_seg;
8599 WMSFT_SegContents ref_seg;
8600 WMSFT_SegContents lib_seg;
8601 WMSFT_SegContents guid_seg;
8602 WMSFT_SegContents res07_seg;
8603 WMSFT_SegContents name_seg;
8604 WMSFT_SegContents string_seg;
8605 WMSFT_SegContents typdesc_seg;
8606 WMSFT_SegContents arraydesc_seg;
8607 WMSFT_SegContents custdata_seg;
8608 WMSFT_SegContents cdguids_seg;
8609 MSFT_SegDir segdir;
8610 WMSFT_SegContents aux_seg;
8611 } WMSFT_TLBFile;
8613 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8614 WMSFT_TLBFile *file)
8616 TLBString *str;
8617 UINT last_offs;
8618 char *data;
8620 file->string_seg.len = 0;
8621 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8622 int size;
8624 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8625 if (size == 0)
8626 return E_UNEXPECTED;
8628 size += sizeof(INT16);
8629 if (size % 4)
8630 size = (size + 4) & ~0x3;
8631 if (size < 8)
8632 size = 8;
8634 file->string_seg.len += size;
8636 /* temporarily use str->offset to store the length of the aligned,
8637 * converted string */
8638 str->offset = size;
8641 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8643 last_offs = 0;
8644 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8645 int size;
8647 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8648 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8649 if (size == 0) {
8650 heap_free(file->string_seg.data);
8651 return E_UNEXPECTED;
8654 *((INT16*)data) = size;
8656 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8658 size = str->offset;
8659 data += size;
8660 str->offset = last_offs;
8661 last_offs += size;
8664 return S_OK;
8667 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8668 WMSFT_TLBFile *file)
8670 TLBString *str;
8671 UINT last_offs;
8672 char *data;
8673 MSFT_NameIntro *last_intro = NULL;
8675 file->header.nametablecount = 0;
8676 file->header.nametablechars = 0;
8678 file->name_seg.len = 0;
8679 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8680 int size;
8682 size = strlenW(str->str);
8683 file->header.nametablechars += size;
8684 file->header.nametablecount++;
8686 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8687 if (size == 0)
8688 return E_UNEXPECTED;
8690 size += sizeof(MSFT_NameIntro);
8691 if (size % 4)
8692 size = (size + 4) & ~0x3;
8693 if (size < 8)
8694 size = 8;
8696 file->name_seg.len += size;
8698 /* temporarily use str->offset to store the length of the aligned,
8699 * converted string */
8700 str->offset = size;
8703 file->name_seg.data = data = heap_alloc(file->name_seg.len);
8705 last_offs = 0;
8706 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8707 int size;
8708 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8710 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8711 data + sizeof(MSFT_NameIntro),
8712 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8713 if (size == 0) {
8714 heap_free(file->name_seg.data);
8715 return E_UNEXPECTED;
8717 data[sizeof(MSFT_NameIntro) + size] = '\0';
8719 intro->hreftype = -1; /* TODO? */
8720 intro->next_hash = -1;
8721 intro->namelen = size & 0xFF;
8722 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8723 intro->namelen |= LHashValOfNameSysA(This->syskind,
8724 This->lcid, data + sizeof(MSFT_NameIntro)) << 16;
8726 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8727 str->offset - size - sizeof(MSFT_NameIntro));
8729 /* update str->offset to actual value to use in other
8730 * compilation functions that require positions within
8731 * the string table */
8732 last_intro = intro;
8733 size = str->offset;
8734 data += size;
8735 str->offset = last_offs;
8736 last_offs += size;
8739 if(last_intro)
8740 last_intro->hreftype = 0; /* last one is 0? */
8742 return S_OK;
8745 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8747 TLBGuid *guid;
8748 MSFT_GuidEntry *entry;
8749 DWORD offs;
8751 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8752 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8754 entry = file->guid_seg.data;
8755 offs = 0;
8756 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
8757 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
8758 entry->hreftype = 0xFFFFFFFF; /* TODO */
8759 entry->next_hash = 0xFFFFFFFF; /* TODO? */
8761 guid->offset = offs;
8763 offs += sizeof(MSFT_GuidEntry);
8764 ++entry;
8767 --entry;
8768 entry->next_hash = 0; /* last one has 0? */
8770 return S_OK;
8773 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
8775 VARIANT v = *value;
8776 VARTYPE arg_type = V_VT(value);
8777 int mask = 0;
8778 HRESULT hres;
8779 DWORD ret = file->custdata_seg.len;
8781 if(arg_type == VT_INT)
8782 arg_type = VT_I4;
8783 if(arg_type == VT_UINT)
8784 arg_type = VT_UI4;
8786 v = *value;
8787 if(V_VT(value) != arg_type) {
8788 hres = VariantChangeType(&v, value, 0, arg_type);
8789 if(FAILED(hres)){
8790 ERR("VariantChangeType failed: %08x\n", hres);
8791 return -1;
8795 /* Check if default value can be stored in-place */
8796 switch(arg_type){
8797 case VT_I4:
8798 case VT_UI4:
8799 mask = 0x3ffffff;
8800 if(V_UI4(&v) > 0x3ffffff)
8801 break;
8802 /* fall through */
8803 case VT_I1:
8804 case VT_UI1:
8805 case VT_BOOL:
8806 if(!mask)
8807 mask = 0xff;
8808 /* fall through */
8809 case VT_I2:
8810 case VT_UI2:
8811 if(!mask)
8812 mask = 0xffff;
8813 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
8816 /* have to allocate space in custdata_seg */
8817 switch(arg_type) {
8818 case VT_I4:
8819 case VT_R4:
8820 case VT_UI4:
8821 case VT_INT:
8822 case VT_UINT:
8823 case VT_HRESULT:
8824 case VT_PTR: {
8825 /* Construct the data to be allocated */
8826 int *data;
8828 if(file->custdata_seg.data){
8829 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
8830 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
8831 file->custdata_seg.len += sizeof(int) * 2;
8832 }else{
8833 file->custdata_seg.len = sizeof(int) * 2;
8834 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8837 data[0] = V_VT(value) + (V_UI4(&v) << 16);
8838 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
8840 /* TODO: Check if the encoded data is already present in custdata_seg */
8842 return ret;
8845 case VT_BSTR: {
8846 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
8847 char *data;
8849 if(file->custdata_seg.data){
8850 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
8851 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
8852 file->custdata_seg.len += len;
8853 }else{
8854 file->custdata_seg.len = len;
8855 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8858 *((unsigned short *)data) = V_VT(value);
8859 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
8860 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
8861 if(V_BSTR(&v)[i] <= 0x7f)
8862 data[i+6] = V_BSTR(&v)[i];
8863 else
8864 data[i+6] = '?';
8866 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
8867 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
8868 data[i] = 0x57;
8870 /* TODO: Check if the encoded data is already present in custdata_seg */
8872 return ret;
8874 default:
8875 FIXME("Argument type not yet handled\n");
8876 return -1;
8880 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
8882 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
8884 DWORD offs = file->arraydesc_seg.len;
8885 DWORD *encoded;
8886 USHORT i;
8888 /* TODO: we should check for duplicates, but that's harder because each
8889 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8890 * at the library-level) */
8892 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
8893 if(!file->arraydesc_seg.data)
8894 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
8895 else
8896 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
8897 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
8899 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
8900 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
8901 for(i = 0; i < desc->cDims; ++i){
8902 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
8903 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
8906 return offs;
8909 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
8911 DWORD junk;
8912 INT16 junk2;
8913 DWORD offs = 0;
8914 DWORD encoded[2];
8915 VARTYPE vt = desc->vt & VT_TYPEMASK, subtype;
8916 char *data;
8918 if(!out_mix)
8919 out_mix = &junk;
8920 if(!out_size)
8921 out_size = &junk2;
8923 switch(vt){
8924 case VT_INT:
8925 subtype = VT_I4;
8926 break;
8927 case VT_UINT:
8928 subtype = VT_UI4;
8929 break;
8930 case VT_VOID:
8931 subtype = VT_EMPTY;
8932 break;
8933 default:
8934 subtype = vt;
8935 break;
8938 switch(vt){
8939 case VT_INT:
8940 case VT_UINT:
8941 case VT_I1:
8942 case VT_UI1:
8943 case VT_I2:
8944 case VT_UI2:
8945 case VT_I4:
8946 case VT_UI4:
8947 case VT_BOOL:
8948 case VT_R4:
8949 case VT_ERROR:
8950 case VT_BSTR:
8951 case VT_HRESULT:
8952 case VT_CY:
8953 case VT_VOID:
8954 case VT_VARIANT:
8955 *out_mix = subtype;
8956 return 0x80000000 | (subtype << 16) | desc->vt;
8959 if(vt == VT_PTR || vt == VT_SAFEARRAY){
8960 DWORD mix;
8961 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
8962 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
8963 *out_mix = 0x7FFF;
8964 *out_size += 2 * sizeof(DWORD);
8965 }else if(vt == VT_CARRAY){
8966 encoded[0] = desc->vt | (0x7FFE << 16);
8967 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
8968 *out_mix = 0x7FFE;
8969 }else if(vt == VT_USERDEFINED){
8970 encoded[0] = desc->vt | (0x7FFF << 16);
8971 encoded[1] = desc->u.hreftype;
8972 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
8973 }else{
8974 FIXME("Don't know what to do! VT: 0x%x\n", desc->vt);
8975 *out_mix = desc->vt;
8976 return 0x80000000 | (desc->vt << 16) | desc->vt;
8979 data = file->typdesc_seg.data;
8980 while(offs < file->typdesc_seg.len){
8981 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
8982 return offs;
8983 offs += sizeof(encoded);
8986 file->typdesc_seg.len += sizeof(encoded);
8987 if(!file->typdesc_seg.data)
8988 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
8989 else
8990 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
8992 memcpy(&data[offs], encoded, sizeof(encoded));
8994 return offs;
8997 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
8999 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9000 DWORD ret = cdguids_seg->len, offs;
9001 MSFT_CDGuid *cdguid = cdguids_seg->data;
9002 TLBCustData *cd;
9004 if(list_empty(custdata_list))
9005 return -1;
9007 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9008 if(!cdguids_seg->data){
9009 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9010 }else
9011 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9013 offs = ret + sizeof(MSFT_CDGuid);
9014 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9015 cdguid->GuidOffset = cd->guid->offset;
9016 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9017 cdguid->next = offs;
9018 offs += sizeof(MSFT_CDGuid);
9019 ++cdguid;
9022 --cdguid;
9023 cdguid->next = -1;
9025 return ret;
9028 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9029 WMSFT_TLBFile *file)
9031 WMSFT_SegContents *aux_seg = &file->aux_seg;
9032 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9033 MSFT_VarRecord *varrecord;
9034 MSFT_FuncRecord *funcrecord;
9035 MEMBERID *memid;
9036 DWORD *name, *offsets, offs;
9038 for(i = 0; i < info->cFuncs; ++i){
9039 TLBFuncDesc *desc = &info->funcdescs[i];
9041 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9043 /* optional fields */
9044 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9045 if(!list_empty(&desc->custdata_list))
9046 recorded_size += 7 * sizeof(INT);
9047 else if(desc->HelpStringContext != 0)
9048 recorded_size += 6 * sizeof(INT);
9049 /* res9? resA? */
9050 else if(desc->Entry)
9051 recorded_size += 3 * sizeof(INT);
9052 else if(desc->HelpString)
9053 recorded_size += 2 * sizeof(INT);
9054 else if(desc->helpcontext)
9055 recorded_size += sizeof(INT);
9057 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9059 for(j = 0; j < desc->funcdesc.cParams; ++j){
9060 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9061 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9062 break;
9066 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9069 for(i = 0; i < info->cVars; ++i){
9070 TLBVarDesc *desc = &info->vardescs[i];
9072 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9074 /* optional fields */
9075 if(desc->HelpStringContext != 0)
9076 recorded_size += 5 * sizeof(INT);
9077 else if(!list_empty(&desc->custdata_list))
9078 recorded_size += 4 * sizeof(INT);
9079 /* res9? */
9080 else if(desc->HelpString)
9081 recorded_size += 2 * sizeof(INT);
9082 else if(desc->HelpContext != 0)
9083 recorded_size += sizeof(INT);
9085 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9088 if(!recorded_size && !extra_size)
9089 return ret;
9091 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9093 aux_seg->len += recorded_size + extra_size;
9095 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9097 if(aux_seg->data)
9098 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9099 else
9100 aux_seg->data = heap_alloc(aux_seg->len);
9102 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9104 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9105 offs = 0;
9107 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9108 for(i = 0; i < info->cFuncs; ++i){
9109 TLBFuncDesc *desc = &info->funcdescs[i];
9110 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9112 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9113 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9114 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9115 funcrecord->VtableOffset = desc->funcdesc.oVft;
9117 /* FKCCIC:
9118 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9119 * ^^^funckind
9120 * ^^^ ^invkind
9121 * ^has_cust_data
9122 * ^^^^callconv
9123 * ^has_param_defaults
9124 * ^oEntry_is_intresource
9126 funcrecord->FKCCIC =
9127 desc->funcdesc.funckind |
9128 (desc->funcdesc.invkind << 3) |
9129 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9130 (desc->funcdesc.callconv << 8);
9132 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9133 funcrecord->FKCCIC |= 0x2000;
9135 for(j = 0; j < desc->funcdesc.cParams; ++j){
9136 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9137 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9138 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9141 if(paramdefault_size > 0)
9142 funcrecord->FKCCIC |= 0x1000;
9144 funcrecord->nrargs = desc->funcdesc.cParams;
9145 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9147 /* optional fields */
9148 /* res9? resA? */
9149 if(!list_empty(&desc->custdata_list)){
9150 size += 7 * sizeof(INT);
9151 funcrecord->HelpContext = desc->helpcontext;
9152 if(desc->HelpString)
9153 funcrecord->oHelpString = desc->HelpString->offset;
9154 else
9155 funcrecord->oHelpString = -1;
9156 if(!desc->Entry)
9157 funcrecord->oEntry = -1;
9158 else if(IS_INTRESOURCE(desc->Entry))
9159 funcrecord->oEntry = LOWORD(desc->Entry);
9160 else
9161 funcrecord->oEntry = desc->Entry->offset;
9162 funcrecord->res9 = -1;
9163 funcrecord->resA = -1;
9164 funcrecord->HelpStringContext = desc->HelpStringContext;
9165 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9166 }else if(desc->HelpStringContext != 0){
9167 size += 6 * sizeof(INT);
9168 funcrecord->HelpContext = desc->helpcontext;
9169 if(desc->HelpString)
9170 funcrecord->oHelpString = desc->HelpString->offset;
9171 else
9172 funcrecord->oHelpString = -1;
9173 if(!desc->Entry)
9174 funcrecord->oEntry = -1;
9175 else if(IS_INTRESOURCE(desc->Entry))
9176 funcrecord->oEntry = LOWORD(desc->Entry);
9177 else
9178 funcrecord->oEntry = desc->Entry->offset;
9179 funcrecord->res9 = -1;
9180 funcrecord->resA = -1;
9181 funcrecord->HelpStringContext = desc->HelpStringContext;
9182 }else if(desc->Entry){
9183 size += 3 * sizeof(INT);
9184 funcrecord->HelpContext = desc->helpcontext;
9185 if(desc->HelpString)
9186 funcrecord->oHelpString = desc->HelpString->offset;
9187 else
9188 funcrecord->oHelpString = -1;
9189 if(!desc->Entry)
9190 funcrecord->oEntry = -1;
9191 else if(IS_INTRESOURCE(desc->Entry))
9192 funcrecord->oEntry = LOWORD(desc->Entry);
9193 else
9194 funcrecord->oEntry = desc->Entry->offset;
9195 }else if(desc->HelpString){
9196 size += 2 * sizeof(INT);
9197 funcrecord->HelpContext = desc->helpcontext;
9198 funcrecord->oHelpString = desc->HelpString->offset;
9199 }else if(desc->helpcontext){
9200 size += sizeof(INT);
9201 funcrecord->HelpContext = desc->helpcontext;
9204 paramdefault = (DWORD*)((char *)funcrecord + size);
9205 size += paramdefault_size;
9207 for(j = 0; j < desc->funcdesc.cParams; ++j){
9208 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9210 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9211 if(desc->pParamDesc[j].Name)
9212 info->oName = desc->pParamDesc[j].Name->offset;
9213 else
9214 info->oName = -1;
9215 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9217 if(paramdefault_size){
9218 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9219 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9220 else if(paramdefault_size)
9221 *paramdefault = -1;
9222 ++paramdefault;
9225 size += sizeof(MSFT_ParameterInfo);
9228 funcrecord->Info = size | (i << 16); /* is it just the index? */
9230 *offsets = offs;
9231 offs += size;
9232 ++offsets;
9234 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9237 varrecord = (MSFT_VarRecord*)funcrecord;
9238 for(i = 0; i < info->cVars; ++i){
9239 TLBVarDesc *desc = &info->vardescs[i];
9240 DWORD size = 5 * sizeof(INT);
9242 varrecord->vardescsize = sizeof(desc->vardesc);
9243 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9244 varrecord->Flags = desc->vardesc.wVarFlags;
9245 varrecord->VarKind = desc->vardesc.varkind;
9247 if(desc->vardesc.varkind == VAR_CONST){
9248 varrecord->vardescsize += sizeof(VARIANT);
9249 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9250 }else
9251 varrecord->OffsValue = desc->vardesc.u.oInst;
9253 /* res9? */
9254 if(desc->HelpStringContext != 0){
9255 size += 5 * sizeof(INT);
9256 varrecord->HelpContext = desc->HelpContext;
9257 if(desc->HelpString)
9258 varrecord->HelpString = desc->HelpString->offset;
9259 else
9260 varrecord->HelpString = -1;
9261 varrecord->res9 = -1;
9262 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9263 varrecord->HelpStringContext = desc->HelpStringContext;
9264 }else if(!list_empty(&desc->custdata_list)){
9265 size += 4 * sizeof(INT);
9266 varrecord->HelpContext = desc->HelpContext;
9267 if(desc->HelpString)
9268 varrecord->HelpString = desc->HelpString->offset;
9269 else
9270 varrecord->HelpString = -1;
9271 varrecord->res9 = -1;
9272 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9273 }else if(desc->HelpString){
9274 size += 2 * sizeof(INT);
9275 varrecord->HelpContext = desc->HelpContext;
9276 if(desc->HelpString)
9277 varrecord->HelpString = desc->HelpString->offset;
9278 else
9279 varrecord->HelpString = -1;
9280 }else if(desc->HelpContext != 0){
9281 size += sizeof(INT);
9282 varrecord->HelpContext = desc->HelpContext;
9285 varrecord->Info = size | (i << 16);
9287 *offsets = offs;
9288 offs += size;
9289 ++offsets;
9291 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9294 memid = (MEMBERID*)varrecord;
9295 for(i = 0; i < info->cFuncs; ++i){
9296 TLBFuncDesc *desc = &info->funcdescs[i];
9297 *memid = desc->funcdesc.memid;
9298 ++memid;
9300 for(i = 0; i < info->cVars; ++i){
9301 TLBVarDesc *desc = &info->vardescs[i];
9302 *memid = desc->vardesc.memid;
9303 ++memid;
9306 name = (UINT*)memid;
9307 for(i = 0; i < info->cFuncs; ++i){
9308 TLBFuncDesc *desc = &info->funcdescs[i];
9309 if(desc->Name)
9310 *name = desc->Name->offset;
9311 else
9312 *name = -1;
9313 ++name;
9315 for(i = 0; i < info->cVars; ++i){
9316 TLBVarDesc *desc = &info->vardescs[i];
9317 if(desc->Name)
9318 *name = desc->Name->offset;
9319 else
9320 *name = -1;
9321 ++name;
9324 return ret;
9327 typedef struct tagWMSFT_RefChunk {
9328 DWORD href;
9329 DWORD res04;
9330 DWORD res08;
9331 DWORD next;
9332 } WMSFT_RefChunk;
9334 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9336 DWORD offs = file->ref_seg.len, i;
9337 WMSFT_RefChunk *chunk;
9339 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9340 if(!file->ref_seg.data)
9341 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9342 else
9343 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9345 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9347 for(i = 0; i < info->cImplTypes; ++i){
9348 chunk->href = info->impltypes[i].hRef;
9349 chunk->res04 = info->impltypes[i].implflags;
9350 chunk->res08 = -1;
9351 if(i < info->cImplTypes - 1)
9352 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9353 else
9354 chunk->next = -1;
9355 ++chunk;
9358 return offs;
9361 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9363 DWORD size;
9365 size = sizeof(MSFT_TypeInfoBase);
9367 if(data){
9368 MSFT_TypeInfoBase *base = (void*)data;
9369 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9370 base->typekind = TKIND_DISPATCH;
9371 else
9372 base->typekind = info->typekind;
9373 base->typekind |= index << 16; /* TODO: There are some other flags here */
9374 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9375 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9376 base->res2 = 0;
9377 base->res3 = 0;
9378 base->res4 = 3;
9379 base->res5 = 0;
9380 base->cElement = (info->cVars << 16) | info->cFuncs;
9381 base->res7 = 0;
9382 base->res8 = 0;
9383 base->res9 = 0;
9384 base->resA = 0;
9385 if(info->guid)
9386 base->posguid = info->guid->offset;
9387 else
9388 base->posguid = -1;
9389 base->flags = info->wTypeFlags;
9390 if(info->Name)
9391 base->NameOffset = info->Name->offset;
9392 else
9393 base->NameOffset = -1;
9394 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9395 if(info->DocString)
9396 base->docstringoffs = info->DocString->offset;
9397 else
9398 base->docstringoffs = -1;
9399 base->helpstringcontext = info->dwHelpStringContext;
9400 base->helpcontext = info->dwHelpContext;
9401 base->oCustData = WMSFT_compile_custdata(&info->custdata_list, file);
9402 base->cImplTypes = info->cImplTypes;
9403 base->cbSizeVft = info->cbSizeVft;
9404 base->size = info->cbSizeInstance;
9405 if(info->typekind == TKIND_COCLASS){
9406 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9407 }else if(info->typekind == TKIND_ALIAS){
9408 base->datatype1 = WMSFT_append_typedesc(&info->tdescAlias, file, NULL, NULL);
9409 }else if(info->typekind == TKIND_MODULE){
9410 if(info->DllName)
9411 base->datatype1 = info->DllName->offset;
9412 else
9413 base->datatype1 = -1;
9414 }else{
9415 if(info->cImplTypes > 0)
9416 base->datatype1 = info->impltypes[0].hRef;
9417 else
9418 base->datatype1 = -1;
9420 base->datatype2 = index; /* FIXME: i think there's more here */
9421 base->res18 = 0;
9422 base->res19 = -1;
9425 return size;
9428 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9430 UINT i;
9432 file->typeinfo_seg.len = 0;
9433 for(i = 0; i < This->TypeInfoCount; ++i){
9434 ITypeInfoImpl *info = This->typeinfos[i];
9435 *junk = file->typeinfo_seg.len;
9436 ++junk;
9437 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9440 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9441 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9443 file->aux_seg.len = 0;
9444 file->aux_seg.data = NULL;
9446 file->typeinfo_seg.len = 0;
9447 for(i = 0; i < This->TypeInfoCount; ++i){
9448 ITypeInfoImpl *info = This->typeinfos[i];
9449 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9450 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9454 typedef struct tagWMSFT_ImpFile {
9455 INT guid_offs;
9456 LCID lcid;
9457 DWORD version;
9458 } WMSFT_ImpFile;
9460 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9462 TLBImpLib *implib;
9463 WMSFT_ImpFile *impfile;
9464 char *data;
9465 DWORD last_offs = 0;
9467 file->impfile_seg.len = 0;
9468 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9469 int size = 0;
9471 if(implib->name){
9472 WCHAR *path = strrchrW(implib->name, '\\');
9473 if(path)
9474 ++path;
9475 else
9476 path = implib->name;
9477 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9478 if (size == 0)
9479 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9482 size += sizeof(INT16);
9483 if (size % 4)
9484 size = (size + 4) & ~0x3;
9485 if (size < 8)
9486 size = 8;
9488 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9491 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9493 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9494 int strlen = 0, size;
9496 impfile = (WMSFT_ImpFile*)data;
9497 impfile->guid_offs = implib->guid->offset;
9498 impfile->lcid = implib->lcid;
9499 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9501 data += sizeof(WMSFT_ImpFile);
9503 if(implib->name){
9504 WCHAR *path= strrchrW(implib->name, '\\');
9505 if(path)
9506 ++path;
9507 else
9508 path = implib->name;
9509 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9510 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9511 if (strlen == 0)
9512 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9515 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9517 size = strlen + sizeof(INT16);
9518 if (size % 4)
9519 size = (size + 4) & ~0x3;
9520 if (size < 8)
9521 size = 8;
9522 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9524 data += size;
9525 implib->offset = last_offs;
9526 last_offs += size + sizeof(WMSFT_ImpFile);
9530 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9532 MSFT_ImpInfo *info;
9533 TLBRefType *ref_type;
9534 UINT i = 0;
9536 WMSFT_compile_impfile(This, file);
9538 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9539 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9541 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9542 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9543 if(ref_type->index == TLB_REF_USE_GUID){
9544 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9545 info->oGuid = ref_type->guid->offset;
9546 }else
9547 info->oGuid = ref_type->index;
9548 info->oImpFile = ref_type->pImpTLInfo->offset;
9549 ++i;
9550 ++info;
9554 static void WMSFT_compile_lib(ITypeLibImpl *This, WMSFT_TLBFile *file)
9556 /* TODO: What actually goes here? */
9557 file->lib_seg.len = 0x80;
9558 file->lib_seg.data = heap_alloc(file->lib_seg.len);
9559 memset(file->lib_seg.data, 0xFF, file->lib_seg.len);
9561 #if 0
9562 /* sometimes, first element is offset to last guid, for some reason */
9563 if(This->guid)
9564 *(DWORD*)file->lib_seg.data =
9565 (list_count(&This->guid_list) - 1) * sizeof(MSFT_GuidEntry);
9566 #endif
9569 static void WMSFT_compile_res07(ITypeLibImpl *This, WMSFT_TLBFile *file)
9571 /* TODO: What actually goes here?
9572 * Wild speculation:
9573 * It's something to do with the Name table (and string table?). When you
9574 * add a new name, the offset to that name from within the Name table gets
9575 * stuck somewhere in res07, apparently starting at the end of the segment
9576 * then moving backwards at a rate of 3 bytes per char in the Name. */
9577 file->res07_seg.len = 0x200;
9578 file->res07_seg.data = heap_alloc(file->res07_seg.len);
9579 memset(file->res07_seg.data, 0xFF, file->res07_seg.len);
9582 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9584 if(contents && contents->len){
9585 segdir->offset = *running_offset;
9586 segdir->length = contents->len;
9587 *running_offset += segdir->length;
9588 }else{
9589 segdir->offset = -1;
9590 segdir->length = 0;
9593 /* TODO: do these ever change? */
9594 segdir->res08 = -1;
9595 segdir->res0c = 0xf;
9598 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9600 DWORD written;
9601 if(segment)
9602 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9605 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9606 DWORD file_len)
9608 DWORD i;
9609 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9611 for(i = 0; i < This->TypeInfoCount; ++i){
9612 base->memoffset += file_len;
9613 ++base;
9616 return S_OK;
9619 static void WMSFT_free_file(WMSFT_TLBFile *file)
9621 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9622 HeapFree(GetProcessHeap(), 0, file->lib_seg.data);
9623 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9624 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9625 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9626 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9627 HeapFree(GetProcessHeap(), 0, file->res07_seg.data);
9628 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9629 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9630 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9631 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9632 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9633 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9634 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9637 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9639 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9640 WMSFT_TLBFile file;
9641 DWORD written, junk_size, junk_offs, running_offset;
9642 BOOL br;
9643 HANDLE outfile;
9644 HRESULT hres;
9645 DWORD *junk;
9647 TRACE("%p\n", This);
9649 memset(&file, 0, sizeof(file));
9651 file.header.magic1 = 0x5446534D;
9652 file.header.magic2 = 0x00010002;
9653 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9654 file.header.lcid2 = This->set_lcid;
9655 file.header.varflags = 0x41; /* TODO?? */
9656 if (This->HelpFile)
9657 file.header.varflags |= 0x10;
9658 if (This->HelpStringDll)
9659 file.header.varflags |= HELPDLLFLAG;
9660 file.header.version = (This->ver_major << 16) | This->ver_minor;
9661 file.header.flags = This->libflags;
9662 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9663 file.header.helpcontext = This->dwHelpContext;
9664 file.header.res44 = 0x20;
9665 file.header.res48 = 0x80;
9666 file.header.dispatchpos = This->dispatch_href;
9668 /* do name and string compilation to get offsets for other compilations */
9669 hres = WMSFT_compile_names(This, &file);
9670 if (FAILED(hres)){
9671 WMSFT_free_file(&file);
9672 return hres;
9675 hres = WMSFT_compile_strings(This, &file);
9676 if (FAILED(hres)){
9677 WMSFT_free_file(&file);
9678 return hres;
9681 hres = WMSFT_compile_guids(This, &file);
9682 if (FAILED(hres)){
9683 WMSFT_free_file(&file);
9684 return hres;
9687 if(This->HelpFile)
9688 file.header.helpfile = This->HelpFile->offset;
9689 else
9690 file.header.helpfile = -1;
9692 if(This->DocString)
9693 file.header.helpstring = This->DocString->offset;
9694 else
9695 file.header.helpstring = -1;
9697 /* do some more segment compilation */
9698 file.header.nimpinfos = list_count(&This->ref_list);
9699 file.header.nrtypeinfos = This->TypeInfoCount;
9701 if(This->Name)
9702 file.header.NameOffset = This->Name->offset;
9703 else
9704 file.header.NameOffset = -1;
9706 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9708 if(This->guid)
9709 file.header.posguid = This->guid->offset;
9710 else
9711 file.header.posguid = -1;
9713 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9714 if(file.header.varflags & HELPDLLFLAG)
9715 junk_size += sizeof(DWORD);
9716 if(junk_size){
9717 junk = heap_alloc_zero(junk_size);
9718 if(file.header.varflags & HELPDLLFLAG){
9719 *junk = This->HelpStringDll->offset;
9720 junk_offs = 1;
9721 }else
9722 junk_offs = 0;
9723 }else{
9724 junk = NULL;
9725 junk_offs = 0;
9728 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9729 WMSFT_compile_impinfo(This, &file);
9730 WMSFT_compile_lib(This, &file);
9731 WMSFT_compile_res07(This, &file);
9733 running_offset = 0;
9735 TRACE("header at: 0x%x\n", running_offset);
9736 running_offset += sizeof(file.header);
9738 TRACE("junk at: 0x%x\n", running_offset);
9739 running_offset += junk_size;
9741 TRACE("segdir at: 0x%x\n", running_offset);
9742 running_offset += sizeof(file.segdir);
9744 TRACE("typeinfo at: 0x%x\n", running_offset);
9745 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9747 TRACE("libtab at: 0x%x\n", running_offset);
9748 tmp_fill_segdir_seg(&file.segdir.pLibtab, &file.lib_seg, &running_offset);
9750 TRACE("guidtab at: 0x%x\n", running_offset);
9751 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9753 TRACE("reftab at: 0x%x\n", running_offset);
9754 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9756 TRACE("impinfo at: 0x%x\n", running_offset);
9757 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9759 TRACE("impfiles at: 0x%x\n", running_offset);
9760 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9762 TRACE("res07 at: 0x%x\n", running_offset);
9763 tmp_fill_segdir_seg(&file.segdir.res07, &file.res07_seg, &running_offset);
9765 TRACE("nametab at: 0x%x\n", running_offset);
9766 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9768 TRACE("stringtab at: 0x%x\n", running_offset);
9769 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9771 TRACE("typdesc at: 0x%x\n", running_offset);
9772 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9774 TRACE("arraydescriptions at: 0x%x\n", running_offset);
9775 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
9777 TRACE("custdata at: 0x%x\n", running_offset);
9778 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
9780 TRACE("cdguids at: 0x%x\n", running_offset);
9781 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
9783 TRACE("res0e at: 0x%x\n", running_offset);
9784 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
9786 TRACE("res0f at: 0x%x\n", running_offset);
9787 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
9789 TRACE("aux_seg at: 0x%x\n", running_offset);
9791 WMSFT_fixup_typeinfos(This, &file, running_offset);
9793 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
9794 FILE_ATTRIBUTE_NORMAL, 0);
9795 if (outfile == INVALID_HANDLE_VALUE){
9796 WMSFT_free_file(&file);
9797 return TYPE_E_IOERROR;
9800 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
9801 if (!br) {
9802 WMSFT_free_file(&file);
9803 CloseHandle(outfile);
9804 return TYPE_E_IOERROR;
9807 br = WriteFile(outfile, junk, junk_size, &written, NULL);
9808 if (!br) {
9809 WMSFT_free_file(&file);
9810 CloseHandle(outfile);
9811 return TYPE_E_IOERROR;
9814 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
9815 if (!br) {
9816 WMSFT_free_file(&file);
9817 CloseHandle(outfile);
9818 return TYPE_E_IOERROR;
9821 WMSFT_write_segment(outfile, &file.typeinfo_seg);
9822 WMSFT_write_segment(outfile, &file.lib_seg);
9823 WMSFT_write_segment(outfile, &file.guid_seg);
9824 WMSFT_write_segment(outfile, &file.ref_seg);
9825 WMSFT_write_segment(outfile, &file.impinfo_seg);
9826 WMSFT_write_segment(outfile, &file.impfile_seg);
9827 WMSFT_write_segment(outfile, &file.res07_seg);
9828 WMSFT_write_segment(outfile, &file.name_seg);
9829 WMSFT_write_segment(outfile, &file.string_seg);
9830 WMSFT_write_segment(outfile, &file.typdesc_seg);
9831 WMSFT_write_segment(outfile, &file.arraydesc_seg);
9832 WMSFT_write_segment(outfile, &file.custdata_seg);
9833 WMSFT_write_segment(outfile, &file.cdguids_seg);
9834 WMSFT_write_segment(outfile, &file.aux_seg);
9836 WMSFT_free_file(&file);
9838 CloseHandle(outfile);
9840 return S_OK;
9843 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
9844 LPOLESTR name)
9846 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9847 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
9848 return E_NOTIMPL;
9851 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
9852 REFGUID guid, VARIANT *varVal)
9854 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9855 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
9856 return E_NOTIMPL;
9859 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
9860 ULONG helpStringContext)
9862 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9863 FIXME("%p %u - stub\n", This, helpStringContext);
9864 return E_NOTIMPL;
9867 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
9868 LPOLESTR filename)
9870 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9871 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
9873 if (!filename)
9874 return E_INVALIDARG;
9876 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
9878 return S_OK;
9881 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
9882 ICreateTypeLib2_fnQueryInterface,
9883 ICreateTypeLib2_fnAddRef,
9884 ICreateTypeLib2_fnRelease,
9885 ICreateTypeLib2_fnCreateTypeInfo,
9886 ICreateTypeLib2_fnSetName,
9887 ICreateTypeLib2_fnSetVersion,
9888 ICreateTypeLib2_fnSetGuid,
9889 ICreateTypeLib2_fnSetDocString,
9890 ICreateTypeLib2_fnSetHelpFileName,
9891 ICreateTypeLib2_fnSetHelpContext,
9892 ICreateTypeLib2_fnSetLcid,
9893 ICreateTypeLib2_fnSetLibFlags,
9894 ICreateTypeLib2_fnSaveAllChanges,
9895 ICreateTypeLib2_fnDeleteTypeInfo,
9896 ICreateTypeLib2_fnSetCustData,
9897 ICreateTypeLib2_fnSetHelpStringContext,
9898 ICreateTypeLib2_fnSetHelpStringDll
9901 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
9902 REFIID riid, void **object)
9904 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9906 return ITypeInfo2_QueryInterface((ITypeInfo2*)This, riid, object);
9909 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
9911 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9913 return ITypeInfo2_AddRef((ITypeInfo2*)This);
9916 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
9918 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9920 return ITypeInfo2_Release((ITypeInfo2*)This);
9923 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
9924 REFGUID guid)
9926 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9928 TRACE("%p %s\n", This, debugstr_guid(guid));
9930 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
9932 return S_OK;
9935 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
9936 UINT typeFlags)
9938 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9939 WORD old_flags;
9940 HRESULT hres;
9942 TRACE("%p %x\n", This, typeFlags);
9944 if (typeFlags & TYPEFLAG_FDUAL) {
9945 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9946 ITypeLib *stdole;
9947 ITypeInfo *dispatch;
9948 HREFTYPE hreftype;
9949 HRESULT hres;
9951 hres = LoadTypeLib(stdole2tlb, &stdole);
9952 if(FAILED(hres))
9953 return hres;
9955 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
9956 ITypeLib_Release(stdole);
9957 if(FAILED(hres))
9958 return hres;
9960 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
9961 ITypeInfo_Release(dispatch);
9962 if(FAILED(hres))
9963 return hres;
9966 old_flags = This->wTypeFlags;
9967 This->wTypeFlags = typeFlags;
9969 hres = ICreateTypeInfo2_LayOut(iface);
9970 if (FAILED(hres)) {
9971 This->wTypeFlags = old_flags;
9972 return hres;
9975 return S_OK;
9978 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
9979 LPOLESTR doc)
9981 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9983 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9985 if (!doc)
9986 return E_INVALIDARG;
9988 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
9990 return S_OK;
9993 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
9994 DWORD helpContext)
9996 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9998 TRACE("%p %d\n", This, helpContext);
10000 This->dwHelpContext = helpContext;
10002 return S_OK;
10005 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10006 WORD majorVerNum, WORD minorVerNum)
10008 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10010 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10012 This->wMajorVerNum = majorVerNum;
10013 This->wMinorVerNum = minorVerNum;
10015 return S_OK;
10018 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10019 ITypeInfo *typeInfo, HREFTYPE *refType)
10021 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10022 UINT index;
10023 ITypeLib *container;
10024 TLBRefType *ref_type;
10025 TLBImpLib *implib;
10026 TYPEATTR *typeattr;
10027 TLIBATTR *libattr;
10028 HRESULT hres;
10030 TRACE("%p %p %p\n", This, typeInfo, refType);
10032 if (!typeInfo || !refType)
10033 return E_INVALIDARG;
10035 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10036 if (FAILED(hres))
10037 return hres;
10039 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10040 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10042 ITypeLib_Release(container);
10044 *refType = target->hreftype;
10046 return S_OK;
10049 hres = ITypeLib_GetLibAttr(container, &libattr);
10050 if (FAILED(hres)) {
10051 ITypeLib_Release(container);
10052 return hres;
10055 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10056 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10057 implib->lcid == libattr->lcid &&
10058 implib->wVersionMajor == libattr->wMajorVerNum &&
10059 implib->wVersionMinor == libattr->wMinorVerNum)
10060 break;
10063 if(&implib->entry == &This->pTypeLib->implib_list){
10064 implib = heap_alloc_zero(sizeof(TLBImpLib));
10066 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10067 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10068 implib->name = SysAllocString(our_container->path);
10069 }else{
10070 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10071 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10072 if(FAILED(hres)){
10073 implib->name = NULL;
10074 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10078 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid);
10079 implib->lcid = libattr->lcid;
10080 implib->wVersionMajor = libattr->wMajorVerNum;
10081 implib->wVersionMinor = libattr->wMinorVerNum;
10083 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10086 ITypeLib_ReleaseTLibAttr(container, libattr);
10087 ITypeLib_Release(container);
10089 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10090 if (FAILED(hres))
10091 return hres;
10093 index = 0;
10094 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10095 if(ref_type->index == TLB_REF_USE_GUID &&
10096 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10097 ref_type->tkind == typeattr->typekind)
10098 break;
10099 ++index;
10102 if(&ref_type->entry == &This->pTypeLib->ref_list){
10103 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10105 ref_type->tkind = typeattr->typekind;
10106 ref_type->pImpTLInfo = implib;
10107 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10109 ref_type->index = TLB_REF_USE_GUID;
10111 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid);
10113 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10116 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10118 *refType = ref_type->reference | 0x1;
10120 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10121 This->pTypeLib->dispatch_href = *refType;
10123 return S_OK;
10126 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10127 UINT index, FUNCDESC *funcDesc)
10129 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10130 TLBFuncDesc tmp_func_desc, *func_desc;
10131 int buf_size, i;
10132 char *buffer;
10133 HRESULT hres;
10135 TRACE("%p %u %p\n", This, index, funcDesc);
10137 if (!funcDesc || funcDesc->oVft & 3)
10138 return E_INVALIDARG;
10140 switch (This->typekind) {
10141 case TKIND_MODULE:
10142 if (funcDesc->funckind != FUNC_STATIC)
10143 return TYPE_E_BADMODULEKIND;
10144 break;
10145 case TKIND_DISPATCH:
10146 if (funcDesc->funckind != FUNC_DISPATCH)
10147 return TYPE_E_BADMODULEKIND;
10148 break;
10149 default:
10150 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10151 return TYPE_E_BADMODULEKIND;
10154 if (index > This->cFuncs)
10155 return TYPE_E_ELEMENTNOTFOUND;
10157 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10158 !funcDesc->cParams)
10159 return TYPE_E_INCONSISTENTPROPFUNCS;
10161 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10162 TLBFuncDesc_Constructor(&tmp_func_desc);
10164 tmp_func_desc.funcdesc = *funcDesc;
10166 if (tmp_func_desc.funcdesc.oVft != 0)
10167 tmp_func_desc.funcdesc.oVft |= 1;
10169 if (funcDesc->cScodes) {
10170 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10171 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10172 } else
10173 tmp_func_desc.funcdesc.lprgscode = NULL;
10175 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10176 for (i = 0; i < funcDesc->cParams; ++i) {
10177 buf_size += sizeof(ELEMDESC);
10178 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10180 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10181 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10183 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10184 if (FAILED(hres)) {
10185 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10186 heap_free(tmp_func_desc.funcdesc.lprgscode);
10187 return hres;
10190 for (i = 0; i < funcDesc->cParams; ++i) {
10191 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10192 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10193 if (FAILED(hres)) {
10194 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10195 heap_free(tmp_func_desc.funcdesc.lprgscode);
10196 return hres;
10198 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10199 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10200 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10201 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10202 if (FAILED(hres)) {
10203 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10204 heap_free(tmp_func_desc.funcdesc.lprgscode);
10205 return hres;
10210 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10212 if (This->funcdescs) {
10213 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10214 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10216 if (index < This->cFuncs) {
10217 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10218 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10219 func_desc = This->funcdescs + index;
10220 } else
10221 func_desc = This->funcdescs + This->cFuncs;
10223 /* move custdata lists to the new memory location */
10224 for(i = 0; i < This->cFuncs + 1; ++i){
10225 if(index != i){
10226 TLBFuncDesc *fd = &This->funcdescs[i];
10227 if(fd->custdata_list.prev == fd->custdata_list.next)
10228 list_init(&fd->custdata_list);
10229 else{
10230 fd->custdata_list.prev->next = &fd->custdata_list;
10231 fd->custdata_list.next->prev = &fd->custdata_list;
10235 } else
10236 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10238 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10239 list_init(&func_desc->custdata_list);
10241 ++This->cFuncs;
10243 This->needs_layout = TRUE;
10245 return S_OK;
10248 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10249 UINT index, HREFTYPE refType)
10251 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10252 TLBImplType *impl_type;
10253 HRESULT hres;
10255 TRACE("%p %u %d\n", This, index, refType);
10257 switch(This->typekind){
10258 case TKIND_COCLASS: {
10259 if (index == -1) {
10260 FIXME("Unhandled index: -1\n");
10261 return E_NOTIMPL;
10264 if(index != This->cImplTypes)
10265 return TYPE_E_ELEMENTNOTFOUND;
10267 break;
10269 case TKIND_INTERFACE:
10270 case TKIND_DISPATCH:
10271 if (index != 0 || This->cImplTypes)
10272 return TYPE_E_ELEMENTNOTFOUND;
10273 break;
10274 default:
10275 FIXME("Unimplemented typekind: %d\n", This->typekind);
10276 return E_NOTIMPL;
10279 if (This->impltypes){
10280 UINT i;
10282 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10283 sizeof(TLBImplType) * (This->cImplTypes + 1));
10285 if (index < This->cImplTypes) {
10286 memmove(This->impltypes + index + 1, This->impltypes + index,
10287 (This->cImplTypes - index) * sizeof(TLBImplType));
10288 impl_type = This->impltypes + index;
10289 } else
10290 impl_type = This->impltypes + This->cImplTypes;
10292 /* move custdata lists to the new memory location */
10293 for(i = 0; i < This->cImplTypes + 1; ++i){
10294 if(index != i){
10295 TLBImplType *it = &This->impltypes[i];
10296 if(it->custdata_list.prev == it->custdata_list.next)
10297 list_init(&it->custdata_list);
10298 else{
10299 it->custdata_list.prev->next = &it->custdata_list;
10300 it->custdata_list.next->prev = &it->custdata_list;
10304 } else
10305 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10307 memset(impl_type, 0, sizeof(TLBImplType));
10308 TLBImplType_Constructor(impl_type);
10309 impl_type->hRef = refType;
10311 ++This->cImplTypes;
10313 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10314 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10316 hres = ICreateTypeInfo2_LayOut(iface);
10317 if (FAILED(hres))
10318 return hres;
10320 return S_OK;
10323 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10324 UINT index, INT implTypeFlags)
10326 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10327 TLBImplType *impl_type = &This->impltypes[index];
10329 TRACE("%p %u %x\n", This, index, implTypeFlags);
10331 if (This->typekind != TKIND_COCLASS)
10332 return TYPE_E_BADMODULEKIND;
10334 if (index >= This->cImplTypes)
10335 return TYPE_E_ELEMENTNOTFOUND;
10337 impl_type->implflags = implTypeFlags;
10339 return S_OK;
10342 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10343 WORD alignment)
10345 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10347 TRACE("%p %d\n", This, alignment);
10349 This->cbAlignment = alignment;
10351 return S_OK;
10354 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10355 LPOLESTR schema)
10357 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10359 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10361 if (!schema)
10362 return E_INVALIDARG;
10364 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10366 This->lpstrSchema = This->Schema->str;
10368 return S_OK;
10371 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10372 UINT index, VARDESC *varDesc)
10374 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10375 TLBVarDesc *var_desc;
10377 TRACE("%p %u %p\n", This, index, varDesc);
10379 if (This->vardescs){
10380 UINT i;
10382 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10383 sizeof(TLBVarDesc) * (This->cVars + 1));
10385 if (index < This->cVars) {
10386 memmove(This->vardescs + index + 1, This->vardescs + index,
10387 (This->cVars - index) * sizeof(TLBVarDesc));
10388 var_desc = This->vardescs + index;
10389 } else
10390 var_desc = This->vardescs + This->cVars;
10392 /* move custdata lists to the new memory location */
10393 for(i = 0; i < This->cVars + 1; ++i){
10394 if(index != i){
10395 TLBVarDesc *var = &This->vardescs[i];
10396 if(var->custdata_list.prev == var->custdata_list.next)
10397 list_init(&var->custdata_list);
10398 else{
10399 var->custdata_list.prev->next = &var->custdata_list;
10400 var->custdata_list.next->prev = &var->custdata_list;
10404 } else
10405 var_desc = This->vardescs = heap_alloc(sizeof(TLBVarDesc));
10407 memset(var_desc, 0, sizeof(TLBVarDesc));
10408 TLBVarDesc_Constructor(var_desc);
10409 var_desc->vardesc = *varDesc;
10411 ++This->cVars;
10413 This->needs_layout = TRUE;
10415 return S_OK;
10418 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10419 UINT index, LPOLESTR *names, UINT numNames)
10421 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10422 TLBFuncDesc *func_desc = &This->funcdescs[index];
10423 int i;
10425 TRACE("%p %u %p %u\n", This, index, names, numNames);
10427 if (!names)
10428 return E_INVALIDARG;
10430 if (index >= This->cFuncs || numNames == 0)
10431 return TYPE_E_ELEMENTNOTFOUND;
10433 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10434 if(numNames > func_desc->funcdesc.cParams)
10435 return TYPE_E_ELEMENTNOTFOUND;
10436 } else
10437 if(numNames > func_desc->funcdesc.cParams + 1)
10438 return TYPE_E_ELEMENTNOTFOUND;
10440 for(i = 0; i < This->cFuncs; ++i) {
10441 TLBFuncDesc *iter = &This->funcdescs[i];
10442 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10443 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10444 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10445 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10446 continue;
10447 return TYPE_E_AMBIGUOUSNAME;
10451 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10453 for (i = 1; i < numNames; ++i) {
10454 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10455 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10458 return S_OK;
10461 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10462 UINT index, LPOLESTR name)
10464 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10465 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
10466 return E_NOTIMPL;
10469 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10470 TYPEDESC *tdescAlias)
10472 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10473 FIXME("%p %p - stub\n", This, tdescAlias);
10474 return E_NOTIMPL;
10477 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10478 UINT index, LPOLESTR dllName, LPOLESTR procName)
10480 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10481 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10482 return E_NOTIMPL;
10485 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10486 UINT index, LPOLESTR docString)
10488 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10489 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
10490 return E_NOTIMPL;
10493 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10494 UINT index, LPOLESTR docString)
10496 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10497 TLBVarDesc *var_desc = &This->vardescs[index];
10499 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10501 if(!docString)
10502 return E_INVALIDARG;
10504 if(index >= This->cVars)
10505 return TYPE_E_ELEMENTNOTFOUND;
10507 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10509 return S_OK;
10512 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10513 UINT index, DWORD helpContext)
10515 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10516 TLBFuncDesc *func_desc = &This->funcdescs[index];
10518 TRACE("%p %u %d\n", This, index, helpContext);
10520 if(index >= This->cFuncs)
10521 return TYPE_E_ELEMENTNOTFOUND;
10523 func_desc->helpcontext = helpContext;
10525 return S_OK;
10528 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10529 UINT index, DWORD helpContext)
10531 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10532 TLBVarDesc *var_desc = &This->vardescs[index];
10534 TRACE("%p %u %d\n", This, index, helpContext);
10536 if(index >= This->cVars)
10537 return TYPE_E_ELEMENTNOTFOUND;
10539 var_desc->HelpContext = helpContext;
10541 return S_OK;
10544 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10545 UINT index, BSTR bstrMops)
10547 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10548 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10549 return E_NOTIMPL;
10552 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10553 IDLDESC *idlDesc)
10555 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10557 TRACE("%p %p\n", This, idlDesc);
10559 if (!idlDesc)
10560 return E_INVALIDARG;
10562 This->idldescType.dwReserved = idlDesc->dwReserved;
10563 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10565 return S_OK;
10568 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10570 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10571 ITypeInfo *tinfo;
10572 TLBFuncDesc *func_desc;
10573 UINT user_vft = 0, i, depth = 0;
10574 HRESULT hres = S_OK;
10576 TRACE("%p\n", This);
10578 This->needs_layout = FALSE;
10580 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10581 if (FAILED(hres))
10582 return hres;
10584 if (This->typekind == TKIND_INTERFACE) {
10585 ITypeInfo *inh;
10586 TYPEATTR *attr;
10587 HREFTYPE inh_href;
10589 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10591 if (SUCCEEDED(hres)) {
10592 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10594 if (SUCCEEDED(hres)) {
10595 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10596 if (FAILED(hres)) {
10597 ITypeInfo_Release(inh);
10598 ITypeInfo_Release(tinfo);
10599 return hres;
10601 This->cbSizeVft = attr->cbSizeVft * 4 / sizeof(void*);
10602 ITypeInfo_ReleaseTypeAttr(inh, attr);
10605 ++depth;
10606 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10607 if(SUCCEEDED(hres)){
10608 ITypeInfo *next;
10609 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10610 if(SUCCEEDED(hres)){
10611 ITypeInfo_Release(inh);
10612 inh = next;
10615 }while(SUCCEEDED(hres));
10616 hres = S_OK;
10618 ITypeInfo_Release(inh);
10619 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10620 This->cbSizeVft = 0;
10621 hres = S_OK;
10622 } else {
10623 ITypeInfo_Release(tinfo);
10624 return hres;
10626 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10627 This->cbSizeVft = 0;
10628 hres = S_OK;
10629 } else {
10630 ITypeInfo_Release(tinfo);
10631 return hres;
10633 } else if (This->typekind == TKIND_DISPATCH)
10634 This->cbSizeVft = 7 * sizeof(void*);
10635 else
10636 This->cbSizeVft = 0;
10638 func_desc = This->funcdescs;
10639 i = 0;
10640 while (i < This->cFuncs) {
10641 if (!(func_desc->funcdesc.oVft & 0x1))
10642 func_desc->funcdesc.oVft = This->cbSizeVft;
10644 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10645 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10647 This->cbSizeVft += sizeof(void*);
10649 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10650 TLBFuncDesc *iter;
10651 UINT j = 0;
10652 BOOL reset = FALSE;
10654 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10656 iter = This->funcdescs;
10657 while (j < This->cFuncs) {
10658 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10659 if (!reset) {
10660 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10661 reset = TRUE;
10662 } else
10663 ++func_desc->funcdesc.memid;
10664 iter = This->funcdescs;
10665 j = 0;
10666 } else {
10667 ++iter;
10668 ++j;
10673 ++func_desc;
10674 ++i;
10677 if (user_vft > This->cbSizeVft)
10678 This->cbSizeVft = user_vft + sizeof(void*);
10680 ITypeInfo_Release(tinfo);
10681 return hres;
10684 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10685 UINT index)
10687 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10688 FIXME("%p %u - stub\n", This, index);
10689 return E_NOTIMPL;
10692 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10693 MEMBERID memid, INVOKEKIND invKind)
10695 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10696 FIXME("%p %x %d - stub\n", This, memid, invKind);
10697 return E_NOTIMPL;
10700 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
10701 UINT index)
10703 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10704 FIXME("%p %u - stub\n", This, index);
10705 return E_NOTIMPL;
10708 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
10709 MEMBERID memid)
10711 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10712 FIXME("%p %x - stub\n", This, memid);
10713 return E_NOTIMPL;
10716 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
10717 UINT index)
10719 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10720 FIXME("%p %u - stub\n", This, index);
10721 return E_NOTIMPL;
10724 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
10725 REFGUID guid, VARIANT *varVal)
10727 TLBGuid *tlbguid;
10729 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10731 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10733 if (!guid || !varVal)
10734 return E_INVALIDARG;
10736 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
10738 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10741 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
10742 UINT index, REFGUID guid, VARIANT *varVal)
10744 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10745 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10746 return E_NOTIMPL;
10749 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
10750 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
10752 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10753 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
10754 return E_NOTIMPL;
10757 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
10758 UINT index, REFGUID guid, VARIANT *varVal)
10760 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10761 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10762 return E_NOTIMPL;
10765 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
10766 UINT index, REFGUID guid, VARIANT *varVal)
10768 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10769 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10770 return E_NOTIMPL;
10773 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
10774 ULONG helpStringContext)
10776 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10778 TRACE("%p %u\n", This, helpStringContext);
10780 This->dwHelpStringContext = helpStringContext;
10782 return S_OK;
10785 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
10786 UINT index, ULONG helpStringContext)
10788 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10789 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10790 return E_NOTIMPL;
10793 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
10794 UINT index, ULONG helpStringContext)
10796 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10797 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10798 return E_NOTIMPL;
10801 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
10803 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10804 FIXME("%p - stub\n", This);
10805 return E_NOTIMPL;
10808 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
10809 LPOLESTR name)
10811 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10813 TRACE("%p %s\n", This, wine_dbgstr_w(name));
10815 if (!name)
10816 return E_INVALIDARG;
10818 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
10820 return S_OK;
10823 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
10824 ICreateTypeInfo2_fnQueryInterface,
10825 ICreateTypeInfo2_fnAddRef,
10826 ICreateTypeInfo2_fnRelease,
10827 ICreateTypeInfo2_fnSetGuid,
10828 ICreateTypeInfo2_fnSetTypeFlags,
10829 ICreateTypeInfo2_fnSetDocString,
10830 ICreateTypeInfo2_fnSetHelpContext,
10831 ICreateTypeInfo2_fnSetVersion,
10832 ICreateTypeInfo2_fnAddRefTypeInfo,
10833 ICreateTypeInfo2_fnAddFuncDesc,
10834 ICreateTypeInfo2_fnAddImplType,
10835 ICreateTypeInfo2_fnSetImplTypeFlags,
10836 ICreateTypeInfo2_fnSetAlignment,
10837 ICreateTypeInfo2_fnSetSchema,
10838 ICreateTypeInfo2_fnAddVarDesc,
10839 ICreateTypeInfo2_fnSetFuncAndParamNames,
10840 ICreateTypeInfo2_fnSetVarName,
10841 ICreateTypeInfo2_fnSetTypeDescAlias,
10842 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
10843 ICreateTypeInfo2_fnSetFuncDocString,
10844 ICreateTypeInfo2_fnSetVarDocString,
10845 ICreateTypeInfo2_fnSetFuncHelpContext,
10846 ICreateTypeInfo2_fnSetVarHelpContext,
10847 ICreateTypeInfo2_fnSetMops,
10848 ICreateTypeInfo2_fnSetTypeIdldesc,
10849 ICreateTypeInfo2_fnLayOut,
10850 ICreateTypeInfo2_fnDeleteFuncDesc,
10851 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
10852 ICreateTypeInfo2_fnDeleteVarDesc,
10853 ICreateTypeInfo2_fnDeleteVarDescByMemId,
10854 ICreateTypeInfo2_fnDeleteImplType,
10855 ICreateTypeInfo2_fnSetCustData,
10856 ICreateTypeInfo2_fnSetFuncCustData,
10857 ICreateTypeInfo2_fnSetParamCustData,
10858 ICreateTypeInfo2_fnSetVarCustData,
10859 ICreateTypeInfo2_fnSetImplTypeCustData,
10860 ICreateTypeInfo2_fnSetHelpStringContext,
10861 ICreateTypeInfo2_fnSetFuncHelpStringContext,
10862 ICreateTypeInfo2_fnSetVarHelpStringContext,
10863 ICreateTypeInfo2_fnInvalidate,
10864 ICreateTypeInfo2_fnSetName