oleaut32: Implement ICreateTypeLib::SaveAllChanges.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob295cac3ddc1a33a66700d21d7e59dfcb9e214364
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 void
2244 MSFT_DoFuncs(TLBContext* pcx,
2245 ITypeInfoImpl* pTI,
2246 int cFuncs,
2247 int cVars,
2248 int offset,
2249 TLBFuncDesc** pptfd)
2252 * member information is stored in a data structure at offset
2253 * indicated by the memoffset field of the typeinfo structure
2254 * There are several distinctive parts.
2255 * The first part starts with a field that holds the total length
2256 * of this (first) part excluding this field. Then follow the records,
2257 * for each member there is one record.
2259 * The first entry is always the length of the record (including this
2260 * length word).
2261 * The rest of the record depends on the type of the member. If there is
2262 * a field indicating the member type (function, variable, interface, etc)
2263 * I have not found it yet. At this time we depend on the information
2264 * in the type info and the usual order how things are stored.
2266 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2267 * for each member;
2269 * Third is an equal sized array with file offsets to the name entry
2270 * of each member.
2272 * The fourth and last (?) part is an array with offsets to the records
2273 * in the first part of this file segment.
2276 int infolen, nameoffset, reclength, i;
2277 int recoffset = offset + sizeof(INT);
2279 char *recbuf = heap_alloc(0xffff);
2280 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2281 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2283 TRACE_(typelib)("\n");
2285 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2287 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2288 ptfd = *pptfd;
2289 for ( i = 0; i < cFuncs ; i++ )
2291 int optional;
2293 /* name, eventually add to a hash table */
2294 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2295 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2297 /* nameoffset is sometimes -1 on the second half of a propget/propput
2298 * pair of functions */
2299 if ((nameoffset == -1) && (i > 0))
2300 ptfd->Name = ptfd_prev->Name;
2301 else
2302 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
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);
2314 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2315 ptfd->helpcontext = pFuncRec->HelpContext;
2317 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2318 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2320 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2322 if (pFuncRec->FKCCIC & 0x2000 )
2324 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2325 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2326 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2328 else
2329 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2331 else
2332 ptfd->Entry = (TLBString*)-1;
2334 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2335 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2337 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2338 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2340 /* fill the FuncDesc Structure */
2341 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2342 offset + infolen + ( i + 1) * sizeof(INT));
2344 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2345 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2346 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2347 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2348 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2349 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2350 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2352 MSFT_GetTdesc(pcx,
2353 pFuncRec->DataType,
2354 &ptfd->funcdesc.elemdescFunc.tdesc,
2355 pTI);
2356 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2358 /* do the parameters/arguments */
2359 if(pFuncRec->nrargs)
2361 int j = 0;
2362 MSFT_ParameterInfo paraminfo;
2364 ptfd->funcdesc.lprgelemdescParam =
2365 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2367 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2369 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2370 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2372 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2374 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2376 MSFT_GetTdesc(pcx,
2377 paraminfo.DataType,
2378 &elemdesc->tdesc,
2379 pTI);
2381 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2383 /* name */
2384 if (paraminfo.oName == -1)
2385 /* this occurs for [propput] or [propget] methods, so
2386 * we should just set the name of the parameter to the
2387 * name of the method. */
2388 ptfd->pParamDesc[j].Name = ptfd->Name;
2389 else
2390 ptfd->pParamDesc[j].Name =
2391 MSFT_ReadName( pcx, paraminfo.oName );
2392 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2394 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2396 /* default value */
2397 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2398 (pFuncRec->FKCCIC & 0x1000) )
2400 INT* pInt = (INT *)((char *)pFuncRec +
2401 reclength -
2402 (pFuncRec->nrargs * 4) * sizeof(INT) );
2404 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2406 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2407 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2409 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2410 pInt[j], pcx);
2412 else
2413 elemdesc->u.paramdesc.pparamdescex = NULL;
2415 /* custom info */
2416 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2417 j*sizeof(pFuncRec->oArgCustData[0])) &&
2418 pFuncRec->FKCCIC & 0x80 )
2420 MSFT_CustData(pcx,
2421 pFuncRec->oArgCustData[j],
2422 &ptfd->pParamDesc[j].custdata_list);
2425 /* SEEK value = jump to offset,
2426 * from there jump to the end of record,
2427 * go back by (j-1) arguments
2429 MSFT_ReadLEDWords( &paraminfo ,
2430 sizeof(MSFT_ParameterInfo), pcx,
2431 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2432 * sizeof(MSFT_ParameterInfo)));
2436 /* scode is not used: archaic win16 stuff FIXME: right? */
2437 ptfd->funcdesc.cScodes = 0 ;
2438 ptfd->funcdesc.lprgscode = NULL ;
2440 ptfd_prev = ptfd;
2441 ++ptfd;
2442 recoffset += reclength;
2444 heap_free(recbuf);
2447 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2448 int cVars, int offset, TLBVarDesc ** pptvd)
2450 int infolen, nameoffset, reclength;
2451 char recbuf[256];
2452 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2453 TLBVarDesc *ptvd;
2454 int i;
2455 int recoffset;
2457 TRACE_(typelib)("\n");
2459 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2460 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2461 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2462 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2463 recoffset += offset+sizeof(INT);
2464 for(i=0;i<cVars;i++, ++ptvd){
2465 /* name, eventually add to a hash table */
2466 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2467 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2468 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2469 /* read the variable information record */
2470 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2471 reclength &= 0xff;
2472 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2474 /* optional data */
2475 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2476 ptvd->HelpContext = pVarRec->HelpContext;
2478 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2479 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2481 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2482 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2484 /* fill the VarDesc Structure */
2485 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2486 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2487 ptvd->vardesc.varkind = pVarRec->VarKind;
2488 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2489 MSFT_GetTdesc(pcx, pVarRec->DataType,
2490 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2491 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2492 if(pVarRec->VarKind == VAR_CONST ){
2493 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2494 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2495 pVarRec->OffsValue, pcx);
2496 } else
2497 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2498 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2499 recoffset += reclength;
2503 /* fill in data for a hreftype (offset). When the referenced type is contained
2504 * in the typelib, it's just an (file) offset in the type info base dir.
2505 * If comes from import, it's an offset+1 in the ImpInfo table
2506 * */
2507 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2508 int offset)
2510 TLBRefType *ref;
2512 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2514 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2516 if(ref->reference == offset) return;
2519 ref = heap_alloc_zero(sizeof(TLBRefType));
2520 list_add_tail(&pTL->ref_list, &ref->entry);
2522 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2523 /* external typelib */
2524 MSFT_ImpInfo impinfo;
2525 TLBImpLib *pImpLib;
2527 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2529 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2530 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2532 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2533 if(pImpLib->offset==impinfo.oImpFile)
2534 break;
2536 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2537 ref->reference = offset & (~0x3);
2538 ref->pImpTLInfo = pImpLib;
2539 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2540 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2541 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2542 ref->index = TLB_REF_USE_GUID;
2543 } else
2544 ref->index = impinfo.oGuid;
2545 }else{
2546 ERR("Cannot find a reference\n");
2547 ref->reference = -1;
2548 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2550 }else{
2551 /* in this typelib */
2552 ref->index = MSFT_HREFTYPE_INDEX(offset);
2553 ref->reference = offset;
2554 ref->pImpTLInfo = TLB_REF_INTERNAL;
2558 /* process Implemented Interfaces of a com class */
2559 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2560 int offset)
2562 int i;
2563 MSFT_RefRecord refrec;
2564 TLBImplType *pImpl;
2566 TRACE_(typelib)("\n");
2568 pTI->impltypes = TLBImplType_Alloc(count);
2569 pImpl = pTI->impltypes;
2570 for(i=0;i<count;i++){
2571 if(offset<0) break; /* paranoia */
2572 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2573 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2574 pImpl->hRef = refrec.reftype;
2575 pImpl->implflags=refrec.flags;
2576 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2577 offset=refrec.onext;
2578 ++pImpl;
2582 * process a typeinfo record
2584 static ITypeInfoImpl * MSFT_DoTypeInfo(
2585 TLBContext *pcx,
2586 int count,
2587 ITypeLibImpl * pLibInfo)
2589 MSFT_TypeInfoBase tiBase;
2590 ITypeInfoImpl *ptiRet;
2592 TRACE_(typelib)("count=%u\n", count);
2594 ptiRet = ITypeInfoImpl_Constructor();
2595 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2596 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2598 /* this is where we are coming from */
2599 ptiRet->pTypeLib = pLibInfo;
2600 ptiRet->index=count;
2602 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2603 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2604 ptiRet->lpstrSchema=NULL; /* reserved */
2605 ptiRet->cbSizeInstance=tiBase.size;
2606 ptiRet->typekind=tiBase.typekind & 0xF;
2607 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2608 ptiRet->cVars=HIWORD(tiBase.cElement);
2609 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2610 ptiRet->wTypeFlags=tiBase.flags;
2611 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2612 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2613 ptiRet->cImplTypes=tiBase.cImplTypes;
2614 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2615 if(ptiRet->typekind == TKIND_ALIAS)
2616 MSFT_GetTdesc(pcx, tiBase.datatype1,
2617 &ptiRet->tdescAlias, ptiRet);
2619 /* FIXME: */
2620 /* IDLDESC idldescType; *//* never saw this one != zero */
2622 /* name, eventually add to a hash table */
2623 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2624 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2625 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2626 /* help info */
2627 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2628 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2629 ptiRet->dwHelpContext=tiBase.helpcontext;
2631 if (ptiRet->typekind == TKIND_MODULE)
2632 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2634 /* note: InfoType's Help file and HelpStringDll come from the containing
2635 * library. Further HelpString and Docstring appear to be the same thing :(
2637 /* functions */
2638 if(ptiRet->cFuncs >0 )
2639 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2640 ptiRet->cVars,
2641 tiBase.memoffset, &ptiRet->funcdescs);
2642 /* variables */
2643 if(ptiRet->cVars >0 )
2644 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2645 ptiRet->cVars,
2646 tiBase.memoffset, &ptiRet->vardescs);
2647 if(ptiRet->cImplTypes >0 ) {
2648 switch(ptiRet->typekind)
2650 case TKIND_COCLASS:
2651 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2652 tiBase.datatype1);
2653 break;
2654 case TKIND_DISPATCH:
2655 /* This is not -1 when the interface is a non-base dual interface or
2656 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2657 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2658 not this interface.
2661 if (tiBase.datatype1 != -1)
2663 ptiRet->impltypes = TLBImplType_Alloc(1);
2664 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2665 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2667 break;
2668 default:
2669 ptiRet->impltypes = TLBImplType_Alloc(1);
2670 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2671 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2672 break;
2675 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2677 TRACE_(typelib)("%s guid: %s kind:%s\n",
2678 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2679 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2680 typekind_desc[ptiRet->typekind]);
2681 if (TRACE_ON(typelib))
2682 dump_TypeInfo(ptiRet);
2684 return ptiRet;
2687 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2689 char *string;
2690 INT16 len_str, len_piece;
2691 int offs = 0, lengthInChars;
2693 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2694 while (1) {
2695 TLBString *tlbstr;
2697 if (offs >= pcx->pTblDir->pStringtab.length)
2698 return S_OK;
2700 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2701 len_piece = len_str + sizeof(INT16);
2702 if(len_piece % 4)
2703 len_piece = (len_piece + 4) & ~0x3;
2704 if(len_piece < 8)
2705 len_piece = 8;
2707 string = heap_alloc(len_piece + 1);
2708 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2709 string[len_str] = '\0';
2711 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2712 string, -1, NULL, 0);
2713 if (!lengthInChars) {
2714 heap_free(string);
2715 return E_UNEXPECTED;
2718 tlbstr = heap_alloc(sizeof(TLBString));
2720 tlbstr->offset = offs;
2721 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2722 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2724 heap_free(string);
2726 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2728 offs += len_piece;
2732 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2733 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2734 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2735 * tradeoff here.
2737 static struct list tlb_cache = LIST_INIT(tlb_cache);
2738 static CRITICAL_SECTION cache_section;
2739 static CRITICAL_SECTION_DEBUG cache_section_debug =
2741 0, 0, &cache_section,
2742 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2743 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2745 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2748 typedef struct TLB_PEFile
2750 IUnknown IUnknown_iface;
2751 LONG refs;
2752 HMODULE dll;
2753 HRSRC typelib_resource;
2754 HGLOBAL typelib_global;
2755 LPVOID typelib_base;
2756 } TLB_PEFile;
2758 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2760 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2763 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2765 if (IsEqualIID(riid, &IID_IUnknown))
2767 *ppv = iface;
2768 IUnknown_AddRef(iface);
2769 return S_OK;
2771 *ppv = NULL;
2772 return E_NOINTERFACE;
2775 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2777 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2778 return InterlockedIncrement(&This->refs);
2781 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2783 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2784 ULONG refs = InterlockedDecrement(&This->refs);
2785 if (!refs)
2787 if (This->typelib_global)
2788 FreeResource(This->typelib_global);
2789 if (This->dll)
2790 FreeLibrary(This->dll);
2791 heap_free(This);
2793 return refs;
2796 static const IUnknownVtbl TLB_PEFile_Vtable =
2798 TLB_PEFile_QueryInterface,
2799 TLB_PEFile_AddRef,
2800 TLB_PEFile_Release
2803 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2805 TLB_PEFile *This;
2806 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2808 This = heap_alloc(sizeof(TLB_PEFile));
2809 if (!This)
2810 return E_OUTOFMEMORY;
2812 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2813 This->refs = 1;
2814 This->dll = NULL;
2815 This->typelib_resource = NULL;
2816 This->typelib_global = NULL;
2817 This->typelib_base = NULL;
2819 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2820 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2822 if (This->dll)
2824 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2825 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2826 if (This->typelib_resource)
2828 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2829 if (This->typelib_global)
2831 This->typelib_base = LockResource(This->typelib_global);
2833 if (This->typelib_base)
2835 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2836 *ppBase = This->typelib_base;
2837 *ppFile = &This->IUnknown_iface;
2838 return S_OK;
2843 TRACE("No TYPELIB resource found\n");
2844 hr = E_FAIL;
2847 TLB_PEFile_Release(&This->IUnknown_iface);
2848 return hr;
2851 typedef struct TLB_NEFile
2853 IUnknown IUnknown_iface;
2854 LONG refs;
2855 LPVOID typelib_base;
2856 } TLB_NEFile;
2858 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2860 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2863 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2865 if (IsEqualIID(riid, &IID_IUnknown))
2867 *ppv = iface;
2868 IUnknown_AddRef(iface);
2869 return S_OK;
2871 *ppv = NULL;
2872 return E_NOINTERFACE;
2875 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2877 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2878 return InterlockedIncrement(&This->refs);
2881 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2883 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2884 ULONG refs = InterlockedDecrement(&This->refs);
2885 if (!refs)
2887 heap_free(This->typelib_base);
2888 heap_free(This);
2890 return refs;
2893 static const IUnknownVtbl TLB_NEFile_Vtable =
2895 TLB_NEFile_QueryInterface,
2896 TLB_NEFile_AddRef,
2897 TLB_NEFile_Release
2900 /***********************************************************************
2901 * read_xx_header [internal]
2903 static int read_xx_header( HFILE lzfd )
2905 IMAGE_DOS_HEADER mzh;
2906 char magic[3];
2908 LZSeek( lzfd, 0, SEEK_SET );
2909 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2910 return 0;
2911 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2912 return 0;
2914 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2915 if ( 2 != LZRead( lzfd, magic, 2 ) )
2916 return 0;
2918 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2920 if ( magic[0] == 'N' && magic[1] == 'E' )
2921 return IMAGE_OS2_SIGNATURE;
2922 if ( magic[0] == 'P' && magic[1] == 'E' )
2923 return IMAGE_NT_SIGNATURE;
2925 magic[2] = '\0';
2926 WARN("Can't handle %s files.\n", magic );
2927 return 0;
2931 /***********************************************************************
2932 * find_ne_resource [internal]
2934 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2935 DWORD *resLen, DWORD *resOff )
2937 IMAGE_OS2_HEADER nehd;
2938 NE_TYPEINFO *typeInfo;
2939 NE_NAMEINFO *nameInfo;
2940 DWORD nehdoffset;
2941 LPBYTE resTab;
2942 DWORD resTabSize;
2943 int count;
2945 /* Read in NE header */
2946 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2947 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2949 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2950 if ( !resTabSize )
2952 TRACE("No resources in NE dll\n" );
2953 return FALSE;
2956 /* Read in resource table */
2957 resTab = heap_alloc( resTabSize );
2958 if ( !resTab ) return FALSE;
2960 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2961 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2963 heap_free( resTab );
2964 return FALSE;
2967 /* Find resource */
2968 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2970 if (!IS_INTRESOURCE(typeid)) /* named type */
2972 BYTE len = strlen( typeid );
2973 while (typeInfo->type_id)
2975 if (!(typeInfo->type_id & 0x8000))
2977 BYTE *p = resTab + typeInfo->type_id;
2978 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2980 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2981 typeInfo->count * sizeof(NE_NAMEINFO));
2984 else /* numeric type id */
2986 WORD id = LOWORD(typeid) | 0x8000;
2987 while (typeInfo->type_id)
2989 if (typeInfo->type_id == id) goto found_type;
2990 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2991 typeInfo->count * sizeof(NE_NAMEINFO));
2994 TRACE("No typeid entry found for %p\n", typeid );
2995 heap_free( resTab );
2996 return FALSE;
2998 found_type:
2999 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3001 if (!IS_INTRESOURCE(resid)) /* named resource */
3003 BYTE len = strlen( resid );
3004 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3006 BYTE *p = resTab + nameInfo->id;
3007 if (nameInfo->id & 0x8000) continue;
3008 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3011 else /* numeric resource id */
3013 WORD id = LOWORD(resid) | 0x8000;
3014 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3015 if (nameInfo->id == id) goto found_name;
3017 TRACE("No resid entry found for %p\n", typeid );
3018 heap_free( resTab );
3019 return FALSE;
3021 found_name:
3022 /* Return resource data */
3023 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3024 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3026 heap_free( resTab );
3027 return TRUE;
3030 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3032 HFILE lzfd = -1;
3033 OFSTRUCT ofs;
3034 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3035 TLB_NEFile *This;
3037 This = heap_alloc(sizeof(TLB_NEFile));
3038 if (!This) return E_OUTOFMEMORY;
3040 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3041 This->refs = 1;
3042 This->typelib_base = NULL;
3044 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3045 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3047 DWORD reslen, offset;
3048 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3050 This->typelib_base = heap_alloc(reslen);
3051 if( !This->typelib_base )
3052 hr = E_OUTOFMEMORY;
3053 else
3055 LZSeek( lzfd, offset, SEEK_SET );
3056 reslen = LZRead( lzfd, This->typelib_base, reslen );
3057 LZClose( lzfd );
3058 *ppBase = This->typelib_base;
3059 *pdwTLBLength = reslen;
3060 *ppFile = &This->IUnknown_iface;
3061 return S_OK;
3066 if( lzfd >= 0) LZClose( lzfd );
3067 TLB_NEFile_Release(&This->IUnknown_iface);
3068 return hr;
3071 typedef struct TLB_Mapping
3073 IUnknown IUnknown_iface;
3074 LONG refs;
3075 HANDLE file;
3076 HANDLE mapping;
3077 LPVOID typelib_base;
3078 } TLB_Mapping;
3080 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3082 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3085 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3087 if (IsEqualIID(riid, &IID_IUnknown))
3089 *ppv = iface;
3090 IUnknown_AddRef(iface);
3091 return S_OK;
3093 *ppv = NULL;
3094 return E_NOINTERFACE;
3097 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3099 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3100 return InterlockedIncrement(&This->refs);
3103 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3105 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3106 ULONG refs = InterlockedDecrement(&This->refs);
3107 if (!refs)
3109 if (This->typelib_base)
3110 UnmapViewOfFile(This->typelib_base);
3111 if (This->mapping)
3112 CloseHandle(This->mapping);
3113 if (This->file != INVALID_HANDLE_VALUE)
3114 CloseHandle(This->file);
3115 heap_free(This);
3117 return refs;
3120 static const IUnknownVtbl TLB_Mapping_Vtable =
3122 TLB_Mapping_QueryInterface,
3123 TLB_Mapping_AddRef,
3124 TLB_Mapping_Release
3127 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3129 TLB_Mapping *This;
3131 This = heap_alloc(sizeof(TLB_Mapping));
3132 if (!This)
3133 return E_OUTOFMEMORY;
3135 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3136 This->refs = 1;
3137 This->file = INVALID_HANDLE_VALUE;
3138 This->mapping = NULL;
3139 This->typelib_base = NULL;
3141 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3142 if (INVALID_HANDLE_VALUE != This->file)
3144 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3145 if (This->mapping)
3147 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3148 if(This->typelib_base)
3150 /* retrieve file size */
3151 *pdwTLBLength = GetFileSize(This->file, NULL);
3152 *ppBase = This->typelib_base;
3153 *ppFile = &This->IUnknown_iface;
3154 return S_OK;
3159 IUnknown_Release(&This->IUnknown_iface);
3160 return TYPE_E_CANTLOADLIBRARY;
3163 /****************************************************************************
3164 * TLB_ReadTypeLib
3166 * find the type of the typelib file and map the typelib resource into
3167 * the memory
3170 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3171 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3173 ITypeLibImpl *entry;
3174 HRESULT ret;
3175 INT index = 1;
3176 LPWSTR index_str, file = (LPWSTR)pszFileName;
3177 LPVOID pBase = NULL;
3178 DWORD dwTLBLength = 0;
3179 IUnknown *pFile = NULL;
3181 *ppTypeLib = NULL;
3183 index_str = strrchrW(pszFileName, '\\');
3184 if(index_str && *++index_str != '\0')
3186 LPWSTR end_ptr;
3187 LONG idx = strtolW(index_str, &end_ptr, 10);
3188 if(*end_ptr == '\0')
3190 int str_len = index_str - pszFileName - 1;
3191 index = idx;
3192 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3193 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3194 file[str_len] = 0;
3198 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3200 if(strchrW(file, '\\'))
3202 lstrcpyW(pszPath, file);
3204 else
3206 int len = GetSystemDirectoryW(pszPath, cchPath);
3207 pszPath[len] = '\\';
3208 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3212 if(file != pszFileName) heap_free(file);
3214 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3216 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3217 EnterCriticalSection(&cache_section);
3218 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3220 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3222 TRACE("cache hit\n");
3223 *ppTypeLib = &entry->ITypeLib2_iface;
3224 ITypeLib2_AddRef(*ppTypeLib);
3225 LeaveCriticalSection(&cache_section);
3226 return S_OK;
3229 LeaveCriticalSection(&cache_section);
3231 /* now actually load and parse the typelib */
3233 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3234 if (ret == TYPE_E_CANTLOADLIBRARY)
3235 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3236 if (ret == TYPE_E_CANTLOADLIBRARY)
3237 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3238 if (SUCCEEDED(ret))
3240 if (dwTLBLength >= 4)
3242 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3243 if (dwSignature == MSFT_SIGNATURE)
3244 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3245 else if (dwSignature == SLTG_SIGNATURE)
3246 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3247 else
3249 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3250 ret = TYPE_E_CANTLOADLIBRARY;
3253 else
3254 ret = TYPE_E_CANTLOADLIBRARY;
3255 IUnknown_Release(pFile);
3258 if(*ppTypeLib) {
3259 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3261 TRACE("adding to cache\n");
3262 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3263 lstrcpyW(impl->path, pszPath);
3264 /* We should really canonicalise the path here. */
3265 impl->index = index;
3267 /* FIXME: check if it has added already in the meantime */
3268 EnterCriticalSection(&cache_section);
3269 list_add_head(&tlb_cache, &impl->entry);
3270 LeaveCriticalSection(&cache_section);
3271 ret = S_OK;
3273 else
3275 if(ret != E_FAIL)
3276 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3278 ret = TYPE_E_CANTLOADLIBRARY;
3282 return ret;
3285 /*================== ITypeLib(2) Methods ===================================*/
3287 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3289 ITypeLibImpl* pTypeLibImpl;
3291 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3292 if (!pTypeLibImpl) return NULL;
3294 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3295 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3296 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3297 pTypeLibImpl->ref = 1;
3299 list_init(&pTypeLibImpl->implib_list);
3300 list_init(&pTypeLibImpl->custdata_list);
3301 list_init(&pTypeLibImpl->name_list);
3302 list_init(&pTypeLibImpl->string_list);
3303 list_init(&pTypeLibImpl->guid_list);
3304 list_init(&pTypeLibImpl->ref_list);
3305 pTypeLibImpl->dispatch_href = -1;
3307 return pTypeLibImpl;
3310 /****************************************************************************
3311 * ITypeLib2_Constructor_MSFT
3313 * loading an MSFT typelib from an in-memory image
3315 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3317 TLBContext cx;
3318 LONG lPSegDir;
3319 MSFT_Header tlbHeader;
3320 MSFT_SegDir tlbSegDir;
3321 ITypeLibImpl * pTypeLibImpl;
3323 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3325 pTypeLibImpl = TypeLibImpl_Constructor();
3326 if (!pTypeLibImpl) return NULL;
3328 /* get pointer to beginning of typelib data */
3329 cx.pos = 0;
3330 cx.oStart=0;
3331 cx.mapping = pLib;
3332 cx.pLibInfo = pTypeLibImpl;
3333 cx.length = dwTLBLength;
3335 /* read header */
3336 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3337 TRACE_(typelib)("header:\n");
3338 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3339 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3340 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3341 return NULL;
3343 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3345 /* there is a small amount of information here until the next important
3346 * part:
3347 * the segment directory . Try to calculate the amount of data */
3348 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3350 /* now read the segment directory */
3351 TRACE("read segment directory (at %d)\n",lPSegDir);
3352 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3353 cx.pTblDir = &tlbSegDir;
3355 /* just check two entries */
3356 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3358 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3359 heap_free(pTypeLibImpl);
3360 return NULL;
3363 MSFT_ReadAllNames(&cx);
3364 MSFT_ReadAllStrings(&cx);
3365 MSFT_ReadAllGuids(&cx);
3367 /* now fill our internal data */
3368 /* TLIBATTR fields */
3369 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3371 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3372 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3373 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3374 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3376 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3377 pTypeLibImpl->lcid = tlbHeader.lcid;
3379 /* name, eventually add to a hash table */
3380 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3382 /* help info */
3383 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3384 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3386 if( tlbHeader.varflags & HELPDLLFLAG)
3388 int offset;
3389 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3390 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3393 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3395 /* custom data */
3396 if(tlbHeader.CustomDataOffset >= 0)
3398 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3401 /* fill in type descriptions */
3402 if(tlbSegDir.pTypdescTab.length > 0)
3404 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3405 INT16 td[4];
3406 pTypeLibImpl->ctTypeDesc = cTD;
3407 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3408 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3409 for(i=0; i<cTD; )
3411 /* FIXME: add several sanity checks here */
3412 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3413 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3415 /* FIXME: check safearray */
3416 if(td[3] < 0)
3417 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3418 else
3419 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3421 else if(td[0] == VT_CARRAY)
3423 /* array descr table here */
3424 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3426 else if(td[0] == VT_USERDEFINED)
3428 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3430 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3433 /* second time around to fill the array subscript info */
3434 for(i=0;i<cTD;i++)
3436 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3437 if(tlbSegDir.pArrayDescriptions.offset>0)
3439 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3440 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3442 if(td[1]<0)
3443 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3444 else
3445 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3447 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3449 for(j = 0; j<td[2]; j++)
3451 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3452 sizeof(INT), &cx, DO_NOT_SEEK);
3453 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3454 sizeof(INT), &cx, DO_NOT_SEEK);
3457 else
3459 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3460 ERR("didn't find array description data\n");
3465 /* imported type libs */
3466 if(tlbSegDir.pImpFiles.offset>0)
3468 TLBImpLib *pImpLib;
3469 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3470 UINT16 size;
3472 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3474 char *name;
3476 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3477 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3478 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3480 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3481 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3482 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3483 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3485 size >>= 2;
3486 name = heap_alloc_zero(size+1);
3487 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3488 pImpLib->name = TLB_MultiByteToBSTR(name);
3489 heap_free(name);
3491 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3492 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3494 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3498 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3499 if(pTypeLibImpl->dispatch_href != -1)
3500 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3502 /* type infos */
3503 if(tlbHeader.nrtypeinfos >= 0 )
3505 ITypeInfoImpl **ppTI;
3506 int i;
3508 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3510 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3512 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3514 ++ppTI;
3515 (pTypeLibImpl->TypeInfoCount)++;
3519 TRACE("(%p)\n", pTypeLibImpl);
3520 return &pTypeLibImpl->ITypeLib2_iface;
3524 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3526 char b[3];
3527 int i;
3528 short s;
3530 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3531 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3532 return FALSE;
3535 guid->Data4[0] = s >> 8;
3536 guid->Data4[1] = s & 0xff;
3538 b[2] = '\0';
3539 for(i = 0; i < 6; i++) {
3540 memcpy(b, str + 24 + 2 * i, 2);
3541 guid->Data4[i + 2] = strtol(b, NULL, 16);
3543 return TRUE;
3546 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3548 WORD bytelen;
3549 DWORD len;
3550 BSTR tmp_str;
3552 *pStr = NULL;
3553 bytelen = *(const WORD*)ptr;
3554 if(bytelen == 0xffff) return 2;
3556 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3557 tmp_str = SysAllocStringLen(NULL, len);
3558 if (*tmp_str) {
3559 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3560 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3561 SysFreeString(tmp_str);
3563 return bytelen + 2;
3566 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3568 WORD bytelen;
3570 *str = NULL;
3571 bytelen = *(const WORD*)ptr;
3572 if(bytelen == 0xffff) return 2;
3573 *str = heap_alloc(bytelen + 1);
3574 memcpy(*str, ptr + 2, bytelen);
3575 (*str)[bytelen] = '\0';
3576 return bytelen + 2;
3579 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3581 BSTR tmp_str;
3582 TLBString *tlbstr;
3584 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3585 if (tlbstr->offset == offset)
3586 return tlbstr;
3589 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3590 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3591 SysFreeString(tmp_str);
3593 return tlbstr;
3596 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3598 char *ptr = pLibBlk;
3599 WORD w;
3601 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3602 FIXME("libblk magic = %04x\n", w);
3603 return 0;
3606 ptr += 6;
3607 if((w = *(WORD*)ptr) != 0xffff) {
3608 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3609 ptr += w;
3611 ptr += 2;
3613 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3615 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3617 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3618 ptr += 4;
3620 pTypeLibImpl->syskind = *(WORD*)ptr;
3621 ptr += 2;
3623 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3624 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3625 else
3626 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3627 ptr += 2;
3629 ptr += 4; /* skip res12 */
3631 pTypeLibImpl->libflags = *(WORD*)ptr;
3632 ptr += 2;
3634 pTypeLibImpl->ver_major = *(WORD*)ptr;
3635 ptr += 2;
3637 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3638 ptr += 2;
3640 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr);
3641 ptr += sizeof(GUID);
3643 return ptr - (char*)pLibBlk;
3646 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3647 typedef struct
3649 unsigned int num;
3650 HREFTYPE refs[1];
3651 } sltg_ref_lookup_t;
3653 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3654 HREFTYPE *typelib_ref)
3656 if(table && typeinfo_ref < table->num)
3658 *typelib_ref = table->refs[typeinfo_ref];
3659 return S_OK;
3662 ERR_(typelib)("Unable to find reference\n");
3663 *typelib_ref = -1;
3664 return E_FAIL;
3667 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3669 BOOL done = FALSE;
3671 while(!done) {
3672 if((*pType & 0xe00) == 0xe00) {
3673 pTD->vt = VT_PTR;
3674 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3675 pTD = pTD->u.lptdesc;
3677 switch(*pType & 0x3f) {
3678 case VT_PTR:
3679 pTD->vt = VT_PTR;
3680 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3681 pTD = pTD->u.lptdesc;
3682 break;
3684 case VT_USERDEFINED:
3685 pTD->vt = VT_USERDEFINED;
3686 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3687 done = TRUE;
3688 break;
3690 case VT_CARRAY:
3692 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3693 array */
3695 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3697 pTD->vt = VT_CARRAY;
3698 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3699 pTD->u.lpadesc->cDims = pSA->cDims;
3700 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3701 pSA->cDims * sizeof(SAFEARRAYBOUND));
3703 pTD = &pTD->u.lpadesc->tdescElem;
3704 break;
3707 case VT_SAFEARRAY:
3709 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3710 useful? */
3712 pType++;
3713 pTD->vt = VT_SAFEARRAY;
3714 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3715 pTD = pTD->u.lptdesc;
3716 break;
3718 default:
3719 pTD->vt = *pType & 0x3f;
3720 done = TRUE;
3721 break;
3723 pType++;
3725 return pType;
3728 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3729 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3731 /* Handle [in/out] first */
3732 if((*pType & 0xc000) == 0xc000)
3733 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3734 else if(*pType & 0x8000)
3735 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3736 else if(*pType & 0x4000)
3737 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3738 else
3739 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3741 if(*pType & 0x2000)
3742 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3744 if(*pType & 0x80)
3745 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3747 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3751 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3752 char *pNameTable)
3754 unsigned int ref;
3755 char *name;
3756 TLBRefType *ref_type;
3757 sltg_ref_lookup_t *table;
3758 HREFTYPE typelib_ref;
3760 if(pRef->magic != SLTG_REF_MAGIC) {
3761 FIXME("Ref magic = %x\n", pRef->magic);
3762 return NULL;
3764 name = ( (char*)pRef->names + pRef->number);
3766 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3767 table->num = pRef->number >> 3;
3769 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3771 /* We don't want the first href to be 0 */
3772 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3774 for(ref = 0; ref < pRef->number >> 3; ref++) {
3775 char *refname;
3776 unsigned int lib_offs, type_num;
3778 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3780 name += SLTG_ReadStringA(name, &refname);
3781 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3782 FIXME_(typelib)("Can't sscanf ref\n");
3783 if(lib_offs != 0xffff) {
3784 TLBImpLib *import;
3786 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3787 if(import->offset == lib_offs)
3788 break;
3790 if(&import->entry == &pTL->implib_list) {
3791 char fname[MAX_PATH+1];
3792 int len;
3793 GUID tmpguid;
3795 import = heap_alloc_zero(sizeof(*import));
3796 import->offset = lib_offs;
3797 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3798 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid);
3799 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3800 &import->wVersionMajor,
3801 &import->wVersionMinor,
3802 &import->lcid, fname) != 4) {
3803 FIXME_(typelib)("can't sscanf ref %s\n",
3804 pNameTable + lib_offs + 40);
3806 len = strlen(fname);
3807 if(fname[len-1] != '#')
3808 FIXME("fname = %s\n", fname);
3809 fname[len-1] = '\0';
3810 import->name = TLB_MultiByteToBSTR(fname);
3811 list_add_tail(&pTL->implib_list, &import->entry);
3813 ref_type->pImpTLInfo = import;
3815 /* Store a reference to IDispatch */
3816 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3817 pTL->dispatch_href = typelib_ref;
3819 } else { /* internal ref */
3820 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3822 ref_type->reference = typelib_ref;
3823 ref_type->index = type_num;
3825 heap_free(refname);
3826 list_add_tail(&pTL->ref_list, &ref_type->entry);
3828 table->refs[ref] = typelib_ref;
3829 typelib_ref += 4;
3831 if((BYTE)*name != SLTG_REF_MAGIC)
3832 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3833 dump_TLBRefType(pTL);
3834 return table;
3837 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3838 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3840 SLTG_ImplInfo *info;
3841 TLBImplType *pImplType;
3842 /* I don't really get this structure, usually it's 0x16 bytes
3843 long, but iuser.tlb contains some that are 0x18 bytes long.
3844 That's ok because we can use the next ptr to jump to the next
3845 one. But how do we know the length of the last one? The WORD
3846 at offs 0x8 might be the clue. For now I'm just assuming that
3847 the last one is the regular 0x16 bytes. */
3849 info = (SLTG_ImplInfo*)pBlk;
3850 while(1){
3851 pTI->cImplTypes++;
3852 if(info->next == 0xffff)
3853 break;
3854 info = (SLTG_ImplInfo*)(pBlk + info->next);
3857 info = (SLTG_ImplInfo*)pBlk;
3858 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
3859 pImplType = pTI->impltypes;
3860 while(1) {
3861 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3862 pImplType->implflags = info->impltypeflags;
3863 ++pImplType;
3865 if(info->next == 0xffff)
3866 break;
3867 if(OneOnly)
3868 FIXME_(typelib)("Interface inheriting more than one interface\n");
3869 info = (SLTG_ImplInfo*)(pBlk + info->next);
3871 info++; /* see comment at top of function */
3872 return (char*)info;
3875 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3876 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3878 TLBVarDesc *pVarDesc;
3879 const TLBString *prevName = NULL;
3880 SLTG_Variable *pItem;
3881 unsigned short i;
3882 WORD *pType;
3884 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
3886 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3887 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3889 pVarDesc->vardesc.memid = pItem->memid;
3891 if (pItem->magic != SLTG_VAR_MAGIC &&
3892 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3893 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3894 return;
3897 if (pItem->name == 0xfffe)
3898 pVarDesc->Name = prevName;
3899 else
3900 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
3902 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
3903 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3904 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3906 if(pItem->flags & 0x02)
3907 pType = &pItem->type;
3908 else
3909 pType = (WORD*)(pBlk + pItem->type);
3911 if (pItem->flags & ~0xda)
3912 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3914 SLTG_DoElem(pType, pBlk,
3915 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3917 if (TRACE_ON(typelib)) {
3918 char buf[300];
3919 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3920 TRACE_(typelib)("elemdescVar: %s\n", buf);
3923 if (pItem->flags & 0x40) {
3924 TRACE_(typelib)("VAR_DISPATCH\n");
3925 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3927 else if (pItem->flags & 0x10) {
3928 TRACE_(typelib)("VAR_CONST\n");
3929 pVarDesc->vardesc.varkind = VAR_CONST;
3930 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3931 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3932 if (pItem->flags & 0x08)
3933 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3934 else {
3935 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3937 case VT_LPSTR:
3938 case VT_LPWSTR:
3939 case VT_BSTR:
3941 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3942 BSTR str;
3943 TRACE_(typelib)("len = %u\n", len);
3944 if (len == 0xffff) {
3945 str = NULL;
3946 } else {
3947 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3948 str = SysAllocStringLen(NULL, alloc_len);
3949 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3951 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3952 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3953 break;
3955 case VT_I2:
3956 case VT_UI2:
3957 case VT_I4:
3958 case VT_UI4:
3959 case VT_INT:
3960 case VT_UINT:
3961 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3962 *(INT*)(pBlk + pItem->byte_offs);
3963 break;
3964 default:
3965 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3969 else {
3970 TRACE_(typelib)("VAR_PERINSTANCE\n");
3971 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3972 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3975 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3976 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3978 if (pItem->flags & 0x80)
3979 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3981 prevName = pVarDesc->Name;
3983 pTI->cVars = cVars;
3986 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3987 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3989 SLTG_Function *pFunc;
3990 unsigned short i;
3991 TLBFuncDesc *pFuncDesc;
3993 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
3995 pFuncDesc = pTI->funcdescs;
3996 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3997 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3999 int param;
4000 WORD *pType, *pArg;
4002 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4003 case SLTG_FUNCTION_MAGIC:
4004 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4005 break;
4006 case SLTG_DISPATCH_FUNCTION_MAGIC:
4007 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4008 break;
4009 case SLTG_STATIC_FUNCTION_MAGIC:
4010 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4011 break;
4012 default:
4013 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4014 continue;
4016 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4018 pFuncDesc->funcdesc.memid = pFunc->dispid;
4019 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4020 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4021 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4022 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4023 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4025 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4026 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4028 if(pFunc->retnextopt & 0x80)
4029 pType = &pFunc->rettype;
4030 else
4031 pType = (WORD*)(pBlk + pFunc->rettype);
4033 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4035 pFuncDesc->funcdesc.lprgelemdescParam =
4036 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4037 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4039 pArg = (WORD*)(pBlk + pFunc->arg_off);
4041 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4042 char *paramName = pNameTable + *pArg;
4043 BOOL HaveOffs;
4044 /* If arg type follows then paramName points to the 2nd
4045 letter of the name, else the next WORD is an offset to
4046 the arg type and paramName points to the first letter.
4047 So let's take one char off paramName and see if we're
4048 pointing at an alpha-numeric char. However if *pArg is
4049 0xffff or 0xfffe then the param has no name, the former
4050 meaning that the next WORD is the type, the latter
4051 meaning that the next WORD is an offset to the type. */
4053 HaveOffs = FALSE;
4054 if(*pArg == 0xffff)
4055 paramName = NULL;
4056 else if(*pArg == 0xfffe) {
4057 paramName = NULL;
4058 HaveOffs = TRUE;
4060 else if(paramName[-1] && !isalnum(paramName[-1]))
4061 HaveOffs = TRUE;
4063 pArg++;
4065 if(HaveOffs) { /* the next word is an offset to type */
4066 pType = (WORD*)(pBlk + *pArg);
4067 SLTG_DoElem(pType, pBlk,
4068 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4069 pArg++;
4070 } else {
4071 if(paramName)
4072 paramName--;
4073 pArg = SLTG_DoElem(pArg, pBlk,
4074 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4077 /* Are we an optional param ? */
4078 if(pFuncDesc->funcdesc.cParams - param <=
4079 pFuncDesc->funcdesc.cParamsOpt)
4080 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4082 if(paramName) {
4083 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4084 paramName - pNameTable, pTI->pTypeLib);
4085 } else {
4086 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4090 pTI->cFuncs = cFuncs;
4093 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4094 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4095 SLTG_TypeInfoTail *pTITail)
4097 char *pFirstItem;
4098 sltg_ref_lookup_t *ref_lookup = NULL;
4100 if(pTIHeader->href_table != 0xffffffff) {
4101 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4102 pNameTable);
4105 pFirstItem = pBlk;
4107 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4108 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4110 heap_free(ref_lookup);
4114 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4115 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4116 const SLTG_TypeInfoTail *pTITail)
4118 char *pFirstItem;
4119 sltg_ref_lookup_t *ref_lookup = NULL;
4121 if(pTIHeader->href_table != 0xffffffff) {
4122 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4123 pNameTable);
4126 pFirstItem = pBlk;
4128 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4129 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4132 if (pTITail->funcs_off != 0xffff)
4133 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4135 heap_free(ref_lookup);
4137 if (TRACE_ON(typelib))
4138 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4141 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4142 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4143 const SLTG_TypeInfoTail *pTITail)
4145 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4148 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4149 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4150 const SLTG_TypeInfoTail *pTITail)
4152 WORD *pType;
4153 sltg_ref_lookup_t *ref_lookup = NULL;
4155 if (pTITail->simple_alias) {
4156 /* if simple alias, no more processing required */
4157 pTI->tdescAlias.vt = pTITail->tdescalias_vt;
4158 return;
4161 if(pTIHeader->href_table != 0xffffffff) {
4162 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4163 pNameTable);
4166 /* otherwise it is an offset to a type */
4167 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4169 SLTG_DoType(pType, pBlk, &pTI->tdescAlias, ref_lookup);
4171 heap_free(ref_lookup);
4174 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4175 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4176 const SLTG_TypeInfoTail *pTITail)
4178 sltg_ref_lookup_t *ref_lookup = NULL;
4179 if (pTIHeader->href_table != 0xffffffff)
4180 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4181 pNameTable);
4183 if (pTITail->vars_off != 0xffff)
4184 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4186 if (pTITail->funcs_off != 0xffff)
4187 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4189 if (pTITail->impls_off != 0xffff)
4190 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4192 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4193 * of dispinterface functions including the IDispatch ones, so
4194 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4195 pTI->cbSizeVft = pTI->cFuncs * sizeof(void *);
4197 heap_free(ref_lookup);
4198 if (TRACE_ON(typelib))
4199 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4202 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4203 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4204 const SLTG_TypeInfoTail *pTITail)
4206 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4209 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4210 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4211 const SLTG_TypeInfoTail *pTITail)
4213 sltg_ref_lookup_t *ref_lookup = NULL;
4214 if (pTIHeader->href_table != 0xffffffff)
4215 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4216 pNameTable);
4218 if (pTITail->vars_off != 0xffff)
4219 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4221 if (pTITail->funcs_off != 0xffff)
4222 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4223 heap_free(ref_lookup);
4224 if (TRACE_ON(typelib))
4225 dump_TypeInfo(pTI);
4228 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4229 manageable copy of it into this */
4230 typedef struct {
4231 WORD small_no;
4232 char *index_name;
4233 char *other_name;
4234 WORD res1a;
4235 WORD name_offs;
4236 WORD more_bytes;
4237 char *extra;
4238 WORD res20;
4239 DWORD helpcontext;
4240 WORD res26;
4241 GUID uuid;
4242 } SLTG_InternalOtherTypeInfo;
4244 /****************************************************************************
4245 * ITypeLib2_Constructor_SLTG
4247 * loading a SLTG typelib from an in-memory image
4249 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4251 ITypeLibImpl *pTypeLibImpl;
4252 SLTG_Header *pHeader;
4253 SLTG_BlkEntry *pBlkEntry;
4254 SLTG_Magic *pMagic;
4255 SLTG_Index *pIndex;
4256 SLTG_Pad9 *pPad9;
4257 LPVOID pBlk, pFirstBlk;
4258 SLTG_LibBlk *pLibBlk;
4259 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4260 char *pAfterOTIBlks = NULL;
4261 char *pNameTable, *ptr;
4262 int i;
4263 DWORD len, order;
4264 ITypeInfoImpl **ppTypeInfoImpl;
4266 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4269 pTypeLibImpl = TypeLibImpl_Constructor();
4270 if (!pTypeLibImpl) return NULL;
4272 pHeader = pLib;
4274 TRACE_(typelib)("header:\n");
4275 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4276 pHeader->nrOfFileBlks );
4277 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4278 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4279 pHeader->SLTG_magic);
4280 return NULL;
4283 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4284 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4286 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4287 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4289 /* Next we have a magic block */
4290 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4292 /* Let's see if we're still in sync */
4293 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4294 sizeof(SLTG_COMPOBJ_MAGIC))) {
4295 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4296 return NULL;
4298 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4299 sizeof(SLTG_DIR_MAGIC))) {
4300 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4301 return NULL;
4304 pIndex = (SLTG_Index*)(pMagic+1);
4306 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4308 pFirstBlk = pPad9 + 1;
4310 /* We'll set up a ptr to the main library block, which is the last one. */
4312 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4313 pBlkEntry[order].next != 0;
4314 order = pBlkEntry[order].next - 1, i++) {
4315 pBlk = (char*)pBlk + pBlkEntry[order].len;
4317 pLibBlk = pBlk;
4319 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4321 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4322 interspersed */
4324 len += 0x40;
4326 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4328 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4331 ptr = (char*)pLibBlk + len;
4333 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4334 WORD w, extra;
4335 len = 0;
4337 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4339 w = *(WORD*)(ptr + 2);
4340 if(w != 0xffff) {
4341 len += w;
4342 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4343 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4344 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4346 w = *(WORD*)(ptr + 4 + len);
4347 if(w != 0xffff) {
4348 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4349 len += w;
4350 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4351 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4352 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4354 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4355 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4356 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4357 if(extra) {
4358 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4359 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4360 len += extra;
4362 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4363 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4364 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4365 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4366 len += sizeof(SLTG_OtherTypeInfo);
4367 ptr += len;
4370 pAfterOTIBlks = ptr;
4372 /* Skip this WORD and get the next DWORD */
4373 len = *(DWORD*)(pAfterOTIBlks + 2);
4375 /* Now add this to pLibBLk look at what we're pointing at and
4376 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4377 dust and we should be pointing at the beginning of the name
4378 table */
4380 pNameTable = (char*)pLibBlk + len;
4382 switch(*(WORD*)pNameTable) {
4383 case 0xffff:
4384 break;
4385 case 0x0200:
4386 pNameTable += 0x20;
4387 break;
4388 default:
4389 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4390 break;
4393 pNameTable += 0x216;
4395 pNameTable += 2;
4397 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4399 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4402 /* Hopefully we now have enough ptrs set up to actually read in
4403 some TypeInfos. It's not clear which order to do them in, so
4404 I'll just follow the links along the BlkEntry chain and read
4405 them in the order in which they are in the file */
4407 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4408 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4410 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4411 pBlkEntry[order].next != 0;
4412 order = pBlkEntry[order].next - 1, i++) {
4414 SLTG_TypeInfoHeader *pTIHeader;
4415 SLTG_TypeInfoTail *pTITail;
4416 SLTG_MemberHeader *pMemHeader;
4418 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4419 FIXME_(typelib)("Index strings don't match\n");
4420 heap_free(pOtherTypeInfoBlks);
4421 return NULL;
4424 pTIHeader = pBlk;
4425 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4426 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4427 heap_free(pOtherTypeInfoBlks);
4428 return NULL;
4430 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4431 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4432 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4434 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4435 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4436 (*ppTypeInfoImpl)->index = i;
4437 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4438 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4439 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid);
4440 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4441 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4442 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4443 (*ppTypeInfoImpl)->wTypeFlags =
4444 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4446 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4447 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4449 if((pTIHeader->typeflags1 & 7) != 2)
4450 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4451 if(pTIHeader->typeflags3 != 2)
4452 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4454 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4455 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4456 typekind_desc[pTIHeader->typekind],
4457 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4458 (*ppTypeInfoImpl)->wTypeFlags);
4460 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4462 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4464 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4465 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4466 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4468 switch(pTIHeader->typekind) {
4469 case TKIND_ENUM:
4470 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4471 pTIHeader, pTITail);
4472 break;
4474 case TKIND_RECORD:
4475 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4476 pTIHeader, pTITail);
4477 break;
4479 case TKIND_INTERFACE:
4480 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4481 pTIHeader, pTITail);
4482 break;
4484 case TKIND_COCLASS:
4485 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4486 pTIHeader, pTITail);
4487 break;
4489 case TKIND_ALIAS:
4490 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4491 pTIHeader, pTITail);
4492 break;
4494 case TKIND_DISPATCH:
4495 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4496 pTIHeader, pTITail);
4497 break;
4499 case TKIND_MODULE:
4500 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4501 pTIHeader, pTITail);
4502 break;
4504 default:
4505 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4506 break;
4510 /* could get cFuncs, cVars and cImplTypes from here
4511 but we've already set those */
4512 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4513 X(06);
4514 X(16);
4515 X(18);
4516 X(1a);
4517 X(1e);
4518 X(24);
4519 X(26);
4520 X(2a);
4521 X(2c);
4522 X(2e);
4523 X(30);
4524 X(32);
4525 X(34);
4526 #undef X
4527 ++ppTypeInfoImpl;
4528 pBlk = (char*)pBlk + pBlkEntry[order].len;
4531 if(i != pTypeLibImpl->TypeInfoCount) {
4532 FIXME("Somehow processed %d TypeInfos\n", i);
4533 heap_free(pOtherTypeInfoBlks);
4534 return NULL;
4537 heap_free(pOtherTypeInfoBlks);
4538 return &pTypeLibImpl->ITypeLib2_iface;
4541 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4543 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4545 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4547 if(IsEqualIID(riid, &IID_IUnknown) ||
4548 IsEqualIID(riid,&IID_ITypeLib)||
4549 IsEqualIID(riid,&IID_ITypeLib2))
4551 *ppv = &This->ITypeLib2_iface;
4553 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4554 IsEqualIID(riid, &IID_ICreateTypeLib2))
4556 *ppv = &This->ICreateTypeLib2_iface;
4558 else
4560 *ppv = NULL;
4561 TRACE("-- Interface: E_NOINTERFACE\n");
4562 return E_NOINTERFACE;
4565 IUnknown_AddRef((IUnknown*)*ppv);
4566 return S_OK;
4569 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4571 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4572 ULONG ref = InterlockedIncrement(&This->ref);
4574 TRACE("(%p) ref=%u\n", This, ref);
4576 return ref;
4579 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4581 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4582 ULONG ref = InterlockedDecrement(&This->ref);
4584 TRACE("(%p) ref=%u\n",This, ref);
4586 if (!ref)
4588 TLBImpLib *pImpLib, *pImpLibNext;
4589 TLBRefType *ref_type;
4590 TLBString *tlbstr, *tlbstr_next;
4591 void *cursor2;
4592 int i;
4594 /* remove cache entry */
4595 if(This->path)
4597 TRACE("removing from cache list\n");
4598 EnterCriticalSection(&cache_section);
4599 if(This->entry.next)
4600 list_remove(&This->entry);
4601 LeaveCriticalSection(&cache_section);
4602 heap_free(This->path);
4604 TRACE(" destroying ITypeLib(%p)\n",This);
4606 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4607 list_remove(&tlbstr->entry);
4608 heap_free(tlbstr);
4611 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4612 list_remove(&tlbstr->entry);
4613 heap_free(tlbstr);
4616 TLB_FreeCustData(&This->custdata_list);
4618 for (i = 0; i < This->ctTypeDesc; i++)
4619 if (This->pTypeDesc[i].vt == VT_CARRAY)
4620 heap_free(This->pTypeDesc[i].u.lpadesc);
4622 heap_free(This->pTypeDesc);
4624 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4626 if (pImpLib->pImpTypeLib)
4627 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4628 SysFreeString(pImpLib->name);
4630 list_remove(&pImpLib->entry);
4631 heap_free(pImpLib);
4634 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4636 list_remove(&ref_type->entry);
4637 heap_free(ref_type);
4640 for (i = 0; i < This->TypeInfoCount; ++i)
4641 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4642 heap_free(This->typeinfos);
4643 heap_free(This);
4644 return 0;
4647 return ref;
4650 /* ITypeLib::GetTypeInfoCount
4652 * Returns the number of type descriptions in the type library
4654 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4656 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4657 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4658 return This->TypeInfoCount;
4661 /* ITypeLib::GetTypeInfo
4663 * retrieves the specified type description in the library.
4665 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4666 ITypeLib2 *iface,
4667 UINT index,
4668 ITypeInfo **ppTInfo)
4670 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4672 TRACE("%p %u %p\n", This, index, ppTInfo);
4674 if(!ppTInfo)
4675 return E_INVALIDARG;
4677 if(index >= This->TypeInfoCount)
4678 return TYPE_E_ELEMENTNOTFOUND;
4680 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4681 ITypeInfo_AddRef(*ppTInfo);
4683 return S_OK;
4687 /* ITypeLibs::GetTypeInfoType
4689 * Retrieves the type of a type description.
4691 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4692 ITypeLib2 *iface,
4693 UINT index,
4694 TYPEKIND *pTKind)
4696 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4698 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4700 if(!pTKind)
4701 return E_INVALIDARG;
4703 if(index >= This->TypeInfoCount)
4704 return TYPE_E_ELEMENTNOTFOUND;
4706 *pTKind = This->typeinfos[index]->typekind;
4708 return S_OK;
4711 /* ITypeLib::GetTypeInfoOfGuid
4713 * Retrieves the type description that corresponds to the specified GUID.
4716 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4717 ITypeLib2 *iface,
4718 REFGUID guid,
4719 ITypeInfo **ppTInfo)
4721 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4722 int i;
4724 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4726 for(i = 0; i < This->TypeInfoCount; ++i){
4727 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4728 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4729 ITypeInfo_AddRef(*ppTInfo);
4730 return S_OK;
4734 return TYPE_E_ELEMENTNOTFOUND;
4737 /* ITypeLib::GetLibAttr
4739 * Retrieves the structure that contains the library's attributes.
4742 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4743 ITypeLib2 *iface,
4744 LPTLIBATTR *attr)
4746 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4748 TRACE("(%p, %p)\n", This, attr);
4750 if (!attr) return E_INVALIDARG;
4752 *attr = heap_alloc(sizeof(**attr));
4753 if (!*attr) return E_OUTOFMEMORY;
4755 (*attr)->guid = *TLB_get_guid_null(This->guid);
4756 (*attr)->lcid = This->set_lcid;
4757 (*attr)->syskind = This->syskind;
4758 (*attr)->wMajorVerNum = This->ver_major;
4759 (*attr)->wMinorVerNum = This->ver_minor;
4760 (*attr)->wLibFlags = This->libflags;
4762 return S_OK;
4765 /* ITypeLib::GetTypeComp
4767 * Enables a client compiler to bind to a library's types, variables,
4768 * constants, and global functions.
4771 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4772 ITypeLib2 *iface,
4773 ITypeComp **ppTComp)
4775 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4777 TRACE("(%p)->(%p)\n",This,ppTComp);
4778 *ppTComp = &This->ITypeComp_iface;
4779 ITypeComp_AddRef(*ppTComp);
4781 return S_OK;
4784 /* ITypeLib::GetDocumentation
4786 * Retrieves the library's documentation string, the complete Help file name
4787 * and path, and the context identifier for the library Help topic in the Help
4788 * file.
4790 * On a successful return all non-null BSTR pointers will have been set,
4791 * possibly to NULL.
4793 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4794 ITypeLib2 *iface,
4795 INT index,
4796 BSTR *pBstrName,
4797 BSTR *pBstrDocString,
4798 DWORD *pdwHelpContext,
4799 BSTR *pBstrHelpFile)
4801 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4802 HRESULT result = E_INVALIDARG;
4803 ITypeInfo *pTInfo;
4805 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4806 This, index,
4807 pBstrName, pBstrDocString,
4808 pdwHelpContext, pBstrHelpFile);
4810 if(index<0)
4812 /* documentation for the typelib */
4813 if(pBstrName)
4815 if (This->Name)
4817 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4818 goto memerr1;
4820 else
4821 *pBstrName = NULL;
4823 if(pBstrDocString)
4825 if (This->DocString)
4827 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4828 goto memerr2;
4830 else if (This->Name)
4832 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->Name))))
4833 goto memerr2;
4835 else
4836 *pBstrDocString = NULL;
4838 if(pdwHelpContext)
4840 *pdwHelpContext = This->dwHelpContext;
4842 if(pBstrHelpFile)
4844 if (This->HelpFile)
4846 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4847 goto memerr3;
4849 else
4850 *pBstrHelpFile = NULL;
4853 result = S_OK;
4855 else
4857 /* for a typeinfo */
4858 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4860 if(SUCCEEDED(result))
4862 result = ITypeInfo_GetDocumentation(pTInfo,
4863 MEMBERID_NIL,
4864 pBstrName,
4865 pBstrDocString,
4866 pdwHelpContext, pBstrHelpFile);
4868 ITypeInfo_Release(pTInfo);
4871 return result;
4872 memerr3:
4873 if (pBstrDocString) SysFreeString (*pBstrDocString);
4874 memerr2:
4875 if (pBstrName) SysFreeString (*pBstrName);
4876 memerr1:
4877 return STG_E_INSUFFICIENTMEMORY;
4880 /* ITypeLib::IsName
4882 * Indicates whether a passed-in string contains the name of a type or member
4883 * described in the library.
4886 static HRESULT WINAPI ITypeLib2_fnIsName(
4887 ITypeLib2 *iface,
4888 LPOLESTR szNameBuf,
4889 ULONG lHashVal,
4890 BOOL *pfName)
4892 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4893 int tic;
4894 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4896 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4897 pfName);
4899 *pfName=TRUE;
4900 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4901 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4902 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4903 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4904 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4905 int pc;
4906 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4907 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
4908 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
4909 goto ITypeLib2_fnIsName_exit;
4912 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
4913 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4914 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4918 *pfName=FALSE;
4920 ITypeLib2_fnIsName_exit:
4921 TRACE("(%p)slow! search for %s: %s found!\n", This,
4922 debugstr_w(szNameBuf), *pfName?"NOT":"");
4924 return S_OK;
4927 /* ITypeLib::FindName
4929 * Finds occurrences of a type description in a type library. This may be used
4930 * to quickly verify that a name exists in a type library.
4933 static HRESULT WINAPI ITypeLib2_fnFindName(
4934 ITypeLib2 *iface,
4935 LPOLESTR name,
4936 ULONG hash,
4937 ITypeInfo **ppTInfo,
4938 MEMBERID *memid,
4939 UINT16 *found)
4941 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4942 int tic;
4943 UINT count = 0;
4944 UINT len;
4946 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4948 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4949 return E_INVALIDARG;
4951 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4952 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4953 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4954 TLBVarDesc *var;
4955 UINT fdc;
4957 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4958 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4959 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4960 int pc;
4962 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4963 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4964 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
4965 goto ITypeLib2_fnFindName_exit;
4969 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
4970 if (var)
4971 goto ITypeLib2_fnFindName_exit;
4973 continue;
4974 ITypeLib2_fnFindName_exit:
4975 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4976 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4977 count++;
4979 TRACE("found %d typeinfos\n", count);
4981 *found = count;
4983 return S_OK;
4986 /* ITypeLib::ReleaseTLibAttr
4988 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4991 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4992 ITypeLib2 *iface,
4993 TLIBATTR *pTLibAttr)
4995 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4996 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4997 heap_free(pTLibAttr);
5000 /* ITypeLib2::GetCustData
5002 * gets the custom data
5004 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5005 ITypeLib2 * iface,
5006 REFGUID guid,
5007 VARIANT *pVarVal)
5009 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5010 TLBCustData *pCData;
5012 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5014 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5015 if(!pCData)
5016 return TYPE_E_ELEMENTNOTFOUND;
5018 VariantInit(pVarVal);
5019 VariantCopy(pVarVal, &pCData->data);
5021 return S_OK;
5024 /* ITypeLib2::GetLibStatistics
5026 * Returns statistics about a type library that are required for efficient
5027 * sizing of hash tables.
5030 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5031 ITypeLib2 * iface,
5032 ULONG *pcUniqueNames,
5033 ULONG *pcchUniqueNames)
5035 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5037 FIXME("(%p): stub!\n", This);
5039 if(pcUniqueNames) *pcUniqueNames=1;
5040 if(pcchUniqueNames) *pcchUniqueNames=1;
5041 return S_OK;
5044 /* ITypeLib2::GetDocumentation2
5046 * Retrieves the library's documentation string, the complete Help file name
5047 * and path, the localization context to use, and the context ID for the
5048 * library Help topic in the Help file.
5051 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5052 ITypeLib2 * iface,
5053 INT index,
5054 LCID lcid,
5055 BSTR *pbstrHelpString,
5056 DWORD *pdwHelpStringContext,
5057 BSTR *pbstrHelpStringDll)
5059 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5060 HRESULT result;
5061 ITypeInfo *pTInfo;
5063 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5065 /* the help string should be obtained from the helpstringdll,
5066 * using the _DLLGetDocumentation function, based on the supplied
5067 * lcid. Nice to do sometime...
5069 if(index<0)
5071 /* documentation for the typelib */
5072 if(pbstrHelpString)
5073 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5074 if(pdwHelpStringContext)
5075 *pdwHelpStringContext=This->dwHelpContext;
5076 if(pbstrHelpStringDll)
5077 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5079 result = S_OK;
5081 else
5083 /* for a typeinfo */
5084 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5086 if(SUCCEEDED(result))
5088 ITypeInfo2 * pTInfo2;
5089 result = ITypeInfo_QueryInterface(pTInfo,
5090 &IID_ITypeInfo2,
5091 (LPVOID*) &pTInfo2);
5093 if(SUCCEEDED(result))
5095 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5096 MEMBERID_NIL,
5097 lcid,
5098 pbstrHelpString,
5099 pdwHelpStringContext,
5100 pbstrHelpStringDll);
5102 ITypeInfo2_Release(pTInfo2);
5105 ITypeInfo_Release(pTInfo);
5108 return result;
5111 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5113 TLBCustData *pCData;
5114 unsigned int ct;
5115 CUSTDATAITEM *cdi;
5117 ct = list_count(custdata_list);
5119 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5120 if(!pCustData->prgCustData)
5121 return E_OUTOFMEMORY;
5123 pCustData->cCustData = ct;
5125 cdi = pCustData->prgCustData;
5126 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5127 cdi->guid = *TLB_get_guid_null(pCData->guid);
5128 VariantCopy(&cdi->varValue, &pCData->data);
5129 ++cdi;
5132 return S_OK;
5136 /* ITypeLib2::GetAllCustData
5138 * Gets all custom data items for the library.
5141 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5142 ITypeLib2 * iface,
5143 CUSTDATA *pCustData)
5145 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5146 TRACE("(%p)->(%p)\n", This, pCustData);
5147 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5150 static const ITypeLib2Vtbl tlbvt = {
5151 ITypeLib2_fnQueryInterface,
5152 ITypeLib2_fnAddRef,
5153 ITypeLib2_fnRelease,
5154 ITypeLib2_fnGetTypeInfoCount,
5155 ITypeLib2_fnGetTypeInfo,
5156 ITypeLib2_fnGetTypeInfoType,
5157 ITypeLib2_fnGetTypeInfoOfGuid,
5158 ITypeLib2_fnGetLibAttr,
5159 ITypeLib2_fnGetTypeComp,
5160 ITypeLib2_fnGetDocumentation,
5161 ITypeLib2_fnIsName,
5162 ITypeLib2_fnFindName,
5163 ITypeLib2_fnReleaseTLibAttr,
5165 ITypeLib2_fnGetCustData,
5166 ITypeLib2_fnGetLibStatistics,
5167 ITypeLib2_fnGetDocumentation2,
5168 ITypeLib2_fnGetAllCustData
5172 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5174 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5176 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5179 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5181 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5183 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5186 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5188 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5190 return ITypeLib2_Release(&This->ITypeLib2_iface);
5193 static HRESULT WINAPI ITypeLibComp_fnBind(
5194 ITypeComp * iface,
5195 OLECHAR * szName,
5196 ULONG lHash,
5197 WORD wFlags,
5198 ITypeInfo ** ppTInfo,
5199 DESCKIND * pDescKind,
5200 BINDPTR * pBindPtr)
5202 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5203 int typemismatch=0, i;
5205 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5207 *pDescKind = DESCKIND_NONE;
5208 pBindPtr->lptcomp = NULL;
5209 *ppTInfo = NULL;
5211 for(i = 0; i < This->TypeInfoCount; ++i){
5212 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5213 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5215 /* FIXME: check wFlags here? */
5216 /* FIXME: we should use a hash table to look this info up using lHash
5217 * instead of an O(n) search */
5218 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5219 (pTypeInfo->typekind == TKIND_MODULE))
5221 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5223 *pDescKind = DESCKIND_TYPECOMP;
5224 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5225 ITypeComp_AddRef(pBindPtr->lptcomp);
5226 TRACE("module or enum: %s\n", debugstr_w(szName));
5227 return S_OK;
5231 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5232 (pTypeInfo->typekind == TKIND_ENUM))
5234 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5235 HRESULT hr;
5237 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5238 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5240 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5241 return S_OK;
5243 else if (hr == TYPE_E_TYPEMISMATCH)
5244 typemismatch = 1;
5247 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5248 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5250 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5251 HRESULT hr;
5252 ITypeInfo *subtypeinfo;
5253 BINDPTR subbindptr;
5254 DESCKIND subdesckind;
5256 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5257 &subtypeinfo, &subdesckind, &subbindptr);
5258 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5260 TYPEDESC tdesc_appobject;
5261 const VARDESC vardesc_appobject =
5263 -2, /* memid */
5264 NULL, /* lpstrSchema */
5266 0 /* oInst */
5269 /* ELEMDESC */
5271 /* TYPEDESC */
5273 &tdesc_appobject
5275 VT_PTR
5278 0, /* wVarFlags */
5279 VAR_STATIC /* varkind */
5282 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5283 tdesc_appobject.vt = VT_USERDEFINED;
5285 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5287 /* cleanup things filled in by Bind call so we can put our
5288 * application object data in there instead */
5289 switch (subdesckind)
5291 case DESCKIND_FUNCDESC:
5292 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5293 break;
5294 case DESCKIND_VARDESC:
5295 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5296 break;
5297 default:
5298 break;
5300 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5302 if (pTypeInfo->hreftype == -1)
5303 FIXME("no hreftype for interface %p\n", pTypeInfo);
5305 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5306 if (FAILED(hr))
5307 return hr;
5309 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5310 *ppTInfo = (ITypeInfo *)pTypeInfo;
5311 ITypeInfo_AddRef(*ppTInfo);
5312 return S_OK;
5314 else if (hr == TYPE_E_TYPEMISMATCH)
5315 typemismatch = 1;
5319 if (typemismatch)
5321 TRACE("type mismatch %s\n", debugstr_w(szName));
5322 return TYPE_E_TYPEMISMATCH;
5324 else
5326 TRACE("name not found %s\n", debugstr_w(szName));
5327 return S_OK;
5331 static HRESULT WINAPI ITypeLibComp_fnBindType(
5332 ITypeComp * iface,
5333 OLECHAR * szName,
5334 ULONG lHash,
5335 ITypeInfo ** ppTInfo,
5336 ITypeComp ** ppTComp)
5338 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5339 ITypeInfoImpl *info;
5341 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5343 if(!szName || !ppTInfo || !ppTComp)
5344 return E_INVALIDARG;
5346 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5347 if(!info){
5348 *ppTInfo = NULL;
5349 *ppTComp = NULL;
5350 return S_OK;
5353 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5354 ITypeInfo_AddRef(*ppTInfo);
5355 *ppTComp = &info->ITypeComp_iface;
5356 ITypeComp_AddRef(*ppTComp);
5358 return S_OK;
5361 static const ITypeCompVtbl tlbtcvt =
5364 ITypeLibComp_fnQueryInterface,
5365 ITypeLibComp_fnAddRef,
5366 ITypeLibComp_fnRelease,
5368 ITypeLibComp_fnBind,
5369 ITypeLibComp_fnBindType
5372 /*================== ITypeInfo(2) Methods ===================================*/
5373 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5375 ITypeInfoImpl *pTypeInfoImpl;
5377 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5378 if (pTypeInfoImpl)
5380 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5381 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5382 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5383 pTypeInfoImpl->ref = 0;
5384 pTypeInfoImpl->hreftype = -1;
5385 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5386 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5387 list_init(&pTypeInfoImpl->custdata_list);
5389 TRACE("(%p)\n", pTypeInfoImpl);
5390 return pTypeInfoImpl;
5393 /* ITypeInfo::QueryInterface
5395 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5396 ITypeInfo2 *iface,
5397 REFIID riid,
5398 VOID **ppvObject)
5400 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5402 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5404 *ppvObject=NULL;
5405 if(IsEqualIID(riid, &IID_IUnknown) ||
5406 IsEqualIID(riid,&IID_ITypeInfo)||
5407 IsEqualIID(riid,&IID_ITypeInfo2))
5408 *ppvObject = This;
5409 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5410 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5411 *ppvObject = &This->ICreateTypeInfo2_iface;
5413 if(*ppvObject){
5414 ITypeInfo2_AddRef(iface);
5415 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5416 return S_OK;
5418 TRACE("-- Interface: E_NOINTERFACE\n");
5419 return E_NOINTERFACE;
5422 /* ITypeInfo::AddRef
5424 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5426 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5427 ULONG ref = InterlockedIncrement(&This->ref);
5429 TRACE("(%p)->ref is %u\n",This, ref);
5431 if (ref == 1 /* incremented from 0 */)
5432 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5434 return ref;
5437 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5439 UINT i;
5441 TRACE("destroying ITypeInfo(%p)\n",This);
5443 for (i = 0; i < This->cFuncs; ++i)
5445 int j;
5446 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5447 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5449 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5450 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5452 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5453 heap_free(elemdesc->u.paramdesc.pparamdescex);
5455 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5457 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5458 heap_free(pFInfo->pParamDesc);
5459 TLB_FreeCustData(&pFInfo->custdata_list);
5461 heap_free(This->funcdescs);
5463 for(i = 0; i < This->cVars; ++i)
5465 TLBVarDesc *pVInfo = &This->vardescs[i];
5466 if (pVInfo->vardesc.varkind == VAR_CONST)
5468 VariantClear(pVInfo->vardesc.u.lpvarValue);
5469 heap_free(pVInfo->vardesc.u.lpvarValue);
5471 TLB_FreeCustData(&pVInfo->custdata_list);
5473 heap_free(This->vardescs);
5475 if(This->impltypes){
5476 for (i = 0; i < This->cImplTypes; ++i){
5477 TLBImplType *pImpl = &This->impltypes[i];
5478 TLB_FreeCustData(&pImpl->custdata_list);
5480 heap_free(This->impltypes);
5483 TLB_FreeCustData(&This->custdata_list);
5485 heap_free(This);
5488 /* ITypeInfo::Release
5490 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5492 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5493 ULONG ref = InterlockedDecrement(&This->ref);
5495 TRACE("(%p)->(%u)\n",This, ref);
5497 if (!ref)
5499 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5500 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5501 if (not_attached_to_typelib)
5502 heap_free(This);
5503 /* otherwise This will be freed when typelib is freed */
5506 return ref;
5509 /* ITypeInfo::GetTypeAttr
5511 * Retrieves a TYPEATTR structure that contains the attributes of the type
5512 * description.
5515 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5516 LPTYPEATTR *ppTypeAttr)
5518 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5519 SIZE_T size;
5521 TRACE("(%p)\n",This);
5523 size = sizeof(**ppTypeAttr);
5524 if (This->typekind == TKIND_ALIAS)
5525 size += TLB_SizeTypeDesc(&This->tdescAlias, FALSE);
5527 *ppTypeAttr = heap_alloc(size);
5528 if (!*ppTypeAttr)
5529 return E_OUTOFMEMORY;
5531 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5532 (*ppTypeAttr)->lcid = This->lcid;
5533 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5534 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5535 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5536 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5537 (*ppTypeAttr)->typekind = This->typekind;
5538 (*ppTypeAttr)->cFuncs = This->cFuncs;
5539 (*ppTypeAttr)->cVars = This->cVars;
5540 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5541 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5542 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5543 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5544 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5545 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5546 (*ppTypeAttr)->tdescAlias = This->tdescAlias;
5547 (*ppTypeAttr)->idldescType = This->idldescType;
5549 if (This->typekind == TKIND_ALIAS)
5550 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5551 &This->tdescAlias, *ppTypeAttr + 1);
5553 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5554 /* This should include all the inherited funcs */
5555 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5556 /* This is always the size of IDispatch's vtbl */
5557 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5558 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5560 return S_OK;
5563 /* ITypeInfo::GetTypeComp
5565 * Retrieves the ITypeComp interface for the type description, which enables a
5566 * client compiler to bind to the type description's members.
5569 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5570 ITypeComp * *ppTComp)
5572 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5574 TRACE("(%p)->(%p)\n", This, ppTComp);
5576 *ppTComp = &This->ITypeComp_iface;
5577 ITypeComp_AddRef(*ppTComp);
5578 return S_OK;
5581 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5583 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5584 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5585 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5586 return size;
5589 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5591 *dest = *src;
5592 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5593 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5595 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5596 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5597 *buffer += sizeof(PARAMDESCEX);
5598 *pparamdescex_dest = *pparamdescex_src;
5599 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5600 VariantInit(&pparamdescex_dest->varDefaultValue);
5601 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5602 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5604 else
5605 dest->u.paramdesc.pparamdescex = NULL;
5606 return S_OK;
5609 static HRESULT TLB_SanitizeBSTR(BSTR str)
5611 UINT len = SysStringLen(str), i;
5612 for (i = 0; i < len; ++i)
5613 if (str[i] > 0x7f)
5614 str[i] = '?';
5615 return S_OK;
5618 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5620 if (V_VT(var) == VT_INT)
5621 return VariantChangeType(var, var, 0, VT_I4);
5622 else if (V_VT(var) == VT_UINT)
5623 return VariantChangeType(var, var, 0, VT_UI4);
5624 else if (V_VT(var) == VT_BSTR)
5625 return TLB_SanitizeBSTR(V_BSTR(var));
5627 return S_OK;
5630 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5632 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5633 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5636 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5638 FUNCDESC *dest;
5639 char *buffer;
5640 SIZE_T size = sizeof(*src);
5641 SHORT i;
5642 HRESULT hr;
5644 size += sizeof(*src->lprgscode) * src->cScodes;
5645 size += TLB_SizeElemDesc(&src->elemdescFunc);
5646 for (i = 0; i < src->cParams; i++)
5648 size += sizeof(ELEMDESC);
5649 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5652 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5653 if (!dest) return E_OUTOFMEMORY;
5655 *dest = *src;
5656 if (dispinterface) /* overwrite funckind */
5657 dest->funckind = FUNC_DISPATCH;
5658 buffer = (char *)(dest + 1);
5660 dest->oVft = dest->oVft & 0xFFFC;
5662 if (dest->cScodes) {
5663 dest->lprgscode = (SCODE *)buffer;
5664 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5665 buffer += sizeof(*src->lprgscode) * src->cScodes;
5666 } else
5667 dest->lprgscode = NULL;
5669 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5670 if (FAILED(hr))
5672 SysFreeString((BSTR)dest);
5673 return hr;
5676 if (dest->cParams) {
5677 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5678 buffer += sizeof(ELEMDESC) * src->cParams;
5679 for (i = 0; i < src->cParams; i++)
5681 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5682 if (FAILED(hr))
5683 break;
5685 if (FAILED(hr))
5687 /* undo the above actions */
5688 for (i = i - 1; i >= 0; i--)
5689 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5690 TLB_FreeElemDesc(&dest->elemdescFunc);
5691 SysFreeString((BSTR)dest);
5692 return hr;
5694 } else
5695 dest->lprgelemdescParam = NULL;
5697 /* special treatment for dispinterfaces: this makes functions appear
5698 * to return their [retval] value when it is really returning an
5699 * HRESULT */
5700 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5702 if (dest->cParams &&
5703 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5705 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5706 if (elemdesc->tdesc.vt != VT_PTR)
5708 ERR("elemdesc should have started with VT_PTR instead of:\n");
5709 if (ERR_ON(ole))
5710 dump_ELEMDESC(elemdesc);
5711 return E_UNEXPECTED;
5714 /* copy last parameter to the return value. we are using a flat
5715 * buffer so there is no danger of leaking memory in
5716 * elemdescFunc */
5717 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5719 /* remove the last parameter */
5720 dest->cParams--;
5722 else
5723 /* otherwise this function is made to appear to have no return
5724 * value */
5725 dest->elemdescFunc.tdesc.vt = VT_VOID;
5729 *dest_ptr = dest;
5730 return S_OK;
5733 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5735 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5737 if (index >= This->cFuncs)
5738 return TYPE_E_ELEMENTNOTFOUND;
5740 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5741 return S_OK;
5744 /* internal function to make the inherited interfaces' methods appear
5745 * part of the interface */
5746 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5747 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5749 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5750 HRESULT hr;
5751 UINT implemented_funcs = 0;
5753 if (funcs)
5754 *funcs = 0;
5755 else
5756 *hrefoffset = DISPATCH_HREF_OFFSET;
5758 if(This->impltypes)
5760 ITypeInfo *pSubTypeInfo;
5761 UINT sub_funcs;
5763 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5764 if (FAILED(hr))
5765 return hr;
5767 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5768 index,
5769 ppFuncDesc,
5770 &sub_funcs, hrefoffset);
5771 implemented_funcs += sub_funcs;
5772 ITypeInfo_Release(pSubTypeInfo);
5773 if (SUCCEEDED(hr))
5774 return hr;
5775 *hrefoffset += DISPATCH_HREF_OFFSET;
5778 if (funcs)
5779 *funcs = implemented_funcs + This->cFuncs;
5780 else
5781 *hrefoffset = 0;
5783 if (index < implemented_funcs)
5784 return E_INVALIDARG;
5785 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5786 ppFuncDesc);
5789 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5791 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5792 while (TRUE)
5794 switch (pTypeDesc->vt)
5796 case VT_USERDEFINED:
5797 pTypeDesc->u.hreftype += hrefoffset;
5798 return;
5799 case VT_PTR:
5800 case VT_SAFEARRAY:
5801 pTypeDesc = pTypeDesc->u.lptdesc;
5802 break;
5803 case VT_CARRAY:
5804 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5805 break;
5806 default:
5807 return;
5812 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5814 SHORT i;
5815 for (i = 0; i < pFuncDesc->cParams; i++)
5816 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5817 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5820 /* ITypeInfo::GetFuncDesc
5822 * Retrieves the FUNCDESC structure that contains information about a
5823 * specified function.
5826 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5827 LPFUNCDESC *ppFuncDesc)
5829 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5830 const FUNCDESC *internal_funcdesc;
5831 HRESULT hr;
5832 UINT hrefoffset = 0;
5834 TRACE("(%p) index %d\n", This, index);
5836 if (!ppFuncDesc)
5837 return E_INVALIDARG;
5839 if (This->needs_layout)
5840 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5842 if (This->typekind == TKIND_DISPATCH)
5843 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5844 &internal_funcdesc, NULL,
5845 &hrefoffset);
5846 else
5847 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5848 &internal_funcdesc);
5849 if (FAILED(hr))
5851 WARN("description for function %d not found\n", index);
5852 return hr;
5855 hr = TLB_AllocAndInitFuncDesc(
5856 internal_funcdesc,
5857 ppFuncDesc,
5858 This->typekind == TKIND_DISPATCH);
5860 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
5861 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5863 TRACE("-- 0x%08x\n", hr);
5864 return hr;
5867 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5869 VARDESC *dest;
5870 char *buffer;
5871 SIZE_T size = sizeof(*src);
5872 HRESULT hr;
5874 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5875 if (src->varkind == VAR_CONST)
5876 size += sizeof(VARIANT);
5877 size += TLB_SizeElemDesc(&src->elemdescVar);
5879 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5880 if (!dest) return E_OUTOFMEMORY;
5882 *dest = *src;
5883 buffer = (char *)(dest + 1);
5884 if (src->lpstrSchema)
5886 int len;
5887 dest->lpstrSchema = (LPOLESTR)buffer;
5888 len = strlenW(src->lpstrSchema);
5889 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5890 buffer += (len + 1) * sizeof(WCHAR);
5893 if (src->varkind == VAR_CONST)
5895 HRESULT hr;
5897 dest->u.lpvarValue = (VARIANT *)buffer;
5898 *dest->u.lpvarValue = *src->u.lpvarValue;
5899 buffer += sizeof(VARIANT);
5900 VariantInit(dest->u.lpvarValue);
5901 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5902 if (FAILED(hr))
5904 SysFreeString((BSTR)dest);
5905 return hr;
5908 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5909 if (FAILED(hr))
5911 if (src->varkind == VAR_CONST)
5912 VariantClear(dest->u.lpvarValue);
5913 SysFreeString((BSTR)dest);
5914 return hr;
5916 *dest_ptr = dest;
5917 return S_OK;
5920 /* ITypeInfo::GetVarDesc
5922 * Retrieves a VARDESC structure that describes the specified variable.
5925 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5926 LPVARDESC *ppVarDesc)
5928 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5929 const TLBVarDesc *pVDesc = &This->vardescs[index];
5931 TRACE("(%p) index %d\n", This, index);
5933 if(index >= This->cVars)
5934 return TYPE_E_ELEMENTNOTFOUND;
5936 if (This->needs_layout)
5937 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5939 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5942 /* ITypeInfo_GetNames
5944 * Retrieves the variable with the specified member ID (or the name of the
5945 * property or method and its parameters) that correspond to the specified
5946 * function ID.
5948 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5949 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5951 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5952 const TLBFuncDesc *pFDesc;
5953 const TLBVarDesc *pVDesc;
5954 int i;
5955 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5956 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
5957 if(pFDesc)
5959 /* function found, now return function and parameter names */
5960 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5962 if(!i)
5963 *rgBstrNames=SysAllocString(TLB_get_bstr(pFDesc->Name));
5964 else
5965 rgBstrNames[i]=SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i-1].Name));
5967 *pcNames=i;
5969 else
5971 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
5972 if(pVDesc)
5974 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
5975 *pcNames=1;
5977 else
5979 if(This->impltypes &&
5980 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
5981 /* recursive search */
5982 ITypeInfo *pTInfo;
5983 HRESULT result;
5984 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5985 if(SUCCEEDED(result))
5987 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5988 ITypeInfo_Release(pTInfo);
5989 return result;
5991 WARN("Could not search inherited interface!\n");
5993 else
5995 WARN("no names found\n");
5997 *pcNames=0;
5998 return TYPE_E_ELEMENTNOTFOUND;
6001 return S_OK;
6005 /* ITypeInfo::GetRefTypeOfImplType
6007 * If a type description describes a COM class, it retrieves the type
6008 * description of the implemented interface types. For an interface,
6009 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6010 * if any exist.
6013 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6014 ITypeInfo2 *iface,
6015 UINT index,
6016 HREFTYPE *pRefType)
6018 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6019 HRESULT hr = S_OK;
6021 TRACE("(%p) index %d\n", This, index);
6022 if (TRACE_ON(ole)) dump_TypeInfo(This);
6024 if(index==(UINT)-1)
6026 /* only valid on dual interfaces;
6027 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6030 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6032 *pRefType = -2;
6034 else
6036 hr = TYPE_E_ELEMENTNOTFOUND;
6039 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6041 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6042 *pRefType = This->pTypeLib->dispatch_href;
6044 else
6046 if(index >= This->cImplTypes)
6047 hr = TYPE_E_ELEMENTNOTFOUND;
6048 else
6049 *pRefType = This->impltypes[index].hRef;
6052 if(TRACE_ON(ole))
6054 if(SUCCEEDED(hr))
6055 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6056 else
6057 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6060 return hr;
6063 /* ITypeInfo::GetImplTypeFlags
6065 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6066 * or base interface in a type description.
6068 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6069 UINT index, INT *pImplTypeFlags)
6071 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6073 TRACE("(%p) index %d\n", This, index);
6075 if(!pImplTypeFlags)
6076 return E_INVALIDARG;
6078 if(This->typekind == TKIND_DISPATCH && index == 0){
6079 *pImplTypeFlags = 0;
6080 return S_OK;
6083 if(index >= This->cImplTypes)
6084 return TYPE_E_ELEMENTNOTFOUND;
6086 *pImplTypeFlags = This->impltypes[index].implflags;
6088 return S_OK;
6091 /* GetIDsOfNames
6092 * Maps between member names and member IDs, and parameter names and
6093 * parameter IDs.
6095 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6096 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6098 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6099 const TLBVarDesc *pVDesc;
6100 HRESULT ret=S_OK;
6101 UINT i, fdc;
6103 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6104 cNames);
6106 /* init out parameters in case of failure */
6107 for (i = 0; i < cNames; i++)
6108 pMemId[i] = MEMBERID_NIL;
6110 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6111 int j;
6112 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6113 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6114 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6115 for(i=1; i < cNames; i++){
6116 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6117 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6118 break;
6119 if( j<pFDesc->funcdesc.cParams)
6120 pMemId[i]=j;
6121 else
6122 ret=DISP_E_UNKNOWNNAME;
6124 TRACE("-- 0x%08x\n", ret);
6125 return ret;
6128 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6129 if(pVDesc){
6130 if(cNames)
6131 *pMemId = pVDesc->vardesc.memid;
6132 return ret;
6134 /* not found, see if it can be found in an inherited interface */
6135 if(This->impltypes) {
6136 /* recursive search */
6137 ITypeInfo *pTInfo;
6138 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6139 if(SUCCEEDED(ret)){
6140 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6141 ITypeInfo_Release(pTInfo);
6142 return ret;
6144 WARN("Could not search inherited interface!\n");
6145 } else
6146 WARN("no names found\n");
6147 return DISP_E_UNKNOWNNAME;
6151 #ifdef __i386__
6153 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6154 __ASM_GLOBAL_FUNC( call_method,
6155 "pushl %ebp\n\t"
6156 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6157 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6158 "movl %esp,%ebp\n\t"
6159 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6160 "pushl %esi\n\t"
6161 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6162 "pushl %edi\n\t"
6163 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6164 "movl 12(%ebp),%edx\n\t"
6165 "movl %esp,%edi\n\t"
6166 "shll $2,%edx\n\t"
6167 "jz 1f\n\t"
6168 "subl %edx,%edi\n\t"
6169 "andl $~15,%edi\n\t"
6170 "movl %edi,%esp\n\t"
6171 "movl 12(%ebp),%ecx\n\t"
6172 "movl 16(%ebp),%esi\n\t"
6173 "cld\n\t"
6174 "rep; movsl\n"
6175 "1:\tcall *8(%ebp)\n\t"
6176 "subl %esp,%edi\n\t"
6177 "movl 20(%ebp),%ecx\n\t"
6178 "movl %edi,(%ecx)\n\t"
6179 "leal -8(%ebp),%esp\n\t"
6180 "popl %edi\n\t"
6181 __ASM_CFI(".cfi_same_value %edi\n\t")
6182 "popl %esi\n\t"
6183 __ASM_CFI(".cfi_same_value %esi\n\t")
6184 "popl %ebp\n\t"
6185 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6186 __ASM_CFI(".cfi_same_value %ebp\n\t")
6187 "ret" )
6189 /* same function but returning floating point */
6190 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6192 /* ITypeInfo::Invoke
6194 * Invokes a method, or accesses a property of an object, that implements the
6195 * interface described by the type description.
6197 DWORD
6198 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6199 DWORD res;
6200 int stack_offset;
6202 if (TRACE_ON(ole)) {
6203 int i;
6204 TRACE("Calling %p(",func);
6205 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6206 if (nrargs > 30) TRACE("...");
6207 TRACE(")\n");
6210 switch (callconv) {
6211 case CC_STDCALL:
6212 case CC_CDECL:
6213 res = call_method( func, nrargs, args, &stack_offset );
6214 break;
6215 default:
6216 FIXME("unsupported calling convention %d\n",callconv);
6217 res = -1;
6218 break;
6220 TRACE("returns %08x\n",res);
6221 return res;
6224 #elif defined(__x86_64__)
6226 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6227 __ASM_GLOBAL_FUNC( call_method,
6228 "pushq %rbp\n\t"
6229 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6230 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6231 "movq %rsp,%rbp\n\t"
6232 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6233 "pushq %rsi\n\t"
6234 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6235 "pushq %rdi\n\t"
6236 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6237 "movq %rcx,%rax\n\t"
6238 "movq $4,%rcx\n\t"
6239 "cmp %rcx,%rdx\n\t"
6240 "cmovgq %rdx,%rcx\n\t"
6241 "leaq 0(,%rcx,8),%rdx\n\t"
6242 "subq %rdx,%rsp\n\t"
6243 "andq $~15,%rsp\n\t"
6244 "movq %rsp,%rdi\n\t"
6245 "movq %r8,%rsi\n\t"
6246 "rep; movsq\n\t"
6247 "movq 0(%rsp),%rcx\n\t"
6248 "movq 8(%rsp),%rdx\n\t"
6249 "movq 16(%rsp),%r8\n\t"
6250 "movq 24(%rsp),%r9\n\t"
6251 "movq %rcx,%xmm0\n\t"
6252 "movq %rdx,%xmm1\n\t"
6253 "movq %r8,%xmm2\n\t"
6254 "movq %r9,%xmm3\n\t"
6255 "callq *%rax\n\t"
6256 "leaq -16(%rbp),%rsp\n\t"
6257 "popq %rdi\n\t"
6258 __ASM_CFI(".cfi_same_value %rdi\n\t")
6259 "popq %rsi\n\t"
6260 __ASM_CFI(".cfi_same_value %rsi\n\t")
6261 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6262 "popq %rbp\n\t"
6263 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6264 __ASM_CFI(".cfi_same_value %rbp\n\t")
6265 "ret")
6267 /* same function but returning floating point */
6268 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6270 #endif /* __x86_64__ */
6272 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6274 HRESULT hr = S_OK;
6275 ITypeInfo *tinfo2 = NULL;
6276 TYPEATTR *tattr = NULL;
6278 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6279 if (hr)
6281 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6282 "hr = 0x%08x\n",
6283 tdesc->u.hreftype, hr);
6284 return hr;
6286 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6287 if (hr)
6289 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6290 ITypeInfo_Release(tinfo2);
6291 return hr;
6294 switch (tattr->typekind)
6296 case TKIND_ENUM:
6297 *vt |= VT_I4;
6298 break;
6300 case TKIND_ALIAS:
6301 tdesc = &tattr->tdescAlias;
6302 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6303 break;
6305 case TKIND_INTERFACE:
6306 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6307 *vt |= VT_DISPATCH;
6308 else
6309 *vt |= VT_UNKNOWN;
6310 break;
6312 case TKIND_DISPATCH:
6313 *vt |= VT_DISPATCH;
6314 break;
6316 case TKIND_COCLASS:
6317 *vt |= VT_DISPATCH;
6318 break;
6320 case TKIND_RECORD:
6321 FIXME("TKIND_RECORD unhandled.\n");
6322 hr = E_NOTIMPL;
6323 break;
6325 case TKIND_UNION:
6326 FIXME("TKIND_UNION unhandled.\n");
6327 hr = E_NOTIMPL;
6328 break;
6330 default:
6331 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6332 hr = E_NOTIMPL;
6333 break;
6335 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6336 ITypeInfo_Release(tinfo2);
6337 return hr;
6340 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6342 HRESULT hr = S_OK;
6344 /* enforce only one level of pointer indirection */
6345 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6347 tdesc = tdesc->u.lptdesc;
6349 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6350 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6351 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6352 if ((tdesc->vt == VT_USERDEFINED) ||
6353 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6355 VARTYPE vt_userdefined = 0;
6356 const TYPEDESC *tdesc_userdefined = tdesc;
6357 if (tdesc->vt == VT_PTR)
6359 vt_userdefined = VT_BYREF;
6360 tdesc_userdefined = tdesc->u.lptdesc;
6362 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6363 if ((hr == S_OK) &&
6364 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6365 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6367 *vt |= vt_userdefined;
6368 return S_OK;
6371 *vt = VT_BYREF;
6374 switch (tdesc->vt)
6376 case VT_HRESULT:
6377 *vt |= VT_ERROR;
6378 break;
6379 case VT_USERDEFINED:
6380 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6381 break;
6382 case VT_VOID:
6383 case VT_CARRAY:
6384 case VT_PTR:
6385 case VT_LPSTR:
6386 case VT_LPWSTR:
6387 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6388 hr = DISP_E_BADVARTYPE;
6389 break;
6390 case VT_SAFEARRAY:
6391 *vt |= VT_ARRAY;
6392 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6393 break;
6394 case VT_INT:
6395 *vt |= VT_I4;
6396 break;
6397 case VT_UINT:
6398 *vt |= VT_UI4;
6399 break;
6400 default:
6401 *vt |= tdesc->vt;
6402 break;
6404 return hr;
6407 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6409 ITypeInfo *tinfo2;
6410 TYPEATTR *tattr;
6411 HRESULT hres;
6413 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6414 if(FAILED(hres))
6415 return hres;
6417 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6418 if(FAILED(hres)) {
6419 ITypeInfo_Release(tinfo2);
6420 return hres;
6423 switch(tattr->typekind) {
6424 case TKIND_ALIAS:
6425 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6426 break;
6428 case TKIND_INTERFACE:
6429 case TKIND_DISPATCH:
6430 *guid = tattr->guid;
6431 break;
6433 default:
6434 ERR("Unexpected typekind %d\n", tattr->typekind);
6435 hres = E_UNEXPECTED;
6438 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6439 ITypeInfo_Release(tinfo2);
6440 return hres;
6443 /***********************************************************************
6444 * DispCallFunc (OLEAUT32.@)
6446 * Invokes a function of the specified calling convention, passing the
6447 * specified arguments and returns the result.
6449 * PARAMS
6450 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6451 * oVft [I] The offset in the vtable. See notes.
6452 * cc [I] Calling convention of the function to call.
6453 * vtReturn [I] The return type of the function.
6454 * cActuals [I] Number of parameters.
6455 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6456 * prgpvarg [I] The arguments to pass.
6457 * pvargResult [O] The return value of the function. Can be NULL.
6459 * RETURNS
6460 * Success: S_OK.
6461 * Failure: HRESULT code.
6463 * NOTES
6464 * The HRESULT return value of this function is not affected by the return
6465 * value of the user supplied function, which is returned in pvargResult.
6467 * If pvInstance is NULL then a non-object function is to be called and oVft
6468 * is the address of the function to call.
6470 * The cc parameter can be one of the following values:
6471 *|CC_FASTCALL
6472 *|CC_CDECL
6473 *|CC_PASCAL
6474 *|CC_STDCALL
6475 *|CC_FPFASTCALL
6476 *|CC_SYSCALL
6477 *|CC_MPWCDECL
6478 *|CC_MPWPASCAL
6481 HRESULT WINAPI
6482 DispCallFunc(
6483 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6484 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6486 #ifdef __i386__
6487 int argspos, stack_offset;
6488 void *func;
6489 UINT i;
6490 DWORD *args;
6492 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6493 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6494 pvargResult, V_VT(pvargResult));
6496 if (cc != CC_STDCALL && cc != CC_CDECL)
6498 FIXME("unsupported calling convention %d\n",cc);
6499 return E_INVALIDARG;
6502 /* maximum size for an argument is sizeof(VARIANT) */
6503 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6505 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6506 argspos = 1;
6507 if (pvInstance)
6509 const FARPROC *vtable = *(FARPROC **)pvInstance;
6510 func = vtable[oVft/sizeof(void *)];
6511 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6513 else func = (void *)oVft;
6515 for (i = 0; i < cActuals; i++)
6517 VARIANT *arg = prgpvarg[i];
6519 switch (prgvt[i])
6521 case VT_EMPTY:
6522 break;
6523 case VT_I8:
6524 case VT_UI8:
6525 case VT_R8:
6526 case VT_DATE:
6527 case VT_CY:
6528 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6529 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6530 break;
6531 case VT_DECIMAL:
6532 case VT_VARIANT:
6533 memcpy( &args[argspos], arg, sizeof(*arg) );
6534 argspos += sizeof(*arg) / sizeof(DWORD);
6535 break;
6536 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6537 args[argspos++] = V_BOOL(arg);
6538 break;
6539 default:
6540 args[argspos++] = V_UI4(arg);
6541 break;
6543 TRACE("arg %u: type %d\n",i,prgvt[i]);
6544 dump_Variant(arg);
6547 switch (vtReturn)
6549 case VT_EMPTY:
6550 call_method( func, argspos - 1, args + 1, &stack_offset );
6551 break;
6552 case VT_R4:
6553 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6554 break;
6555 case VT_R8:
6556 case VT_DATE:
6557 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6558 break;
6559 case VT_DECIMAL:
6560 case VT_VARIANT:
6561 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6562 call_method( func, argspos, args, &stack_offset );
6563 break;
6564 case VT_I8:
6565 case VT_UI8:
6566 case VT_CY:
6567 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6568 break;
6569 case VT_HRESULT:
6570 WARN("invalid return type %u\n", vtReturn);
6571 heap_free( args );
6572 return E_INVALIDARG;
6573 default:
6574 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6575 break;
6577 heap_free( args );
6578 if (stack_offset && cc == CC_STDCALL)
6580 WARN( "stack pointer off by %d\n", stack_offset );
6581 return DISP_E_BADCALLEE;
6583 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6584 TRACE("retval: "); dump_Variant(pvargResult);
6585 return S_OK;
6587 #elif defined(__x86_64__)
6588 int argspos;
6589 UINT i;
6590 DWORD_PTR *args;
6591 void *func;
6593 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6594 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6595 pvargResult, V_VT(pvargResult));
6597 if (cc != CC_STDCALL && cc != CC_CDECL)
6599 FIXME("unsupported calling convention %d\n",cc);
6600 return E_INVALIDARG;
6603 /* maximum size for an argument is sizeof(DWORD_PTR) */
6604 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6606 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6607 argspos = 1;
6608 if (pvInstance)
6610 const FARPROC *vtable = *(FARPROC **)pvInstance;
6611 func = vtable[oVft/sizeof(void *)];
6612 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6614 else func = (void *)oVft;
6616 for (i = 0; i < cActuals; i++)
6618 VARIANT *arg = prgpvarg[i];
6620 switch (prgvt[i])
6622 case VT_DECIMAL:
6623 case VT_VARIANT:
6624 args[argspos++] = (ULONG_PTR)arg;
6625 break;
6626 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6627 args[argspos++] = V_BOOL(arg);
6628 break;
6629 default:
6630 args[argspos++] = V_UI8(arg);
6631 break;
6633 TRACE("arg %u: type %d\n",i,prgvt[i]);
6634 dump_Variant(arg);
6637 switch (vtReturn)
6639 case VT_R4:
6640 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6641 break;
6642 case VT_R8:
6643 case VT_DATE:
6644 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6645 break;
6646 case VT_DECIMAL:
6647 case VT_VARIANT:
6648 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6649 call_method( func, argspos, args );
6650 break;
6651 case VT_HRESULT:
6652 WARN("invalid return type %u\n", vtReturn);
6653 heap_free( args );
6654 return E_INVALIDARG;
6655 default:
6656 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6657 break;
6659 heap_free( args );
6660 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6661 TRACE("retval: "); dump_Variant(pvargResult);
6662 return S_OK;
6664 #else
6665 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6666 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6667 return E_NOTIMPL;
6668 #endif
6671 static inline BOOL func_restricted( const FUNCDESC *desc )
6673 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6676 #define INVBUF_ELEMENT_SIZE \
6677 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6678 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6679 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6680 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6681 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6682 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6683 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6684 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6686 static HRESULT WINAPI ITypeInfo_fnInvoke(
6687 ITypeInfo2 *iface,
6688 VOID *pIUnk,
6689 MEMBERID memid,
6690 UINT16 wFlags,
6691 DISPPARAMS *pDispParams,
6692 VARIANT *pVarResult,
6693 EXCEPINFO *pExcepInfo,
6694 UINT *pArgErr)
6696 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6697 int i;
6698 unsigned int var_index;
6699 TYPEKIND type_kind;
6700 HRESULT hres;
6701 const TLBFuncDesc *pFuncInfo;
6702 UINT fdc;
6704 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6705 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6708 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6709 return DISP_E_MEMBERNOTFOUND;
6711 if (!pDispParams)
6713 ERR("NULL pDispParams not allowed\n");
6714 return E_INVALIDARG;
6717 dump_DispParms(pDispParams);
6719 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6721 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6722 pDispParams->cNamedArgs, pDispParams->cArgs);
6723 return E_INVALIDARG;
6726 /* we do this instead of using GetFuncDesc since it will return a fake
6727 * FUNCDESC for dispinterfaces and we want the real function description */
6728 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6729 pFuncInfo = &This->funcdescs[fdc];
6730 if ((memid == pFuncInfo->funcdesc.memid) &&
6731 (wFlags & pFuncInfo->funcdesc.invkind) &&
6732 !func_restricted( &pFuncInfo->funcdesc ))
6733 break;
6736 if (fdc < This->cFuncs) {
6737 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6739 if (TRACE_ON(ole))
6741 TRACE("invoking:\n");
6742 dump_TLBFuncDescOne(pFuncInfo);
6745 switch (func_desc->funckind) {
6746 case FUNC_PUREVIRTUAL:
6747 case FUNC_VIRTUAL: {
6748 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6749 VARIANT varresult;
6750 VARIANT retval; /* pointer for storing byref retvals in */
6751 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6752 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6753 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6754 UINT cNamedArgs = pDispParams->cNamedArgs;
6755 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6756 UINT vargs_converted=0;
6758 hres = S_OK;
6760 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6762 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6764 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6765 hres = DISP_E_PARAMNOTFOUND;
6766 goto func_fail;
6770 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6772 ERR("functions with the vararg attribute do not support named arguments\n");
6773 hres = DISP_E_NONAMEDARGS;
6774 goto func_fail;
6777 for (i = 0; i < func_desc->cParams; i++)
6779 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6780 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6781 if (FAILED(hres))
6782 goto func_fail;
6785 TRACE("changing args\n");
6786 for (i = 0; i < func_desc->cParams; i++)
6788 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6789 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6790 VARIANTARG *src_arg;
6792 if (wParamFlags & PARAMFLAG_FLCID)
6794 VARIANTARG *arg;
6795 arg = prgpvarg[i] = &rgvarg[i];
6796 V_VT(arg) = VT_I4;
6797 V_I4(arg) = This->pTypeLib->lcid;
6798 continue;
6801 src_arg = NULL;
6803 if (cNamedArgs)
6805 USHORT j;
6806 for (j = 0; j < cNamedArgs; j++)
6807 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6809 src_arg = &pDispParams->rgvarg[j];
6810 break;
6814 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6816 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6817 vargs_converted++;
6820 if (wParamFlags & PARAMFLAG_FRETVAL)
6822 /* under most conditions the caller is not allowed to
6823 * pass in a dispparam arg in the index of what would be
6824 * the retval parameter. however, there is an exception
6825 * where the extra parameter is used in an extra
6826 * IDispatch::Invoke below */
6827 if ((i < pDispParams->cArgs) &&
6828 ((func_desc->cParams != 1) || !pVarResult ||
6829 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6831 hres = DISP_E_BADPARAMCOUNT;
6832 break;
6835 /* note: this check is placed so that if the caller passes
6836 * in a VARIANTARG for the retval we just ignore it, like
6837 * native does */
6838 if (i == func_desc->cParams - 1)
6840 VARIANTARG *arg;
6841 arg = prgpvarg[i] = &rgvarg[i];
6842 memset(arg, 0, sizeof(*arg));
6843 V_VT(arg) = rgvt[i];
6844 memset(&retval, 0, sizeof(retval));
6845 V_BYREF(arg) = &retval;
6847 else
6849 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6850 hres = E_UNEXPECTED;
6851 break;
6854 else if (src_arg)
6856 dump_Variant(src_arg);
6858 if(rgvt[i]!=V_VT(src_arg))
6860 if (rgvt[i] == VT_VARIANT)
6861 hres = VariantCopy(&rgvarg[i], src_arg);
6862 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6864 if (rgvt[i] == V_VT(src_arg))
6865 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6866 else
6868 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6869 if (wParamFlags & PARAMFLAG_FIN)
6870 hres = VariantCopy(&missing_arg[i], src_arg);
6871 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6873 V_VT(&rgvarg[i]) = rgvt[i];
6875 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6877 SAFEARRAY *a;
6878 SAFEARRAYBOUND bound;
6879 VARIANT *v;
6880 LONG j;
6881 bound.lLbound = 0;
6882 bound.cElements = pDispParams->cArgs-i;
6883 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6885 ERR("SafeArrayCreate failed\n");
6886 break;
6888 hres = SafeArrayAccessData(a, (LPVOID)&v);
6889 if (hres != S_OK)
6891 ERR("SafeArrayAccessData failed with %x\n", hres);
6892 SafeArrayDestroy(a);
6893 break;
6895 for (j = 0; j < bound.cElements; j++)
6896 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6897 hres = SafeArrayUnaccessData(a);
6898 if (hres != S_OK)
6900 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6901 SafeArrayDestroy(a);
6902 break;
6904 V_ARRAY(&rgvarg[i]) = a;
6905 V_VT(&rgvarg[i]) = rgvt[i];
6907 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6909 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6910 if (wParamFlags & PARAMFLAG_FIN)
6911 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6912 else
6913 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6914 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6915 V_VT(&rgvarg[i]) = rgvt[i];
6917 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6919 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6920 V_VT(&rgvarg[i]) = rgvt[i];
6922 else
6924 /* FIXME: this doesn't work for VT_BYREF arguments if
6925 * they are not the same type as in the paramdesc */
6926 V_VT(&rgvarg[i]) = V_VT(src_arg);
6927 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6928 V_VT(&rgvarg[i]) = rgvt[i];
6931 if (FAILED(hres))
6933 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6934 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6935 debugstr_VT(src_arg), debugstr_VF(src_arg));
6936 break;
6938 prgpvarg[i] = &rgvarg[i];
6940 else
6942 prgpvarg[i] = src_arg;
6945 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6946 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6947 && V_UNKNOWN(prgpvarg[i])) {
6948 IUnknown *userdefined_iface;
6949 GUID guid;
6951 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6952 if(FAILED(hres))
6953 break;
6955 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6956 if(FAILED(hres)) {
6957 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6958 break;
6961 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6962 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6965 else if (wParamFlags & PARAMFLAG_FOPT)
6967 VARIANTARG *arg;
6968 arg = prgpvarg[i] = &rgvarg[i];
6969 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6971 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6972 if (FAILED(hres))
6973 break;
6975 else
6977 VARIANTARG *missing_arg;
6978 /* if the function wants a pointer to a variant then
6979 * set that up, otherwise just pass the VT_ERROR in
6980 * the argument by value */
6981 if (rgvt[i] & VT_BYREF)
6983 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6984 V_VT(arg) = VT_VARIANT | VT_BYREF;
6985 V_VARIANTREF(arg) = missing_arg;
6987 else
6988 missing_arg = arg;
6989 V_VT(missing_arg) = VT_ERROR;
6990 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6993 else
6995 hres = DISP_E_BADPARAMCOUNT;
6996 break;
6999 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7001 /* VT_VOID is a special case for return types, so it is not
7002 * handled in the general function */
7003 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7004 V_VT(&varresult) = VT_EMPTY;
7005 else
7007 V_VT(&varresult) = 0;
7008 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7009 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7012 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7013 V_VT(&varresult), func_desc->cParams, rgvt,
7014 prgpvarg, &varresult);
7016 vargs_converted = 0;
7018 for (i = 0; i < func_desc->cParams; i++)
7020 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7021 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7023 if (wParamFlags & PARAMFLAG_FLCID)
7024 continue;
7025 else if (wParamFlags & PARAMFLAG_FRETVAL)
7027 if (TRACE_ON(ole))
7029 TRACE("[retval] value: ");
7030 dump_Variant(prgpvarg[i]);
7033 if (pVarResult)
7035 VariantInit(pVarResult);
7036 /* deref return value */
7037 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7040 VARIANT_ClearInd(prgpvarg[i]);
7042 else if (vargs_converted < pDispParams->cArgs)
7044 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7045 if (wParamFlags & PARAMFLAG_FOUT)
7047 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7049 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7051 if (FAILED(hres))
7053 ERR("failed to convert param %d to vt %d\n", i,
7054 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7055 break;
7059 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7060 func_desc->cParamsOpt < 0 &&
7061 i == func_desc->cParams-1)
7063 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7064 LONG j, ubound;
7065 VARIANT *v;
7066 hres = SafeArrayGetUBound(a, 1, &ubound);
7067 if (hres != S_OK)
7069 ERR("SafeArrayGetUBound failed with %x\n", hres);
7070 break;
7072 hres = SafeArrayAccessData(a, (LPVOID)&v);
7073 if (hres != S_OK)
7075 ERR("SafeArrayAccessData failed with %x\n", hres);
7076 break;
7078 for (j = 0; j <= ubound; j++)
7079 VariantClear(&v[j]);
7080 hres = SafeArrayUnaccessData(a);
7081 if (hres != S_OK)
7083 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7084 break;
7087 VariantClear(&rgvarg[i]);
7088 vargs_converted++;
7090 else if (wParamFlags & PARAMFLAG_FOPT)
7092 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7093 VariantClear(&rgvarg[i]);
7096 VariantClear(&missing_arg[i]);
7099 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7101 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7102 hres = DISP_E_EXCEPTION;
7103 if (pExcepInfo)
7105 IErrorInfo *pErrorInfo;
7106 pExcepInfo->scode = V_ERROR(&varresult);
7107 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7109 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7110 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7111 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7112 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7114 IErrorInfo_Release(pErrorInfo);
7118 if (V_VT(&varresult) != VT_ERROR)
7120 TRACE("varresult value: ");
7121 dump_Variant(&varresult);
7123 if (pVarResult)
7125 VariantClear(pVarResult);
7126 *pVarResult = varresult;
7128 else
7129 VariantClear(&varresult);
7132 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7133 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7134 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7135 (pDispParams->cArgs != 0))
7137 if (V_VT(pVarResult) == VT_DISPATCH)
7139 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7140 /* Note: not VariantClear; we still need the dispatch
7141 * pointer to be valid */
7142 VariantInit(pVarResult);
7143 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7144 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7145 pDispParams, pVarResult, pExcepInfo, pArgErr);
7146 IDispatch_Release(pDispatch);
7148 else
7150 VariantClear(pVarResult);
7151 hres = DISP_E_NOTACOLLECTION;
7155 func_fail:
7156 heap_free(buffer);
7157 break;
7159 case FUNC_DISPATCH: {
7160 IDispatch *disp;
7162 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7163 if (SUCCEEDED(hres)) {
7164 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7165 hres = IDispatch_Invoke(
7166 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7167 pVarResult,pExcepInfo,pArgErr
7169 if (FAILED(hres))
7170 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7171 IDispatch_Release(disp);
7172 } else
7173 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7174 break;
7176 default:
7177 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7178 hres = E_FAIL;
7179 break;
7182 TRACE("-- 0x%08x\n", hres);
7183 return hres;
7185 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7186 VARDESC *var_desc;
7188 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7189 if(FAILED(hres)) return hres;
7191 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7192 dump_VARDESC(var_desc);
7193 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7194 return E_NOTIMPL;
7197 /* not found, look for it in inherited interfaces */
7198 ITypeInfo2_GetTypeKind(iface, &type_kind);
7199 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7200 if(This->impltypes) {
7201 /* recursive search */
7202 ITypeInfo *pTInfo;
7203 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7204 if(SUCCEEDED(hres)){
7205 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7206 ITypeInfo_Release(pTInfo);
7207 return hres;
7209 WARN("Could not search inherited interface!\n");
7212 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7213 return DISP_E_MEMBERNOTFOUND;
7216 /* ITypeInfo::GetDocumentation
7218 * Retrieves the documentation string, the complete Help file name and path,
7219 * and the context ID for the Help topic for a specified type description.
7221 * (Can be tested by the Visual Basic Editor in Word for instance.)
7223 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7224 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7225 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7227 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7228 const TLBFuncDesc *pFDesc;
7229 const TLBVarDesc *pVDesc;
7230 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7231 " HelpContext(%p) HelpFile(%p)\n",
7232 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7233 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7234 if(pBstrName)
7235 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7236 if(pBstrDocString)
7237 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7238 if(pdwHelpContext)
7239 *pdwHelpContext=This->dwHelpContext;
7240 if(pBstrHelpFile)
7241 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7242 return S_OK;
7243 }else {/* for a member */
7244 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7245 if(pFDesc){
7246 if(pBstrName)
7247 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7248 if(pBstrDocString)
7249 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7250 if(pdwHelpContext)
7251 *pdwHelpContext=pFDesc->helpcontext;
7252 if(pBstrHelpFile)
7253 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7254 return S_OK;
7256 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7257 if(pVDesc){
7258 if(pBstrName)
7259 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7260 if(pBstrDocString)
7261 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7262 if(pdwHelpContext)
7263 *pdwHelpContext=pVDesc->HelpContext;
7264 if(pBstrHelpFile)
7265 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7266 return S_OK;
7270 if(This->impltypes &&
7271 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7272 /* recursive search */
7273 ITypeInfo *pTInfo;
7274 HRESULT result;
7275 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7276 if(SUCCEEDED(result)) {
7277 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7278 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7279 ITypeInfo_Release(pTInfo);
7280 return result;
7282 WARN("Could not search inherited interface!\n");
7285 WARN("member %d not found\n", memid);
7286 return TYPE_E_ELEMENTNOTFOUND;
7289 /* ITypeInfo::GetDllEntry
7291 * Retrieves a description or specification of an entry point for a function
7292 * in a DLL.
7294 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7295 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7296 WORD *pwOrdinal)
7298 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7299 const TLBFuncDesc *pFDesc;
7301 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7303 if (pBstrDllName) *pBstrDllName = NULL;
7304 if (pBstrName) *pBstrName = NULL;
7305 if (pwOrdinal) *pwOrdinal = 0;
7307 if (This->typekind != TKIND_MODULE)
7308 return TYPE_E_BADMODULEKIND;
7310 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7311 if(pFDesc){
7312 dump_TypeInfo(This);
7313 if (TRACE_ON(ole))
7314 dump_TLBFuncDescOne(pFDesc);
7316 if (pBstrDllName)
7317 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7319 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7320 if (pBstrName)
7321 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7322 if (pwOrdinal)
7323 *pwOrdinal = -1;
7324 return S_OK;
7326 if (pBstrName)
7327 *pBstrName = NULL;
7328 if (pwOrdinal)
7329 *pwOrdinal = LOWORD(pFDesc->Entry);
7330 return S_OK;
7332 return TYPE_E_ELEMENTNOTFOUND;
7335 /* internal function to make the inherited interfaces' methods appear
7336 * part of the interface */
7337 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7338 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7340 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7341 HRESULT hr;
7343 TRACE("%p, 0x%x\n", iface, *hRefType);
7345 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7347 ITypeInfo *pSubTypeInfo;
7349 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7350 if (FAILED(hr))
7351 return hr;
7353 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7354 hRefType, ppTInfo);
7355 ITypeInfo_Release(pSubTypeInfo);
7356 if (SUCCEEDED(hr))
7357 return hr;
7359 *hRefType -= DISPATCH_HREF_OFFSET;
7361 if (!(*hRefType & DISPATCH_HREF_MASK))
7362 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7363 else
7364 return E_FAIL;
7367 /* ITypeInfo::GetRefTypeInfo
7369 * If a type description references other type descriptions, it retrieves
7370 * the referenced type descriptions.
7372 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7373 ITypeInfo2 *iface,
7374 HREFTYPE hRefType,
7375 ITypeInfo **ppTInfo)
7377 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7378 HRESULT result = E_FAIL;
7380 if(!ppTInfo)
7381 return E_INVALIDARG;
7383 if ((INT)hRefType < 0) {
7384 ITypeInfoImpl *pTypeInfoImpl;
7386 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7387 !(This->typekind == TKIND_INTERFACE ||
7388 This->typekind == TKIND_DISPATCH))
7389 return TYPE_E_ELEMENTNOTFOUND;
7391 /* when we meet a DUAL typeinfo, we must create the alternate
7392 * version of it.
7394 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7396 *pTypeInfoImpl = *This;
7397 pTypeInfoImpl->ref = 0;
7399 if (This->typekind == TKIND_INTERFACE)
7400 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7401 else
7402 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7404 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7405 /* the AddRef implicitly adds a reference to the parent typelib, which
7406 * stops the copied data from being destroyed until the new typeinfo's
7407 * refcount goes to zero, but we need to signal to the new instance to
7408 * not free its data structures when it is destroyed */
7409 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7411 ITypeInfo_AddRef(*ppTInfo);
7413 result = S_OK;
7414 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7415 (This->typekind == TKIND_DISPATCH))
7417 HREFTYPE href_dispatch = hRefType;
7418 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7419 } else {
7420 TLBRefType *ref_type;
7421 ITypeLib *pTLib = NULL;
7422 UINT i;
7424 if(!(hRefType & 0x1)){
7425 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7427 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7429 result = S_OK;
7430 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7431 ITypeInfo_AddRef(*ppTInfo);
7432 goto end;
7435 result = TYPE_E_ELEMENTNOTFOUND;
7436 goto end;
7439 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7441 if(ref_type->reference == (hRefType & (~0x3)))
7442 break;
7444 if(&ref_type->entry == &This->pTypeLib->ref_list)
7446 FIXME("Can't find pRefType for ref %x\n", hRefType);
7447 goto end;
7450 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7451 UINT Index;
7452 TRACE("internal reference\n");
7453 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7454 } else {
7455 if(ref_type->pImpTLInfo->pImpTypeLib) {
7456 TRACE("typeinfo in imported typelib that is already loaded\n");
7457 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7458 ITypeLib_AddRef(pTLib);
7459 result = S_OK;
7460 } else {
7461 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7462 result = LoadRegTypeLib( TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7463 ref_type->pImpTLInfo->wVersionMajor,
7464 ref_type->pImpTLInfo->wVersionMinor,
7465 ref_type->pImpTLInfo->lcid,
7466 &pTLib);
7468 if(FAILED(result)) {
7469 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7470 result=LoadTypeLib(libnam, &pTLib);
7471 SysFreeString(libnam);
7473 if(SUCCEEDED(result)) {
7474 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7475 ITypeLib_AddRef(pTLib);
7479 if(SUCCEEDED(result)) {
7480 if(ref_type->index == TLB_REF_USE_GUID)
7481 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7482 else
7483 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7485 if (pTLib != NULL)
7486 ITypeLib_Release(pTLib);
7489 end:
7490 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7491 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7492 return result;
7495 /* ITypeInfo::AddressOfMember
7497 * Retrieves the addresses of static functions or variables, such as those
7498 * defined in a DLL.
7500 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7501 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7503 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7504 HRESULT hr;
7505 BSTR dll, entry;
7506 WORD ordinal;
7507 HMODULE module;
7509 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7511 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7512 if (FAILED(hr))
7513 return hr;
7515 module = LoadLibraryW(dll);
7516 if (!module)
7518 ERR("couldn't load %s\n", debugstr_w(dll));
7519 SysFreeString(dll);
7520 SysFreeString(entry);
7521 return STG_E_FILENOTFOUND;
7523 /* FIXME: store library somewhere where we can free it */
7525 if (entry)
7527 LPSTR entryA;
7528 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7529 entryA = heap_alloc(len);
7530 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7532 *ppv = GetProcAddress(module, entryA);
7533 if (!*ppv)
7534 ERR("function not found %s\n", debugstr_a(entryA));
7536 heap_free(entryA);
7538 else
7540 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7541 if (!*ppv)
7542 ERR("function not found %d\n", ordinal);
7545 SysFreeString(dll);
7546 SysFreeString(entry);
7548 if (!*ppv)
7549 return TYPE_E_DLLFUNCTIONNOTFOUND;
7551 return S_OK;
7554 /* ITypeInfo::CreateInstance
7556 * Creates a new instance of a type that describes a component object class
7557 * (coclass).
7559 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7560 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7562 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7563 HRESULT hr;
7564 TYPEATTR *pTA;
7566 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7568 *ppvObj = NULL;
7570 if(pOuterUnk)
7572 WARN("Not able to aggregate\n");
7573 return CLASS_E_NOAGGREGATION;
7576 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7577 if(FAILED(hr)) return hr;
7579 if(pTA->typekind != TKIND_COCLASS)
7581 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7582 hr = E_INVALIDARG;
7583 goto end;
7586 hr = S_FALSE;
7587 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7589 IUnknown *pUnk;
7590 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7591 TRACE("GetActiveObject rets %08x\n", hr);
7592 if(hr == S_OK)
7594 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7595 IUnknown_Release(pUnk);
7599 if(hr != S_OK)
7600 hr = CoCreateInstance(&pTA->guid, NULL,
7601 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7602 riid, ppvObj);
7604 end:
7605 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7606 return hr;
7609 /* ITypeInfo::GetMops
7611 * Retrieves marshalling information.
7613 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7614 BSTR *pBstrMops)
7616 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7617 FIXME("(%p %d) stub!\n", This, memid);
7618 *pBstrMops = NULL;
7619 return S_OK;
7622 /* ITypeInfo::GetContainingTypeLib
7624 * Retrieves the containing type library and the index of the type description
7625 * within that type library.
7627 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7628 ITypeLib * *ppTLib, UINT *pIndex)
7630 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7632 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7633 if (pIndex) {
7634 *pIndex=This->index;
7635 TRACE("returning pIndex=%d\n", *pIndex);
7638 if (ppTLib) {
7639 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7640 ITypeLib_AddRef(*ppTLib);
7641 TRACE("returning ppTLib=%p\n", *ppTLib);
7644 return S_OK;
7647 /* ITypeInfo::ReleaseTypeAttr
7649 * Releases a TYPEATTR previously returned by Get
7652 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7653 TYPEATTR* pTypeAttr)
7655 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7656 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7657 heap_free(pTypeAttr);
7660 /* ITypeInfo::ReleaseFuncDesc
7662 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7664 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7665 ITypeInfo2 *iface,
7666 FUNCDESC *pFuncDesc)
7668 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7669 SHORT i;
7671 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7673 for (i = 0; i < pFuncDesc->cParams; i++)
7674 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7675 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7677 SysFreeString((BSTR)pFuncDesc);
7680 /* ITypeInfo::ReleaseVarDesc
7682 * Releases a VARDESC previously returned by GetVarDesc.
7684 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7685 VARDESC *pVarDesc)
7687 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7688 TRACE("(%p)->(%p)\n", This, pVarDesc);
7690 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7691 if (pVarDesc->varkind == VAR_CONST)
7692 VariantClear(pVarDesc->u.lpvarValue);
7693 SysFreeString((BSTR)pVarDesc);
7696 /* ITypeInfo2::GetTypeKind
7698 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7701 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7702 TYPEKIND *pTypeKind)
7704 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7705 *pTypeKind=This->typekind;
7706 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7707 return S_OK;
7710 /* ITypeInfo2::GetTypeFlags
7712 * Returns the type flags without any allocations. This returns a DWORD type
7713 * flag, which expands the type flags without growing the TYPEATTR (type
7714 * attribute).
7717 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7719 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7720 *pTypeFlags=This->wTypeFlags;
7721 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7722 return S_OK;
7725 /* ITypeInfo2::GetFuncIndexOfMemId
7726 * Binds to a specific member based on a known DISPID, where the member name
7727 * is not known (for example, when binding to a default member).
7730 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7731 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7733 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7734 UINT fdc;
7735 HRESULT result;
7737 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7738 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7739 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7740 break;
7742 if(fdc < This->cFuncs) {
7743 *pFuncIndex = fdc;
7744 result = S_OK;
7745 } else
7746 result = TYPE_E_ELEMENTNOTFOUND;
7748 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7749 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7750 return result;
7753 /* TypeInfo2::GetVarIndexOfMemId
7755 * Binds to a specific member based on a known DISPID, where the member name
7756 * is not known (for example, when binding to a default member).
7759 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7760 MEMBERID memid, UINT *pVarIndex)
7762 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7763 TLBVarDesc *pVarInfo;
7765 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7767 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7768 if(!pVarInfo)
7769 return TYPE_E_ELEMENTNOTFOUND;
7771 *pVarIndex = (pVarInfo - This->vardescs);
7773 return S_OK;
7776 /* ITypeInfo2::GetCustData
7778 * Gets the custom data
7780 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7781 ITypeInfo2 * iface,
7782 REFGUID guid,
7783 VARIANT *pVarVal)
7785 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7786 TLBCustData *pCData;
7788 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7790 if(!guid || !pVarVal)
7791 return E_INVALIDARG;
7793 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7795 VariantInit( pVarVal);
7796 if (pCData)
7797 VariantCopy( pVarVal, &pCData->data);
7798 else
7799 VariantClear( pVarVal );
7800 return S_OK;
7803 /* ITypeInfo2::GetFuncCustData
7805 * Gets the custom data
7807 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7808 ITypeInfo2 * iface,
7809 UINT index,
7810 REFGUID guid,
7811 VARIANT *pVarVal)
7813 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7814 TLBCustData *pCData;
7815 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7817 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7819 if(index >= This->cFuncs)
7820 return TYPE_E_ELEMENTNOTFOUND;
7822 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7823 if(!pCData)
7824 return TYPE_E_ELEMENTNOTFOUND;
7826 VariantInit(pVarVal);
7827 VariantCopy(pVarVal, &pCData->data);
7829 return S_OK;
7832 /* ITypeInfo2::GetParamCustData
7834 * Gets the custom data
7836 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7837 ITypeInfo2 * iface,
7838 UINT indexFunc,
7839 UINT indexParam,
7840 REFGUID guid,
7841 VARIANT *pVarVal)
7843 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7844 TLBCustData *pCData;
7845 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7847 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7848 debugstr_guid(guid), pVarVal);
7850 if(indexFunc >= This->cFuncs)
7851 return TYPE_E_ELEMENTNOTFOUND;
7853 if(indexParam >= pFDesc->funcdesc.cParams)
7854 return TYPE_E_ELEMENTNOTFOUND;
7856 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7857 if(!pCData)
7858 return TYPE_E_ELEMENTNOTFOUND;
7860 VariantInit(pVarVal);
7861 VariantCopy(pVarVal, &pCData->data);
7863 return S_OK;
7866 /* ITypeInfo2::GetVarCustData
7868 * Gets the custom data
7870 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7871 ITypeInfo2 * iface,
7872 UINT index,
7873 REFGUID guid,
7874 VARIANT *pVarVal)
7876 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7877 TLBCustData *pCData;
7878 TLBVarDesc *pVDesc = &This->vardescs[index];
7880 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7882 if(index >= This->cVars)
7883 return TYPE_E_ELEMENTNOTFOUND;
7885 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7886 if(!pCData)
7887 return TYPE_E_ELEMENTNOTFOUND;
7889 VariantInit(pVarVal);
7890 VariantCopy(pVarVal, &pCData->data);
7892 return S_OK;
7895 /* ITypeInfo2::GetImplCustData
7897 * Gets the custom data
7899 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7900 ITypeInfo2 * iface,
7901 UINT index,
7902 REFGUID guid,
7903 VARIANT *pVarVal)
7905 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7906 TLBCustData *pCData;
7907 TLBImplType *pRDesc = &This->impltypes[index];
7909 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7911 if(index >= This->cImplTypes)
7912 return TYPE_E_ELEMENTNOTFOUND;
7914 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7915 if(!pCData)
7916 return TYPE_E_ELEMENTNOTFOUND;
7918 VariantInit(pVarVal);
7919 VariantCopy(pVarVal, &pCData->data);
7921 return S_OK;
7924 /* ITypeInfo2::GetDocumentation2
7926 * Retrieves the documentation string, the complete Help file name and path,
7927 * the localization context to use, and the context ID for the library Help
7928 * topic in the Help file.
7931 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7932 ITypeInfo2 * iface,
7933 MEMBERID memid,
7934 LCID lcid,
7935 BSTR *pbstrHelpString,
7936 DWORD *pdwHelpStringContext,
7937 BSTR *pbstrHelpStringDll)
7939 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7940 const TLBFuncDesc *pFDesc;
7941 const TLBVarDesc *pVDesc;
7942 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7943 "HelpStringContext(%p) HelpStringDll(%p)\n",
7944 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7945 pbstrHelpStringDll );
7946 /* the help string should be obtained from the helpstringdll,
7947 * using the _DLLGetDocumentation function, based on the supplied
7948 * lcid. Nice to do sometime...
7950 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7951 if(pbstrHelpString)
7952 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
7953 if(pdwHelpStringContext)
7954 *pdwHelpStringContext=This->dwHelpStringContext;
7955 if(pbstrHelpStringDll)
7956 *pbstrHelpStringDll=
7957 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7958 return S_OK;
7959 }else {/* for a member */
7960 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7961 if(pFDesc){
7962 if(pbstrHelpString)
7963 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7964 if(pdwHelpStringContext)
7965 *pdwHelpStringContext=pFDesc->HelpStringContext;
7966 if(pbstrHelpStringDll)
7967 *pbstrHelpStringDll=
7968 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7969 return S_OK;
7971 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7972 if(pVDesc){
7973 if(pbstrHelpString)
7974 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7975 if(pdwHelpStringContext)
7976 *pdwHelpStringContext=pVDesc->HelpStringContext;
7977 if(pbstrHelpStringDll)
7978 *pbstrHelpStringDll=
7979 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7980 return S_OK;
7983 return TYPE_E_ELEMENTNOTFOUND;
7986 /* ITypeInfo2::GetAllCustData
7988 * Gets all custom data items for the Type info.
7991 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7992 ITypeInfo2 * iface,
7993 CUSTDATA *pCustData)
7995 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7997 TRACE("%p %p\n", This, pCustData);
7999 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
8002 /* ITypeInfo2::GetAllFuncCustData
8004 * Gets all custom data items for the specified Function
8007 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8008 ITypeInfo2 * iface,
8009 UINT index,
8010 CUSTDATA *pCustData)
8012 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8013 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8015 TRACE("%p %u %p\n", This, index, pCustData);
8017 if(index >= This->cFuncs)
8018 return TYPE_E_ELEMENTNOTFOUND;
8020 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8023 /* ITypeInfo2::GetAllParamCustData
8025 * Gets all custom data items for the Functions
8028 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8029 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8031 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8032 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8034 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8036 if(indexFunc >= This->cFuncs)
8037 return TYPE_E_ELEMENTNOTFOUND;
8039 if(indexParam >= pFDesc->funcdesc.cParams)
8040 return TYPE_E_ELEMENTNOTFOUND;
8042 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8045 /* ITypeInfo2::GetAllVarCustData
8047 * Gets all custom data items for the specified Variable
8050 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8051 UINT index, CUSTDATA *pCustData)
8053 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8054 TLBVarDesc * pVDesc = &This->vardescs[index];
8056 TRACE("%p %u %p\n", This, index, pCustData);
8058 if(index >= This->cVars)
8059 return TYPE_E_ELEMENTNOTFOUND;
8061 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8064 /* ITypeInfo2::GetAllImplCustData
8066 * Gets all custom data items for the specified implementation type
8069 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8070 ITypeInfo2 * iface,
8071 UINT index,
8072 CUSTDATA *pCustData)
8074 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8075 TLBImplType *pRDesc = &This->impltypes[index];
8077 TRACE("%p %u %p\n", This, index, pCustData);
8079 if(index >= This->cImplTypes)
8080 return TYPE_E_ELEMENTNOTFOUND;
8082 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8085 static const ITypeInfo2Vtbl tinfvt =
8088 ITypeInfo_fnQueryInterface,
8089 ITypeInfo_fnAddRef,
8090 ITypeInfo_fnRelease,
8092 ITypeInfo_fnGetTypeAttr,
8093 ITypeInfo_fnGetTypeComp,
8094 ITypeInfo_fnGetFuncDesc,
8095 ITypeInfo_fnGetVarDesc,
8096 ITypeInfo_fnGetNames,
8097 ITypeInfo_fnGetRefTypeOfImplType,
8098 ITypeInfo_fnGetImplTypeFlags,
8099 ITypeInfo_fnGetIDsOfNames,
8100 ITypeInfo_fnInvoke,
8101 ITypeInfo_fnGetDocumentation,
8102 ITypeInfo_fnGetDllEntry,
8103 ITypeInfo_fnGetRefTypeInfo,
8104 ITypeInfo_fnAddressOfMember,
8105 ITypeInfo_fnCreateInstance,
8106 ITypeInfo_fnGetMops,
8107 ITypeInfo_fnGetContainingTypeLib,
8108 ITypeInfo_fnReleaseTypeAttr,
8109 ITypeInfo_fnReleaseFuncDesc,
8110 ITypeInfo_fnReleaseVarDesc,
8112 ITypeInfo2_fnGetTypeKind,
8113 ITypeInfo2_fnGetTypeFlags,
8114 ITypeInfo2_fnGetFuncIndexOfMemId,
8115 ITypeInfo2_fnGetVarIndexOfMemId,
8116 ITypeInfo2_fnGetCustData,
8117 ITypeInfo2_fnGetFuncCustData,
8118 ITypeInfo2_fnGetParamCustData,
8119 ITypeInfo2_fnGetVarCustData,
8120 ITypeInfo2_fnGetImplTypeCustData,
8121 ITypeInfo2_fnGetDocumentation2,
8122 ITypeInfo2_fnGetAllCustData,
8123 ITypeInfo2_fnGetAllFuncCustData,
8124 ITypeInfo2_fnGetAllParamCustData,
8125 ITypeInfo2_fnGetAllVarCustData,
8126 ITypeInfo2_fnGetAllImplTypeCustData,
8129 /******************************************************************************
8130 * CreateDispTypeInfo [OLEAUT32.31]
8132 * Build type information for an object so it can be called through an
8133 * IDispatch interface.
8135 * RETURNS
8136 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8137 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8139 * NOTES
8140 * This call allows an objects methods to be accessed through IDispatch, by
8141 * building an ITypeInfo object that IDispatch can use to call through.
8143 HRESULT WINAPI CreateDispTypeInfo(
8144 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8145 LCID lcid, /* [I] Locale Id */
8146 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8148 ITypeInfoImpl *pTIClass, *pTIIface;
8149 ITypeLibImpl *pTypeLibImpl;
8150 unsigned int param, func;
8151 TLBFuncDesc *pFuncDesc;
8152 TLBRefType *ref;
8154 TRACE("\n");
8155 pTypeLibImpl = TypeLibImpl_Constructor();
8156 if (!pTypeLibImpl) return E_FAIL;
8158 pTypeLibImpl->TypeInfoCount = 2;
8159 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8161 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8162 pTIIface->pTypeLib = pTypeLibImpl;
8163 pTIIface->index = 0;
8164 pTIIface->Name = NULL;
8165 pTIIface->dwHelpContext = -1;
8166 pTIIface->guid = NULL;
8167 pTIIface->lcid = lcid;
8168 pTIIface->typekind = TKIND_INTERFACE;
8169 pTIIface->wMajorVerNum = 0;
8170 pTIIface->wMinorVerNum = 0;
8171 pTIIface->cbAlignment = 2;
8172 pTIIface->cbSizeInstance = -1;
8173 pTIIface->cbSizeVft = -1;
8174 pTIIface->cFuncs = 0;
8175 pTIIface->cImplTypes = 0;
8176 pTIIface->cVars = 0;
8177 pTIIface->wTypeFlags = 0;
8178 pTIIface->hreftype = 0;
8180 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8181 pFuncDesc = pTIIface->funcdescs;
8182 for(func = 0; func < pidata->cMembers; func++) {
8183 METHODDATA *md = pidata->pmethdata + func;
8184 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8185 pFuncDesc->funcdesc.memid = md->dispid;
8186 pFuncDesc->funcdesc.lprgscode = NULL;
8187 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8188 pFuncDesc->funcdesc.invkind = md->wFlags;
8189 pFuncDesc->funcdesc.callconv = md->cc;
8190 pFuncDesc->funcdesc.cParams = md->cArgs;
8191 pFuncDesc->funcdesc.cParamsOpt = 0;
8192 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8193 pFuncDesc->funcdesc.cScodes = 0;
8194 pFuncDesc->funcdesc.wFuncFlags = 0;
8195 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8196 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8197 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8198 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8199 md->cArgs * sizeof(ELEMDESC));
8200 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8201 for(param = 0; param < md->cArgs; param++) {
8202 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8203 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8205 pFuncDesc->helpcontext = 0;
8206 pFuncDesc->HelpStringContext = 0;
8207 pFuncDesc->HelpString = NULL;
8208 pFuncDesc->Entry = NULL;
8209 list_init(&pFuncDesc->custdata_list);
8210 pTIIface->cFuncs++;
8211 ++pFuncDesc;
8214 dump_TypeInfo(pTIIface);
8216 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8217 pTIClass->pTypeLib = pTypeLibImpl;
8218 pTIClass->index = 1;
8219 pTIClass->Name = NULL;
8220 pTIClass->dwHelpContext = -1;
8221 pTIClass->guid = NULL;
8222 pTIClass->lcid = lcid;
8223 pTIClass->typekind = TKIND_COCLASS;
8224 pTIClass->wMajorVerNum = 0;
8225 pTIClass->wMinorVerNum = 0;
8226 pTIClass->cbAlignment = 2;
8227 pTIClass->cbSizeInstance = -1;
8228 pTIClass->cbSizeVft = -1;
8229 pTIClass->cFuncs = 0;
8230 pTIClass->cImplTypes = 1;
8231 pTIClass->cVars = 0;
8232 pTIClass->wTypeFlags = 0;
8233 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8235 pTIClass->impltypes = TLBImplType_Alloc(1);
8237 ref = heap_alloc_zero(sizeof(*ref));
8238 ref->pImpTLInfo = TLB_REF_INTERNAL;
8239 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8241 dump_TypeInfo(pTIClass);
8243 *pptinfo = (ITypeInfo*)pTIClass;
8245 ITypeInfo_AddRef(*pptinfo);
8246 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8248 return S_OK;
8252 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8254 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8256 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
8259 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8261 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8263 return ITypeInfo_AddRef((ITypeInfo *)This);
8266 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8268 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8270 return ITypeInfo_Release((ITypeInfo *)This);
8273 static HRESULT WINAPI ITypeComp_fnBind(
8274 ITypeComp * iface,
8275 OLECHAR * szName,
8276 ULONG lHash,
8277 WORD wFlags,
8278 ITypeInfo ** ppTInfo,
8279 DESCKIND * pDescKind,
8280 BINDPTR * pBindPtr)
8282 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8283 const TLBFuncDesc *pFDesc;
8284 const TLBVarDesc *pVDesc;
8285 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8286 UINT fdc;
8288 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8290 *pDescKind = DESCKIND_NONE;
8291 pBindPtr->lpfuncdesc = NULL;
8292 *ppTInfo = NULL;
8294 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8295 pFDesc = &This->funcdescs[fdc];
8296 if (!strcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8297 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8298 break;
8299 else
8300 /* name found, but wrong flags */
8301 hr = TYPE_E_TYPEMISMATCH;
8305 if (fdc < This->cFuncs)
8307 HRESULT hr = TLB_AllocAndInitFuncDesc(
8308 &pFDesc->funcdesc,
8309 &pBindPtr->lpfuncdesc,
8310 This->typekind == TKIND_DISPATCH);
8311 if (FAILED(hr))
8312 return hr;
8313 *pDescKind = DESCKIND_FUNCDESC;
8314 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8315 ITypeInfo_AddRef(*ppTInfo);
8316 return S_OK;
8317 } else {
8318 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8319 if(pVDesc){
8320 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8321 if (FAILED(hr))
8322 return hr;
8323 *pDescKind = DESCKIND_VARDESC;
8324 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8325 ITypeInfo_AddRef(*ppTInfo);
8326 return S_OK;
8329 /* FIXME: search each inherited interface, not just the first */
8330 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8331 /* recursive search */
8332 ITypeInfo *pTInfo;
8333 ITypeComp *pTComp;
8334 HRESULT hr;
8335 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8336 if (SUCCEEDED(hr))
8338 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8339 ITypeInfo_Release(pTInfo);
8341 if (SUCCEEDED(hr))
8343 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8344 ITypeComp_Release(pTComp);
8345 return hr;
8347 WARN("Could not search inherited interface!\n");
8349 if (hr == DISP_E_MEMBERNOTFOUND)
8350 hr = S_OK;
8351 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8352 return hr;
8355 static HRESULT WINAPI ITypeComp_fnBindType(
8356 ITypeComp * iface,
8357 OLECHAR * szName,
8358 ULONG lHash,
8359 ITypeInfo ** ppTInfo,
8360 ITypeComp ** ppTComp)
8362 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8364 /* strange behaviour (does nothing) but like the
8365 * original */
8367 if (!ppTInfo || !ppTComp)
8368 return E_POINTER;
8370 *ppTInfo = NULL;
8371 *ppTComp = NULL;
8373 return S_OK;
8376 static const ITypeCompVtbl tcompvt =
8379 ITypeComp_fnQueryInterface,
8380 ITypeComp_fnAddRef,
8381 ITypeComp_fnRelease,
8383 ITypeComp_fnBind,
8384 ITypeComp_fnBindType
8387 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8388 REFIID riid, void **object)
8390 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8392 return ITypeLib2_QueryInterface((ITypeLib2*)This, riid, object);
8395 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8397 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8399 return ITypeLib2_AddRef((ITypeLib2*)This);
8402 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8404 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8406 return ITypeLib2_Release((ITypeLib2*)This);
8409 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8410 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8412 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8413 ITypeInfoImpl *info;
8414 HRESULT hres;
8416 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8418 if (!ctinfo || !name)
8419 return E_INVALIDARG;
8421 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8422 if (info)
8423 return TYPE_E_NAMECONFLICT;
8425 if (This->typeinfos)
8426 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8427 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8428 else
8429 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8431 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8433 info->pTypeLib = This;
8434 info->Name = TLB_append_str(&This->name_list, name);
8435 info->index = This->TypeInfoCount;
8436 info->typekind = kind;
8437 info->cbAlignment = 4;
8439 switch(info->typekind) {
8440 case TKIND_ENUM:
8441 case TKIND_INTERFACE:
8442 case TKIND_DISPATCH:
8443 case TKIND_COCLASS:
8444 info->cbSizeInstance = 4;
8445 break;
8446 case TKIND_RECORD:
8447 case TKIND_UNION:
8448 info->cbSizeInstance = 0;
8449 break;
8450 case TKIND_MODULE:
8451 info->cbSizeInstance = 2;
8452 break;
8453 case TKIND_ALIAS:
8454 info->cbSizeInstance = -0x75;
8455 break;
8456 default:
8457 FIXME("unrecognized typekind %d\n", info->typekind);
8458 info->cbSizeInstance = 0xdeadbeef;
8459 break;
8462 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8463 &IID_ICreateTypeInfo, (void **)ctinfo);
8464 if (FAILED(hres)) {
8465 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8466 return hres;
8469 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8471 ++This->TypeInfoCount;
8473 return S_OK;
8476 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8477 LPOLESTR name)
8479 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8481 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8483 if (!name)
8484 return E_INVALIDARG;
8486 This->Name = TLB_append_str(&This->name_list, name);
8488 return S_OK;
8491 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8492 WORD majorVerNum, WORD minorVerNum)
8494 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8496 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8498 This->ver_major = majorVerNum;
8499 This->ver_minor = minorVerNum;
8501 return S_OK;
8504 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8505 REFGUID guid)
8507 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8509 TRACE("%p %s\n", This, debugstr_guid(guid));
8511 This->guid = TLB_append_guid(&This->guid_list, guid);
8513 return S_OK;
8516 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8517 LPOLESTR doc)
8519 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8521 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8523 if (!doc)
8524 return E_INVALIDARG;
8526 This->DocString = TLB_append_str(&This->string_list, doc);
8528 return S_OK;
8531 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8532 LPOLESTR helpFileName)
8534 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8536 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8538 if (!helpFileName)
8539 return E_INVALIDARG;
8541 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8543 return S_OK;
8546 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8547 DWORD helpContext)
8549 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8551 TRACE("%p %d\n", This, helpContext);
8553 This->dwHelpContext = helpContext;
8555 return S_OK;
8558 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8559 LCID lcid)
8561 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8563 TRACE("%p %x\n", This, lcid);
8565 This->set_lcid = lcid;
8567 return S_OK;
8570 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8571 UINT libFlags)
8573 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8575 TRACE("%p %x\n", This, libFlags);
8577 This->libflags = libFlags;
8579 return S_OK;
8582 typedef struct tagWMSFT_SegContents {
8583 DWORD len;
8584 void *data;
8585 } WMSFT_SegContents;
8587 typedef struct tagWMSFT_TLBFile {
8588 MSFT_Header header;
8589 WMSFT_SegContents typeinfo_seg;
8590 WMSFT_SegContents impfile_seg;
8591 WMSFT_SegContents impinfo_seg;
8592 WMSFT_SegContents ref_seg;
8593 WMSFT_SegContents lib_seg;
8594 WMSFT_SegContents guid_seg;
8595 WMSFT_SegContents res07_seg;
8596 WMSFT_SegContents name_seg;
8597 WMSFT_SegContents string_seg;
8598 WMSFT_SegContents typdesc_seg;
8599 WMSFT_SegContents arraydesc_seg;
8600 WMSFT_SegContents custdata_seg;
8601 WMSFT_SegContents cdguids_seg;
8602 MSFT_SegDir segdir;
8603 WMSFT_SegContents aux_seg;
8604 } WMSFT_TLBFile;
8606 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8607 WMSFT_TLBFile *file)
8609 TLBString *str;
8610 UINT last_offs;
8611 char *data;
8613 file->string_seg.len = 0;
8614 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8615 int size;
8617 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8618 if (size == 0)
8619 return E_UNEXPECTED;
8621 size += sizeof(INT16);
8622 if (size % 4)
8623 size = (size + 4) & ~0x3;
8624 if (size < 8)
8625 size = 8;
8627 file->string_seg.len += size;
8629 /* temporarily use str->offset to store the length of the aligned,
8630 * converted string */
8631 str->offset = size;
8634 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8636 last_offs = 0;
8637 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8638 int size;
8640 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8641 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8642 if (size == 0) {
8643 heap_free(file->string_seg.data);
8644 return E_UNEXPECTED;
8647 *((INT16*)data) = size;
8649 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8651 size = str->offset;
8652 data += size;
8653 str->offset = last_offs;
8654 last_offs += size;
8657 return S_OK;
8660 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8661 WMSFT_TLBFile *file)
8663 TLBString *str;
8664 UINT last_offs;
8665 char *data;
8666 MSFT_NameIntro *last_intro = NULL;
8668 file->header.nametablecount = 0;
8669 file->header.nametablechars = 0;
8671 file->name_seg.len = 0;
8672 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8673 int size;
8675 size = strlenW(str->str);
8676 file->header.nametablechars += size;
8677 file->header.nametablecount++;
8679 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8680 if (size == 0)
8681 return E_UNEXPECTED;
8683 size += sizeof(MSFT_NameIntro);
8684 if (size % 4)
8685 size = (size + 4) & ~0x3;
8686 if (size < 8)
8687 size = 8;
8689 file->name_seg.len += size;
8691 /* temporarily use str->offset to store the length of the aligned,
8692 * converted string */
8693 str->offset = size;
8696 file->name_seg.data = data = heap_alloc(file->name_seg.len);
8698 last_offs = 0;
8699 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8700 int size;
8701 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8703 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8704 data + sizeof(MSFT_NameIntro),
8705 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8706 if (size == 0) {
8707 heap_free(file->name_seg.data);
8708 return E_UNEXPECTED;
8710 data[sizeof(MSFT_NameIntro) + size] = '\0';
8712 intro->hreftype = -1; /* TODO? */
8713 intro->next_hash = -1;
8714 intro->namelen = size & 0xFF;
8715 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8716 intro->namelen |= LHashValOfNameSysA(This->syskind,
8717 This->lcid, data + sizeof(MSFT_NameIntro)) << 16;
8719 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8720 str->offset - size - sizeof(MSFT_NameIntro));
8722 /* update str->offset to actual value to use in other
8723 * compilation functions that require positions within
8724 * the string table */
8725 last_intro = intro;
8726 size = str->offset;
8727 data += size;
8728 str->offset = last_offs;
8729 last_offs += size;
8732 if(last_intro)
8733 last_intro->hreftype = 0; /* last one is 0? */
8735 return S_OK;
8738 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8740 TLBGuid *guid;
8741 MSFT_GuidEntry *entry;
8742 DWORD offs;
8744 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8745 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8747 entry = file->guid_seg.data;
8748 offs = 0;
8749 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
8750 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
8751 entry->hreftype = 0xFFFFFFFF; /* TODO */
8752 entry->next_hash = 0xFFFFFFFF; /* TODO? */
8754 guid->offset = offs;
8756 offs += sizeof(MSFT_GuidEntry);
8757 ++entry;
8760 --entry;
8761 entry->next_hash = 0; /* last one has 0? */
8763 return S_OK;
8766 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
8768 VARIANT v = *value;
8769 VARTYPE arg_type = V_VT(value);
8770 int mask = 0;
8771 HRESULT hres;
8772 DWORD ret = file->custdata_seg.len;
8774 if(arg_type == VT_INT)
8775 arg_type = VT_I4;
8776 if(arg_type == VT_UINT)
8777 arg_type = VT_UI4;
8779 v = *value;
8780 if(V_VT(value) != arg_type) {
8781 hres = VariantChangeType(&v, value, 0, arg_type);
8782 if(FAILED(hres)){
8783 ERR("VariantChangeType failed: %08x\n", hres);
8784 return -1;
8788 /* Check if default value can be stored in-place */
8789 switch(arg_type){
8790 case VT_I4:
8791 case VT_UI4:
8792 mask = 0x3ffffff;
8793 if(V_UI4(&v) > 0x3ffffff)
8794 break;
8795 /* fall through */
8796 case VT_I1:
8797 case VT_UI1:
8798 case VT_BOOL:
8799 if(!mask)
8800 mask = 0xff;
8801 /* fall through */
8802 case VT_I2:
8803 case VT_UI2:
8804 if(!mask)
8805 mask = 0xffff;
8806 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
8809 /* have to allocate space in custdata_seg */
8810 switch(arg_type) {
8811 case VT_I4:
8812 case VT_R4:
8813 case VT_UI4:
8814 case VT_INT:
8815 case VT_UINT:
8816 case VT_HRESULT:
8817 case VT_PTR: {
8818 /* Construct the data to be allocated */
8819 int *data;
8821 if(file->custdata_seg.data){
8822 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
8823 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
8824 file->custdata_seg.len += sizeof(int) * 2;
8825 }else{
8826 file->custdata_seg.len = sizeof(int) * 2;
8827 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8830 data[0] = V_VT(value) + (V_UI4(&v) << 16);
8831 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
8833 /* TODO: Check if the encoded data is already present in custdata_seg */
8835 return ret;
8838 case VT_BSTR: {
8839 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
8840 char *data;
8842 if(file->custdata_seg.data){
8843 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
8844 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
8845 file->custdata_seg.len += len;
8846 }else{
8847 file->custdata_seg.len = len;
8848 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8851 *((unsigned short *)data) = V_VT(value);
8852 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
8853 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
8854 if(V_BSTR(&v)[i] <= 0x7f)
8855 data[i+6] = V_BSTR(&v)[i];
8856 else
8857 data[i+6] = '?';
8859 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
8860 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
8861 data[i] = 0x57;
8863 /* TODO: Check if the encoded data is already present in custdata_seg */
8865 return ret;
8867 default:
8868 FIXME("Argument type not yet handled\n");
8869 return -1;
8873 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
8875 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
8877 DWORD offs = file->arraydesc_seg.len;
8878 DWORD *encoded;
8879 USHORT i;
8881 /* TODO: we should check for duplicates, but that's harder because each
8882 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8883 * at the library-level) */
8885 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
8886 if(!file->arraydesc_seg.data)
8887 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
8888 else
8889 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
8890 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
8892 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
8893 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
8894 for(i = 0; i < desc->cDims; ++i){
8895 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
8896 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
8899 return offs;
8902 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
8904 DWORD junk;
8905 INT16 junk2;
8906 DWORD offs = 0;
8907 DWORD encoded[2];
8908 VARTYPE vt = desc->vt & VT_TYPEMASK, subtype;
8909 char *data;
8911 if(!out_mix)
8912 out_mix = &junk;
8913 if(!out_size)
8914 out_size = &junk2;
8916 switch(vt){
8917 case VT_INT:
8918 subtype = VT_I4;
8919 break;
8920 case VT_UINT:
8921 subtype = VT_UI4;
8922 break;
8923 case VT_VOID:
8924 subtype = VT_EMPTY;
8925 break;
8926 default:
8927 subtype = vt;
8928 break;
8931 switch(vt){
8932 case VT_INT:
8933 case VT_UINT:
8934 case VT_I1:
8935 case VT_UI1:
8936 case VT_I2:
8937 case VT_UI2:
8938 case VT_I4:
8939 case VT_UI4:
8940 case VT_BOOL:
8941 case VT_R4:
8942 case VT_ERROR:
8943 case VT_BSTR:
8944 case VT_HRESULT:
8945 case VT_CY:
8946 case VT_VOID:
8947 case VT_VARIANT:
8948 *out_mix = subtype;
8949 return 0x80000000 | (subtype << 16) | desc->vt;
8952 if(vt == VT_PTR || vt == VT_SAFEARRAY){
8953 DWORD mix;
8954 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
8955 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
8956 *out_mix = 0x7FFF;
8957 *out_size += 2 * sizeof(DWORD);
8958 }else if(vt == VT_CARRAY){
8959 encoded[0] = desc->vt | (0x7FFE << 16);
8960 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
8961 *out_mix = 0x7FFE;
8962 }else if(vt == VT_USERDEFINED){
8963 encoded[0] = desc->vt | (0x7FFF << 16);
8964 encoded[1] = desc->u.hreftype;
8965 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
8966 }else{
8967 FIXME("Don't know what to do! VT: 0x%x\n", desc->vt);
8968 *out_mix = desc->vt;
8969 return 0x80000000 | (desc->vt << 16) | desc->vt;
8972 data = file->typdesc_seg.data;
8973 while(offs < file->typdesc_seg.len){
8974 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
8975 return offs;
8976 offs += sizeof(encoded);
8979 file->typdesc_seg.len += sizeof(encoded);
8980 if(!file->typdesc_seg.data)
8981 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
8982 else
8983 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
8985 memcpy(&data[offs], encoded, sizeof(encoded));
8987 return offs;
8990 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
8992 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
8993 DWORD ret = cdguids_seg->len, offs;
8994 MSFT_CDGuid *cdguid = cdguids_seg->data;
8995 TLBCustData *cd;
8997 if(list_empty(custdata_list))
8998 return -1;
9000 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9001 if(!cdguids_seg->data){
9002 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9003 }else
9004 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9006 offs = ret + sizeof(MSFT_CDGuid);
9007 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9008 cdguid->GuidOffset = cd->guid->offset;
9009 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9010 cdguid->next = offs;
9011 offs += sizeof(MSFT_CDGuid);
9012 ++cdguid;
9015 --cdguid;
9016 cdguid->next = -1;
9018 return ret;
9021 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9022 WMSFT_TLBFile *file)
9024 WMSFT_SegContents *aux_seg = &file->aux_seg;
9025 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9026 MSFT_VarRecord *varrecord;
9027 MSFT_FuncRecord *funcrecord;
9028 MEMBERID *memid;
9029 DWORD *name, *offsets, offs;
9031 for(i = 0; i < info->cFuncs; ++i){
9032 TLBFuncDesc *desc = &info->funcdescs[i];
9034 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9036 /* optional fields */
9037 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9038 if(!list_empty(&desc->custdata_list))
9039 recorded_size += 7 * sizeof(INT);
9040 else if(desc->HelpStringContext != 0)
9041 recorded_size += 6 * sizeof(INT);
9042 /* res9? resA? */
9043 else if(desc->Entry)
9044 recorded_size += 3 * sizeof(INT);
9045 else if(desc->HelpString)
9046 recorded_size += 2 * sizeof(INT);
9047 else if(desc->helpcontext)
9048 recorded_size += sizeof(INT);
9050 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9052 for(j = 0; j < desc->funcdesc.cParams; ++j){
9053 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9054 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9055 break;
9059 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9062 for(i = 0; i < info->cVars; ++i){
9063 TLBVarDesc *desc = &info->vardescs[i];
9065 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9067 /* optional fields */
9068 if(desc->HelpStringContext != 0)
9069 recorded_size += 5 * sizeof(INT);
9070 else if(!list_empty(&desc->custdata_list))
9071 recorded_size += 4 * sizeof(INT);
9072 /* res9? */
9073 else if(desc->HelpString)
9074 recorded_size += 2 * sizeof(INT);
9075 else if(desc->HelpContext != 0)
9076 recorded_size += sizeof(INT);
9078 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9081 if(!recorded_size && !extra_size)
9082 return ret;
9084 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9086 aux_seg->len += recorded_size + extra_size;
9088 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9090 if(aux_seg->data)
9091 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9092 else
9093 aux_seg->data = heap_alloc(aux_seg->len);
9095 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9097 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9098 offs = 0;
9100 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9101 for(i = 0; i < info->cFuncs; ++i){
9102 TLBFuncDesc *desc = &info->funcdescs[i];
9103 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9105 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9106 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9107 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9108 funcrecord->VtableOffset = desc->funcdesc.oVft;
9110 /* FKCCIC:
9111 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9112 * ^^^funckind
9113 * ^^^ ^invkind
9114 * ^has_cust_data
9115 * ^^^^callconv
9116 * ^has_param_defaults
9117 * ^oEntry_is_intresource
9119 funcrecord->FKCCIC =
9120 desc->funcdesc.funckind |
9121 (desc->funcdesc.invkind << 3) |
9122 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9123 (desc->funcdesc.callconv << 8);
9125 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9126 funcrecord->FKCCIC |= 0x2000;
9128 for(j = 0; j < desc->funcdesc.cParams; ++j){
9129 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9130 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9131 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9134 if(paramdefault_size > 0)
9135 funcrecord->FKCCIC |= 0x1000;
9137 funcrecord->nrargs = desc->funcdesc.cParams;
9138 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9140 /* optional fields */
9141 /* res9? resA? */
9142 if(!list_empty(&desc->custdata_list)){
9143 size += 7 * sizeof(INT);
9144 funcrecord->HelpContext = desc->helpcontext;
9145 if(desc->HelpString)
9146 funcrecord->oHelpString = desc->HelpString->offset;
9147 else
9148 funcrecord->oHelpString = -1;
9149 if(!desc->Entry)
9150 funcrecord->oEntry = -1;
9151 else if(IS_INTRESOURCE(desc->Entry))
9152 funcrecord->oEntry = LOWORD(desc->Entry);
9153 else
9154 funcrecord->oEntry = desc->Entry->offset;
9155 funcrecord->res9 = -1;
9156 funcrecord->resA = -1;
9157 funcrecord->HelpStringContext = desc->HelpStringContext;
9158 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9159 }else if(desc->HelpStringContext != 0){
9160 size += 6 * sizeof(INT);
9161 funcrecord->HelpContext = desc->helpcontext;
9162 if(desc->HelpString)
9163 funcrecord->oHelpString = desc->HelpString->offset;
9164 else
9165 funcrecord->oHelpString = -1;
9166 if(!desc->Entry)
9167 funcrecord->oEntry = -1;
9168 else if(IS_INTRESOURCE(desc->Entry))
9169 funcrecord->oEntry = LOWORD(desc->Entry);
9170 else
9171 funcrecord->oEntry = desc->Entry->offset;
9172 funcrecord->res9 = -1;
9173 funcrecord->resA = -1;
9174 funcrecord->HelpStringContext = desc->HelpStringContext;
9175 }else if(desc->Entry){
9176 size += 3 * sizeof(INT);
9177 funcrecord->HelpContext = desc->helpcontext;
9178 if(desc->HelpString)
9179 funcrecord->oHelpString = desc->HelpString->offset;
9180 else
9181 funcrecord->oHelpString = -1;
9182 if(!desc->Entry)
9183 funcrecord->oEntry = -1;
9184 else if(IS_INTRESOURCE(desc->Entry))
9185 funcrecord->oEntry = LOWORD(desc->Entry);
9186 else
9187 funcrecord->oEntry = desc->Entry->offset;
9188 }else if(desc->HelpString){
9189 size += 2 * sizeof(INT);
9190 funcrecord->HelpContext = desc->helpcontext;
9191 funcrecord->oHelpString = desc->HelpString->offset;
9192 }else if(desc->helpcontext){
9193 size += sizeof(INT);
9194 funcrecord->HelpContext = desc->helpcontext;
9197 paramdefault = (DWORD*)((char *)funcrecord + size);
9198 size += paramdefault_size;
9200 for(j = 0; j < desc->funcdesc.cParams; ++j){
9201 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9203 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9204 if(desc->pParamDesc[j].Name)
9205 info->oName = desc->pParamDesc[j].Name->offset;
9206 else
9207 info->oName = -1;
9208 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9210 if(paramdefault_size){
9211 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9212 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9213 else if(paramdefault_size)
9214 *paramdefault = -1;
9215 ++paramdefault;
9218 size += sizeof(MSFT_ParameterInfo);
9221 funcrecord->Info = size | (i << 16); /* is it just the index? */
9223 *offsets = offs;
9224 offs += size;
9225 ++offsets;
9227 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9230 varrecord = (MSFT_VarRecord*)funcrecord;
9231 for(i = 0; i < info->cVars; ++i){
9232 TLBVarDesc *desc = &info->vardescs[i];
9233 DWORD size = 5 * sizeof(INT);
9235 varrecord->vardescsize = sizeof(desc->vardesc);
9236 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9237 varrecord->Flags = desc->vardesc.wVarFlags;
9238 varrecord->VarKind = desc->vardesc.varkind;
9240 if(desc->vardesc.varkind == VAR_CONST){
9241 varrecord->vardescsize += sizeof(VARIANT);
9242 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9243 }else
9244 varrecord->OffsValue = desc->vardesc.u.oInst;
9246 /* res9? */
9247 if(desc->HelpStringContext != 0){
9248 size += 5 * sizeof(INT);
9249 varrecord->HelpContext = desc->HelpContext;
9250 if(desc->HelpString)
9251 varrecord->HelpString = desc->HelpString->offset;
9252 else
9253 varrecord->HelpString = -1;
9254 varrecord->res9 = -1;
9255 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9256 varrecord->HelpStringContext = desc->HelpStringContext;
9257 }else if(!list_empty(&desc->custdata_list)){
9258 size += 4 * sizeof(INT);
9259 varrecord->HelpContext = desc->HelpContext;
9260 if(desc->HelpString)
9261 varrecord->HelpString = desc->HelpString->offset;
9262 else
9263 varrecord->HelpString = -1;
9264 varrecord->res9 = -1;
9265 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9266 }else if(desc->HelpString){
9267 size += 2 * sizeof(INT);
9268 varrecord->HelpContext = desc->HelpContext;
9269 if(desc->HelpString)
9270 varrecord->HelpString = desc->HelpString->offset;
9271 else
9272 varrecord->HelpString = -1;
9273 }else if(desc->HelpContext != 0){
9274 size += sizeof(INT);
9275 varrecord->HelpContext = desc->HelpContext;
9278 varrecord->Info = size | (i << 16);
9280 *offsets = offs;
9281 offs += size;
9282 ++offsets;
9284 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9287 memid = (MEMBERID*)varrecord;
9288 for(i = 0; i < info->cFuncs; ++i){
9289 TLBFuncDesc *desc = &info->funcdescs[i];
9290 *memid = desc->funcdesc.memid;
9291 ++memid;
9293 for(i = 0; i < info->cVars; ++i){
9294 TLBVarDesc *desc = &info->vardescs[i];
9295 *memid = desc->vardesc.memid;
9296 ++memid;
9299 name = (UINT*)memid;
9300 for(i = 0; i < info->cFuncs; ++i){
9301 TLBFuncDesc *desc = &info->funcdescs[i];
9302 if(desc->Name)
9303 *name = desc->Name->offset;
9304 else
9305 *name = -1;
9306 ++name;
9308 for(i = 0; i < info->cVars; ++i){
9309 TLBVarDesc *desc = &info->vardescs[i];
9310 if(desc->Name)
9311 *name = desc->Name->offset;
9312 else
9313 *name = -1;
9314 ++name;
9317 return ret;
9320 typedef struct tagWMSFT_RefChunk {
9321 DWORD href;
9322 DWORD res04;
9323 DWORD res08;
9324 DWORD next;
9325 } WMSFT_RefChunk;
9327 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9329 DWORD offs = file->ref_seg.len, i;
9330 WMSFT_RefChunk *chunk;
9332 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9333 if(!file->ref_seg.data)
9334 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9335 else
9336 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9338 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9340 for(i = 0; i < info->cImplTypes; ++i){
9341 chunk->href = info->impltypes[i].hRef;
9342 chunk->res04 = info->impltypes[i].implflags;
9343 chunk->res08 = -1;
9344 if(i < info->cImplTypes - 1)
9345 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9346 else
9347 chunk->next = -1;
9348 ++chunk;
9351 return offs;
9354 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9356 DWORD size;
9358 size = sizeof(MSFT_TypeInfoBase);
9360 if(data){
9361 MSFT_TypeInfoBase *base = (void*)data;
9362 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9363 base->typekind = TKIND_DISPATCH;
9364 else
9365 base->typekind = info->typekind;
9366 base->typekind |= index << 16; /* TODO: There are some other flags here */
9367 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9368 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9369 base->res2 = 0;
9370 base->res3 = 0;
9371 base->res4 = 3;
9372 base->res5 = 0;
9373 base->cElement = (info->cVars << 16) | info->cFuncs;
9374 base->res7 = 0;
9375 base->res8 = 0;
9376 base->res9 = 0;
9377 base->resA = 0;
9378 if(info->guid)
9379 base->posguid = info->guid->offset;
9380 else
9381 base->posguid = -1;
9382 base->flags = info->wTypeFlags;
9383 if(info->Name)
9384 base->NameOffset = info->Name->offset;
9385 else
9386 base->NameOffset = -1;
9387 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9388 if(info->DocString)
9389 base->docstringoffs = info->DocString->offset;
9390 else
9391 base->docstringoffs = -1;
9392 base->helpstringcontext = info->dwHelpStringContext;
9393 base->helpcontext = info->dwHelpContext;
9394 base->oCustData = WMSFT_compile_custdata(&info->custdata_list, file);
9395 base->cImplTypes = info->cImplTypes;
9396 base->cbSizeVft = info->cbSizeVft;
9397 base->size = info->cbSizeInstance;
9398 if(info->typekind == TKIND_COCLASS){
9399 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9400 }else if(info->typekind == TKIND_ALIAS){
9401 base->datatype1 = WMSFT_append_typedesc(&info->tdescAlias, file, NULL, NULL);
9402 }else if(info->typekind == TKIND_MODULE){
9403 if(info->DllName)
9404 base->datatype1 = info->DllName->offset;
9405 else
9406 base->datatype1 = -1;
9407 }else{
9408 if(info->cImplTypes > 0)
9409 base->datatype1 = info->impltypes[0].hRef;
9410 else
9411 base->datatype1 = -1;
9413 base->datatype2 = index; /* FIXME: i think there's more here */
9414 base->res18 = 0;
9415 base->res19 = -1;
9418 return size;
9421 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9423 UINT i;
9425 file->typeinfo_seg.len = 0;
9426 for(i = 0; i < This->TypeInfoCount; ++i){
9427 ITypeInfoImpl *info = This->typeinfos[i];
9428 *junk = file->typeinfo_seg.len;
9429 ++junk;
9430 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9433 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9434 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9436 file->aux_seg.len = 0;
9437 file->aux_seg.data = NULL;
9439 file->typeinfo_seg.len = 0;
9440 for(i = 0; i < This->TypeInfoCount; ++i){
9441 ITypeInfoImpl *info = This->typeinfos[i];
9442 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9443 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9447 typedef struct tagWMSFT_ImpFile {
9448 INT guid_offs;
9449 LCID lcid;
9450 DWORD version;
9451 } WMSFT_ImpFile;
9453 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9455 TLBImpLib *implib;
9456 WMSFT_ImpFile *impfile;
9457 char *data;
9458 DWORD last_offs = 0;
9460 file->impfile_seg.len = 0;
9461 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9462 int size = 0;
9464 if(implib->name){
9465 WCHAR *path = strrchrW(implib->name, '\\');
9466 if(path)
9467 ++path;
9468 else
9469 path = implib->name;
9470 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9471 if (size == 0)
9472 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9475 size += sizeof(INT16);
9476 if (size % 4)
9477 size = (size + 4) & ~0x3;
9478 if (size < 8)
9479 size = 8;
9481 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9484 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9486 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9487 int strlen = 0, size;
9489 impfile = (WMSFT_ImpFile*)data;
9490 impfile->guid_offs = implib->guid->offset;
9491 impfile->lcid = implib->lcid;
9492 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9494 data += sizeof(WMSFT_ImpFile);
9496 if(implib->name){
9497 WCHAR *path= strrchrW(implib->name, '\\');
9498 if(path)
9499 ++path;
9500 else
9501 path = implib->name;
9502 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9503 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9504 if (strlen == 0)
9505 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9508 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9510 size = strlen + sizeof(INT16);
9511 if (size % 4)
9512 size = (size + 4) & ~0x3;
9513 if (size < 8)
9514 size = 8;
9515 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9517 data += size;
9518 implib->offset = last_offs;
9519 last_offs += size + sizeof(WMSFT_ImpFile);
9523 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9525 MSFT_ImpInfo *info;
9526 TLBRefType *ref_type;
9527 UINT i = 0;
9529 WMSFT_compile_impfile(This, file);
9531 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9532 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9534 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9535 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9536 if(ref_type->index == TLB_REF_USE_GUID){
9537 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9538 info->oGuid = ref_type->guid->offset;
9539 }else
9540 info->oGuid = ref_type->index;
9541 info->oImpFile = ref_type->pImpTLInfo->offset;
9542 ++i;
9543 ++info;
9547 static void WMSFT_compile_lib(ITypeLibImpl *This, WMSFT_TLBFile *file)
9549 /* TODO: What actually goes here? */
9550 file->lib_seg.len = 0x80;
9551 file->lib_seg.data = heap_alloc(file->lib_seg.len);
9552 memset(file->lib_seg.data, 0xFF, file->lib_seg.len);
9554 #if 0
9555 /* sometimes, first element is offset to last guid, for some reason */
9556 if(This->guid)
9557 *(DWORD*)file->lib_seg.data =
9558 (list_count(&This->guid_list) - 1) * sizeof(MSFT_GuidEntry);
9559 #endif
9562 static void WMSFT_compile_res07(ITypeLibImpl *This, WMSFT_TLBFile *file)
9564 /* TODO: What actually goes here?
9565 * Wild speculation:
9566 * It's something to do with the Name table (and string table?). When you
9567 * add a new name, the offset to that name from within the Name table gets
9568 * stuck somewhere in res07, apparently starting at the end of the segment
9569 * then moving backwards at a rate of 3 bytes per char in the Name. */
9570 file->res07_seg.len = 0x200;
9571 file->res07_seg.data = heap_alloc(file->res07_seg.len);
9572 memset(file->res07_seg.data, 0xFF, file->res07_seg.len);
9575 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9577 if(contents && contents->len){
9578 segdir->offset = *running_offset;
9579 segdir->length = contents->len;
9580 *running_offset += segdir->length;
9581 }else{
9582 segdir->offset = -1;
9583 segdir->length = 0;
9586 /* TODO: do these ever change? */
9587 segdir->res08 = -1;
9588 segdir->res0c = 0xf;
9591 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9593 DWORD written;
9594 if(segment)
9595 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9598 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9599 DWORD file_len)
9601 DWORD i;
9602 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9604 for(i = 0; i < This->TypeInfoCount; ++i){
9605 base->memoffset += file_len;
9606 ++base;
9609 return S_OK;
9612 static void WMSFT_free_file(WMSFT_TLBFile *file)
9614 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9615 HeapFree(GetProcessHeap(), 0, file->lib_seg.data);
9616 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9617 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9618 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9619 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9620 HeapFree(GetProcessHeap(), 0, file->res07_seg.data);
9621 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9622 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9623 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9624 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9625 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9626 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9627 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9630 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9632 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9633 WMSFT_TLBFile file;
9634 DWORD written, junk_size, junk_offs, running_offset;
9635 BOOL br;
9636 HANDLE outfile;
9637 HRESULT hres;
9638 DWORD *junk;
9640 TRACE("%p\n", This);
9642 memset(&file, 0, sizeof(file));
9644 file.header.magic1 = 0x5446534D;
9645 file.header.magic2 = 0x00010002;
9646 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9647 file.header.lcid2 = This->set_lcid;
9648 file.header.varflags = 0x41; /* TODO?? */
9649 if (This->HelpFile)
9650 file.header.varflags |= 0x10;
9651 if (This->HelpStringDll)
9652 file.header.varflags |= HELPDLLFLAG;
9653 file.header.version = (This->ver_major << 16) | This->ver_minor;
9654 file.header.flags = This->libflags;
9655 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9656 file.header.helpcontext = This->dwHelpContext;
9657 file.header.res44 = 0x20;
9658 file.header.res48 = 0x80;
9659 file.header.dispatchpos = This->dispatch_href;
9661 /* do name and string compilation to get offsets for other compilations */
9662 hres = WMSFT_compile_names(This, &file);
9663 if (FAILED(hres)){
9664 WMSFT_free_file(&file);
9665 return hres;
9668 hres = WMSFT_compile_strings(This, &file);
9669 if (FAILED(hres)){
9670 WMSFT_free_file(&file);
9671 return hres;
9674 hres = WMSFT_compile_guids(This, &file);
9675 if (FAILED(hres)){
9676 WMSFT_free_file(&file);
9677 return hres;
9680 if(This->HelpFile)
9681 file.header.helpfile = This->HelpFile->offset;
9682 else
9683 file.header.helpfile = -1;
9685 if(This->DocString)
9686 file.header.helpstring = This->DocString->offset;
9687 else
9688 file.header.helpstring = -1;
9690 /* do some more segment compilation */
9691 file.header.nimpinfos = list_count(&This->ref_list);
9692 file.header.nrtypeinfos = This->TypeInfoCount;
9694 if(This->Name)
9695 file.header.NameOffset = This->Name->offset;
9696 else
9697 file.header.NameOffset = -1;
9699 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9701 if(This->guid)
9702 file.header.posguid = This->guid->offset;
9703 else
9704 file.header.posguid = -1;
9706 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9707 if(file.header.varflags & HELPDLLFLAG)
9708 junk_size += sizeof(DWORD);
9709 if(junk_size){
9710 junk = heap_alloc_zero(junk_size);
9711 if(file.header.varflags & HELPDLLFLAG){
9712 *junk = This->HelpStringDll->offset;
9713 junk_offs = 1;
9714 }else
9715 junk_offs = 0;
9716 }else{
9717 junk = NULL;
9718 junk_offs = 0;
9721 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9722 WMSFT_compile_impinfo(This, &file);
9723 WMSFT_compile_lib(This, &file);
9724 WMSFT_compile_res07(This, &file);
9726 running_offset = 0;
9728 TRACE("header at: 0x%x\n", running_offset);
9729 running_offset += sizeof(file.header);
9731 TRACE("junk at: 0x%x\n", running_offset);
9732 running_offset += junk_size;
9734 TRACE("segdir at: 0x%x\n", running_offset);
9735 running_offset += sizeof(file.segdir);
9737 TRACE("typeinfo at: 0x%x\n", running_offset);
9738 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9740 TRACE("libtab at: 0x%x\n", running_offset);
9741 tmp_fill_segdir_seg(&file.segdir.pLibtab, &file.lib_seg, &running_offset);
9743 TRACE("guidtab at: 0x%x\n", running_offset);
9744 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9746 TRACE("reftab at: 0x%x\n", running_offset);
9747 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9749 TRACE("impinfo at: 0x%x\n", running_offset);
9750 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9752 TRACE("impfiles at: 0x%x\n", running_offset);
9753 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9755 TRACE("res07 at: 0x%x\n", running_offset);
9756 tmp_fill_segdir_seg(&file.segdir.res07, &file.res07_seg, &running_offset);
9758 TRACE("nametab at: 0x%x\n", running_offset);
9759 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9761 TRACE("stringtab at: 0x%x\n", running_offset);
9762 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9764 TRACE("typdesc at: 0x%x\n", running_offset);
9765 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9767 TRACE("arraydescriptions at: 0x%x\n", running_offset);
9768 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
9770 TRACE("custdata at: 0x%x\n", running_offset);
9771 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
9773 TRACE("cdguids at: 0x%x\n", running_offset);
9774 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
9776 TRACE("res0e at: 0x%x\n", running_offset);
9777 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
9779 TRACE("res0f at: 0x%x\n", running_offset);
9780 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
9782 TRACE("aux_seg at: 0x%x\n", running_offset);
9784 WMSFT_fixup_typeinfos(This, &file, running_offset);
9786 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
9787 FILE_ATTRIBUTE_NORMAL, 0);
9788 if (outfile == INVALID_HANDLE_VALUE){
9789 WMSFT_free_file(&file);
9790 return TYPE_E_IOERROR;
9793 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
9794 if (!br) {
9795 WMSFT_free_file(&file);
9796 CloseHandle(outfile);
9797 return TYPE_E_IOERROR;
9800 br = WriteFile(outfile, junk, junk_size, &written, NULL);
9801 if (!br) {
9802 WMSFT_free_file(&file);
9803 CloseHandle(outfile);
9804 return TYPE_E_IOERROR;
9807 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
9808 if (!br) {
9809 WMSFT_free_file(&file);
9810 CloseHandle(outfile);
9811 return TYPE_E_IOERROR;
9814 WMSFT_write_segment(outfile, &file.typeinfo_seg);
9815 WMSFT_write_segment(outfile, &file.lib_seg);
9816 WMSFT_write_segment(outfile, &file.guid_seg);
9817 WMSFT_write_segment(outfile, &file.ref_seg);
9818 WMSFT_write_segment(outfile, &file.impinfo_seg);
9819 WMSFT_write_segment(outfile, &file.impfile_seg);
9820 WMSFT_write_segment(outfile, &file.res07_seg);
9821 WMSFT_write_segment(outfile, &file.name_seg);
9822 WMSFT_write_segment(outfile, &file.string_seg);
9823 WMSFT_write_segment(outfile, &file.typdesc_seg);
9824 WMSFT_write_segment(outfile, &file.arraydesc_seg);
9825 WMSFT_write_segment(outfile, &file.custdata_seg);
9826 WMSFT_write_segment(outfile, &file.cdguids_seg);
9827 WMSFT_write_segment(outfile, &file.aux_seg);
9829 WMSFT_free_file(&file);
9831 CloseHandle(outfile);
9833 return S_OK;
9836 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
9837 LPOLESTR name)
9839 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9840 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
9841 return E_NOTIMPL;
9844 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
9845 REFGUID guid, VARIANT *varVal)
9847 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9848 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
9849 return E_NOTIMPL;
9852 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
9853 ULONG helpStringContext)
9855 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9856 FIXME("%p %u - stub\n", This, helpStringContext);
9857 return E_NOTIMPL;
9860 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
9861 LPOLESTR filename)
9863 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9864 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
9866 if (!filename)
9867 return E_INVALIDARG;
9869 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
9871 return S_OK;
9874 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
9875 ICreateTypeLib2_fnQueryInterface,
9876 ICreateTypeLib2_fnAddRef,
9877 ICreateTypeLib2_fnRelease,
9878 ICreateTypeLib2_fnCreateTypeInfo,
9879 ICreateTypeLib2_fnSetName,
9880 ICreateTypeLib2_fnSetVersion,
9881 ICreateTypeLib2_fnSetGuid,
9882 ICreateTypeLib2_fnSetDocString,
9883 ICreateTypeLib2_fnSetHelpFileName,
9884 ICreateTypeLib2_fnSetHelpContext,
9885 ICreateTypeLib2_fnSetLcid,
9886 ICreateTypeLib2_fnSetLibFlags,
9887 ICreateTypeLib2_fnSaveAllChanges,
9888 ICreateTypeLib2_fnDeleteTypeInfo,
9889 ICreateTypeLib2_fnSetCustData,
9890 ICreateTypeLib2_fnSetHelpStringContext,
9891 ICreateTypeLib2_fnSetHelpStringDll
9894 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
9895 REFIID riid, void **object)
9897 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9899 return ITypeInfo2_QueryInterface((ITypeInfo2*)This, riid, object);
9902 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
9904 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9906 return ITypeInfo2_AddRef((ITypeInfo2*)This);
9909 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
9911 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9913 return ITypeInfo2_Release((ITypeInfo2*)This);
9916 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
9917 REFGUID guid)
9919 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9921 TRACE("%p %s\n", This, debugstr_guid(guid));
9923 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
9925 return S_OK;
9928 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
9929 UINT typeFlags)
9931 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9932 WORD old_flags;
9933 HRESULT hres;
9935 TRACE("%p %x\n", This, typeFlags);
9937 if (typeFlags & TYPEFLAG_FDUAL) {
9938 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9939 ITypeLib *stdole;
9940 ITypeInfo *dispatch;
9941 HREFTYPE hreftype;
9942 HRESULT hres;
9944 hres = LoadTypeLib(stdole2tlb, &stdole);
9945 if(FAILED(hres))
9946 return hres;
9948 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
9949 ITypeLib_Release(stdole);
9950 if(FAILED(hres))
9951 return hres;
9953 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
9954 ITypeInfo_Release(dispatch);
9955 if(FAILED(hres))
9956 return hres;
9959 old_flags = This->wTypeFlags;
9960 This->wTypeFlags = typeFlags;
9962 hres = ICreateTypeInfo2_LayOut(iface);
9963 if (FAILED(hres)) {
9964 This->wTypeFlags = old_flags;
9965 return hres;
9968 return S_OK;
9971 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
9972 LPOLESTR doc)
9974 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9976 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9978 if (!doc)
9979 return E_INVALIDARG;
9981 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
9983 return S_OK;
9986 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
9987 DWORD helpContext)
9989 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9991 TRACE("%p %d\n", This, helpContext);
9993 This->dwHelpContext = helpContext;
9995 return S_OK;
9998 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
9999 WORD majorVerNum, WORD minorVerNum)
10001 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10003 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10005 This->wMajorVerNum = majorVerNum;
10006 This->wMinorVerNum = minorVerNum;
10008 return S_OK;
10011 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10012 ITypeInfo *typeInfo, HREFTYPE *refType)
10014 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10015 UINT index;
10016 ITypeLib *container;
10017 TLBRefType *ref_type;
10018 TLBImpLib *implib;
10019 TYPEATTR *typeattr;
10020 TLIBATTR *libattr;
10021 HRESULT hres;
10023 TRACE("%p %p %p\n", This, typeInfo, refType);
10025 if (!typeInfo || !refType)
10026 return E_INVALIDARG;
10028 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10029 if (FAILED(hres))
10030 return hres;
10032 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10033 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10035 ITypeLib_Release(container);
10037 *refType = target->hreftype;
10039 return S_OK;
10042 hres = ITypeLib_GetLibAttr(container, &libattr);
10043 if (FAILED(hres)) {
10044 ITypeLib_Release(container);
10045 return hres;
10048 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10049 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10050 implib->lcid == libattr->lcid &&
10051 implib->wVersionMajor == libattr->wMajorVerNum &&
10052 implib->wVersionMinor == libattr->wMinorVerNum)
10053 break;
10056 if(&implib->entry == &This->pTypeLib->implib_list){
10057 implib = heap_alloc_zero(sizeof(TLBImpLib));
10059 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10060 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10061 implib->name = SysAllocString(our_container->path);
10062 }else{
10063 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10064 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10065 if(FAILED(hres)){
10066 implib->name = NULL;
10067 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10071 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid);
10072 implib->lcid = libattr->lcid;
10073 implib->wVersionMajor = libattr->wMajorVerNum;
10074 implib->wVersionMinor = libattr->wMinorVerNum;
10076 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10079 ITypeLib_ReleaseTLibAttr(container, libattr);
10080 ITypeLib_Release(container);
10082 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10083 if (FAILED(hres))
10084 return hres;
10086 index = 0;
10087 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10088 if(ref_type->index == TLB_REF_USE_GUID &&
10089 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10090 ref_type->tkind == typeattr->typekind)
10091 break;
10092 ++index;
10095 if(&ref_type->entry == &This->pTypeLib->ref_list){
10096 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10098 ref_type->tkind = typeattr->typekind;
10099 ref_type->pImpTLInfo = implib;
10100 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10102 ref_type->index = TLB_REF_USE_GUID;
10104 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid);
10106 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10109 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10111 *refType = ref_type->reference | 0x1;
10113 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10114 This->pTypeLib->dispatch_href = *refType;
10116 return S_OK;
10119 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10120 UINT index, FUNCDESC *funcDesc)
10122 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10123 TLBFuncDesc tmp_func_desc, *func_desc;
10124 int buf_size, i;
10125 char *buffer;
10126 HRESULT hres;
10128 TRACE("%p %u %p\n", This, index, funcDesc);
10130 if (!funcDesc || funcDesc->oVft & 3)
10131 return E_INVALIDARG;
10133 switch (This->typekind) {
10134 case TKIND_MODULE:
10135 if (funcDesc->funckind != FUNC_STATIC)
10136 return TYPE_E_BADMODULEKIND;
10137 break;
10138 case TKIND_DISPATCH:
10139 if (funcDesc->funckind != FUNC_DISPATCH)
10140 return TYPE_E_BADMODULEKIND;
10141 break;
10142 default:
10143 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10144 return TYPE_E_BADMODULEKIND;
10147 if (index > This->cFuncs)
10148 return TYPE_E_ELEMENTNOTFOUND;
10150 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10151 !funcDesc->cParams)
10152 return TYPE_E_INCONSISTENTPROPFUNCS;
10154 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10155 TLBFuncDesc_Constructor(&tmp_func_desc);
10157 tmp_func_desc.funcdesc = *funcDesc;
10159 if (tmp_func_desc.funcdesc.oVft != 0)
10160 tmp_func_desc.funcdesc.oVft |= 1;
10162 if (funcDesc->cScodes) {
10163 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10164 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10165 } else
10166 tmp_func_desc.funcdesc.lprgscode = NULL;
10168 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10169 for (i = 0; i < funcDesc->cParams; ++i) {
10170 buf_size += sizeof(ELEMDESC);
10171 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10173 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10174 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10176 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10177 if (FAILED(hres)) {
10178 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10179 heap_free(tmp_func_desc.funcdesc.lprgscode);
10180 return hres;
10183 for (i = 0; i < funcDesc->cParams; ++i) {
10184 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10185 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10186 if (FAILED(hres)) {
10187 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10188 heap_free(tmp_func_desc.funcdesc.lprgscode);
10189 return hres;
10191 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10192 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10193 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10194 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10195 if (FAILED(hres)) {
10196 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10197 heap_free(tmp_func_desc.funcdesc.lprgscode);
10198 return hres;
10203 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10205 if (This->funcdescs) {
10206 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10207 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10209 if (index < This->cFuncs) {
10210 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10211 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10212 func_desc = This->funcdescs + index;
10213 } else
10214 func_desc = This->funcdescs + This->cFuncs;
10216 /* move custdata lists to the new memory location */
10217 for(i = 0; i < This->cFuncs + 1; ++i){
10218 if(index != i){
10219 TLBFuncDesc *fd = &This->funcdescs[i];
10220 if(fd->custdata_list.prev == fd->custdata_list.next)
10221 list_init(&fd->custdata_list);
10222 else{
10223 fd->custdata_list.prev->next = &fd->custdata_list;
10224 fd->custdata_list.next->prev = &fd->custdata_list;
10228 } else
10229 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10231 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10232 list_init(&func_desc->custdata_list);
10234 ++This->cFuncs;
10236 This->needs_layout = TRUE;
10238 return S_OK;
10241 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10242 UINT index, HREFTYPE refType)
10244 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10245 TLBImplType *impl_type;
10246 HRESULT hres;
10248 TRACE("%p %u %d\n", This, index, refType);
10250 switch(This->typekind){
10251 case TKIND_COCLASS: {
10252 if (index == -1) {
10253 FIXME("Unhandled index: -1\n");
10254 return E_NOTIMPL;
10257 if(index != This->cImplTypes)
10258 return TYPE_E_ELEMENTNOTFOUND;
10260 break;
10262 case TKIND_INTERFACE:
10263 case TKIND_DISPATCH:
10264 if (index != 0 || This->cImplTypes)
10265 return TYPE_E_ELEMENTNOTFOUND;
10266 break;
10267 default:
10268 FIXME("Unimplemented typekind: %d\n", This->typekind);
10269 return E_NOTIMPL;
10272 if (This->impltypes){
10273 UINT i;
10275 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10276 sizeof(TLBImplType) * (This->cImplTypes + 1));
10278 if (index < This->cImplTypes) {
10279 memmove(This->impltypes + index + 1, This->impltypes + index,
10280 (This->cImplTypes - index) * sizeof(TLBImplType));
10281 impl_type = This->impltypes + index;
10282 } else
10283 impl_type = This->impltypes + This->cImplTypes;
10285 /* move custdata lists to the new memory location */
10286 for(i = 0; i < This->cImplTypes + 1; ++i){
10287 if(index != i){
10288 TLBImplType *it = &This->impltypes[i];
10289 if(it->custdata_list.prev == it->custdata_list.next)
10290 list_init(&it->custdata_list);
10291 else{
10292 it->custdata_list.prev->next = &it->custdata_list;
10293 it->custdata_list.next->prev = &it->custdata_list;
10297 } else
10298 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10300 memset(impl_type, 0, sizeof(TLBImplType));
10301 TLBImplType_Constructor(impl_type);
10302 impl_type->hRef = refType;
10304 ++This->cImplTypes;
10306 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10307 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10309 hres = ICreateTypeInfo2_LayOut(iface);
10310 if (FAILED(hres))
10311 return hres;
10313 return S_OK;
10316 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10317 UINT index, INT implTypeFlags)
10319 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10320 TLBImplType *impl_type = &This->impltypes[index];
10322 TRACE("%p %u %x\n", This, index, implTypeFlags);
10324 if (This->typekind != TKIND_COCLASS)
10325 return TYPE_E_BADMODULEKIND;
10327 if (index >= This->cImplTypes)
10328 return TYPE_E_ELEMENTNOTFOUND;
10330 impl_type->implflags = implTypeFlags;
10332 return S_OK;
10335 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10336 WORD alignment)
10338 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10340 TRACE("%p %d\n", This, alignment);
10342 This->cbAlignment = alignment;
10344 return S_OK;
10347 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10348 LPOLESTR schema)
10350 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10352 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10354 if (!schema)
10355 return E_INVALIDARG;
10357 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10359 This->lpstrSchema = This->Schema->str;
10361 return S_OK;
10364 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10365 UINT index, VARDESC *varDesc)
10367 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10368 TLBVarDesc *var_desc;
10370 TRACE("%p %u %p\n", This, index, varDesc);
10372 if (This->vardescs){
10373 UINT i;
10375 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10376 sizeof(TLBVarDesc) * (This->cVars + 1));
10378 if (index < This->cVars) {
10379 memmove(This->vardescs + index + 1, This->vardescs + index,
10380 (This->cVars - index) * sizeof(TLBVarDesc));
10381 var_desc = This->vardescs + index;
10382 } else
10383 var_desc = This->vardescs + This->cVars;
10385 /* move custdata lists to the new memory location */
10386 for(i = 0; i < This->cVars + 1; ++i){
10387 if(index != i){
10388 TLBVarDesc *var = &This->vardescs[i];
10389 if(var->custdata_list.prev == var->custdata_list.next)
10390 list_init(&var->custdata_list);
10391 else{
10392 var->custdata_list.prev->next = &var->custdata_list;
10393 var->custdata_list.next->prev = &var->custdata_list;
10397 } else
10398 var_desc = This->vardescs = heap_alloc(sizeof(TLBVarDesc));
10400 memset(var_desc, 0, sizeof(TLBVarDesc));
10401 TLBVarDesc_Constructor(var_desc);
10402 var_desc->vardesc = *varDesc;
10404 ++This->cVars;
10406 This->needs_layout = TRUE;
10408 return S_OK;
10411 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10412 UINT index, LPOLESTR *names, UINT numNames)
10414 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10415 TLBFuncDesc *func_desc = &This->funcdescs[index];
10416 int i;
10418 TRACE("%p %u %p %u\n", This, index, names, numNames);
10420 if (!names)
10421 return E_INVALIDARG;
10423 if (index >= This->cFuncs || numNames == 0)
10424 return TYPE_E_ELEMENTNOTFOUND;
10426 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10427 if(numNames > func_desc->funcdesc.cParams)
10428 return TYPE_E_ELEMENTNOTFOUND;
10429 } else
10430 if(numNames > func_desc->funcdesc.cParams + 1)
10431 return TYPE_E_ELEMENTNOTFOUND;
10433 for(i = 0; i < This->cFuncs; ++i) {
10434 TLBFuncDesc *iter = &This->funcdescs[i];
10435 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10436 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10437 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10438 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10439 continue;
10440 return TYPE_E_AMBIGUOUSNAME;
10444 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10446 for (i = 1; i < numNames; ++i) {
10447 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10448 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10451 return S_OK;
10454 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10455 UINT index, LPOLESTR name)
10457 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10458 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
10459 return E_NOTIMPL;
10462 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10463 TYPEDESC *tdescAlias)
10465 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10466 FIXME("%p %p - stub\n", This, tdescAlias);
10467 return E_NOTIMPL;
10470 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10471 UINT index, LPOLESTR dllName, LPOLESTR procName)
10473 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10474 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10475 return E_NOTIMPL;
10478 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10479 UINT index, LPOLESTR docString)
10481 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10482 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
10483 return E_NOTIMPL;
10486 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10487 UINT index, LPOLESTR docString)
10489 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10490 TLBVarDesc *var_desc = &This->vardescs[index];
10492 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10494 if(!docString)
10495 return E_INVALIDARG;
10497 if(index >= This->cVars)
10498 return TYPE_E_ELEMENTNOTFOUND;
10500 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10502 return S_OK;
10505 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10506 UINT index, DWORD helpContext)
10508 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10509 TLBFuncDesc *func_desc = &This->funcdescs[index];
10511 TRACE("%p %u %d\n", This, index, helpContext);
10513 if(index >= This->cFuncs)
10514 return TYPE_E_ELEMENTNOTFOUND;
10516 func_desc->helpcontext = helpContext;
10518 return S_OK;
10521 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10522 UINT index, DWORD helpContext)
10524 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10525 TLBVarDesc *var_desc = &This->vardescs[index];
10527 TRACE("%p %u %d\n", This, index, helpContext);
10529 if(index >= This->cVars)
10530 return TYPE_E_ELEMENTNOTFOUND;
10532 var_desc->HelpContext = helpContext;
10534 return S_OK;
10537 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10538 UINT index, BSTR bstrMops)
10540 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10541 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10542 return E_NOTIMPL;
10545 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10546 IDLDESC *idlDesc)
10548 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10550 TRACE("%p %p\n", This, idlDesc);
10552 if (!idlDesc)
10553 return E_INVALIDARG;
10555 This->idldescType.dwReserved = idlDesc->dwReserved;
10556 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10558 return S_OK;
10561 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10563 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10564 ITypeInfo *tinfo;
10565 TLBFuncDesc *func_desc;
10566 UINT user_vft = 0, i, depth = 0;
10567 HRESULT hres = S_OK;
10569 TRACE("%p\n", This);
10571 This->needs_layout = FALSE;
10573 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10574 if (FAILED(hres))
10575 return hres;
10577 if (This->typekind == TKIND_INTERFACE) {
10578 ITypeInfo *inh;
10579 TYPEATTR *attr;
10580 HREFTYPE inh_href;
10582 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10584 if (SUCCEEDED(hres)) {
10585 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10587 if (SUCCEEDED(hres)) {
10588 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10589 if (FAILED(hres)) {
10590 ITypeInfo_Release(inh);
10591 ITypeInfo_Release(tinfo);
10592 return hres;
10594 This->cbSizeVft = attr->cbSizeVft * 4 / sizeof(void*);
10595 ITypeInfo_ReleaseTypeAttr(inh, attr);
10598 ++depth;
10599 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10600 if(SUCCEEDED(hres)){
10601 ITypeInfo *next;
10602 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10603 if(SUCCEEDED(hres)){
10604 ITypeInfo_Release(inh);
10605 inh = next;
10608 }while(SUCCEEDED(hres));
10609 hres = S_OK;
10611 ITypeInfo_Release(inh);
10612 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10613 This->cbSizeVft = 0;
10614 hres = S_OK;
10615 } else {
10616 ITypeInfo_Release(tinfo);
10617 return hres;
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 (This->typekind == TKIND_DISPATCH)
10627 This->cbSizeVft = 7 * sizeof(void*);
10628 else
10629 This->cbSizeVft = 0;
10631 func_desc = This->funcdescs;
10632 i = 0;
10633 while (i < This->cFuncs) {
10634 if (!(func_desc->funcdesc.oVft & 0x1))
10635 func_desc->funcdesc.oVft = This->cbSizeVft;
10637 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10638 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10640 This->cbSizeVft += sizeof(void*);
10642 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10643 TLBFuncDesc *iter;
10644 UINT j = 0;
10645 BOOL reset = FALSE;
10647 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10649 iter = This->funcdescs;
10650 while (j < This->cFuncs) {
10651 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10652 if (!reset) {
10653 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10654 reset = TRUE;
10655 } else
10656 ++func_desc->funcdesc.memid;
10657 iter = This->funcdescs;
10658 j = 0;
10659 } else {
10660 ++iter;
10661 ++j;
10666 ++func_desc;
10667 ++i;
10670 if (user_vft > This->cbSizeVft)
10671 This->cbSizeVft = user_vft + sizeof(void*);
10673 ITypeInfo_Release(tinfo);
10674 return hres;
10677 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10678 UINT index)
10680 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10681 FIXME("%p %u - stub\n", This, index);
10682 return E_NOTIMPL;
10685 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10686 MEMBERID memid, INVOKEKIND invKind)
10688 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10689 FIXME("%p %x %d - stub\n", This, memid, invKind);
10690 return E_NOTIMPL;
10693 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
10694 UINT index)
10696 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10697 FIXME("%p %u - stub\n", This, index);
10698 return E_NOTIMPL;
10701 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
10702 MEMBERID memid)
10704 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10705 FIXME("%p %x - stub\n", This, memid);
10706 return E_NOTIMPL;
10709 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
10710 UINT index)
10712 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10713 FIXME("%p %u - stub\n", This, index);
10714 return E_NOTIMPL;
10717 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
10718 REFGUID guid, VARIANT *varVal)
10720 TLBGuid *tlbguid;
10722 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10724 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10726 if (!guid || !varVal)
10727 return E_INVALIDARG;
10729 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
10731 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10734 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
10735 UINT index, REFGUID guid, VARIANT *varVal)
10737 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10738 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10739 return E_NOTIMPL;
10742 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
10743 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
10745 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10746 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
10747 return E_NOTIMPL;
10750 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
10751 UINT index, REFGUID guid, VARIANT *varVal)
10753 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10754 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10755 return E_NOTIMPL;
10758 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
10759 UINT index, REFGUID guid, VARIANT *varVal)
10761 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10762 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10763 return E_NOTIMPL;
10766 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
10767 ULONG helpStringContext)
10769 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10771 TRACE("%p %u\n", This, helpStringContext);
10773 This->dwHelpStringContext = helpStringContext;
10775 return S_OK;
10778 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
10779 UINT index, ULONG helpStringContext)
10781 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10782 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10783 return E_NOTIMPL;
10786 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
10787 UINT index, ULONG helpStringContext)
10789 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10790 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10791 return E_NOTIMPL;
10794 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
10796 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10797 FIXME("%p - stub\n", This);
10798 return E_NOTIMPL;
10801 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
10802 LPOLESTR name)
10804 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10806 TRACE("%p %s\n", This, wine_dbgstr_w(name));
10808 if (!name)
10809 return E_INVALIDARG;
10811 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
10813 return S_OK;
10816 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
10817 ICreateTypeInfo2_fnQueryInterface,
10818 ICreateTypeInfo2_fnAddRef,
10819 ICreateTypeInfo2_fnRelease,
10820 ICreateTypeInfo2_fnSetGuid,
10821 ICreateTypeInfo2_fnSetTypeFlags,
10822 ICreateTypeInfo2_fnSetDocString,
10823 ICreateTypeInfo2_fnSetHelpContext,
10824 ICreateTypeInfo2_fnSetVersion,
10825 ICreateTypeInfo2_fnAddRefTypeInfo,
10826 ICreateTypeInfo2_fnAddFuncDesc,
10827 ICreateTypeInfo2_fnAddImplType,
10828 ICreateTypeInfo2_fnSetImplTypeFlags,
10829 ICreateTypeInfo2_fnSetAlignment,
10830 ICreateTypeInfo2_fnSetSchema,
10831 ICreateTypeInfo2_fnAddVarDesc,
10832 ICreateTypeInfo2_fnSetFuncAndParamNames,
10833 ICreateTypeInfo2_fnSetVarName,
10834 ICreateTypeInfo2_fnSetTypeDescAlias,
10835 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
10836 ICreateTypeInfo2_fnSetFuncDocString,
10837 ICreateTypeInfo2_fnSetVarDocString,
10838 ICreateTypeInfo2_fnSetFuncHelpContext,
10839 ICreateTypeInfo2_fnSetVarHelpContext,
10840 ICreateTypeInfo2_fnSetMops,
10841 ICreateTypeInfo2_fnSetTypeIdldesc,
10842 ICreateTypeInfo2_fnLayOut,
10843 ICreateTypeInfo2_fnDeleteFuncDesc,
10844 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
10845 ICreateTypeInfo2_fnDeleteVarDesc,
10846 ICreateTypeInfo2_fnDeleteVarDescByMemId,
10847 ICreateTypeInfo2_fnDeleteImplType,
10848 ICreateTypeInfo2_fnSetCustData,
10849 ICreateTypeInfo2_fnSetFuncCustData,
10850 ICreateTypeInfo2_fnSetParamCustData,
10851 ICreateTypeInfo2_fnSetVarCustData,
10852 ICreateTypeInfo2_fnSetImplTypeCustData,
10853 ICreateTypeInfo2_fnSetHelpStringContext,
10854 ICreateTypeInfo2_fnSetFuncHelpStringContext,
10855 ICreateTypeInfo2_fnSetVarHelpStringContext,
10856 ICreateTypeInfo2_fnInvalidate,
10857 ICreateTypeInfo2_fnSetName