oleaut32: Only copy previous function name if both are property accessors.
[wine.git] / dlls / oleaut32 / typelib.c
blobbb3be43e03f638343ad25420c8e0560271786a96
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
63 #include "winerror.h"
64 #include "windef.h"
65 #include "winbase.h"
66 #include "winnls.h"
67 #include "winreg.h"
68 #include "winuser.h"
69 #include "lzexpand.h"
71 #include "wine/unicode.h"
72 #include "objbase.h"
73 #include "typelib.h"
74 #include "wine/debug.h"
75 #include "variant.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib);
81 typedef struct
83 WORD offset;
84 WORD length;
85 WORD flags;
86 WORD id;
87 WORD handle;
88 WORD usage;
89 } NE_NAMEINFO;
91 typedef struct
93 WORD type_id; /* Type identifier */
94 WORD count; /* Number of resources of this type */
95 DWORD resloader; /* SetResourceHandler() */
97 * Name info array.
99 } NE_TYPEINFO;
101 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
102 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
104 /****************************************************************************
105 * FromLExxx
107 * Takes p_iVal (which is in little endian) and returns it
108 * in the host machine's byte order.
110 #ifdef WORDS_BIGENDIAN
111 static WORD FromLEWord(WORD p_iVal)
113 return (((p_iVal & 0x00FF) << 8) |
114 ((p_iVal & 0xFF00) >> 8));
118 static DWORD FromLEDWord(DWORD p_iVal)
120 return (((p_iVal & 0x000000FF) << 24) |
121 ((p_iVal & 0x0000FF00) << 8) |
122 ((p_iVal & 0x00FF0000) >> 8) |
123 ((p_iVal & 0xFF000000) >> 24));
125 #else
126 #define FromLEWord(X) (X)
127 #define FromLEDWord(X) (X)
128 #endif
130 #define DISPATCH_HREF_OFFSET 0x01000000
131 #define DISPATCH_HREF_MASK 0xff000000
133 /****************************************************************************
134 * FromLExxx
136 * Fix byte order in any structure if necessary
138 #ifdef WORDS_BIGENDIAN
139 static void FromLEWords(void *p_Val, int p_iSize)
141 WORD *Val = p_Val;
143 p_iSize /= sizeof(WORD);
145 while (p_iSize) {
146 *Val = FromLEWord(*Val);
147 Val++;
148 p_iSize--;
153 static void FromLEDWords(void *p_Val, int p_iSize)
155 DWORD *Val = p_Val;
157 p_iSize /= sizeof(DWORD);
159 while (p_iSize) {
160 *Val = FromLEDWord(*Val);
161 Val++;
162 p_iSize--;
165 #else
166 #define FromLEWords(X,Y) /*nothing*/
167 #define FromLEDWords(X,Y) /*nothing*/
168 #endif
171 * Find a typelib key which matches a requested maj.min version.
173 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
175 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
176 WCHAR buffer[60];
177 char key_name[16];
178 DWORD len, i;
179 INT best_maj = -1, best_min = -1;
180 HKEY hkey;
182 memcpy( buffer, typelibW, sizeof(typelibW) );
183 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
185 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
186 return FALSE;
188 len = sizeof(key_name);
189 i = 0;
190 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
192 INT v_maj, v_min;
194 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
196 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
198 if (*wMaj == 0xffff && *wMin == 0xffff)
200 if (v_maj > best_maj) best_maj = v_maj;
201 if (v_min > best_min) best_min = v_min;
203 else if (*wMaj == v_maj)
205 best_maj = v_maj;
207 if (*wMin == v_min)
209 best_min = v_min;
210 break; /* exact match */
212 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
215 len = sizeof(key_name);
217 RegCloseKey( hkey );
219 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
221 if (*wMaj == 0xffff && *wMin == 0xffff)
223 if (best_maj >= 0 && best_min >= 0)
225 *wMaj = best_maj;
226 *wMin = best_min;
227 return TRUE;
231 if (*wMaj == best_maj && best_min >= 0)
233 *wMin = best_min;
234 return TRUE;
236 return FALSE;
239 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
240 /* buffer must be at least 60 characters long */
241 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
243 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
244 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
246 memcpy( buffer, TypelibW, sizeof(TypelibW) );
247 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
248 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
249 return buffer;
252 /* get the path of an interface key, in the form "Interface\\<guid>" */
253 /* buffer must be at least 50 characters long */
254 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
256 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
258 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
259 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
260 return buffer;
263 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
264 /* buffer must be at least 16 characters long */
265 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
267 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
268 static const WCHAR win16W[] = {'w','i','n','1','6',0};
269 static const WCHAR win32W[] = {'w','i','n','3','2',0};
270 static const WCHAR win64W[] = {'w','i','n','6','4',0};
272 sprintfW( buffer, LcidFormatW, lcid );
273 switch(syskind)
275 case SYS_WIN16: strcatW( buffer, win16W ); break;
276 case SYS_WIN32: strcatW( buffer, win32W ); break;
277 case SYS_WIN64: strcatW( buffer, win64W ); break;
278 default:
279 TRACE("Typelib is for unsupported syskind %i\n", syskind);
280 return NULL;
282 return buffer;
285 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
288 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
289 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
290 SYSKIND syskind, LCID lcid, LPBSTR path )
292 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
293 LCID myLCID = lcid;
294 HKEY hkey;
295 WCHAR buffer[60];
296 WCHAR Path[MAX_PATH];
297 LONG res;
299 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
301 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
302 get_typelib_key( guid, wMaj, wMin, buffer );
304 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
305 if (res == ERROR_FILE_NOT_FOUND)
307 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
308 return TYPE_E_LIBNOTREGISTERED;
310 else if (res != ERROR_SUCCESS)
312 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
313 return TYPE_E_REGISTRYACCESS;
316 while (hr != S_OK)
318 LONG dwPathLen = sizeof(Path);
320 get_lcid_subkey( myLCID, syskind, buffer );
322 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
324 if (!lcid)
325 break;
326 else if (myLCID == lcid)
328 /* try with sub-langid */
329 myLCID = SUBLANGID(lcid);
331 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
333 /* try with system langid */
334 myLCID = 0;
336 else
338 break;
341 else
343 *path = SysAllocString( Path );
344 hr = S_OK;
347 RegCloseKey( hkey );
348 TRACE_(typelib)("-- 0x%08x\n", hr);
349 return hr;
352 /****************************************************************************
353 * QueryPathOfRegTypeLib [OLEAUT32.164]
355 * Gets the path to a registered type library.
357 * PARAMS
358 * guid [I] referenced guid
359 * wMaj [I] major version
360 * wMin [I] minor version
361 * lcid [I] locale id
362 * path [O] path of typelib
364 * RETURNS
365 * Success: S_OK.
366 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
367 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
368 * opened.
370 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
372 #ifdef _WIN64
373 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
374 if(SUCCEEDED(hres))
375 return hres;
376 #endif
377 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
380 /******************************************************************************
381 * CreateTypeLib [OLEAUT32.160] creates a typelib
383 * RETURNS
384 * Success: S_OK
385 * Failure: Status
387 HRESULT WINAPI CreateTypeLib(
388 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
390 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
391 return E_FAIL;
394 /******************************************************************************
395 * LoadTypeLib [OLEAUT32.161]
397 * Loads a type library
399 * PARAMS
400 * szFile [I] Name of file to load from.
401 * pptLib [O] Pointer that receives ITypeLib object on success.
403 * RETURNS
404 * Success: S_OK
405 * Failure: Status
407 * SEE
408 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
410 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
412 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
413 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
416 /******************************************************************************
417 * LoadTypeLibEx [OLEAUT32.183]
419 * Loads and optionally registers a type library
421 * RETURNS
422 * Success: S_OK
423 * Failure: Status
425 HRESULT WINAPI LoadTypeLibEx(
426 LPCOLESTR szFile, /* [in] Name of file to load from */
427 REGKIND regkind, /* [in] Specify kind of registration */
428 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
430 WCHAR szPath[MAX_PATH+1];
431 HRESULT res;
433 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
435 *pptLib = NULL;
437 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
439 if (SUCCEEDED(res))
440 switch(regkind)
442 case REGKIND_DEFAULT:
443 /* don't register typelibs supplied with full path. Experimentation confirms the following */
444 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
445 (szFile[0] && (szFile[1] == ':'))) break;
446 /* else fall-through */
448 case REGKIND_REGISTER:
449 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
451 ITypeLib_Release(*pptLib);
452 *pptLib = 0;
454 break;
455 case REGKIND_NONE:
456 break;
459 TRACE(" returns %08x\n",res);
460 return res;
463 /******************************************************************************
464 * LoadRegTypeLib [OLEAUT32.162]
466 * Loads a registered type library.
468 * PARAMS
469 * rguid [I] GUID of the registered type library.
470 * wVerMajor [I] major version.
471 * wVerMinor [I] minor version.
472 * lcid [I] locale ID.
473 * ppTLib [O] pointer that receives an ITypeLib object on success.
475 * RETURNS
476 * Success: S_OK.
477 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
478 * LoadTypeLib.
480 HRESULT WINAPI LoadRegTypeLib(
481 REFGUID rguid,
482 WORD wVerMajor,
483 WORD wVerMinor,
484 LCID lcid,
485 ITypeLib **ppTLib)
487 BSTR bstr=NULL;
488 HRESULT res;
490 *ppTLib = NULL;
492 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
494 if(SUCCEEDED(res))
496 res= LoadTypeLib(bstr, ppTLib);
497 SysFreeString(bstr);
500 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
502 return res;
506 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
507 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
508 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
509 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
510 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
511 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
513 /******************************************************************************
514 * RegisterTypeLib [OLEAUT32.163]
515 * Adds information about a type library to the System Registry
516 * NOTES
517 * Docs: ITypeLib FAR * ptlib
518 * Docs: OLECHAR FAR* szFullPath
519 * Docs: OLECHAR FAR* szHelpDir
521 * RETURNS
522 * Success: S_OK
523 * Failure: Status
525 HRESULT WINAPI RegisterTypeLib(
526 ITypeLib * ptlib, /* [in] Pointer to the library*/
527 OLECHAR * szFullPath, /* [in] full Path of the library*/
528 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
529 may be NULL*/
531 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
532 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
533 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
534 HRESULT res;
535 TLIBATTR *attr;
536 WCHAR keyName[60];
537 WCHAR tmp[16];
538 HKEY key, subKey;
539 UINT types, tidx;
540 TYPEKIND kind;
541 DWORD disposition;
543 if (ptlib == NULL || szFullPath == NULL)
544 return E_INVALIDARG;
546 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
547 return E_FAIL;
549 #ifdef _WIN64
550 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
551 #else
552 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
553 #endif
555 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
557 res = S_OK;
558 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
559 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
561 LPOLESTR doc;
563 /* Set the human-readable name of the typelib */
564 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
565 res = E_FAIL;
566 else if (doc)
568 if (RegSetValueExW(key, NULL, 0, REG_SZ,
569 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
570 res = E_FAIL;
572 SysFreeString(doc);
575 /* Make up the name of the typelib path subkey */
576 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
578 /* Create the typelib path subkey */
579 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
580 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
582 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
583 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
584 res = E_FAIL;
586 RegCloseKey(subKey);
588 else
589 res = E_FAIL;
591 /* Create the flags subkey */
592 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
593 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
595 /* FIXME: is %u correct? */
596 static const WCHAR formatW[] = {'%','u',0};
597 WCHAR buf[20];
598 sprintfW(buf, formatW, attr->wLibFlags);
599 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
600 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
601 res = E_FAIL;
603 RegCloseKey(subKey);
605 else
606 res = E_FAIL;
608 /* create the helpdir subkey */
609 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
610 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
612 BOOL freeHelpDir = FALSE;
613 OLECHAR* pIndexStr;
615 /* if we created a new key, and helpDir was null, set the helpdir
616 to the directory which contains the typelib. However,
617 if we just opened an existing key, we leave the helpdir alone */
618 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
619 szHelpDir = SysAllocString(szFullPath);
620 pIndexStr = strrchrW(szHelpDir, '\\');
621 if (pIndexStr) {
622 *pIndexStr = 0;
624 freeHelpDir = TRUE;
627 /* if we have an szHelpDir, set it! */
628 if (szHelpDir != NULL) {
629 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
630 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
631 res = E_FAIL;
635 /* tidy up */
636 if (freeHelpDir) SysFreeString(szHelpDir);
637 RegCloseKey(subKey);
639 } else {
640 res = E_FAIL;
643 RegCloseKey(key);
645 else
646 res = E_FAIL;
648 /* register OLE Automation-compatible interfaces for this typelib */
649 types = ITypeLib_GetTypeInfoCount(ptlib);
650 for (tidx=0; tidx<types; tidx++) {
651 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
652 LPOLESTR name = NULL;
653 ITypeInfo *tinfo = NULL;
655 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
657 switch (kind) {
658 case TKIND_INTERFACE:
659 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
660 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
661 break;
663 case TKIND_DISPATCH:
664 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
665 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
666 break;
668 default:
669 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
670 break;
673 if (tinfo) {
674 TYPEATTR *tattr = NULL;
675 ITypeInfo_GetTypeAttr(tinfo, &tattr);
677 if (tattr) {
678 TRACE_(typelib)("guid=%s, flags=%04x (",
679 debugstr_guid(&tattr->guid),
680 tattr->wTypeFlags);
682 if (TRACE_ON(typelib)) {
683 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
684 XX(FAPPOBJECT);
685 XX(FCANCREATE);
686 XX(FLICENSED);
687 XX(FPREDECLID);
688 XX(FHIDDEN);
689 XX(FCONTROL);
690 XX(FDUAL);
691 XX(FNONEXTENSIBLE);
692 XX(FOLEAUTOMATION);
693 XX(FRESTRICTED);
694 XX(FAGGREGATABLE);
695 XX(FREPLACEABLE);
696 XX(FDISPATCHABLE);
697 XX(FREVERSEBIND);
698 XX(FPROXY);
699 #undef XX
700 MESSAGE("\n");
703 /* Register all dispinterfaces (which includes dual interfaces) and
704 oleautomation interfaces */
705 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
706 kind == TKIND_DISPATCH)
708 /* register interface<->typelib coupling */
709 get_interface_key( &tattr->guid, keyName );
710 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
711 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
713 if (name)
714 RegSetValueExW(key, NULL, 0, REG_SZ,
715 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
717 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (const BYTE *)PSOA, sizeof PSOA);
721 RegCloseKey(subKey);
724 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
726 RegSetValueExW(subKey, NULL, 0, REG_SZ,
727 (const BYTE *)PSOA, sizeof PSOA);
728 RegCloseKey(subKey);
731 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
732 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
734 WCHAR buffer[40];
735 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
736 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
738 StringFromGUID2(&attr->guid, buffer, 40);
739 RegSetValueExW(subKey, NULL, 0, REG_SZ,
740 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
741 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
742 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
743 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
744 RegCloseKey(subKey);
747 RegCloseKey(key);
751 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
754 ITypeInfo_Release(tinfo);
757 SysFreeString(name);
761 ITypeLib_ReleaseTLibAttr(ptlib, attr);
763 return res;
767 /******************************************************************************
768 * UnRegisterTypeLib [OLEAUT32.186]
769 * Removes information about a type library from the System Registry
770 * NOTES
772 * RETURNS
773 * Success: S_OK
774 * Failure: Status
776 HRESULT WINAPI UnRegisterTypeLib(
777 REFGUID libid, /* [in] Guid of the library */
778 WORD wVerMajor, /* [in] major version */
779 WORD wVerMinor, /* [in] minor version */
780 LCID lcid, /* [in] locale id */
781 SYSKIND syskind)
783 BSTR tlibPath = NULL;
784 DWORD tmpLength;
785 WCHAR keyName[60];
786 WCHAR subKeyName[50];
787 int result = S_OK;
788 DWORD i = 0;
789 BOOL deleteOtherStuff;
790 HKEY key = NULL;
791 HKEY subKey = NULL;
792 TYPEATTR* typeAttr = NULL;
793 TYPEKIND kind;
794 ITypeInfo* typeInfo = NULL;
795 ITypeLib* typeLib = NULL;
796 int numTypes;
798 TRACE("(IID: %s)\n",debugstr_guid(libid));
800 /* Create the path to the key */
801 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
803 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
805 TRACE("Unsupported syskind %i\n", syskind);
806 result = E_INVALIDARG;
807 goto end;
810 /* get the path to the typelib on disk */
811 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
812 result = E_INVALIDARG;
813 goto end;
816 /* Try and open the key to the type library. */
817 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
818 result = E_INVALIDARG;
819 goto end;
822 /* Try and load the type library */
823 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
824 result = TYPE_E_INVALIDSTATE;
825 goto end;
828 /* remove any types registered with this typelib */
829 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
830 for (i=0; i<numTypes; i++) {
831 /* get the kind of type */
832 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
833 goto enddeleteloop;
836 /* skip non-interfaces, and get type info for the type */
837 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
838 goto enddeleteloop;
840 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
841 goto enddeleteloop;
843 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
844 goto enddeleteloop;
847 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
848 kind == TKIND_DISPATCH)
850 /* the path to the type */
851 get_interface_key( &typeAttr->guid, subKeyName );
853 /* Delete its bits */
854 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
855 goto enddeleteloop;
857 RegDeleteKeyW(subKey, ProxyStubClsidW);
858 RegDeleteKeyW(subKey, ProxyStubClsid32W);
859 RegDeleteKeyW(subKey, TypeLibW);
860 RegCloseKey(subKey);
861 subKey = NULL;
862 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
865 enddeleteloop:
866 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
867 typeAttr = NULL;
868 if (typeInfo) ITypeInfo_Release(typeInfo);
869 typeInfo = NULL;
872 /* Now, delete the type library path subkey */
873 get_lcid_subkey( lcid, syskind, subKeyName );
874 RegDeleteKeyW(key, subKeyName);
875 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
876 RegDeleteKeyW(key, subKeyName);
878 /* check if there is anything besides the FLAGS/HELPDIR keys.
879 If there is, we don't delete them */
880 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
881 deleteOtherStuff = TRUE;
882 i = 0;
883 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
884 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
886 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
887 if (!strcmpW(subKeyName, FLAGSW)) continue;
888 if (!strcmpW(subKeyName, HELPDIRW)) continue;
889 deleteOtherStuff = FALSE;
890 break;
893 /* only delete the other parts of the key if we're absolutely sure */
894 if (deleteOtherStuff) {
895 RegDeleteKeyW(key, FLAGSW);
896 RegDeleteKeyW(key, HELPDIRW);
897 RegCloseKey(key);
898 key = NULL;
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
901 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
902 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
905 end:
906 SysFreeString(tlibPath);
907 if (typeLib) ITypeLib_Release(typeLib);
908 if (subKey) RegCloseKey(subKey);
909 if (key) RegCloseKey(key);
910 return result;
913 /******************************************************************************
914 * RegisterTypeLibForUser [OLEAUT32.442]
915 * Adds information about a type library to the user registry
916 * NOTES
917 * Docs: ITypeLib FAR * ptlib
918 * Docs: OLECHAR FAR* szFullPath
919 * Docs: OLECHAR FAR* szHelpDir
921 * RETURNS
922 * Success: S_OK
923 * Failure: Status
925 HRESULT WINAPI RegisterTypeLibForUser(
926 ITypeLib * ptlib, /* [in] Pointer to the library*/
927 OLECHAR * szFullPath, /* [in] full Path of the library*/
928 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
929 may be NULL*/
931 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
932 debugstr_w(szFullPath), debugstr_w(szHelpDir));
933 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
936 /******************************************************************************
937 * UnRegisterTypeLibForUser [OLEAUT32.443]
938 * Removes information about a type library from the user registry
940 * RETURNS
941 * Success: S_OK
942 * Failure: Status
944 HRESULT WINAPI UnRegisterTypeLibForUser(
945 REFGUID libid, /* [in] GUID of the library */
946 WORD wVerMajor, /* [in] major version */
947 WORD wVerMinor, /* [in] minor version */
948 LCID lcid, /* [in] locale id */
949 SYSKIND syskind)
951 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
952 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
953 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
956 /*======================= ITypeLib implementation =======================*/
958 typedef struct tagTLBGuid {
959 GUID guid;
960 UINT offset;
961 struct list entry;
962 } TLBGuid;
964 typedef struct tagTLBCustData
966 TLBGuid *guid;
967 VARIANT data;
968 struct list entry;
969 } TLBCustData;
971 /* data structure for import typelibs */
972 typedef struct tagTLBImpLib
974 int offset; /* offset in the file (MSFT)
975 offset in nametable (SLTG)
976 just used to identify library while reading
977 data from file */
978 TLBGuid *guid; /* libid */
979 BSTR name; /* name */
981 LCID lcid; /* lcid of imported typelib */
983 WORD wVersionMajor; /* major version number */
984 WORD wVersionMinor; /* minor version number */
986 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
987 NULL if not yet loaded */
988 struct list entry;
989 } TLBImpLib;
991 typedef struct tagTLBString {
992 BSTR str;
993 UINT offset;
994 struct list entry;
995 } TLBString;
997 /* internal ITypeLib data */
998 typedef struct tagITypeLibImpl
1000 ITypeLib2 ITypeLib2_iface;
1001 ITypeComp ITypeComp_iface;
1002 ICreateTypeLib2 ICreateTypeLib2_iface;
1003 LONG ref;
1004 TLBGuid *guid;
1005 LCID lcid;
1006 SYSKIND syskind;
1007 WORD ver_major;
1008 WORD ver_minor;
1009 WORD libflags;
1010 LCID set_lcid;
1012 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1013 * exported to the application as a UNICODE string.
1015 struct list string_list;
1016 struct list name_list;
1017 struct list guid_list;
1019 const TLBString *Name;
1020 const TLBString *DocString;
1021 const TLBString *HelpFile;
1022 const TLBString *HelpStringDll;
1023 DWORD dwHelpContext;
1024 int TypeInfoCount; /* nr of typeinfo's in librarry */
1025 struct tagITypeInfoImpl **typeinfos;
1026 struct list custdata_list;
1027 struct list implib_list;
1028 int ctTypeDesc; /* number of items in type desc array */
1029 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1030 library. Only used while reading MSFT
1031 typelibs */
1032 struct list ref_list; /* list of ref types in this typelib */
1033 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1036 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1037 struct list entry;
1038 WCHAR *path;
1039 INT index;
1040 } ITypeLibImpl;
1042 static const ITypeLib2Vtbl tlbvt;
1043 static const ITypeCompVtbl tlbtcvt;
1044 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1046 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1048 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1051 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1053 return impl_from_ITypeLib2((ITypeLib2*)iface);
1056 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1058 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1061 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1063 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1066 /* ITypeLib methods */
1067 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1068 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1070 /*======================= ITypeInfo implementation =======================*/
1072 /* data for referenced types */
1073 typedef struct tagTLBRefType
1075 INT index; /* Type index for internal ref or for external ref
1076 it the format is SLTG. -2 indicates to
1077 use guid */
1079 TYPEKIND tkind;
1080 TLBGuid *guid; /* guid of the referenced type */
1081 /* if index == TLB_REF_USE_GUID */
1083 HREFTYPE reference; /* The href of this ref */
1084 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1085 TLB_REF_INTERNAL for internal refs
1086 TLB_REF_NOT_FOUND for broken refs */
1088 struct list entry;
1089 } TLBRefType;
1091 #define TLB_REF_USE_GUID -2
1093 #define TLB_REF_INTERNAL (void*)-2
1094 #define TLB_REF_NOT_FOUND (void*)-1
1096 /* internal Parameter data */
1097 typedef struct tagTLBParDesc
1099 const TLBString *Name;
1100 struct list custdata_list;
1101 } TLBParDesc;
1103 /* internal Function data */
1104 typedef struct tagTLBFuncDesc
1106 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1107 const TLBString *Name; /* the name of this function */
1108 TLBParDesc *pParamDesc; /* array with param names and custom data */
1109 int helpcontext;
1110 int HelpStringContext;
1111 const TLBString *HelpString;
1112 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1113 struct list custdata_list;
1114 } TLBFuncDesc;
1116 /* internal Variable data */
1117 typedef struct tagTLBVarDesc
1119 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1120 const TLBString *Name; /* the name of this variable */
1121 int HelpContext;
1122 int HelpStringContext;
1123 const TLBString *HelpString;
1124 struct list custdata_list;
1125 } TLBVarDesc;
1127 /* internal implemented interface data */
1128 typedef struct tagTLBImplType
1130 HREFTYPE hRef; /* hRef of interface */
1131 int implflags; /* IMPLFLAG_*s */
1132 struct list custdata_list;
1133 } TLBImplType;
1135 /* internal TypeInfo data */
1136 typedef struct tagITypeInfoImpl
1138 ITypeInfo2 ITypeInfo2_iface;
1139 ITypeComp ITypeComp_iface;
1140 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1141 LONG ref;
1142 BOOL not_attached_to_typelib;
1143 BOOL needs_layout;
1145 TLBGuid *guid;
1146 LCID lcid;
1147 MEMBERID memidConstructor;
1148 MEMBERID memidDestructor;
1149 LPOLESTR lpstrSchema;
1150 ULONG cbSizeInstance;
1151 TYPEKIND typekind;
1152 WORD cFuncs;
1153 WORD cVars;
1154 WORD cImplTypes;
1155 WORD cbSizeVft;
1156 WORD cbAlignment;
1157 WORD wTypeFlags;
1158 WORD wMajorVerNum;
1159 WORD wMinorVerNum;
1160 TYPEDESC tdescAlias;
1161 IDLDESC idldescType;
1163 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1164 int index; /* index in this typelib; */
1165 HREFTYPE hreftype; /* hreftype for app object binding */
1166 /* type libs seem to store the doc strings in ascii
1167 * so why should we do it in unicode?
1169 const TLBString *Name;
1170 const TLBString *DocString;
1171 const TLBString *DllName;
1172 const TLBString *Schema;
1173 DWORD dwHelpContext;
1174 DWORD dwHelpStringContext;
1176 /* functions */
1177 TLBFuncDesc *funcdescs;
1179 /* variables */
1180 TLBVarDesc *vardescs;
1182 /* Implemented Interfaces */
1183 TLBImplType *impltypes;
1185 struct list custdata_list;
1186 } ITypeInfoImpl;
1188 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1190 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1193 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1195 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1198 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1200 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1203 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1205 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1208 static const ITypeInfo2Vtbl tinfvt;
1209 static const ITypeCompVtbl tcompvt;
1210 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1212 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1213 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1215 typedef struct tagTLBContext
1217 unsigned int oStart; /* start of TLB in file */
1218 unsigned int pos; /* current pos */
1219 unsigned int length; /* total length */
1220 void *mapping; /* memory mapping */
1221 MSFT_SegDir * pTblDir;
1222 ITypeLibImpl* pLibInfo;
1223 } TLBContext;
1226 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1228 static inline BSTR TLB_get_bstr(const TLBString *str)
1230 return str != NULL ? str->str : NULL;
1233 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1235 if(!str)
1236 return 1;
1237 return memcmp(left, str->str, len);
1240 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1242 return guid != NULL ? &guid->guid : NULL;
1245 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1247 return guid != NULL ? &guid->guid : &GUID_NULL;
1251 debug
1253 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1254 if (pTD->vt & VT_RESERVED)
1255 szVarType += strlen(strcpy(szVarType, "reserved | "));
1256 if (pTD->vt & VT_BYREF)
1257 szVarType += strlen(strcpy(szVarType, "ref to "));
1258 if (pTD->vt & VT_ARRAY)
1259 szVarType += strlen(strcpy(szVarType, "array of "));
1260 if (pTD->vt & VT_VECTOR)
1261 szVarType += strlen(strcpy(szVarType, "vector of "));
1262 switch(pTD->vt & VT_TYPEMASK) {
1263 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1264 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1265 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1266 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1267 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1268 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1269 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1270 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1271 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1272 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1273 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1274 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1275 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1276 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1277 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1278 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1279 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1280 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1281 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1282 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1283 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1284 pTD->u.hreftype); break;
1285 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1286 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1287 case VT_PTR: sprintf(szVarType, "ptr to ");
1288 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1289 break;
1290 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1291 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1292 break;
1293 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1294 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1295 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1296 break;
1298 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1302 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1303 char buf[200];
1304 USHORT flags = edesc->u.paramdesc.wParamFlags;
1305 dump_TypeDesc(&edesc->tdesc,buf);
1306 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1307 MESSAGE("\t\tu.paramdesc.wParamFlags");
1308 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1309 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1310 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1311 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1312 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1313 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1314 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1315 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1316 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1318 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1319 int i;
1320 MESSAGE("memid is %08x\n",funcdesc->memid);
1321 for (i=0;i<funcdesc->cParams;i++) {
1322 MESSAGE("Param %d:\n",i);
1323 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1325 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1326 switch (funcdesc->funckind) {
1327 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1328 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1329 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1330 case FUNC_STATIC: MESSAGE("static");break;
1331 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1332 default: MESSAGE("unknown");break;
1334 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1335 switch (funcdesc->invkind) {
1336 case INVOKE_FUNC: MESSAGE("func");break;
1337 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1338 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1339 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1341 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1342 switch (funcdesc->callconv) {
1343 case CC_CDECL: MESSAGE("cdecl");break;
1344 case CC_PASCAL: MESSAGE("pascal");break;
1345 case CC_STDCALL: MESSAGE("stdcall");break;
1346 case CC_SYSCALL: MESSAGE("syscall");break;
1347 default:break;
1349 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1350 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1351 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1353 MESSAGE("\telemdescFunc (return value type):\n");
1354 dump_ELEMDESC(&funcdesc->elemdescFunc);
1357 static const char * const typekind_desc[] =
1359 "TKIND_ENUM",
1360 "TKIND_RECORD",
1361 "TKIND_MODULE",
1362 "TKIND_INTERFACE",
1363 "TKIND_DISPATCH",
1364 "TKIND_COCLASS",
1365 "TKIND_ALIAS",
1366 "TKIND_UNION",
1367 "TKIND_MAX"
1370 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1372 int i;
1373 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1374 for (i=0;i<pfd->funcdesc.cParams;i++)
1375 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1378 dump_FUNCDESC(&(pfd->funcdesc));
1380 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1381 if(pfd->Entry == NULL)
1382 MESSAGE("\tentry: (null)\n");
1383 else if(pfd->Entry == (void*)-1)
1384 MESSAGE("\tentry: invalid\n");
1385 else if(IS_INTRESOURCE(pfd->Entry))
1386 MESSAGE("\tentry: %p\n", pfd->Entry);
1387 else
1388 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1390 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1392 while (n)
1394 dump_TLBFuncDescOne(pfd);
1395 ++pfd;
1396 --n;
1399 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1401 while (n)
1403 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1404 ++pvd;
1405 --n;
1409 static void dump_TLBImpLib(const TLBImpLib *import)
1411 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1412 debugstr_w(import->name));
1413 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1414 import->wVersionMinor, import->lcid, import->offset);
1417 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1419 TLBRefType *ref;
1421 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1423 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1424 if(ref->index == -1)
1425 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1426 else
1427 TRACE_(typelib)("type no: %d\n", ref->index);
1429 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1431 TRACE_(typelib)("in lib\n");
1432 dump_TLBImpLib(ref->pImpTLInfo);
1437 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1439 if(!impl)
1440 return;
1441 while (n) {
1442 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1443 impl->hRef, impl->implflags);
1444 ++impl;
1445 --n;
1449 static void dump_Variant(const VARIANT * pvar)
1451 SYSTEMTIME st;
1453 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1455 if (pvar)
1457 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1458 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1460 TRACE(",%p", V_BYREF(pvar));
1462 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1464 TRACE(",%p", V_ARRAY(pvar));
1466 else switch (V_TYPE(pvar))
1468 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1469 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1470 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1471 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1472 case VT_INT:
1473 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1474 case VT_UINT:
1475 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1476 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1477 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1478 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1479 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1480 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1481 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1482 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1483 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1484 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1485 V_CY(pvar).s.Lo); break;
1486 case VT_DATE:
1487 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1488 TRACE(",<invalid>");
1489 else
1490 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1491 st.wHour, st.wMinute, st.wSecond);
1492 break;
1493 case VT_ERROR:
1494 case VT_VOID:
1495 case VT_USERDEFINED:
1496 case VT_EMPTY:
1497 case VT_NULL: break;
1498 default: TRACE(",?"); break;
1501 TRACE("}\n");
1504 static void dump_DispParms(const DISPPARAMS * pdp)
1506 unsigned int index;
1508 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1510 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1512 TRACE("named args:\n");
1513 for (index = 0; index < pdp->cNamedArgs; index++)
1514 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1517 if (pdp->cArgs && pdp->rgvarg)
1519 TRACE("args:\n");
1520 for (index = 0; index < pdp->cArgs; index++)
1521 dump_Variant( &pdp->rgvarg[index] );
1525 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1527 TRACE("%p ref=%u\n", pty, pty->ref);
1528 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1529 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1530 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1531 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1532 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1533 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1534 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1535 if (TRACE_ON(ole))
1536 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1537 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1538 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1541 static void dump_VARDESC(const VARDESC *v)
1543 MESSAGE("memid %d\n",v->memid);
1544 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1545 MESSAGE("oInst %d\n",v->u.oInst);
1546 dump_ELEMDESC(&(v->elemdescVar));
1547 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1548 MESSAGE("varkind %d\n",v->varkind);
1551 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1553 /* VT_LPWSTR is largest type that, may appear in type description */
1554 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1555 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1556 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1557 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1558 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1559 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1560 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1561 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1564 static void TLB_abort(void)
1566 DebugBreak();
1569 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1571 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1572 if (!ret) ERR("cannot allocate memory\n");
1573 return ret;
1576 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1578 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1579 if (!ret) ERR("cannot allocate memory\n");
1580 return ret;
1583 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1585 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1588 void heap_free(void *ptr)
1590 HeapFree(GetProcessHeap(), 0, ptr);
1593 /* returns the size required for a deep copy of a typedesc into a
1594 * flat buffer */
1595 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1597 SIZE_T size = 0;
1599 if (alloc_initial_space)
1600 size += sizeof(TYPEDESC);
1602 switch (tdesc->vt)
1604 case VT_PTR:
1605 case VT_SAFEARRAY:
1606 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1607 break;
1608 case VT_CARRAY:
1609 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1610 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1611 break;
1613 return size;
1616 /* deep copy a typedesc into a flat buffer */
1617 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1619 if (!dest)
1621 dest = buffer;
1622 buffer = (char *)buffer + sizeof(TYPEDESC);
1625 *dest = *src;
1627 switch (src->vt)
1629 case VT_PTR:
1630 case VT_SAFEARRAY:
1631 dest->u.lptdesc = buffer;
1632 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1633 break;
1634 case VT_CARRAY:
1635 dest->u.lpadesc = buffer;
1636 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1637 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1638 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1639 break;
1641 return buffer;
1644 /* free custom data allocated by MSFT_CustData */
1645 static inline void TLB_FreeCustData(struct list *custdata_list)
1647 TLBCustData *cd, *cdn;
1648 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1650 list_remove(&cd->entry);
1651 VariantClear(&cd->data);
1652 heap_free(cd);
1656 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1658 DWORD len;
1659 BSTR ret;
1661 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1662 ret = SysAllocStringLen(NULL, len - 1);
1663 if (!ret) return ret;
1664 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1665 return ret;
1668 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1669 UINT n, MEMBERID memid)
1671 while(n){
1672 if(funcdescs->funcdesc.memid == memid)
1673 return funcdescs;
1674 ++funcdescs;
1675 --n;
1677 return NULL;
1680 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1681 UINT n, const OLECHAR *name)
1683 while(n){
1684 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1685 return funcdescs;
1686 ++funcdescs;
1687 --n;
1689 return NULL;
1692 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1693 UINT n, MEMBERID memid)
1695 while(n){
1696 if(vardescs->vardesc.memid == memid)
1697 return vardescs;
1698 ++vardescs;
1699 --n;
1701 return NULL;
1704 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1705 UINT n, const OLECHAR *name)
1707 while(n){
1708 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1709 return vardescs;
1710 ++vardescs;
1711 --n;
1713 return NULL;
1716 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1718 TLBCustData *cust_data;
1719 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1720 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1721 return cust_data;
1722 return NULL;
1725 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1726 UINT n, const OLECHAR *name)
1728 while(n){
1729 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1730 return *typeinfos;
1731 ++typeinfos;
1732 --n;
1734 return NULL;
1737 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1739 list_init(&var_desc->custdata_list);
1742 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1744 TLBVarDesc *ret;
1746 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1747 if(!ret)
1748 return NULL;
1750 while(n){
1751 TLBVarDesc_Constructor(&ret[n-1]);
1752 --n;
1755 return ret;
1758 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1760 TLBParDesc *ret;
1762 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1763 if(!ret)
1764 return NULL;
1766 while(n){
1767 list_init(&ret[n-1].custdata_list);
1768 --n;
1771 return ret;
1774 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1776 list_init(&func_desc->custdata_list);
1779 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1781 TLBFuncDesc *ret;
1783 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1784 if(!ret)
1785 return NULL;
1787 while(n){
1788 TLBFuncDesc_Constructor(&ret[n-1]);
1789 --n;
1792 return ret;
1795 static void TLBImplType_Constructor(TLBImplType *impl)
1797 list_init(&impl->custdata_list);
1800 static TLBImplType *TLBImplType_Alloc(UINT n)
1802 TLBImplType *ret;
1804 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1805 if(!ret)
1806 return NULL;
1808 while(n){
1809 TLBImplType_Constructor(&ret[n-1]);
1810 --n;
1813 return ret;
1816 static TLBGuid *TLB_append_guid(struct list *guid_list, const GUID *new_guid)
1818 TLBGuid *guid;
1820 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1821 if (IsEqualGUID(&guid->guid, new_guid))
1822 return guid;
1825 guid = heap_alloc(sizeof(TLBGuid));
1826 if (!guid)
1827 return NULL;
1829 memcpy(&guid->guid, new_guid, sizeof(GUID));
1831 list_add_tail(guid_list, &guid->entry);
1833 return guid;
1836 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1838 TLBCustData *cust_data;
1840 switch(V_VT(var)){
1841 case VT_I4:
1842 case VT_R4:
1843 case VT_UI4:
1844 case VT_INT:
1845 case VT_UINT:
1846 case VT_HRESULT:
1847 case VT_BSTR:
1848 break;
1849 default:
1850 return DISP_E_BADVARTYPE;
1853 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1855 if (!cust_data) {
1856 cust_data = heap_alloc(sizeof(TLBCustData));
1857 if (!cust_data)
1858 return E_OUTOFMEMORY;
1860 cust_data->guid = tlbguid;
1861 VariantInit(&cust_data->data);
1863 list_add_tail(custdata_list, &cust_data->entry);
1864 }else
1865 VariantClear(&cust_data->data);
1867 return VariantCopy(&cust_data->data, var);
1870 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1872 TLBString *str;
1874 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1875 if (strcmpW(str->str, new_str) == 0)
1876 return str;
1879 str = heap_alloc(sizeof(TLBString));
1880 if (!str)
1881 return NULL;
1883 str->str = SysAllocString(new_str);
1884 if (!str->str) {
1885 heap_free(str);
1886 return NULL;
1889 list_add_tail(string_list, &str->entry);
1891 return str;
1894 /**********************************************************************
1896 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1898 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1900 return pcx->pos;
1903 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1905 if (where != DO_NOT_SEEK)
1907 where += pcx->oStart;
1908 if (where > pcx->length)
1910 /* FIXME */
1911 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1912 TLB_abort();
1914 pcx->pos = where;
1918 /* read function */
1919 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1921 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1922 pcx->pos, count, pcx->oStart, pcx->length, where);
1924 MSFT_Seek(pcx, where);
1925 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1926 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1927 pcx->pos += count;
1928 return count;
1931 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1932 LONG where )
1934 DWORD ret;
1936 ret = MSFT_Read(buffer, count, pcx, where);
1937 FromLEDWords(buffer, ret);
1939 return ret;
1942 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1943 LONG where )
1945 DWORD ret;
1947 ret = MSFT_Read(buffer, count, pcx, where);
1948 FromLEWords(buffer, ret);
1950 return ret;
1953 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
1955 TLBGuid *guid;
1956 MSFT_GuidEntry entry;
1957 int offs = 0;
1959 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
1960 while (1) {
1961 if (offs >= pcx->pTblDir->pGuidTab.length)
1962 return S_OK;
1964 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
1966 guid = heap_alloc(sizeof(TLBGuid));
1968 guid->offset = offs;
1969 guid->guid = entry.guid;
1971 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
1973 offs += sizeof(MSFT_GuidEntry);
1977 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
1979 TLBGuid *ret;
1981 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
1982 if(ret->offset == offset){
1983 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
1984 return ret;
1988 return NULL;
1991 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1993 MSFT_NameIntro niName;
1995 if (offset < 0)
1997 ERR_(typelib)("bad offset %d\n", offset);
1998 return -1;
2001 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2002 pcx->pTblDir->pNametab.offset+offset);
2004 return niName.hreftype;
2007 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2009 char *string;
2010 MSFT_NameIntro intro;
2011 INT16 len_piece;
2012 int offs = 0, lengthInChars;
2014 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2015 while (1) {
2016 TLBString *tlbstr;
2018 if (offs >= pcx->pTblDir->pNametab.length)
2019 return S_OK;
2021 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2022 intro.namelen &= 0xFF;
2023 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2024 if(len_piece % 4)
2025 len_piece = (len_piece + 4) & ~0x3;
2026 if(len_piece < 8)
2027 len_piece = 8;
2029 string = heap_alloc(len_piece + 1);
2030 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2031 string[intro.namelen] = '\0';
2033 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2034 string, -1, NULL, 0);
2035 if (!lengthInChars) {
2036 heap_free(string);
2037 return E_UNEXPECTED;
2040 tlbstr = heap_alloc(sizeof(TLBString));
2042 tlbstr->offset = offs;
2043 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2044 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2046 heap_free(string);
2048 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2050 offs += len_piece;
2054 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2056 TLBString *tlbstr;
2058 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2059 if (tlbstr->offset == offset) {
2060 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2061 return tlbstr;
2065 return NULL;
2068 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2070 TLBString *tlbstr;
2072 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2073 if (tlbstr->offset == offset) {
2074 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2075 return tlbstr;
2079 return NULL;
2083 * read a value and fill a VARIANT structure
2085 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2087 int size;
2089 TRACE_(typelib)("\n");
2091 if(offset <0) { /* data are packed in here */
2092 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2093 V_I4(pVar) = offset & 0x3ffffff;
2094 return;
2096 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2097 pcx->pTblDir->pCustData.offset + offset );
2098 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2099 switch (V_VT(pVar)){
2100 case VT_EMPTY: /* FIXME: is this right? */
2101 case VT_NULL: /* FIXME: is this right? */
2102 case VT_I2 : /* this should not happen */
2103 case VT_I4 :
2104 case VT_R4 :
2105 case VT_ERROR :
2106 case VT_BOOL :
2107 case VT_I1 :
2108 case VT_UI1 :
2109 case VT_UI2 :
2110 case VT_UI4 :
2111 case VT_INT :
2112 case VT_UINT :
2113 case VT_VOID : /* FIXME: is this right? */
2114 case VT_HRESULT :
2115 size=4; break;
2116 case VT_R8 :
2117 case VT_CY :
2118 case VT_DATE :
2119 case VT_I8 :
2120 case VT_UI8 :
2121 case VT_DECIMAL : /* FIXME: is this right? */
2122 case VT_FILETIME :
2123 size=8;break;
2124 /* pointer types with known behaviour */
2125 case VT_BSTR :{
2126 char * ptr;
2127 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2128 if(size < 0) {
2129 char next;
2130 DWORD origPos = MSFT_Tell(pcx), nullPos;
2132 do {
2133 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
2134 } while (next);
2135 nullPos = MSFT_Tell(pcx);
2136 size = nullPos - origPos;
2137 MSFT_Seek(pcx, origPos);
2139 ptr = heap_alloc_zero(size);/* allocate temp buffer */
2140 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
2141 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2142 /* FIXME: do we need a AtoW conversion here? */
2143 V_UNION(pVar, bstrVal[size])='\0';
2144 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2145 heap_free(ptr);
2147 size=-4; break;
2148 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2149 case VT_DISPATCH :
2150 case VT_VARIANT :
2151 case VT_UNKNOWN :
2152 case VT_PTR :
2153 case VT_SAFEARRAY :
2154 case VT_CARRAY :
2155 case VT_USERDEFINED :
2156 case VT_LPSTR :
2157 case VT_LPWSTR :
2158 case VT_BLOB :
2159 case VT_STREAM :
2160 case VT_STORAGE :
2161 case VT_STREAMED_OBJECT :
2162 case VT_STORED_OBJECT :
2163 case VT_BLOB_OBJECT :
2164 case VT_CF :
2165 case VT_CLSID :
2166 default:
2167 size=0;
2168 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2169 V_VT(pVar));
2172 if(size>0) /* (big|small) endian correct? */
2173 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2174 return;
2177 * create a linked list with custom data
2179 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2181 MSFT_CDGuid entry;
2182 TLBCustData* pNew;
2183 int count=0;
2185 TRACE_(typelib)("\n");
2187 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2189 while(offset >=0){
2190 count++;
2191 pNew=heap_alloc_zero(sizeof(TLBCustData));
2192 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2193 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2194 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2195 list_add_head(custdata_list, &pNew->entry);
2196 offset = entry.next;
2198 return count;
2201 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
2202 ITypeInfoImpl *pTI)
2204 if(type <0)
2205 pTd->vt=type & VT_TYPEMASK;
2206 else
2207 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2209 if(pTd->vt == VT_USERDEFINED)
2210 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
2212 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2215 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
2217 /* resolve referenced type if any */
2218 while (lpTypeDesc)
2220 switch (lpTypeDesc->vt)
2222 case VT_PTR:
2223 lpTypeDesc = lpTypeDesc->u.lptdesc;
2224 break;
2226 case VT_CARRAY:
2227 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
2228 break;
2230 case VT_USERDEFINED:
2231 MSFT_DoRefType(pcx, pTI->pTypeLib,
2232 lpTypeDesc->u.hreftype);
2234 lpTypeDesc = NULL;
2235 break;
2237 default:
2238 lpTypeDesc = NULL;
2243 static int TLB_is_propgetput(INVOKEKIND invkind)
2245 return (invkind == INVOKE_PROPERTYGET ||
2246 invkind == INVOKE_PROPERTYPUT ||
2247 invkind == INVOKE_PROPERTYPUTREF);
2250 static void
2251 MSFT_DoFuncs(TLBContext* pcx,
2252 ITypeInfoImpl* pTI,
2253 int cFuncs,
2254 int cVars,
2255 int offset,
2256 TLBFuncDesc** pptfd)
2259 * member information is stored in a data structure at offset
2260 * indicated by the memoffset field of the typeinfo structure
2261 * There are several distinctive parts.
2262 * The first part starts with a field that holds the total length
2263 * of this (first) part excluding this field. Then follow the records,
2264 * for each member there is one record.
2266 * The first entry is always the length of the record (including this
2267 * length word).
2268 * The rest of the record depends on the type of the member. If there is
2269 * a field indicating the member type (function, variable, interface, etc)
2270 * I have not found it yet. At this time we depend on the information
2271 * in the type info and the usual order how things are stored.
2273 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2274 * for each member;
2276 * Third is an equal sized array with file offsets to the name entry
2277 * of each member.
2279 * The fourth and last (?) part is an array with offsets to the records
2280 * in the first part of this file segment.
2283 int infolen, nameoffset, reclength, i;
2284 int recoffset = offset + sizeof(INT);
2286 char *recbuf = heap_alloc(0xffff);
2287 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2288 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2290 TRACE_(typelib)("\n");
2292 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2294 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2295 ptfd = *pptfd;
2296 for ( i = 0; i < cFuncs ; i++ )
2298 int optional;
2300 /* name, eventually add to a hash table */
2301 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2302 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2304 /* read the function information record */
2305 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2307 reclength &= 0xffff;
2309 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2311 /* size without argument data */
2312 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2313 if (pFuncRec->FKCCIC & 0x1000)
2314 optional -= pFuncRec->nrargs * sizeof(INT);
2316 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2317 ptfd->helpcontext = pFuncRec->HelpContext;
2319 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2320 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2322 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2324 if (pFuncRec->FKCCIC & 0x2000 )
2326 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2327 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2328 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2330 else
2331 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2333 else
2334 ptfd->Entry = (TLBString*)-1;
2336 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2337 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2339 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2340 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2342 /* fill the FuncDesc Structure */
2343 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2344 offset + infolen + ( i + 1) * sizeof(INT));
2346 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2347 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2348 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2349 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2350 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2351 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2352 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2354 /* nameoffset is sometimes -1 on the second half of a propget/propput
2355 * pair of functions */
2356 if ((nameoffset == -1) && (i > 0) &&
2357 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2358 TLB_is_propgetput(ptfd->funcdesc.invkind))
2359 ptfd->Name = ptfd_prev->Name;
2360 else
2361 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2363 MSFT_GetTdesc(pcx,
2364 pFuncRec->DataType,
2365 &ptfd->funcdesc.elemdescFunc.tdesc,
2366 pTI);
2367 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2369 /* do the parameters/arguments */
2370 if(pFuncRec->nrargs)
2372 int j = 0;
2373 MSFT_ParameterInfo paraminfo;
2375 ptfd->funcdesc.lprgelemdescParam =
2376 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2378 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2380 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2381 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2383 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2385 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2387 MSFT_GetTdesc(pcx,
2388 paraminfo.DataType,
2389 &elemdesc->tdesc,
2390 pTI);
2392 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2394 /* name */
2395 if (paraminfo.oName == -1)
2396 /* this occurs for [propput] or [propget] methods, so
2397 * we should just set the name of the parameter to the
2398 * name of the method. */
2399 ptfd->pParamDesc[j].Name = ptfd->Name;
2400 else
2401 ptfd->pParamDesc[j].Name =
2402 MSFT_ReadName( pcx, paraminfo.oName );
2403 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2405 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2407 /* default value */
2408 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2409 (pFuncRec->FKCCIC & 0x1000) )
2411 INT* pInt = (INT *)((char *)pFuncRec +
2412 reclength -
2413 (pFuncRec->nrargs * 4) * sizeof(INT) );
2415 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2417 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2418 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2420 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2421 pInt[j], pcx);
2423 else
2424 elemdesc->u.paramdesc.pparamdescex = NULL;
2426 /* custom info */
2427 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2428 j*sizeof(pFuncRec->oArgCustData[0])) &&
2429 pFuncRec->FKCCIC & 0x80 )
2431 MSFT_CustData(pcx,
2432 pFuncRec->oArgCustData[j],
2433 &ptfd->pParamDesc[j].custdata_list);
2436 /* SEEK value = jump to offset,
2437 * from there jump to the end of record,
2438 * go back by (j-1) arguments
2440 MSFT_ReadLEDWords( &paraminfo ,
2441 sizeof(MSFT_ParameterInfo), pcx,
2442 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2443 * sizeof(MSFT_ParameterInfo)));
2447 /* scode is not used: archaic win16 stuff FIXME: right? */
2448 ptfd->funcdesc.cScodes = 0 ;
2449 ptfd->funcdesc.lprgscode = NULL ;
2451 ptfd_prev = ptfd;
2452 ++ptfd;
2453 recoffset += reclength;
2455 heap_free(recbuf);
2458 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2459 int cVars, int offset, TLBVarDesc ** pptvd)
2461 int infolen, nameoffset, reclength;
2462 char recbuf[256];
2463 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2464 TLBVarDesc *ptvd;
2465 int i;
2466 int recoffset;
2468 TRACE_(typelib)("\n");
2470 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2471 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2472 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2473 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2474 recoffset += offset+sizeof(INT);
2475 for(i=0;i<cVars;i++, ++ptvd){
2476 /* name, eventually add to a hash table */
2477 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2478 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2479 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2480 /* read the variable information record */
2481 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2482 reclength &= 0xff;
2483 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2485 /* optional data */
2486 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2487 ptvd->HelpContext = pVarRec->HelpContext;
2489 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2490 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2492 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2493 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2495 /* fill the VarDesc Structure */
2496 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2497 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2498 ptvd->vardesc.varkind = pVarRec->VarKind;
2499 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2500 MSFT_GetTdesc(pcx, pVarRec->DataType,
2501 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2502 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2503 if(pVarRec->VarKind == VAR_CONST ){
2504 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2505 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2506 pVarRec->OffsValue, pcx);
2507 } else
2508 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2509 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2510 recoffset += reclength;
2514 /* fill in data for a hreftype (offset). When the referenced type is contained
2515 * in the typelib, it's just an (file) offset in the type info base dir.
2516 * If comes from import, it's an offset+1 in the ImpInfo table
2517 * */
2518 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2519 int offset)
2521 TLBRefType *ref;
2523 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2525 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2527 if(ref->reference == offset) return;
2530 ref = heap_alloc_zero(sizeof(TLBRefType));
2531 list_add_tail(&pTL->ref_list, &ref->entry);
2533 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2534 /* external typelib */
2535 MSFT_ImpInfo impinfo;
2536 TLBImpLib *pImpLib;
2538 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2540 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2541 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2543 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2544 if(pImpLib->offset==impinfo.oImpFile)
2545 break;
2547 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2548 ref->reference = offset & (~0x3);
2549 ref->pImpTLInfo = pImpLib;
2550 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2551 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2552 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2553 ref->index = TLB_REF_USE_GUID;
2554 } else
2555 ref->index = impinfo.oGuid;
2556 }else{
2557 ERR("Cannot find a reference\n");
2558 ref->reference = -1;
2559 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2561 }else{
2562 /* in this typelib */
2563 ref->index = MSFT_HREFTYPE_INDEX(offset);
2564 ref->reference = offset;
2565 ref->pImpTLInfo = TLB_REF_INTERNAL;
2569 /* process Implemented Interfaces of a com class */
2570 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2571 int offset)
2573 int i;
2574 MSFT_RefRecord refrec;
2575 TLBImplType *pImpl;
2577 TRACE_(typelib)("\n");
2579 pTI->impltypes = TLBImplType_Alloc(count);
2580 pImpl = pTI->impltypes;
2581 for(i=0;i<count;i++){
2582 if(offset<0) break; /* paranoia */
2583 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2584 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2585 pImpl->hRef = refrec.reftype;
2586 pImpl->implflags=refrec.flags;
2587 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2588 offset=refrec.onext;
2589 ++pImpl;
2593 * process a typeinfo record
2595 static ITypeInfoImpl * MSFT_DoTypeInfo(
2596 TLBContext *pcx,
2597 int count,
2598 ITypeLibImpl * pLibInfo)
2600 MSFT_TypeInfoBase tiBase;
2601 ITypeInfoImpl *ptiRet;
2603 TRACE_(typelib)("count=%u\n", count);
2605 ptiRet = ITypeInfoImpl_Constructor();
2606 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2607 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2609 /* this is where we are coming from */
2610 ptiRet->pTypeLib = pLibInfo;
2611 ptiRet->index=count;
2613 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2614 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2615 ptiRet->lpstrSchema=NULL; /* reserved */
2616 ptiRet->cbSizeInstance=tiBase.size;
2617 ptiRet->typekind=tiBase.typekind & 0xF;
2618 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2619 ptiRet->cVars=HIWORD(tiBase.cElement);
2620 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2621 ptiRet->wTypeFlags=tiBase.flags;
2622 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2623 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2624 ptiRet->cImplTypes=tiBase.cImplTypes;
2625 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2626 if(ptiRet->typekind == TKIND_ALIAS)
2627 MSFT_GetTdesc(pcx, tiBase.datatype1,
2628 &ptiRet->tdescAlias, ptiRet);
2630 /* FIXME: */
2631 /* IDLDESC idldescType; *//* never saw this one != zero */
2633 /* name, eventually add to a hash table */
2634 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2635 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2636 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2637 /* help info */
2638 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2639 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2640 ptiRet->dwHelpContext=tiBase.helpcontext;
2642 if (ptiRet->typekind == TKIND_MODULE)
2643 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2645 /* note: InfoType's Help file and HelpStringDll come from the containing
2646 * library. Further HelpString and Docstring appear to be the same thing :(
2648 /* functions */
2649 if(ptiRet->cFuncs >0 )
2650 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2651 ptiRet->cVars,
2652 tiBase.memoffset, &ptiRet->funcdescs);
2653 /* variables */
2654 if(ptiRet->cVars >0 )
2655 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2656 ptiRet->cVars,
2657 tiBase.memoffset, &ptiRet->vardescs);
2658 if(ptiRet->cImplTypes >0 ) {
2659 switch(ptiRet->typekind)
2661 case TKIND_COCLASS:
2662 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2663 tiBase.datatype1);
2664 break;
2665 case TKIND_DISPATCH:
2666 /* This is not -1 when the interface is a non-base dual interface or
2667 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2668 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2669 not this interface.
2672 if (tiBase.datatype1 != -1)
2674 ptiRet->impltypes = TLBImplType_Alloc(1);
2675 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2676 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2678 break;
2679 default:
2680 ptiRet->impltypes = TLBImplType_Alloc(1);
2681 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2682 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2683 break;
2686 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2688 TRACE_(typelib)("%s guid: %s kind:%s\n",
2689 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2690 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2691 typekind_desc[ptiRet->typekind]);
2692 if (TRACE_ON(typelib))
2693 dump_TypeInfo(ptiRet);
2695 return ptiRet;
2698 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2700 char *string;
2701 INT16 len_str, len_piece;
2702 int offs = 0, lengthInChars;
2704 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2705 while (1) {
2706 TLBString *tlbstr;
2708 if (offs >= pcx->pTblDir->pStringtab.length)
2709 return S_OK;
2711 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2712 len_piece = len_str + sizeof(INT16);
2713 if(len_piece % 4)
2714 len_piece = (len_piece + 4) & ~0x3;
2715 if(len_piece < 8)
2716 len_piece = 8;
2718 string = heap_alloc(len_piece + 1);
2719 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2720 string[len_str] = '\0';
2722 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2723 string, -1, NULL, 0);
2724 if (!lengthInChars) {
2725 heap_free(string);
2726 return E_UNEXPECTED;
2729 tlbstr = heap_alloc(sizeof(TLBString));
2731 tlbstr->offset = offs;
2732 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2733 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2735 heap_free(string);
2737 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2739 offs += len_piece;
2743 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2744 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2745 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2746 * tradeoff here.
2748 static struct list tlb_cache = LIST_INIT(tlb_cache);
2749 static CRITICAL_SECTION cache_section;
2750 static CRITICAL_SECTION_DEBUG cache_section_debug =
2752 0, 0, &cache_section,
2753 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2754 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2756 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2759 typedef struct TLB_PEFile
2761 IUnknown IUnknown_iface;
2762 LONG refs;
2763 HMODULE dll;
2764 HRSRC typelib_resource;
2765 HGLOBAL typelib_global;
2766 LPVOID typelib_base;
2767 } TLB_PEFile;
2769 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2771 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2774 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2776 if (IsEqualIID(riid, &IID_IUnknown))
2778 *ppv = iface;
2779 IUnknown_AddRef(iface);
2780 return S_OK;
2782 *ppv = NULL;
2783 return E_NOINTERFACE;
2786 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2788 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2789 return InterlockedIncrement(&This->refs);
2792 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2794 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2795 ULONG refs = InterlockedDecrement(&This->refs);
2796 if (!refs)
2798 if (This->typelib_global)
2799 FreeResource(This->typelib_global);
2800 if (This->dll)
2801 FreeLibrary(This->dll);
2802 heap_free(This);
2804 return refs;
2807 static const IUnknownVtbl TLB_PEFile_Vtable =
2809 TLB_PEFile_QueryInterface,
2810 TLB_PEFile_AddRef,
2811 TLB_PEFile_Release
2814 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2816 TLB_PEFile *This;
2817 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2819 This = heap_alloc(sizeof(TLB_PEFile));
2820 if (!This)
2821 return E_OUTOFMEMORY;
2823 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2824 This->refs = 1;
2825 This->dll = NULL;
2826 This->typelib_resource = NULL;
2827 This->typelib_global = NULL;
2828 This->typelib_base = NULL;
2830 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2831 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2833 if (This->dll)
2835 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2836 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2837 if (This->typelib_resource)
2839 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2840 if (This->typelib_global)
2842 This->typelib_base = LockResource(This->typelib_global);
2844 if (This->typelib_base)
2846 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2847 *ppBase = This->typelib_base;
2848 *ppFile = &This->IUnknown_iface;
2849 return S_OK;
2854 TRACE("No TYPELIB resource found\n");
2855 hr = E_FAIL;
2858 TLB_PEFile_Release(&This->IUnknown_iface);
2859 return hr;
2862 typedef struct TLB_NEFile
2864 IUnknown IUnknown_iface;
2865 LONG refs;
2866 LPVOID typelib_base;
2867 } TLB_NEFile;
2869 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2871 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2874 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2876 if (IsEqualIID(riid, &IID_IUnknown))
2878 *ppv = iface;
2879 IUnknown_AddRef(iface);
2880 return S_OK;
2882 *ppv = NULL;
2883 return E_NOINTERFACE;
2886 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2888 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2889 return InterlockedIncrement(&This->refs);
2892 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2894 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2895 ULONG refs = InterlockedDecrement(&This->refs);
2896 if (!refs)
2898 heap_free(This->typelib_base);
2899 heap_free(This);
2901 return refs;
2904 static const IUnknownVtbl TLB_NEFile_Vtable =
2906 TLB_NEFile_QueryInterface,
2907 TLB_NEFile_AddRef,
2908 TLB_NEFile_Release
2911 /***********************************************************************
2912 * read_xx_header [internal]
2914 static int read_xx_header( HFILE lzfd )
2916 IMAGE_DOS_HEADER mzh;
2917 char magic[3];
2919 LZSeek( lzfd, 0, SEEK_SET );
2920 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2921 return 0;
2922 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2923 return 0;
2925 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2926 if ( 2 != LZRead( lzfd, magic, 2 ) )
2927 return 0;
2929 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2931 if ( magic[0] == 'N' && magic[1] == 'E' )
2932 return IMAGE_OS2_SIGNATURE;
2933 if ( magic[0] == 'P' && magic[1] == 'E' )
2934 return IMAGE_NT_SIGNATURE;
2936 magic[2] = '\0';
2937 WARN("Can't handle %s files.\n", magic );
2938 return 0;
2942 /***********************************************************************
2943 * find_ne_resource [internal]
2945 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2946 DWORD *resLen, DWORD *resOff )
2948 IMAGE_OS2_HEADER nehd;
2949 NE_TYPEINFO *typeInfo;
2950 NE_NAMEINFO *nameInfo;
2951 DWORD nehdoffset;
2952 LPBYTE resTab;
2953 DWORD resTabSize;
2954 int count;
2956 /* Read in NE header */
2957 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2958 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2960 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2961 if ( !resTabSize )
2963 TRACE("No resources in NE dll\n" );
2964 return FALSE;
2967 /* Read in resource table */
2968 resTab = heap_alloc( resTabSize );
2969 if ( !resTab ) return FALSE;
2971 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2972 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2974 heap_free( resTab );
2975 return FALSE;
2978 /* Find resource */
2979 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2981 if (!IS_INTRESOURCE(typeid)) /* named type */
2983 BYTE len = strlen( typeid );
2984 while (typeInfo->type_id)
2986 if (!(typeInfo->type_id & 0x8000))
2988 BYTE *p = resTab + typeInfo->type_id;
2989 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2991 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2992 typeInfo->count * sizeof(NE_NAMEINFO));
2995 else /* numeric type id */
2997 WORD id = LOWORD(typeid) | 0x8000;
2998 while (typeInfo->type_id)
3000 if (typeInfo->type_id == id) goto found_type;
3001 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3002 typeInfo->count * sizeof(NE_NAMEINFO));
3005 TRACE("No typeid entry found for %p\n", typeid );
3006 heap_free( resTab );
3007 return FALSE;
3009 found_type:
3010 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3012 if (!IS_INTRESOURCE(resid)) /* named resource */
3014 BYTE len = strlen( resid );
3015 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3017 BYTE *p = resTab + nameInfo->id;
3018 if (nameInfo->id & 0x8000) continue;
3019 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3022 else /* numeric resource id */
3024 WORD id = LOWORD(resid) | 0x8000;
3025 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3026 if (nameInfo->id == id) goto found_name;
3028 TRACE("No resid entry found for %p\n", typeid );
3029 heap_free( resTab );
3030 return FALSE;
3032 found_name:
3033 /* Return resource data */
3034 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3035 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3037 heap_free( resTab );
3038 return TRUE;
3041 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3043 HFILE lzfd = -1;
3044 OFSTRUCT ofs;
3045 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3046 TLB_NEFile *This;
3048 This = heap_alloc(sizeof(TLB_NEFile));
3049 if (!This) return E_OUTOFMEMORY;
3051 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3052 This->refs = 1;
3053 This->typelib_base = NULL;
3055 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3056 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3058 DWORD reslen, offset;
3059 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3061 This->typelib_base = heap_alloc(reslen);
3062 if( !This->typelib_base )
3063 hr = E_OUTOFMEMORY;
3064 else
3066 LZSeek( lzfd, offset, SEEK_SET );
3067 reslen = LZRead( lzfd, This->typelib_base, reslen );
3068 LZClose( lzfd );
3069 *ppBase = This->typelib_base;
3070 *pdwTLBLength = reslen;
3071 *ppFile = &This->IUnknown_iface;
3072 return S_OK;
3077 if( lzfd >= 0) LZClose( lzfd );
3078 TLB_NEFile_Release(&This->IUnknown_iface);
3079 return hr;
3082 typedef struct TLB_Mapping
3084 IUnknown IUnknown_iface;
3085 LONG refs;
3086 HANDLE file;
3087 HANDLE mapping;
3088 LPVOID typelib_base;
3089 } TLB_Mapping;
3091 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3093 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3096 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3098 if (IsEqualIID(riid, &IID_IUnknown))
3100 *ppv = iface;
3101 IUnknown_AddRef(iface);
3102 return S_OK;
3104 *ppv = NULL;
3105 return E_NOINTERFACE;
3108 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3110 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3111 return InterlockedIncrement(&This->refs);
3114 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3116 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3117 ULONG refs = InterlockedDecrement(&This->refs);
3118 if (!refs)
3120 if (This->typelib_base)
3121 UnmapViewOfFile(This->typelib_base);
3122 if (This->mapping)
3123 CloseHandle(This->mapping);
3124 if (This->file != INVALID_HANDLE_VALUE)
3125 CloseHandle(This->file);
3126 heap_free(This);
3128 return refs;
3131 static const IUnknownVtbl TLB_Mapping_Vtable =
3133 TLB_Mapping_QueryInterface,
3134 TLB_Mapping_AddRef,
3135 TLB_Mapping_Release
3138 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3140 TLB_Mapping *This;
3142 This = heap_alloc(sizeof(TLB_Mapping));
3143 if (!This)
3144 return E_OUTOFMEMORY;
3146 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3147 This->refs = 1;
3148 This->file = INVALID_HANDLE_VALUE;
3149 This->mapping = NULL;
3150 This->typelib_base = NULL;
3152 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3153 if (INVALID_HANDLE_VALUE != This->file)
3155 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3156 if (This->mapping)
3158 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3159 if(This->typelib_base)
3161 /* retrieve file size */
3162 *pdwTLBLength = GetFileSize(This->file, NULL);
3163 *ppBase = This->typelib_base;
3164 *ppFile = &This->IUnknown_iface;
3165 return S_OK;
3170 IUnknown_Release(&This->IUnknown_iface);
3171 return TYPE_E_CANTLOADLIBRARY;
3174 /****************************************************************************
3175 * TLB_ReadTypeLib
3177 * find the type of the typelib file and map the typelib resource into
3178 * the memory
3181 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3182 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3184 ITypeLibImpl *entry;
3185 HRESULT ret;
3186 INT index = 1;
3187 LPWSTR index_str, file = (LPWSTR)pszFileName;
3188 LPVOID pBase = NULL;
3189 DWORD dwTLBLength = 0;
3190 IUnknown *pFile = NULL;
3192 *ppTypeLib = NULL;
3194 index_str = strrchrW(pszFileName, '\\');
3195 if(index_str && *++index_str != '\0')
3197 LPWSTR end_ptr;
3198 LONG idx = strtolW(index_str, &end_ptr, 10);
3199 if(*end_ptr == '\0')
3201 int str_len = index_str - pszFileName - 1;
3202 index = idx;
3203 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3204 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3205 file[str_len] = 0;
3209 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3211 if(strchrW(file, '\\'))
3213 lstrcpyW(pszPath, file);
3215 else
3217 int len = GetSystemDirectoryW(pszPath, cchPath);
3218 pszPath[len] = '\\';
3219 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3223 if(file != pszFileName) heap_free(file);
3225 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3227 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3228 EnterCriticalSection(&cache_section);
3229 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3231 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3233 TRACE("cache hit\n");
3234 *ppTypeLib = &entry->ITypeLib2_iface;
3235 ITypeLib2_AddRef(*ppTypeLib);
3236 LeaveCriticalSection(&cache_section);
3237 return S_OK;
3240 LeaveCriticalSection(&cache_section);
3242 /* now actually load and parse the typelib */
3244 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3245 if (ret == TYPE_E_CANTLOADLIBRARY)
3246 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3247 if (ret == TYPE_E_CANTLOADLIBRARY)
3248 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3249 if (SUCCEEDED(ret))
3251 if (dwTLBLength >= 4)
3253 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3254 if (dwSignature == MSFT_SIGNATURE)
3255 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3256 else if (dwSignature == SLTG_SIGNATURE)
3257 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3258 else
3260 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3261 ret = TYPE_E_CANTLOADLIBRARY;
3264 else
3265 ret = TYPE_E_CANTLOADLIBRARY;
3266 IUnknown_Release(pFile);
3269 if(*ppTypeLib) {
3270 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3272 TRACE("adding to cache\n");
3273 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3274 lstrcpyW(impl->path, pszPath);
3275 /* We should really canonicalise the path here. */
3276 impl->index = index;
3278 /* FIXME: check if it has added already in the meantime */
3279 EnterCriticalSection(&cache_section);
3280 list_add_head(&tlb_cache, &impl->entry);
3281 LeaveCriticalSection(&cache_section);
3282 ret = S_OK;
3284 else
3286 if(ret != E_FAIL)
3287 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3289 ret = TYPE_E_CANTLOADLIBRARY;
3293 return ret;
3296 /*================== ITypeLib(2) Methods ===================================*/
3298 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3300 ITypeLibImpl* pTypeLibImpl;
3302 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3303 if (!pTypeLibImpl) return NULL;
3305 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3306 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3307 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3308 pTypeLibImpl->ref = 1;
3310 list_init(&pTypeLibImpl->implib_list);
3311 list_init(&pTypeLibImpl->custdata_list);
3312 list_init(&pTypeLibImpl->name_list);
3313 list_init(&pTypeLibImpl->string_list);
3314 list_init(&pTypeLibImpl->guid_list);
3315 list_init(&pTypeLibImpl->ref_list);
3316 pTypeLibImpl->dispatch_href = -1;
3318 return pTypeLibImpl;
3321 /****************************************************************************
3322 * ITypeLib2_Constructor_MSFT
3324 * loading an MSFT typelib from an in-memory image
3326 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3328 TLBContext cx;
3329 LONG lPSegDir;
3330 MSFT_Header tlbHeader;
3331 MSFT_SegDir tlbSegDir;
3332 ITypeLibImpl * pTypeLibImpl;
3334 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3336 pTypeLibImpl = TypeLibImpl_Constructor();
3337 if (!pTypeLibImpl) return NULL;
3339 /* get pointer to beginning of typelib data */
3340 cx.pos = 0;
3341 cx.oStart=0;
3342 cx.mapping = pLib;
3343 cx.pLibInfo = pTypeLibImpl;
3344 cx.length = dwTLBLength;
3346 /* read header */
3347 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3348 TRACE_(typelib)("header:\n");
3349 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3350 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3351 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3352 return NULL;
3354 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3356 /* there is a small amount of information here until the next important
3357 * part:
3358 * the segment directory . Try to calculate the amount of data */
3359 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3361 /* now read the segment directory */
3362 TRACE("read segment directory (at %d)\n",lPSegDir);
3363 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3364 cx.pTblDir = &tlbSegDir;
3366 /* just check two entries */
3367 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3369 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3370 heap_free(pTypeLibImpl);
3371 return NULL;
3374 MSFT_ReadAllNames(&cx);
3375 MSFT_ReadAllStrings(&cx);
3376 MSFT_ReadAllGuids(&cx);
3378 /* now fill our internal data */
3379 /* TLIBATTR fields */
3380 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3382 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3383 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3384 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3385 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3387 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3388 pTypeLibImpl->lcid = tlbHeader.lcid;
3390 /* name, eventually add to a hash table */
3391 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3393 /* help info */
3394 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3395 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3397 if( tlbHeader.varflags & HELPDLLFLAG)
3399 int offset;
3400 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3401 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3404 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3406 /* custom data */
3407 if(tlbHeader.CustomDataOffset >= 0)
3409 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3412 /* fill in type descriptions */
3413 if(tlbSegDir.pTypdescTab.length > 0)
3415 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3416 INT16 td[4];
3417 pTypeLibImpl->ctTypeDesc = cTD;
3418 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3419 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3420 for(i=0; i<cTD; )
3422 /* FIXME: add several sanity checks here */
3423 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3424 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3426 /* FIXME: check safearray */
3427 if(td[3] < 0)
3428 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3429 else
3430 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3432 else if(td[0] == VT_CARRAY)
3434 /* array descr table here */
3435 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3437 else if(td[0] == VT_USERDEFINED)
3439 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3441 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3444 /* second time around to fill the array subscript info */
3445 for(i=0;i<cTD;i++)
3447 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3448 if(tlbSegDir.pArrayDescriptions.offset>0)
3450 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3451 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3453 if(td[1]<0)
3454 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3455 else
3456 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3458 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3460 for(j = 0; j<td[2]; j++)
3462 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3463 sizeof(INT), &cx, DO_NOT_SEEK);
3464 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3465 sizeof(INT), &cx, DO_NOT_SEEK);
3468 else
3470 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3471 ERR("didn't find array description data\n");
3476 /* imported type libs */
3477 if(tlbSegDir.pImpFiles.offset>0)
3479 TLBImpLib *pImpLib;
3480 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3481 UINT16 size;
3483 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3485 char *name;
3487 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3488 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3489 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3491 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3492 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3493 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3494 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3496 size >>= 2;
3497 name = heap_alloc_zero(size+1);
3498 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3499 pImpLib->name = TLB_MultiByteToBSTR(name);
3500 heap_free(name);
3502 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3503 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3505 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3509 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3510 if(pTypeLibImpl->dispatch_href != -1)
3511 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3513 /* type infos */
3514 if(tlbHeader.nrtypeinfos >= 0 )
3516 ITypeInfoImpl **ppTI;
3517 int i;
3519 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3521 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3523 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3525 ++ppTI;
3526 (pTypeLibImpl->TypeInfoCount)++;
3530 TRACE("(%p)\n", pTypeLibImpl);
3531 return &pTypeLibImpl->ITypeLib2_iface;
3535 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3537 char b[3];
3538 int i;
3539 short s;
3541 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3542 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3543 return FALSE;
3546 guid->Data4[0] = s >> 8;
3547 guid->Data4[1] = s & 0xff;
3549 b[2] = '\0';
3550 for(i = 0; i < 6; i++) {
3551 memcpy(b, str + 24 + 2 * i, 2);
3552 guid->Data4[i + 2] = strtol(b, NULL, 16);
3554 return TRUE;
3557 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3559 WORD bytelen;
3560 DWORD len;
3561 BSTR tmp_str;
3563 *pStr = NULL;
3564 bytelen = *(const WORD*)ptr;
3565 if(bytelen == 0xffff) return 2;
3567 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3568 tmp_str = SysAllocStringLen(NULL, len);
3569 if (*tmp_str) {
3570 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3571 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3572 SysFreeString(tmp_str);
3574 return bytelen + 2;
3577 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3579 WORD bytelen;
3581 *str = NULL;
3582 bytelen = *(const WORD*)ptr;
3583 if(bytelen == 0xffff) return 2;
3584 *str = heap_alloc(bytelen + 1);
3585 memcpy(*str, ptr + 2, bytelen);
3586 (*str)[bytelen] = '\0';
3587 return bytelen + 2;
3590 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3592 BSTR tmp_str;
3593 TLBString *tlbstr;
3595 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3596 if (tlbstr->offset == offset)
3597 return tlbstr;
3600 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3601 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3602 SysFreeString(tmp_str);
3604 return tlbstr;
3607 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3609 char *ptr = pLibBlk;
3610 WORD w;
3612 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3613 FIXME("libblk magic = %04x\n", w);
3614 return 0;
3617 ptr += 6;
3618 if((w = *(WORD*)ptr) != 0xffff) {
3619 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3620 ptr += w;
3622 ptr += 2;
3624 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3626 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3628 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3629 ptr += 4;
3631 pTypeLibImpl->syskind = *(WORD*)ptr;
3632 ptr += 2;
3634 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3635 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3636 else
3637 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3638 ptr += 2;
3640 ptr += 4; /* skip res12 */
3642 pTypeLibImpl->libflags = *(WORD*)ptr;
3643 ptr += 2;
3645 pTypeLibImpl->ver_major = *(WORD*)ptr;
3646 ptr += 2;
3648 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3649 ptr += 2;
3651 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr);
3652 ptr += sizeof(GUID);
3654 return ptr - (char*)pLibBlk;
3657 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3658 typedef struct
3660 unsigned int num;
3661 HREFTYPE refs[1];
3662 } sltg_ref_lookup_t;
3664 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3665 HREFTYPE *typelib_ref)
3667 if(table && typeinfo_ref < table->num)
3669 *typelib_ref = table->refs[typeinfo_ref];
3670 return S_OK;
3673 ERR_(typelib)("Unable to find reference\n");
3674 *typelib_ref = -1;
3675 return E_FAIL;
3678 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3680 BOOL done = FALSE;
3682 while(!done) {
3683 if((*pType & 0xe00) == 0xe00) {
3684 pTD->vt = VT_PTR;
3685 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3686 pTD = pTD->u.lptdesc;
3688 switch(*pType & 0x3f) {
3689 case VT_PTR:
3690 pTD->vt = VT_PTR;
3691 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3692 pTD = pTD->u.lptdesc;
3693 break;
3695 case VT_USERDEFINED:
3696 pTD->vt = VT_USERDEFINED;
3697 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3698 done = TRUE;
3699 break;
3701 case VT_CARRAY:
3703 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3704 array */
3706 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3708 pTD->vt = VT_CARRAY;
3709 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3710 pTD->u.lpadesc->cDims = pSA->cDims;
3711 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3712 pSA->cDims * sizeof(SAFEARRAYBOUND));
3714 pTD = &pTD->u.lpadesc->tdescElem;
3715 break;
3718 case VT_SAFEARRAY:
3720 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3721 useful? */
3723 pType++;
3724 pTD->vt = VT_SAFEARRAY;
3725 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3726 pTD = pTD->u.lptdesc;
3727 break;
3729 default:
3730 pTD->vt = *pType & 0x3f;
3731 done = TRUE;
3732 break;
3734 pType++;
3736 return pType;
3739 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3740 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3742 /* Handle [in/out] first */
3743 if((*pType & 0xc000) == 0xc000)
3744 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3745 else if(*pType & 0x8000)
3746 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3747 else if(*pType & 0x4000)
3748 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3749 else
3750 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3752 if(*pType & 0x2000)
3753 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3755 if(*pType & 0x80)
3756 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3758 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3762 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3763 char *pNameTable)
3765 unsigned int ref;
3766 char *name;
3767 TLBRefType *ref_type;
3768 sltg_ref_lookup_t *table;
3769 HREFTYPE typelib_ref;
3771 if(pRef->magic != SLTG_REF_MAGIC) {
3772 FIXME("Ref magic = %x\n", pRef->magic);
3773 return NULL;
3775 name = ( (char*)pRef->names + pRef->number);
3777 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3778 table->num = pRef->number >> 3;
3780 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3782 /* We don't want the first href to be 0 */
3783 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3785 for(ref = 0; ref < pRef->number >> 3; ref++) {
3786 char *refname;
3787 unsigned int lib_offs, type_num;
3789 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3791 name += SLTG_ReadStringA(name, &refname);
3792 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3793 FIXME_(typelib)("Can't sscanf ref\n");
3794 if(lib_offs != 0xffff) {
3795 TLBImpLib *import;
3797 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3798 if(import->offset == lib_offs)
3799 break;
3801 if(&import->entry == &pTL->implib_list) {
3802 char fname[MAX_PATH+1];
3803 int len;
3804 GUID tmpguid;
3806 import = heap_alloc_zero(sizeof(*import));
3807 import->offset = lib_offs;
3808 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3809 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid);
3810 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3811 &import->wVersionMajor,
3812 &import->wVersionMinor,
3813 &import->lcid, fname) != 4) {
3814 FIXME_(typelib)("can't sscanf ref %s\n",
3815 pNameTable + lib_offs + 40);
3817 len = strlen(fname);
3818 if(fname[len-1] != '#')
3819 FIXME("fname = %s\n", fname);
3820 fname[len-1] = '\0';
3821 import->name = TLB_MultiByteToBSTR(fname);
3822 list_add_tail(&pTL->implib_list, &import->entry);
3824 ref_type->pImpTLInfo = import;
3826 /* Store a reference to IDispatch */
3827 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3828 pTL->dispatch_href = typelib_ref;
3830 } else { /* internal ref */
3831 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3833 ref_type->reference = typelib_ref;
3834 ref_type->index = type_num;
3836 heap_free(refname);
3837 list_add_tail(&pTL->ref_list, &ref_type->entry);
3839 table->refs[ref] = typelib_ref;
3840 typelib_ref += 4;
3842 if((BYTE)*name != SLTG_REF_MAGIC)
3843 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3844 dump_TLBRefType(pTL);
3845 return table;
3848 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3849 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3851 SLTG_ImplInfo *info;
3852 TLBImplType *pImplType;
3853 /* I don't really get this structure, usually it's 0x16 bytes
3854 long, but iuser.tlb contains some that are 0x18 bytes long.
3855 That's ok because we can use the next ptr to jump to the next
3856 one. But how do we know the length of the last one? The WORD
3857 at offs 0x8 might be the clue. For now I'm just assuming that
3858 the last one is the regular 0x16 bytes. */
3860 info = (SLTG_ImplInfo*)pBlk;
3861 while(1){
3862 pTI->cImplTypes++;
3863 if(info->next == 0xffff)
3864 break;
3865 info = (SLTG_ImplInfo*)(pBlk + info->next);
3868 info = (SLTG_ImplInfo*)pBlk;
3869 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
3870 pImplType = pTI->impltypes;
3871 while(1) {
3872 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3873 pImplType->implflags = info->impltypeflags;
3874 ++pImplType;
3876 if(info->next == 0xffff)
3877 break;
3878 if(OneOnly)
3879 FIXME_(typelib)("Interface inheriting more than one interface\n");
3880 info = (SLTG_ImplInfo*)(pBlk + info->next);
3882 info++; /* see comment at top of function */
3883 return (char*)info;
3886 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3887 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3889 TLBVarDesc *pVarDesc;
3890 const TLBString *prevName = NULL;
3891 SLTG_Variable *pItem;
3892 unsigned short i;
3893 WORD *pType;
3895 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
3897 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3898 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3900 pVarDesc->vardesc.memid = pItem->memid;
3902 if (pItem->magic != SLTG_VAR_MAGIC &&
3903 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3904 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3905 return;
3908 if (pItem->name == 0xfffe)
3909 pVarDesc->Name = prevName;
3910 else
3911 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
3913 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
3914 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3915 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3917 if(pItem->flags & 0x02)
3918 pType = &pItem->type;
3919 else
3920 pType = (WORD*)(pBlk + pItem->type);
3922 if (pItem->flags & ~0xda)
3923 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3925 SLTG_DoElem(pType, pBlk,
3926 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3928 if (TRACE_ON(typelib)) {
3929 char buf[300];
3930 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3931 TRACE_(typelib)("elemdescVar: %s\n", buf);
3934 if (pItem->flags & 0x40) {
3935 TRACE_(typelib)("VAR_DISPATCH\n");
3936 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3938 else if (pItem->flags & 0x10) {
3939 TRACE_(typelib)("VAR_CONST\n");
3940 pVarDesc->vardesc.varkind = VAR_CONST;
3941 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3942 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3943 if (pItem->flags & 0x08)
3944 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3945 else {
3946 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3948 case VT_LPSTR:
3949 case VT_LPWSTR:
3950 case VT_BSTR:
3952 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3953 BSTR str;
3954 TRACE_(typelib)("len = %u\n", len);
3955 if (len == 0xffff) {
3956 str = NULL;
3957 } else {
3958 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3959 str = SysAllocStringLen(NULL, alloc_len);
3960 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3962 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3963 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3964 break;
3966 case VT_I2:
3967 case VT_UI2:
3968 case VT_I4:
3969 case VT_UI4:
3970 case VT_INT:
3971 case VT_UINT:
3972 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3973 *(INT*)(pBlk + pItem->byte_offs);
3974 break;
3975 default:
3976 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3980 else {
3981 TRACE_(typelib)("VAR_PERINSTANCE\n");
3982 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3983 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3986 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3987 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3989 if (pItem->flags & 0x80)
3990 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3992 prevName = pVarDesc->Name;
3994 pTI->cVars = cVars;
3997 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3998 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4000 SLTG_Function *pFunc;
4001 unsigned short i;
4002 TLBFuncDesc *pFuncDesc;
4004 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4006 pFuncDesc = pTI->funcdescs;
4007 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4008 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4010 int param;
4011 WORD *pType, *pArg;
4013 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4014 case SLTG_FUNCTION_MAGIC:
4015 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4016 break;
4017 case SLTG_DISPATCH_FUNCTION_MAGIC:
4018 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4019 break;
4020 case SLTG_STATIC_FUNCTION_MAGIC:
4021 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4022 break;
4023 default:
4024 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4025 continue;
4027 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4029 pFuncDesc->funcdesc.memid = pFunc->dispid;
4030 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4031 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4032 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4033 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4034 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4036 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4037 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4039 if(pFunc->retnextopt & 0x80)
4040 pType = &pFunc->rettype;
4041 else
4042 pType = (WORD*)(pBlk + pFunc->rettype);
4044 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4046 pFuncDesc->funcdesc.lprgelemdescParam =
4047 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4048 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4050 pArg = (WORD*)(pBlk + pFunc->arg_off);
4052 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4053 char *paramName = pNameTable + *pArg;
4054 BOOL HaveOffs;
4055 /* If arg type follows then paramName points to the 2nd
4056 letter of the name, else the next WORD is an offset to
4057 the arg type and paramName points to the first letter.
4058 So let's take one char off paramName and see if we're
4059 pointing at an alpha-numeric char. However if *pArg is
4060 0xffff or 0xfffe then the param has no name, the former
4061 meaning that the next WORD is the type, the latter
4062 meaning that the next WORD is an offset to the type. */
4064 HaveOffs = FALSE;
4065 if(*pArg == 0xffff)
4066 paramName = NULL;
4067 else if(*pArg == 0xfffe) {
4068 paramName = NULL;
4069 HaveOffs = TRUE;
4071 else if(paramName[-1] && !isalnum(paramName[-1]))
4072 HaveOffs = TRUE;
4074 pArg++;
4076 if(HaveOffs) { /* the next word is an offset to type */
4077 pType = (WORD*)(pBlk + *pArg);
4078 SLTG_DoElem(pType, pBlk,
4079 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4080 pArg++;
4081 } else {
4082 if(paramName)
4083 paramName--;
4084 pArg = SLTG_DoElem(pArg, pBlk,
4085 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4088 /* Are we an optional param ? */
4089 if(pFuncDesc->funcdesc.cParams - param <=
4090 pFuncDesc->funcdesc.cParamsOpt)
4091 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4093 if(paramName) {
4094 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4095 paramName - pNameTable, pTI->pTypeLib);
4096 } else {
4097 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4101 pTI->cFuncs = cFuncs;
4104 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4105 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4106 SLTG_TypeInfoTail *pTITail)
4108 char *pFirstItem;
4109 sltg_ref_lookup_t *ref_lookup = NULL;
4111 if(pTIHeader->href_table != 0xffffffff) {
4112 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4113 pNameTable);
4116 pFirstItem = pBlk;
4118 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4119 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4121 heap_free(ref_lookup);
4125 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4126 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4127 const SLTG_TypeInfoTail *pTITail)
4129 char *pFirstItem;
4130 sltg_ref_lookup_t *ref_lookup = NULL;
4132 if(pTIHeader->href_table != 0xffffffff) {
4133 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4134 pNameTable);
4137 pFirstItem = pBlk;
4139 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4140 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4143 if (pTITail->funcs_off != 0xffff)
4144 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4146 heap_free(ref_lookup);
4148 if (TRACE_ON(typelib))
4149 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4152 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4153 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4154 const SLTG_TypeInfoTail *pTITail)
4156 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4159 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4160 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4161 const SLTG_TypeInfoTail *pTITail)
4163 WORD *pType;
4164 sltg_ref_lookup_t *ref_lookup = NULL;
4166 if (pTITail->simple_alias) {
4167 /* if simple alias, no more processing required */
4168 pTI->tdescAlias.vt = pTITail->tdescalias_vt;
4169 return;
4172 if(pTIHeader->href_table != 0xffffffff) {
4173 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4174 pNameTable);
4177 /* otherwise it is an offset to a type */
4178 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4180 SLTG_DoType(pType, pBlk, &pTI->tdescAlias, ref_lookup);
4182 heap_free(ref_lookup);
4185 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4186 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4187 const SLTG_TypeInfoTail *pTITail)
4189 sltg_ref_lookup_t *ref_lookup = NULL;
4190 if (pTIHeader->href_table != 0xffffffff)
4191 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4192 pNameTable);
4194 if (pTITail->vars_off != 0xffff)
4195 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4197 if (pTITail->funcs_off != 0xffff)
4198 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4200 if (pTITail->impls_off != 0xffff)
4201 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4203 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4204 * of dispinterface functions including the IDispatch ones, so
4205 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4206 pTI->cbSizeVft = pTI->cFuncs * sizeof(void *);
4208 heap_free(ref_lookup);
4209 if (TRACE_ON(typelib))
4210 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4213 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4214 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4215 const SLTG_TypeInfoTail *pTITail)
4217 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4220 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4221 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4222 const SLTG_TypeInfoTail *pTITail)
4224 sltg_ref_lookup_t *ref_lookup = NULL;
4225 if (pTIHeader->href_table != 0xffffffff)
4226 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4227 pNameTable);
4229 if (pTITail->vars_off != 0xffff)
4230 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4232 if (pTITail->funcs_off != 0xffff)
4233 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4234 heap_free(ref_lookup);
4235 if (TRACE_ON(typelib))
4236 dump_TypeInfo(pTI);
4239 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4240 manageable copy of it into this */
4241 typedef struct {
4242 WORD small_no;
4243 char *index_name;
4244 char *other_name;
4245 WORD res1a;
4246 WORD name_offs;
4247 WORD more_bytes;
4248 char *extra;
4249 WORD res20;
4250 DWORD helpcontext;
4251 WORD res26;
4252 GUID uuid;
4253 } SLTG_InternalOtherTypeInfo;
4255 /****************************************************************************
4256 * ITypeLib2_Constructor_SLTG
4258 * loading a SLTG typelib from an in-memory image
4260 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4262 ITypeLibImpl *pTypeLibImpl;
4263 SLTG_Header *pHeader;
4264 SLTG_BlkEntry *pBlkEntry;
4265 SLTG_Magic *pMagic;
4266 SLTG_Index *pIndex;
4267 SLTG_Pad9 *pPad9;
4268 LPVOID pBlk, pFirstBlk;
4269 SLTG_LibBlk *pLibBlk;
4270 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4271 char *pAfterOTIBlks = NULL;
4272 char *pNameTable, *ptr;
4273 int i;
4274 DWORD len, order;
4275 ITypeInfoImpl **ppTypeInfoImpl;
4277 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4280 pTypeLibImpl = TypeLibImpl_Constructor();
4281 if (!pTypeLibImpl) return NULL;
4283 pHeader = pLib;
4285 TRACE_(typelib)("header:\n");
4286 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4287 pHeader->nrOfFileBlks );
4288 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4289 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4290 pHeader->SLTG_magic);
4291 return NULL;
4294 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4295 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4297 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4298 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4300 /* Next we have a magic block */
4301 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4303 /* Let's see if we're still in sync */
4304 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4305 sizeof(SLTG_COMPOBJ_MAGIC))) {
4306 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4307 return NULL;
4309 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4310 sizeof(SLTG_DIR_MAGIC))) {
4311 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4312 return NULL;
4315 pIndex = (SLTG_Index*)(pMagic+1);
4317 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4319 pFirstBlk = pPad9 + 1;
4321 /* We'll set up a ptr to the main library block, which is the last one. */
4323 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4324 pBlkEntry[order].next != 0;
4325 order = pBlkEntry[order].next - 1, i++) {
4326 pBlk = (char*)pBlk + pBlkEntry[order].len;
4328 pLibBlk = pBlk;
4330 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4332 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4333 interspersed */
4335 len += 0x40;
4337 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4339 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4342 ptr = (char*)pLibBlk + len;
4344 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4345 WORD w, extra;
4346 len = 0;
4348 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4350 w = *(WORD*)(ptr + 2);
4351 if(w != 0xffff) {
4352 len += w;
4353 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4354 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4355 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4357 w = *(WORD*)(ptr + 4 + len);
4358 if(w != 0xffff) {
4359 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4360 len += w;
4361 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4362 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4363 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4365 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4366 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4367 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4368 if(extra) {
4369 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4370 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4371 len += extra;
4373 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4374 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4375 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4376 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4377 len += sizeof(SLTG_OtherTypeInfo);
4378 ptr += len;
4381 pAfterOTIBlks = ptr;
4383 /* Skip this WORD and get the next DWORD */
4384 len = *(DWORD*)(pAfterOTIBlks + 2);
4386 /* Now add this to pLibBLk look at what we're pointing at and
4387 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4388 dust and we should be pointing at the beginning of the name
4389 table */
4391 pNameTable = (char*)pLibBlk + len;
4393 switch(*(WORD*)pNameTable) {
4394 case 0xffff:
4395 break;
4396 case 0x0200:
4397 pNameTable += 0x20;
4398 break;
4399 default:
4400 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4401 break;
4404 pNameTable += 0x216;
4406 pNameTable += 2;
4408 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4410 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4413 /* Hopefully we now have enough ptrs set up to actually read in
4414 some TypeInfos. It's not clear which order to do them in, so
4415 I'll just follow the links along the BlkEntry chain and read
4416 them in the order in which they are in the file */
4418 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4419 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4421 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4422 pBlkEntry[order].next != 0;
4423 order = pBlkEntry[order].next - 1, i++) {
4425 SLTG_TypeInfoHeader *pTIHeader;
4426 SLTG_TypeInfoTail *pTITail;
4427 SLTG_MemberHeader *pMemHeader;
4429 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4430 FIXME_(typelib)("Index strings don't match\n");
4431 heap_free(pOtherTypeInfoBlks);
4432 return NULL;
4435 pTIHeader = pBlk;
4436 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4437 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4438 heap_free(pOtherTypeInfoBlks);
4439 return NULL;
4441 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4442 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4443 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4445 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4446 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4447 (*ppTypeInfoImpl)->index = i;
4448 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4449 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4450 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid);
4451 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4452 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4453 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4454 (*ppTypeInfoImpl)->wTypeFlags =
4455 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4457 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4458 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4460 if((pTIHeader->typeflags1 & 7) != 2)
4461 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4462 if(pTIHeader->typeflags3 != 2)
4463 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4465 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4466 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4467 typekind_desc[pTIHeader->typekind],
4468 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4469 (*ppTypeInfoImpl)->wTypeFlags);
4471 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4473 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4475 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4476 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4477 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4479 switch(pTIHeader->typekind) {
4480 case TKIND_ENUM:
4481 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4482 pTIHeader, pTITail);
4483 break;
4485 case TKIND_RECORD:
4486 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4487 pTIHeader, pTITail);
4488 break;
4490 case TKIND_INTERFACE:
4491 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4492 pTIHeader, pTITail);
4493 break;
4495 case TKIND_COCLASS:
4496 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4497 pTIHeader, pTITail);
4498 break;
4500 case TKIND_ALIAS:
4501 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4502 pTIHeader, pTITail);
4503 break;
4505 case TKIND_DISPATCH:
4506 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4507 pTIHeader, pTITail);
4508 break;
4510 case TKIND_MODULE:
4511 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4512 pTIHeader, pTITail);
4513 break;
4515 default:
4516 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4517 break;
4521 /* could get cFuncs, cVars and cImplTypes from here
4522 but we've already set those */
4523 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4524 X(06);
4525 X(16);
4526 X(18);
4527 X(1a);
4528 X(1e);
4529 X(24);
4530 X(26);
4531 X(2a);
4532 X(2c);
4533 X(2e);
4534 X(30);
4535 X(32);
4536 X(34);
4537 #undef X
4538 ++ppTypeInfoImpl;
4539 pBlk = (char*)pBlk + pBlkEntry[order].len;
4542 if(i != pTypeLibImpl->TypeInfoCount) {
4543 FIXME("Somehow processed %d TypeInfos\n", i);
4544 heap_free(pOtherTypeInfoBlks);
4545 return NULL;
4548 heap_free(pOtherTypeInfoBlks);
4549 return &pTypeLibImpl->ITypeLib2_iface;
4552 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4554 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4556 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4558 if(IsEqualIID(riid, &IID_IUnknown) ||
4559 IsEqualIID(riid,&IID_ITypeLib)||
4560 IsEqualIID(riid,&IID_ITypeLib2))
4562 *ppv = &This->ITypeLib2_iface;
4564 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4565 IsEqualIID(riid, &IID_ICreateTypeLib2))
4567 *ppv = &This->ICreateTypeLib2_iface;
4569 else
4571 *ppv = NULL;
4572 TRACE("-- Interface: E_NOINTERFACE\n");
4573 return E_NOINTERFACE;
4576 IUnknown_AddRef((IUnknown*)*ppv);
4577 return S_OK;
4580 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4582 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4583 ULONG ref = InterlockedIncrement(&This->ref);
4585 TRACE("(%p) ref=%u\n", This, ref);
4587 return ref;
4590 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4592 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4593 ULONG ref = InterlockedDecrement(&This->ref);
4595 TRACE("(%p) ref=%u\n",This, ref);
4597 if (!ref)
4599 TLBImpLib *pImpLib, *pImpLibNext;
4600 TLBRefType *ref_type;
4601 TLBString *tlbstr, *tlbstr_next;
4602 void *cursor2;
4603 int i;
4605 /* remove cache entry */
4606 if(This->path)
4608 TRACE("removing from cache list\n");
4609 EnterCriticalSection(&cache_section);
4610 if(This->entry.next)
4611 list_remove(&This->entry);
4612 LeaveCriticalSection(&cache_section);
4613 heap_free(This->path);
4615 TRACE(" destroying ITypeLib(%p)\n",This);
4617 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4618 list_remove(&tlbstr->entry);
4619 heap_free(tlbstr);
4622 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4623 list_remove(&tlbstr->entry);
4624 heap_free(tlbstr);
4627 TLB_FreeCustData(&This->custdata_list);
4629 for (i = 0; i < This->ctTypeDesc; i++)
4630 if (This->pTypeDesc[i].vt == VT_CARRAY)
4631 heap_free(This->pTypeDesc[i].u.lpadesc);
4633 heap_free(This->pTypeDesc);
4635 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4637 if (pImpLib->pImpTypeLib)
4638 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4639 SysFreeString(pImpLib->name);
4641 list_remove(&pImpLib->entry);
4642 heap_free(pImpLib);
4645 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4647 list_remove(&ref_type->entry);
4648 heap_free(ref_type);
4651 for (i = 0; i < This->TypeInfoCount; ++i)
4652 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4653 heap_free(This->typeinfos);
4654 heap_free(This);
4655 return 0;
4658 return ref;
4661 /* ITypeLib::GetTypeInfoCount
4663 * Returns the number of type descriptions in the type library
4665 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4667 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4668 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4669 return This->TypeInfoCount;
4672 /* ITypeLib::GetTypeInfo
4674 * retrieves the specified type description in the library.
4676 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4677 ITypeLib2 *iface,
4678 UINT index,
4679 ITypeInfo **ppTInfo)
4681 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4683 TRACE("%p %u %p\n", This, index, ppTInfo);
4685 if(!ppTInfo)
4686 return E_INVALIDARG;
4688 if(index >= This->TypeInfoCount)
4689 return TYPE_E_ELEMENTNOTFOUND;
4691 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4692 ITypeInfo_AddRef(*ppTInfo);
4694 return S_OK;
4698 /* ITypeLibs::GetTypeInfoType
4700 * Retrieves the type of a type description.
4702 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4703 ITypeLib2 *iface,
4704 UINT index,
4705 TYPEKIND *pTKind)
4707 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4709 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4711 if(!pTKind)
4712 return E_INVALIDARG;
4714 if(index >= This->TypeInfoCount)
4715 return TYPE_E_ELEMENTNOTFOUND;
4717 *pTKind = This->typeinfos[index]->typekind;
4719 return S_OK;
4722 /* ITypeLib::GetTypeInfoOfGuid
4724 * Retrieves the type description that corresponds to the specified GUID.
4727 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4728 ITypeLib2 *iface,
4729 REFGUID guid,
4730 ITypeInfo **ppTInfo)
4732 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4733 int i;
4735 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4737 for(i = 0; i < This->TypeInfoCount; ++i){
4738 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4739 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4740 ITypeInfo_AddRef(*ppTInfo);
4741 return S_OK;
4745 return TYPE_E_ELEMENTNOTFOUND;
4748 /* ITypeLib::GetLibAttr
4750 * Retrieves the structure that contains the library's attributes.
4753 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4754 ITypeLib2 *iface,
4755 LPTLIBATTR *attr)
4757 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4759 TRACE("(%p, %p)\n", This, attr);
4761 if (!attr) return E_INVALIDARG;
4763 *attr = heap_alloc(sizeof(**attr));
4764 if (!*attr) return E_OUTOFMEMORY;
4766 (*attr)->guid = *TLB_get_guid_null(This->guid);
4767 (*attr)->lcid = This->set_lcid;
4768 (*attr)->syskind = This->syskind;
4769 (*attr)->wMajorVerNum = This->ver_major;
4770 (*attr)->wMinorVerNum = This->ver_minor;
4771 (*attr)->wLibFlags = This->libflags;
4773 return S_OK;
4776 /* ITypeLib::GetTypeComp
4778 * Enables a client compiler to bind to a library's types, variables,
4779 * constants, and global functions.
4782 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4783 ITypeLib2 *iface,
4784 ITypeComp **ppTComp)
4786 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4788 TRACE("(%p)->(%p)\n",This,ppTComp);
4789 *ppTComp = &This->ITypeComp_iface;
4790 ITypeComp_AddRef(*ppTComp);
4792 return S_OK;
4795 /* ITypeLib::GetDocumentation
4797 * Retrieves the library's documentation string, the complete Help file name
4798 * and path, and the context identifier for the library Help topic in the Help
4799 * file.
4801 * On a successful return all non-null BSTR pointers will have been set,
4802 * possibly to NULL.
4804 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4805 ITypeLib2 *iface,
4806 INT index,
4807 BSTR *pBstrName,
4808 BSTR *pBstrDocString,
4809 DWORD *pdwHelpContext,
4810 BSTR *pBstrHelpFile)
4812 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4813 HRESULT result = E_INVALIDARG;
4814 ITypeInfo *pTInfo;
4816 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4817 This, index,
4818 pBstrName, pBstrDocString,
4819 pdwHelpContext, pBstrHelpFile);
4821 if(index<0)
4823 /* documentation for the typelib */
4824 if(pBstrName)
4826 if (This->Name)
4828 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4829 goto memerr1;
4831 else
4832 *pBstrName = NULL;
4834 if(pBstrDocString)
4836 if (This->DocString)
4838 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4839 goto memerr2;
4841 else if (This->Name)
4843 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->Name))))
4844 goto memerr2;
4846 else
4847 *pBstrDocString = NULL;
4849 if(pdwHelpContext)
4851 *pdwHelpContext = This->dwHelpContext;
4853 if(pBstrHelpFile)
4855 if (This->HelpFile)
4857 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4858 goto memerr3;
4860 else
4861 *pBstrHelpFile = NULL;
4864 result = S_OK;
4866 else
4868 /* for a typeinfo */
4869 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4871 if(SUCCEEDED(result))
4873 result = ITypeInfo_GetDocumentation(pTInfo,
4874 MEMBERID_NIL,
4875 pBstrName,
4876 pBstrDocString,
4877 pdwHelpContext, pBstrHelpFile);
4879 ITypeInfo_Release(pTInfo);
4882 return result;
4883 memerr3:
4884 if (pBstrDocString) SysFreeString (*pBstrDocString);
4885 memerr2:
4886 if (pBstrName) SysFreeString (*pBstrName);
4887 memerr1:
4888 return STG_E_INSUFFICIENTMEMORY;
4891 /* ITypeLib::IsName
4893 * Indicates whether a passed-in string contains the name of a type or member
4894 * described in the library.
4897 static HRESULT WINAPI ITypeLib2_fnIsName(
4898 ITypeLib2 *iface,
4899 LPOLESTR szNameBuf,
4900 ULONG lHashVal,
4901 BOOL *pfName)
4903 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4904 int tic;
4905 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4907 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4908 pfName);
4910 *pfName=TRUE;
4911 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4912 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4913 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4914 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4915 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4916 int pc;
4917 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4918 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
4919 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
4920 goto ITypeLib2_fnIsName_exit;
4923 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
4924 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4925 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4929 *pfName=FALSE;
4931 ITypeLib2_fnIsName_exit:
4932 TRACE("(%p)slow! search for %s: %s found!\n", This,
4933 debugstr_w(szNameBuf), *pfName?"NOT":"");
4935 return S_OK;
4938 /* ITypeLib::FindName
4940 * Finds occurrences of a type description in a type library. This may be used
4941 * to quickly verify that a name exists in a type library.
4944 static HRESULT WINAPI ITypeLib2_fnFindName(
4945 ITypeLib2 *iface,
4946 LPOLESTR name,
4947 ULONG hash,
4948 ITypeInfo **ppTInfo,
4949 MEMBERID *memid,
4950 UINT16 *found)
4952 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4953 int tic;
4954 UINT count = 0;
4955 UINT len;
4957 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4959 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4960 return E_INVALIDARG;
4962 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4963 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4964 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4965 TLBVarDesc *var;
4966 UINT fdc;
4968 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4969 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4970 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4971 int pc;
4973 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4974 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4975 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
4976 goto ITypeLib2_fnFindName_exit;
4980 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
4981 if (var)
4982 goto ITypeLib2_fnFindName_exit;
4984 continue;
4985 ITypeLib2_fnFindName_exit:
4986 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4987 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4988 count++;
4990 TRACE("found %d typeinfos\n", count);
4992 *found = count;
4994 return S_OK;
4997 /* ITypeLib::ReleaseTLibAttr
4999 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5002 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5003 ITypeLib2 *iface,
5004 TLIBATTR *pTLibAttr)
5006 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5007 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5008 heap_free(pTLibAttr);
5011 /* ITypeLib2::GetCustData
5013 * gets the custom data
5015 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5016 ITypeLib2 * iface,
5017 REFGUID guid,
5018 VARIANT *pVarVal)
5020 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5021 TLBCustData *pCData;
5023 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5025 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5026 if(!pCData)
5027 return TYPE_E_ELEMENTNOTFOUND;
5029 VariantInit(pVarVal);
5030 VariantCopy(pVarVal, &pCData->data);
5032 return S_OK;
5035 /* ITypeLib2::GetLibStatistics
5037 * Returns statistics about a type library that are required for efficient
5038 * sizing of hash tables.
5041 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5042 ITypeLib2 * iface,
5043 ULONG *pcUniqueNames,
5044 ULONG *pcchUniqueNames)
5046 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5048 FIXME("(%p): stub!\n", This);
5050 if(pcUniqueNames) *pcUniqueNames=1;
5051 if(pcchUniqueNames) *pcchUniqueNames=1;
5052 return S_OK;
5055 /* ITypeLib2::GetDocumentation2
5057 * Retrieves the library's documentation string, the complete Help file name
5058 * and path, the localization context to use, and the context ID for the
5059 * library Help topic in the Help file.
5062 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5063 ITypeLib2 * iface,
5064 INT index,
5065 LCID lcid,
5066 BSTR *pbstrHelpString,
5067 DWORD *pdwHelpStringContext,
5068 BSTR *pbstrHelpStringDll)
5070 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5071 HRESULT result;
5072 ITypeInfo *pTInfo;
5074 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5076 /* the help string should be obtained from the helpstringdll,
5077 * using the _DLLGetDocumentation function, based on the supplied
5078 * lcid. Nice to do sometime...
5080 if(index<0)
5082 /* documentation for the typelib */
5083 if(pbstrHelpString)
5084 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5085 if(pdwHelpStringContext)
5086 *pdwHelpStringContext=This->dwHelpContext;
5087 if(pbstrHelpStringDll)
5088 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5090 result = S_OK;
5092 else
5094 /* for a typeinfo */
5095 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5097 if(SUCCEEDED(result))
5099 ITypeInfo2 * pTInfo2;
5100 result = ITypeInfo_QueryInterface(pTInfo,
5101 &IID_ITypeInfo2,
5102 (LPVOID*) &pTInfo2);
5104 if(SUCCEEDED(result))
5106 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5107 MEMBERID_NIL,
5108 lcid,
5109 pbstrHelpString,
5110 pdwHelpStringContext,
5111 pbstrHelpStringDll);
5113 ITypeInfo2_Release(pTInfo2);
5116 ITypeInfo_Release(pTInfo);
5119 return result;
5122 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5124 TLBCustData *pCData;
5125 unsigned int ct;
5126 CUSTDATAITEM *cdi;
5128 ct = list_count(custdata_list);
5130 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5131 if(!pCustData->prgCustData)
5132 return E_OUTOFMEMORY;
5134 pCustData->cCustData = ct;
5136 cdi = pCustData->prgCustData;
5137 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5138 cdi->guid = *TLB_get_guid_null(pCData->guid);
5139 VariantCopy(&cdi->varValue, &pCData->data);
5140 ++cdi;
5143 return S_OK;
5147 /* ITypeLib2::GetAllCustData
5149 * Gets all custom data items for the library.
5152 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5153 ITypeLib2 * iface,
5154 CUSTDATA *pCustData)
5156 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5157 TRACE("(%p)->(%p)\n", This, pCustData);
5158 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5161 static const ITypeLib2Vtbl tlbvt = {
5162 ITypeLib2_fnQueryInterface,
5163 ITypeLib2_fnAddRef,
5164 ITypeLib2_fnRelease,
5165 ITypeLib2_fnGetTypeInfoCount,
5166 ITypeLib2_fnGetTypeInfo,
5167 ITypeLib2_fnGetTypeInfoType,
5168 ITypeLib2_fnGetTypeInfoOfGuid,
5169 ITypeLib2_fnGetLibAttr,
5170 ITypeLib2_fnGetTypeComp,
5171 ITypeLib2_fnGetDocumentation,
5172 ITypeLib2_fnIsName,
5173 ITypeLib2_fnFindName,
5174 ITypeLib2_fnReleaseTLibAttr,
5176 ITypeLib2_fnGetCustData,
5177 ITypeLib2_fnGetLibStatistics,
5178 ITypeLib2_fnGetDocumentation2,
5179 ITypeLib2_fnGetAllCustData
5183 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5185 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5187 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5190 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5192 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5194 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5197 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5199 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5201 return ITypeLib2_Release(&This->ITypeLib2_iface);
5204 static HRESULT WINAPI ITypeLibComp_fnBind(
5205 ITypeComp * iface,
5206 OLECHAR * szName,
5207 ULONG lHash,
5208 WORD wFlags,
5209 ITypeInfo ** ppTInfo,
5210 DESCKIND * pDescKind,
5211 BINDPTR * pBindPtr)
5213 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5214 int typemismatch=0, i;
5216 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5218 *pDescKind = DESCKIND_NONE;
5219 pBindPtr->lptcomp = NULL;
5220 *ppTInfo = NULL;
5222 for(i = 0; i < This->TypeInfoCount; ++i){
5223 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5224 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5226 /* FIXME: check wFlags here? */
5227 /* FIXME: we should use a hash table to look this info up using lHash
5228 * instead of an O(n) search */
5229 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5230 (pTypeInfo->typekind == TKIND_MODULE))
5232 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5234 *pDescKind = DESCKIND_TYPECOMP;
5235 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5236 ITypeComp_AddRef(pBindPtr->lptcomp);
5237 TRACE("module or enum: %s\n", debugstr_w(szName));
5238 return S_OK;
5242 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5243 (pTypeInfo->typekind == TKIND_ENUM))
5245 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5246 HRESULT hr;
5248 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5249 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5251 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5252 return S_OK;
5254 else if (hr == TYPE_E_TYPEMISMATCH)
5255 typemismatch = 1;
5258 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5259 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5261 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5262 HRESULT hr;
5263 ITypeInfo *subtypeinfo;
5264 BINDPTR subbindptr;
5265 DESCKIND subdesckind;
5267 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5268 &subtypeinfo, &subdesckind, &subbindptr);
5269 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5271 TYPEDESC tdesc_appobject;
5272 const VARDESC vardesc_appobject =
5274 -2, /* memid */
5275 NULL, /* lpstrSchema */
5277 0 /* oInst */
5280 /* ELEMDESC */
5282 /* TYPEDESC */
5284 &tdesc_appobject
5286 VT_PTR
5289 0, /* wVarFlags */
5290 VAR_STATIC /* varkind */
5293 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5294 tdesc_appobject.vt = VT_USERDEFINED;
5296 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5298 /* cleanup things filled in by Bind call so we can put our
5299 * application object data in there instead */
5300 switch (subdesckind)
5302 case DESCKIND_FUNCDESC:
5303 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5304 break;
5305 case DESCKIND_VARDESC:
5306 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5307 break;
5308 default:
5309 break;
5311 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5313 if (pTypeInfo->hreftype == -1)
5314 FIXME("no hreftype for interface %p\n", pTypeInfo);
5316 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5317 if (FAILED(hr))
5318 return hr;
5320 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5321 *ppTInfo = (ITypeInfo *)pTypeInfo;
5322 ITypeInfo_AddRef(*ppTInfo);
5323 return S_OK;
5325 else if (hr == TYPE_E_TYPEMISMATCH)
5326 typemismatch = 1;
5330 if (typemismatch)
5332 TRACE("type mismatch %s\n", debugstr_w(szName));
5333 return TYPE_E_TYPEMISMATCH;
5335 else
5337 TRACE("name not found %s\n", debugstr_w(szName));
5338 return S_OK;
5342 static HRESULT WINAPI ITypeLibComp_fnBindType(
5343 ITypeComp * iface,
5344 OLECHAR * szName,
5345 ULONG lHash,
5346 ITypeInfo ** ppTInfo,
5347 ITypeComp ** ppTComp)
5349 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5350 ITypeInfoImpl *info;
5352 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5354 if(!szName || !ppTInfo || !ppTComp)
5355 return E_INVALIDARG;
5357 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5358 if(!info){
5359 *ppTInfo = NULL;
5360 *ppTComp = NULL;
5361 return S_OK;
5364 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5365 ITypeInfo_AddRef(*ppTInfo);
5366 *ppTComp = &info->ITypeComp_iface;
5367 ITypeComp_AddRef(*ppTComp);
5369 return S_OK;
5372 static const ITypeCompVtbl tlbtcvt =
5375 ITypeLibComp_fnQueryInterface,
5376 ITypeLibComp_fnAddRef,
5377 ITypeLibComp_fnRelease,
5379 ITypeLibComp_fnBind,
5380 ITypeLibComp_fnBindType
5383 /*================== ITypeInfo(2) Methods ===================================*/
5384 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5386 ITypeInfoImpl *pTypeInfoImpl;
5388 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5389 if (pTypeInfoImpl)
5391 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5392 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5393 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5394 pTypeInfoImpl->ref = 0;
5395 pTypeInfoImpl->hreftype = -1;
5396 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5397 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5398 list_init(&pTypeInfoImpl->custdata_list);
5400 TRACE("(%p)\n", pTypeInfoImpl);
5401 return pTypeInfoImpl;
5404 /* ITypeInfo::QueryInterface
5406 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5407 ITypeInfo2 *iface,
5408 REFIID riid,
5409 VOID **ppvObject)
5411 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5413 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5415 *ppvObject=NULL;
5416 if(IsEqualIID(riid, &IID_IUnknown) ||
5417 IsEqualIID(riid,&IID_ITypeInfo)||
5418 IsEqualIID(riid,&IID_ITypeInfo2))
5419 *ppvObject = This;
5420 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5421 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5422 *ppvObject = &This->ICreateTypeInfo2_iface;
5424 if(*ppvObject){
5425 ITypeInfo2_AddRef(iface);
5426 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5427 return S_OK;
5429 TRACE("-- Interface: E_NOINTERFACE\n");
5430 return E_NOINTERFACE;
5433 /* ITypeInfo::AddRef
5435 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5437 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5438 ULONG ref = InterlockedIncrement(&This->ref);
5440 TRACE("(%p)->ref is %u\n",This, ref);
5442 if (ref == 1 /* incremented from 0 */)
5443 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5445 return ref;
5448 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5450 UINT i;
5452 TRACE("destroying ITypeInfo(%p)\n",This);
5454 for (i = 0; i < This->cFuncs; ++i)
5456 int j;
5457 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5458 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5460 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5461 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5463 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5464 heap_free(elemdesc->u.paramdesc.pparamdescex);
5466 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5468 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5469 heap_free(pFInfo->pParamDesc);
5470 TLB_FreeCustData(&pFInfo->custdata_list);
5472 heap_free(This->funcdescs);
5474 for(i = 0; i < This->cVars; ++i)
5476 TLBVarDesc *pVInfo = &This->vardescs[i];
5477 if (pVInfo->vardesc.varkind == VAR_CONST)
5479 VariantClear(pVInfo->vardesc.u.lpvarValue);
5480 heap_free(pVInfo->vardesc.u.lpvarValue);
5482 TLB_FreeCustData(&pVInfo->custdata_list);
5484 heap_free(This->vardescs);
5486 if(This->impltypes){
5487 for (i = 0; i < This->cImplTypes; ++i){
5488 TLBImplType *pImpl = &This->impltypes[i];
5489 TLB_FreeCustData(&pImpl->custdata_list);
5491 heap_free(This->impltypes);
5494 TLB_FreeCustData(&This->custdata_list);
5496 heap_free(This);
5499 /* ITypeInfo::Release
5501 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5503 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5504 ULONG ref = InterlockedDecrement(&This->ref);
5506 TRACE("(%p)->(%u)\n",This, ref);
5508 if (!ref)
5510 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5511 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5512 if (not_attached_to_typelib)
5513 heap_free(This);
5514 /* otherwise This will be freed when typelib is freed */
5517 return ref;
5520 /* ITypeInfo::GetTypeAttr
5522 * Retrieves a TYPEATTR structure that contains the attributes of the type
5523 * description.
5526 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5527 LPTYPEATTR *ppTypeAttr)
5529 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5530 SIZE_T size;
5532 TRACE("(%p)\n",This);
5534 size = sizeof(**ppTypeAttr);
5535 if (This->typekind == TKIND_ALIAS)
5536 size += TLB_SizeTypeDesc(&This->tdescAlias, FALSE);
5538 *ppTypeAttr = heap_alloc(size);
5539 if (!*ppTypeAttr)
5540 return E_OUTOFMEMORY;
5542 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5543 (*ppTypeAttr)->lcid = This->lcid;
5544 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5545 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5546 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5547 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5548 (*ppTypeAttr)->typekind = This->typekind;
5549 (*ppTypeAttr)->cFuncs = This->cFuncs;
5550 (*ppTypeAttr)->cVars = This->cVars;
5551 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5552 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5553 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5554 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5555 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5556 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5557 (*ppTypeAttr)->tdescAlias = This->tdescAlias;
5558 (*ppTypeAttr)->idldescType = This->idldescType;
5560 if (This->typekind == TKIND_ALIAS)
5561 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5562 &This->tdescAlias, *ppTypeAttr + 1);
5564 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5565 /* This should include all the inherited funcs */
5566 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5567 /* This is always the size of IDispatch's vtbl */
5568 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5569 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5571 return S_OK;
5574 /* ITypeInfo::GetTypeComp
5576 * Retrieves the ITypeComp interface for the type description, which enables a
5577 * client compiler to bind to the type description's members.
5580 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5581 ITypeComp * *ppTComp)
5583 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5585 TRACE("(%p)->(%p)\n", This, ppTComp);
5587 *ppTComp = &This->ITypeComp_iface;
5588 ITypeComp_AddRef(*ppTComp);
5589 return S_OK;
5592 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5594 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5595 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5596 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5597 return size;
5600 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5602 *dest = *src;
5603 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5604 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5606 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5607 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5608 *buffer += sizeof(PARAMDESCEX);
5609 *pparamdescex_dest = *pparamdescex_src;
5610 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5611 VariantInit(&pparamdescex_dest->varDefaultValue);
5612 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5613 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5615 else
5616 dest->u.paramdesc.pparamdescex = NULL;
5617 return S_OK;
5620 static HRESULT TLB_SanitizeBSTR(BSTR str)
5622 UINT len = SysStringLen(str), i;
5623 for (i = 0; i < len; ++i)
5624 if (str[i] > 0x7f)
5625 str[i] = '?';
5626 return S_OK;
5629 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5631 if (V_VT(var) == VT_INT)
5632 return VariantChangeType(var, var, 0, VT_I4);
5633 else if (V_VT(var) == VT_UINT)
5634 return VariantChangeType(var, var, 0, VT_UI4);
5635 else if (V_VT(var) == VT_BSTR)
5636 return TLB_SanitizeBSTR(V_BSTR(var));
5638 return S_OK;
5641 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5643 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5644 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5647 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5649 FUNCDESC *dest;
5650 char *buffer;
5651 SIZE_T size = sizeof(*src);
5652 SHORT i;
5653 HRESULT hr;
5655 size += sizeof(*src->lprgscode) * src->cScodes;
5656 size += TLB_SizeElemDesc(&src->elemdescFunc);
5657 for (i = 0; i < src->cParams; i++)
5659 size += sizeof(ELEMDESC);
5660 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5663 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5664 if (!dest) return E_OUTOFMEMORY;
5666 *dest = *src;
5667 if (dispinterface) /* overwrite funckind */
5668 dest->funckind = FUNC_DISPATCH;
5669 buffer = (char *)(dest + 1);
5671 dest->oVft = dest->oVft & 0xFFFC;
5673 if (dest->cScodes) {
5674 dest->lprgscode = (SCODE *)buffer;
5675 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5676 buffer += sizeof(*src->lprgscode) * src->cScodes;
5677 } else
5678 dest->lprgscode = NULL;
5680 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5681 if (FAILED(hr))
5683 SysFreeString((BSTR)dest);
5684 return hr;
5687 if (dest->cParams) {
5688 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5689 buffer += sizeof(ELEMDESC) * src->cParams;
5690 for (i = 0; i < src->cParams; i++)
5692 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5693 if (FAILED(hr))
5694 break;
5696 if (FAILED(hr))
5698 /* undo the above actions */
5699 for (i = i - 1; i >= 0; i--)
5700 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5701 TLB_FreeElemDesc(&dest->elemdescFunc);
5702 SysFreeString((BSTR)dest);
5703 return hr;
5705 } else
5706 dest->lprgelemdescParam = NULL;
5708 /* special treatment for dispinterfaces: this makes functions appear
5709 * to return their [retval] value when it is really returning an
5710 * HRESULT */
5711 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5713 if (dest->cParams &&
5714 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5716 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5717 if (elemdesc->tdesc.vt != VT_PTR)
5719 ERR("elemdesc should have started with VT_PTR instead of:\n");
5720 if (ERR_ON(ole))
5721 dump_ELEMDESC(elemdesc);
5722 return E_UNEXPECTED;
5725 /* copy last parameter to the return value. we are using a flat
5726 * buffer so there is no danger of leaking memory in
5727 * elemdescFunc */
5728 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5730 /* remove the last parameter */
5731 dest->cParams--;
5733 else
5734 /* otherwise this function is made to appear to have no return
5735 * value */
5736 dest->elemdescFunc.tdesc.vt = VT_VOID;
5740 *dest_ptr = dest;
5741 return S_OK;
5744 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5746 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5748 if (index >= This->cFuncs)
5749 return TYPE_E_ELEMENTNOTFOUND;
5751 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5752 return S_OK;
5755 /* internal function to make the inherited interfaces' methods appear
5756 * part of the interface */
5757 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5758 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5760 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5761 HRESULT hr;
5762 UINT implemented_funcs = 0;
5764 if (funcs)
5765 *funcs = 0;
5766 else
5767 *hrefoffset = DISPATCH_HREF_OFFSET;
5769 if(This->impltypes)
5771 ITypeInfo *pSubTypeInfo;
5772 UINT sub_funcs;
5774 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5775 if (FAILED(hr))
5776 return hr;
5778 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5779 index,
5780 ppFuncDesc,
5781 &sub_funcs, hrefoffset);
5782 implemented_funcs += sub_funcs;
5783 ITypeInfo_Release(pSubTypeInfo);
5784 if (SUCCEEDED(hr))
5785 return hr;
5786 *hrefoffset += DISPATCH_HREF_OFFSET;
5789 if (funcs)
5790 *funcs = implemented_funcs + This->cFuncs;
5791 else
5792 *hrefoffset = 0;
5794 if (index < implemented_funcs)
5795 return E_INVALIDARG;
5796 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5797 ppFuncDesc);
5800 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5802 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5803 while (TRUE)
5805 switch (pTypeDesc->vt)
5807 case VT_USERDEFINED:
5808 pTypeDesc->u.hreftype += hrefoffset;
5809 return;
5810 case VT_PTR:
5811 case VT_SAFEARRAY:
5812 pTypeDesc = pTypeDesc->u.lptdesc;
5813 break;
5814 case VT_CARRAY:
5815 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5816 break;
5817 default:
5818 return;
5823 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5825 SHORT i;
5826 for (i = 0; i < pFuncDesc->cParams; i++)
5827 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5828 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5831 /* ITypeInfo::GetFuncDesc
5833 * Retrieves the FUNCDESC structure that contains information about a
5834 * specified function.
5837 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5838 LPFUNCDESC *ppFuncDesc)
5840 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5841 const FUNCDESC *internal_funcdesc;
5842 HRESULT hr;
5843 UINT hrefoffset = 0;
5845 TRACE("(%p) index %d\n", This, index);
5847 if (!ppFuncDesc)
5848 return E_INVALIDARG;
5850 if (This->needs_layout)
5851 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5853 if (This->typekind == TKIND_DISPATCH)
5854 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5855 &internal_funcdesc, NULL,
5856 &hrefoffset);
5857 else
5858 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5859 &internal_funcdesc);
5860 if (FAILED(hr))
5862 WARN("description for function %d not found\n", index);
5863 return hr;
5866 hr = TLB_AllocAndInitFuncDesc(
5867 internal_funcdesc,
5868 ppFuncDesc,
5869 This->typekind == TKIND_DISPATCH);
5871 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
5872 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5874 TRACE("-- 0x%08x\n", hr);
5875 return hr;
5878 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5880 VARDESC *dest;
5881 char *buffer;
5882 SIZE_T size = sizeof(*src);
5883 HRESULT hr;
5885 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5886 if (src->varkind == VAR_CONST)
5887 size += sizeof(VARIANT);
5888 size += TLB_SizeElemDesc(&src->elemdescVar);
5890 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5891 if (!dest) return E_OUTOFMEMORY;
5893 *dest = *src;
5894 buffer = (char *)(dest + 1);
5895 if (src->lpstrSchema)
5897 int len;
5898 dest->lpstrSchema = (LPOLESTR)buffer;
5899 len = strlenW(src->lpstrSchema);
5900 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5901 buffer += (len + 1) * sizeof(WCHAR);
5904 if (src->varkind == VAR_CONST)
5906 HRESULT hr;
5908 dest->u.lpvarValue = (VARIANT *)buffer;
5909 *dest->u.lpvarValue = *src->u.lpvarValue;
5910 buffer += sizeof(VARIANT);
5911 VariantInit(dest->u.lpvarValue);
5912 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5913 if (FAILED(hr))
5915 SysFreeString((BSTR)dest);
5916 return hr;
5919 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5920 if (FAILED(hr))
5922 if (src->varkind == VAR_CONST)
5923 VariantClear(dest->u.lpvarValue);
5924 SysFreeString((BSTR)dest);
5925 return hr;
5927 *dest_ptr = dest;
5928 return S_OK;
5931 /* ITypeInfo::GetVarDesc
5933 * Retrieves a VARDESC structure that describes the specified variable.
5936 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5937 LPVARDESC *ppVarDesc)
5939 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5940 const TLBVarDesc *pVDesc = &This->vardescs[index];
5942 TRACE("(%p) index %d\n", This, index);
5944 if(index >= This->cVars)
5945 return TYPE_E_ELEMENTNOTFOUND;
5947 if (This->needs_layout)
5948 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5950 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5953 /* ITypeInfo_GetNames
5955 * Retrieves the variable with the specified member ID (or the name of the
5956 * property or method and its parameters) that correspond to the specified
5957 * function ID.
5959 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5960 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5962 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5963 const TLBFuncDesc *pFDesc;
5964 const TLBVarDesc *pVDesc;
5965 int i;
5966 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5967 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
5968 if(pFDesc)
5970 /* function found, now return function and parameter names */
5971 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5973 if(!i)
5974 *rgBstrNames=SysAllocString(TLB_get_bstr(pFDesc->Name));
5975 else
5976 rgBstrNames[i]=SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i-1].Name));
5978 *pcNames=i;
5980 else
5982 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
5983 if(pVDesc)
5985 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
5986 *pcNames=1;
5988 else
5990 if(This->impltypes &&
5991 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
5992 /* recursive search */
5993 ITypeInfo *pTInfo;
5994 HRESULT result;
5995 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5996 if(SUCCEEDED(result))
5998 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5999 ITypeInfo_Release(pTInfo);
6000 return result;
6002 WARN("Could not search inherited interface!\n");
6004 else
6006 WARN("no names found\n");
6008 *pcNames=0;
6009 return TYPE_E_ELEMENTNOTFOUND;
6012 return S_OK;
6016 /* ITypeInfo::GetRefTypeOfImplType
6018 * If a type description describes a COM class, it retrieves the type
6019 * description of the implemented interface types. For an interface,
6020 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6021 * if any exist.
6024 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6025 ITypeInfo2 *iface,
6026 UINT index,
6027 HREFTYPE *pRefType)
6029 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6030 HRESULT hr = S_OK;
6032 TRACE("(%p) index %d\n", This, index);
6033 if (TRACE_ON(ole)) dump_TypeInfo(This);
6035 if(index==(UINT)-1)
6037 /* only valid on dual interfaces;
6038 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6041 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6043 *pRefType = -2;
6045 else
6047 hr = TYPE_E_ELEMENTNOTFOUND;
6050 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6052 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6053 *pRefType = This->pTypeLib->dispatch_href;
6055 else
6057 if(index >= This->cImplTypes)
6058 hr = TYPE_E_ELEMENTNOTFOUND;
6059 else
6060 *pRefType = This->impltypes[index].hRef;
6063 if(TRACE_ON(ole))
6065 if(SUCCEEDED(hr))
6066 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6067 else
6068 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6071 return hr;
6074 /* ITypeInfo::GetImplTypeFlags
6076 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6077 * or base interface in a type description.
6079 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6080 UINT index, INT *pImplTypeFlags)
6082 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6084 TRACE("(%p) index %d\n", This, index);
6086 if(!pImplTypeFlags)
6087 return E_INVALIDARG;
6089 if(This->typekind == TKIND_DISPATCH && index == 0){
6090 *pImplTypeFlags = 0;
6091 return S_OK;
6094 if(index >= This->cImplTypes)
6095 return TYPE_E_ELEMENTNOTFOUND;
6097 *pImplTypeFlags = This->impltypes[index].implflags;
6099 return S_OK;
6102 /* GetIDsOfNames
6103 * Maps between member names and member IDs, and parameter names and
6104 * parameter IDs.
6106 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6107 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6109 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6110 const TLBVarDesc *pVDesc;
6111 HRESULT ret=S_OK;
6112 UINT i, fdc;
6114 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6115 cNames);
6117 /* init out parameters in case of failure */
6118 for (i = 0; i < cNames; i++)
6119 pMemId[i] = MEMBERID_NIL;
6121 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6122 int j;
6123 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6124 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6125 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6126 for(i=1; i < cNames; i++){
6127 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6128 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6129 break;
6130 if( j<pFDesc->funcdesc.cParams)
6131 pMemId[i]=j;
6132 else
6133 ret=DISP_E_UNKNOWNNAME;
6135 TRACE("-- 0x%08x\n", ret);
6136 return ret;
6139 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6140 if(pVDesc){
6141 if(cNames)
6142 *pMemId = pVDesc->vardesc.memid;
6143 return ret;
6145 /* not found, see if it can be found in an inherited interface */
6146 if(This->impltypes) {
6147 /* recursive search */
6148 ITypeInfo *pTInfo;
6149 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6150 if(SUCCEEDED(ret)){
6151 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6152 ITypeInfo_Release(pTInfo);
6153 return ret;
6155 WARN("Could not search inherited interface!\n");
6156 } else
6157 WARN("no names found\n");
6158 return DISP_E_UNKNOWNNAME;
6162 #ifdef __i386__
6164 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6165 __ASM_GLOBAL_FUNC( call_method,
6166 "pushl %ebp\n\t"
6167 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6168 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6169 "movl %esp,%ebp\n\t"
6170 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6171 "pushl %esi\n\t"
6172 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6173 "pushl %edi\n\t"
6174 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6175 "movl 12(%ebp),%edx\n\t"
6176 "movl %esp,%edi\n\t"
6177 "shll $2,%edx\n\t"
6178 "jz 1f\n\t"
6179 "subl %edx,%edi\n\t"
6180 "andl $~15,%edi\n\t"
6181 "movl %edi,%esp\n\t"
6182 "movl 12(%ebp),%ecx\n\t"
6183 "movl 16(%ebp),%esi\n\t"
6184 "cld\n\t"
6185 "rep; movsl\n"
6186 "1:\tcall *8(%ebp)\n\t"
6187 "subl %esp,%edi\n\t"
6188 "movl 20(%ebp),%ecx\n\t"
6189 "movl %edi,(%ecx)\n\t"
6190 "leal -8(%ebp),%esp\n\t"
6191 "popl %edi\n\t"
6192 __ASM_CFI(".cfi_same_value %edi\n\t")
6193 "popl %esi\n\t"
6194 __ASM_CFI(".cfi_same_value %esi\n\t")
6195 "popl %ebp\n\t"
6196 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6197 __ASM_CFI(".cfi_same_value %ebp\n\t")
6198 "ret" )
6200 /* same function but returning floating point */
6201 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6203 /* ITypeInfo::Invoke
6205 * Invokes a method, or accesses a property of an object, that implements the
6206 * interface described by the type description.
6208 DWORD
6209 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6210 DWORD res;
6211 int stack_offset;
6213 if (TRACE_ON(ole)) {
6214 int i;
6215 TRACE("Calling %p(",func);
6216 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6217 if (nrargs > 30) TRACE("...");
6218 TRACE(")\n");
6221 switch (callconv) {
6222 case CC_STDCALL:
6223 case CC_CDECL:
6224 res = call_method( func, nrargs, args, &stack_offset );
6225 break;
6226 default:
6227 FIXME("unsupported calling convention %d\n",callconv);
6228 res = -1;
6229 break;
6231 TRACE("returns %08x\n",res);
6232 return res;
6235 #elif defined(__x86_64__)
6237 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6238 __ASM_GLOBAL_FUNC( call_method,
6239 "pushq %rbp\n\t"
6240 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6241 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6242 "movq %rsp,%rbp\n\t"
6243 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6244 "pushq %rsi\n\t"
6245 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6246 "pushq %rdi\n\t"
6247 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6248 "movq %rcx,%rax\n\t"
6249 "movq $4,%rcx\n\t"
6250 "cmp %rcx,%rdx\n\t"
6251 "cmovgq %rdx,%rcx\n\t"
6252 "leaq 0(,%rcx,8),%rdx\n\t"
6253 "subq %rdx,%rsp\n\t"
6254 "andq $~15,%rsp\n\t"
6255 "movq %rsp,%rdi\n\t"
6256 "movq %r8,%rsi\n\t"
6257 "rep; movsq\n\t"
6258 "movq 0(%rsp),%rcx\n\t"
6259 "movq 8(%rsp),%rdx\n\t"
6260 "movq 16(%rsp),%r8\n\t"
6261 "movq 24(%rsp),%r9\n\t"
6262 "movq %rcx,%xmm0\n\t"
6263 "movq %rdx,%xmm1\n\t"
6264 "movq %r8,%xmm2\n\t"
6265 "movq %r9,%xmm3\n\t"
6266 "callq *%rax\n\t"
6267 "leaq -16(%rbp),%rsp\n\t"
6268 "popq %rdi\n\t"
6269 __ASM_CFI(".cfi_same_value %rdi\n\t")
6270 "popq %rsi\n\t"
6271 __ASM_CFI(".cfi_same_value %rsi\n\t")
6272 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6273 "popq %rbp\n\t"
6274 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6275 __ASM_CFI(".cfi_same_value %rbp\n\t")
6276 "ret")
6278 /* same function but returning floating point */
6279 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6281 #endif /* __x86_64__ */
6283 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6285 HRESULT hr = S_OK;
6286 ITypeInfo *tinfo2 = NULL;
6287 TYPEATTR *tattr = NULL;
6289 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6290 if (hr)
6292 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6293 "hr = 0x%08x\n",
6294 tdesc->u.hreftype, hr);
6295 return hr;
6297 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6298 if (hr)
6300 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6301 ITypeInfo_Release(tinfo2);
6302 return hr;
6305 switch (tattr->typekind)
6307 case TKIND_ENUM:
6308 *vt |= VT_I4;
6309 break;
6311 case TKIND_ALIAS:
6312 tdesc = &tattr->tdescAlias;
6313 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6314 break;
6316 case TKIND_INTERFACE:
6317 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6318 *vt |= VT_DISPATCH;
6319 else
6320 *vt |= VT_UNKNOWN;
6321 break;
6323 case TKIND_DISPATCH:
6324 *vt |= VT_DISPATCH;
6325 break;
6327 case TKIND_COCLASS:
6328 *vt |= VT_DISPATCH;
6329 break;
6331 case TKIND_RECORD:
6332 FIXME("TKIND_RECORD unhandled.\n");
6333 hr = E_NOTIMPL;
6334 break;
6336 case TKIND_UNION:
6337 FIXME("TKIND_UNION unhandled.\n");
6338 hr = E_NOTIMPL;
6339 break;
6341 default:
6342 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6343 hr = E_NOTIMPL;
6344 break;
6346 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6347 ITypeInfo_Release(tinfo2);
6348 return hr;
6351 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6353 HRESULT hr = S_OK;
6355 /* enforce only one level of pointer indirection */
6356 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6358 tdesc = tdesc->u.lptdesc;
6360 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6361 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6362 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6363 if ((tdesc->vt == VT_USERDEFINED) ||
6364 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6366 VARTYPE vt_userdefined = 0;
6367 const TYPEDESC *tdesc_userdefined = tdesc;
6368 if (tdesc->vt == VT_PTR)
6370 vt_userdefined = VT_BYREF;
6371 tdesc_userdefined = tdesc->u.lptdesc;
6373 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6374 if ((hr == S_OK) &&
6375 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6376 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6378 *vt |= vt_userdefined;
6379 return S_OK;
6382 *vt = VT_BYREF;
6385 switch (tdesc->vt)
6387 case VT_HRESULT:
6388 *vt |= VT_ERROR;
6389 break;
6390 case VT_USERDEFINED:
6391 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6392 break;
6393 case VT_VOID:
6394 case VT_CARRAY:
6395 case VT_PTR:
6396 case VT_LPSTR:
6397 case VT_LPWSTR:
6398 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6399 hr = DISP_E_BADVARTYPE;
6400 break;
6401 case VT_SAFEARRAY:
6402 *vt |= VT_ARRAY;
6403 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6404 break;
6405 case VT_INT:
6406 *vt |= VT_I4;
6407 break;
6408 case VT_UINT:
6409 *vt |= VT_UI4;
6410 break;
6411 default:
6412 *vt |= tdesc->vt;
6413 break;
6415 return hr;
6418 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6420 ITypeInfo *tinfo2;
6421 TYPEATTR *tattr;
6422 HRESULT hres;
6424 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6425 if(FAILED(hres))
6426 return hres;
6428 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6429 if(FAILED(hres)) {
6430 ITypeInfo_Release(tinfo2);
6431 return hres;
6434 switch(tattr->typekind) {
6435 case TKIND_ALIAS:
6436 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6437 break;
6439 case TKIND_INTERFACE:
6440 case TKIND_DISPATCH:
6441 *guid = tattr->guid;
6442 break;
6444 default:
6445 ERR("Unexpected typekind %d\n", tattr->typekind);
6446 hres = E_UNEXPECTED;
6449 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6450 ITypeInfo_Release(tinfo2);
6451 return hres;
6454 /***********************************************************************
6455 * DispCallFunc (OLEAUT32.@)
6457 * Invokes a function of the specified calling convention, passing the
6458 * specified arguments and returns the result.
6460 * PARAMS
6461 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6462 * oVft [I] The offset in the vtable. See notes.
6463 * cc [I] Calling convention of the function to call.
6464 * vtReturn [I] The return type of the function.
6465 * cActuals [I] Number of parameters.
6466 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6467 * prgpvarg [I] The arguments to pass.
6468 * pvargResult [O] The return value of the function. Can be NULL.
6470 * RETURNS
6471 * Success: S_OK.
6472 * Failure: HRESULT code.
6474 * NOTES
6475 * The HRESULT return value of this function is not affected by the return
6476 * value of the user supplied function, which is returned in pvargResult.
6478 * If pvInstance is NULL then a non-object function is to be called and oVft
6479 * is the address of the function to call.
6481 * The cc parameter can be one of the following values:
6482 *|CC_FASTCALL
6483 *|CC_CDECL
6484 *|CC_PASCAL
6485 *|CC_STDCALL
6486 *|CC_FPFASTCALL
6487 *|CC_SYSCALL
6488 *|CC_MPWCDECL
6489 *|CC_MPWPASCAL
6492 HRESULT WINAPI
6493 DispCallFunc(
6494 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6495 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6497 #ifdef __i386__
6498 int argspos, stack_offset;
6499 void *func;
6500 UINT i;
6501 DWORD *args;
6503 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6504 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6505 pvargResult, V_VT(pvargResult));
6507 if (cc != CC_STDCALL && cc != CC_CDECL)
6509 FIXME("unsupported calling convention %d\n",cc);
6510 return E_INVALIDARG;
6513 /* maximum size for an argument is sizeof(VARIANT) */
6514 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6516 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6517 argspos = 1;
6518 if (pvInstance)
6520 const FARPROC *vtable = *(FARPROC **)pvInstance;
6521 func = vtable[oVft/sizeof(void *)];
6522 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6524 else func = (void *)oVft;
6526 for (i = 0; i < cActuals; i++)
6528 VARIANT *arg = prgpvarg[i];
6530 switch (prgvt[i])
6532 case VT_EMPTY:
6533 break;
6534 case VT_I8:
6535 case VT_UI8:
6536 case VT_R8:
6537 case VT_DATE:
6538 case VT_CY:
6539 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6540 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6541 break;
6542 case VT_DECIMAL:
6543 case VT_VARIANT:
6544 memcpy( &args[argspos], arg, sizeof(*arg) );
6545 argspos += sizeof(*arg) / sizeof(DWORD);
6546 break;
6547 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6548 args[argspos++] = V_BOOL(arg);
6549 break;
6550 default:
6551 args[argspos++] = V_UI4(arg);
6552 break;
6554 TRACE("arg %u: type %d\n",i,prgvt[i]);
6555 dump_Variant(arg);
6558 switch (vtReturn)
6560 case VT_EMPTY:
6561 call_method( func, argspos - 1, args + 1, &stack_offset );
6562 break;
6563 case VT_R4:
6564 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6565 break;
6566 case VT_R8:
6567 case VT_DATE:
6568 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6569 break;
6570 case VT_DECIMAL:
6571 case VT_VARIANT:
6572 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6573 call_method( func, argspos, args, &stack_offset );
6574 break;
6575 case VT_I8:
6576 case VT_UI8:
6577 case VT_CY:
6578 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6579 break;
6580 case VT_HRESULT:
6581 WARN("invalid return type %u\n", vtReturn);
6582 heap_free( args );
6583 return E_INVALIDARG;
6584 default:
6585 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6586 break;
6588 heap_free( args );
6589 if (stack_offset && cc == CC_STDCALL)
6591 WARN( "stack pointer off by %d\n", stack_offset );
6592 return DISP_E_BADCALLEE;
6594 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6595 TRACE("retval: "); dump_Variant(pvargResult);
6596 return S_OK;
6598 #elif defined(__x86_64__)
6599 int argspos;
6600 UINT i;
6601 DWORD_PTR *args;
6602 void *func;
6604 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6605 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6606 pvargResult, V_VT(pvargResult));
6608 if (cc != CC_STDCALL && cc != CC_CDECL)
6610 FIXME("unsupported calling convention %d\n",cc);
6611 return E_INVALIDARG;
6614 /* maximum size for an argument is sizeof(DWORD_PTR) */
6615 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6617 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6618 argspos = 1;
6619 if (pvInstance)
6621 const FARPROC *vtable = *(FARPROC **)pvInstance;
6622 func = vtable[oVft/sizeof(void *)];
6623 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6625 else func = (void *)oVft;
6627 for (i = 0; i < cActuals; i++)
6629 VARIANT *arg = prgpvarg[i];
6631 switch (prgvt[i])
6633 case VT_DECIMAL:
6634 case VT_VARIANT:
6635 args[argspos++] = (ULONG_PTR)arg;
6636 break;
6637 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6638 args[argspos++] = V_BOOL(arg);
6639 break;
6640 default:
6641 args[argspos++] = V_UI8(arg);
6642 break;
6644 TRACE("arg %u: type %d\n",i,prgvt[i]);
6645 dump_Variant(arg);
6648 switch (vtReturn)
6650 case VT_R4:
6651 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6652 break;
6653 case VT_R8:
6654 case VT_DATE:
6655 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6656 break;
6657 case VT_DECIMAL:
6658 case VT_VARIANT:
6659 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6660 call_method( func, argspos, args );
6661 break;
6662 case VT_HRESULT:
6663 WARN("invalid return type %u\n", vtReturn);
6664 heap_free( args );
6665 return E_INVALIDARG;
6666 default:
6667 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6668 break;
6670 heap_free( args );
6671 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6672 TRACE("retval: "); dump_Variant(pvargResult);
6673 return S_OK;
6675 #else
6676 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6677 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6678 return E_NOTIMPL;
6679 #endif
6682 static inline BOOL func_restricted( const FUNCDESC *desc )
6684 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6687 #define INVBUF_ELEMENT_SIZE \
6688 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6689 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6690 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6691 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6692 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6693 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6694 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6695 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6697 static HRESULT WINAPI ITypeInfo_fnInvoke(
6698 ITypeInfo2 *iface,
6699 VOID *pIUnk,
6700 MEMBERID memid,
6701 UINT16 wFlags,
6702 DISPPARAMS *pDispParams,
6703 VARIANT *pVarResult,
6704 EXCEPINFO *pExcepInfo,
6705 UINT *pArgErr)
6707 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6708 int i;
6709 unsigned int var_index;
6710 TYPEKIND type_kind;
6711 HRESULT hres;
6712 const TLBFuncDesc *pFuncInfo;
6713 UINT fdc;
6715 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6716 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6719 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6720 return DISP_E_MEMBERNOTFOUND;
6722 if (!pDispParams)
6724 ERR("NULL pDispParams not allowed\n");
6725 return E_INVALIDARG;
6728 dump_DispParms(pDispParams);
6730 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6732 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6733 pDispParams->cNamedArgs, pDispParams->cArgs);
6734 return E_INVALIDARG;
6737 /* we do this instead of using GetFuncDesc since it will return a fake
6738 * FUNCDESC for dispinterfaces and we want the real function description */
6739 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6740 pFuncInfo = &This->funcdescs[fdc];
6741 if ((memid == pFuncInfo->funcdesc.memid) &&
6742 (wFlags & pFuncInfo->funcdesc.invkind) &&
6743 !func_restricted( &pFuncInfo->funcdesc ))
6744 break;
6747 if (fdc < This->cFuncs) {
6748 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6750 if (TRACE_ON(ole))
6752 TRACE("invoking:\n");
6753 dump_TLBFuncDescOne(pFuncInfo);
6756 switch (func_desc->funckind) {
6757 case FUNC_PUREVIRTUAL:
6758 case FUNC_VIRTUAL: {
6759 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6760 VARIANT varresult;
6761 VARIANT retval; /* pointer for storing byref retvals in */
6762 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6763 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6764 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6765 UINT cNamedArgs = pDispParams->cNamedArgs;
6766 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6767 UINT vargs_converted=0;
6769 hres = S_OK;
6771 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6773 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6775 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6776 hres = DISP_E_PARAMNOTFOUND;
6777 goto func_fail;
6781 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6783 ERR("functions with the vararg attribute do not support named arguments\n");
6784 hres = DISP_E_NONAMEDARGS;
6785 goto func_fail;
6788 for (i = 0; i < func_desc->cParams; i++)
6790 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6791 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6792 if (FAILED(hres))
6793 goto func_fail;
6796 TRACE("changing args\n");
6797 for (i = 0; i < func_desc->cParams; i++)
6799 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6800 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6801 VARIANTARG *src_arg;
6803 if (wParamFlags & PARAMFLAG_FLCID)
6805 VARIANTARG *arg;
6806 arg = prgpvarg[i] = &rgvarg[i];
6807 V_VT(arg) = VT_I4;
6808 V_I4(arg) = This->pTypeLib->lcid;
6809 continue;
6812 src_arg = NULL;
6814 if (cNamedArgs)
6816 USHORT j;
6817 for (j = 0; j < cNamedArgs; j++)
6818 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6820 src_arg = &pDispParams->rgvarg[j];
6821 break;
6825 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6827 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6828 vargs_converted++;
6831 if (wParamFlags & PARAMFLAG_FRETVAL)
6833 /* under most conditions the caller is not allowed to
6834 * pass in a dispparam arg in the index of what would be
6835 * the retval parameter. however, there is an exception
6836 * where the extra parameter is used in an extra
6837 * IDispatch::Invoke below */
6838 if ((i < pDispParams->cArgs) &&
6839 ((func_desc->cParams != 1) || !pVarResult ||
6840 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6842 hres = DISP_E_BADPARAMCOUNT;
6843 break;
6846 /* note: this check is placed so that if the caller passes
6847 * in a VARIANTARG for the retval we just ignore it, like
6848 * native does */
6849 if (i == func_desc->cParams - 1)
6851 VARIANTARG *arg;
6852 arg = prgpvarg[i] = &rgvarg[i];
6853 memset(arg, 0, sizeof(*arg));
6854 V_VT(arg) = rgvt[i];
6855 memset(&retval, 0, sizeof(retval));
6856 V_BYREF(arg) = &retval;
6858 else
6860 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6861 hres = E_UNEXPECTED;
6862 break;
6865 else if (src_arg)
6867 dump_Variant(src_arg);
6869 if(rgvt[i]!=V_VT(src_arg))
6871 if (rgvt[i] == VT_VARIANT)
6872 hres = VariantCopy(&rgvarg[i], src_arg);
6873 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6875 if (rgvt[i] == V_VT(src_arg))
6876 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6877 else
6879 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6880 if (wParamFlags & PARAMFLAG_FIN)
6881 hres = VariantCopy(&missing_arg[i], src_arg);
6882 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6884 V_VT(&rgvarg[i]) = rgvt[i];
6886 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6888 SAFEARRAY *a;
6889 SAFEARRAYBOUND bound;
6890 VARIANT *v;
6891 LONG j;
6892 bound.lLbound = 0;
6893 bound.cElements = pDispParams->cArgs-i;
6894 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6896 ERR("SafeArrayCreate failed\n");
6897 break;
6899 hres = SafeArrayAccessData(a, (LPVOID)&v);
6900 if (hres != S_OK)
6902 ERR("SafeArrayAccessData failed with %x\n", hres);
6903 SafeArrayDestroy(a);
6904 break;
6906 for (j = 0; j < bound.cElements; j++)
6907 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6908 hres = SafeArrayUnaccessData(a);
6909 if (hres != S_OK)
6911 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6912 SafeArrayDestroy(a);
6913 break;
6915 V_ARRAY(&rgvarg[i]) = a;
6916 V_VT(&rgvarg[i]) = rgvt[i];
6918 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6920 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6921 if (wParamFlags & PARAMFLAG_FIN)
6922 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6923 else
6924 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6925 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6926 V_VT(&rgvarg[i]) = rgvt[i];
6928 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6930 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6931 V_VT(&rgvarg[i]) = rgvt[i];
6933 else
6935 /* FIXME: this doesn't work for VT_BYREF arguments if
6936 * they are not the same type as in the paramdesc */
6937 V_VT(&rgvarg[i]) = V_VT(src_arg);
6938 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6939 V_VT(&rgvarg[i]) = rgvt[i];
6942 if (FAILED(hres))
6944 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6945 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6946 debugstr_VT(src_arg), debugstr_VF(src_arg));
6947 break;
6949 prgpvarg[i] = &rgvarg[i];
6951 else
6953 prgpvarg[i] = src_arg;
6956 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6957 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6958 && V_UNKNOWN(prgpvarg[i])) {
6959 IUnknown *userdefined_iface;
6960 GUID guid;
6962 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6963 if(FAILED(hres))
6964 break;
6966 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6967 if(FAILED(hres)) {
6968 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6969 break;
6972 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6973 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6976 else if (wParamFlags & PARAMFLAG_FOPT)
6978 VARIANTARG *arg;
6979 arg = prgpvarg[i] = &rgvarg[i];
6980 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6982 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6983 if (FAILED(hres))
6984 break;
6986 else
6988 VARIANTARG *missing_arg;
6989 /* if the function wants a pointer to a variant then
6990 * set that up, otherwise just pass the VT_ERROR in
6991 * the argument by value */
6992 if (rgvt[i] & VT_BYREF)
6994 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6995 V_VT(arg) = VT_VARIANT | VT_BYREF;
6996 V_VARIANTREF(arg) = missing_arg;
6998 else
6999 missing_arg = arg;
7000 V_VT(missing_arg) = VT_ERROR;
7001 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7004 else
7006 hres = DISP_E_BADPARAMCOUNT;
7007 break;
7010 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7012 /* VT_VOID is a special case for return types, so it is not
7013 * handled in the general function */
7014 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7015 V_VT(&varresult) = VT_EMPTY;
7016 else
7018 V_VT(&varresult) = 0;
7019 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7020 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7023 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7024 V_VT(&varresult), func_desc->cParams, rgvt,
7025 prgpvarg, &varresult);
7027 vargs_converted = 0;
7029 for (i = 0; i < func_desc->cParams; i++)
7031 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7032 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7034 if (wParamFlags & PARAMFLAG_FLCID)
7035 continue;
7036 else if (wParamFlags & PARAMFLAG_FRETVAL)
7038 if (TRACE_ON(ole))
7040 TRACE("[retval] value: ");
7041 dump_Variant(prgpvarg[i]);
7044 if (pVarResult)
7046 VariantInit(pVarResult);
7047 /* deref return value */
7048 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7051 VARIANT_ClearInd(prgpvarg[i]);
7053 else if (vargs_converted < pDispParams->cArgs)
7055 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7056 if (wParamFlags & PARAMFLAG_FOUT)
7058 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7060 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7062 if (FAILED(hres))
7064 ERR("failed to convert param %d to vt %d\n", i,
7065 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7066 break;
7070 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7071 func_desc->cParamsOpt < 0 &&
7072 i == func_desc->cParams-1)
7074 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7075 LONG j, ubound;
7076 VARIANT *v;
7077 hres = SafeArrayGetUBound(a, 1, &ubound);
7078 if (hres != S_OK)
7080 ERR("SafeArrayGetUBound failed with %x\n", hres);
7081 break;
7083 hres = SafeArrayAccessData(a, (LPVOID)&v);
7084 if (hres != S_OK)
7086 ERR("SafeArrayAccessData failed with %x\n", hres);
7087 break;
7089 for (j = 0; j <= ubound; j++)
7090 VariantClear(&v[j]);
7091 hres = SafeArrayUnaccessData(a);
7092 if (hres != S_OK)
7094 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7095 break;
7098 VariantClear(&rgvarg[i]);
7099 vargs_converted++;
7101 else if (wParamFlags & PARAMFLAG_FOPT)
7103 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7104 VariantClear(&rgvarg[i]);
7107 VariantClear(&missing_arg[i]);
7110 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7112 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7113 hres = DISP_E_EXCEPTION;
7114 if (pExcepInfo)
7116 IErrorInfo *pErrorInfo;
7117 pExcepInfo->scode = V_ERROR(&varresult);
7118 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7120 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7121 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7122 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7123 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7125 IErrorInfo_Release(pErrorInfo);
7129 if (V_VT(&varresult) != VT_ERROR)
7131 TRACE("varresult value: ");
7132 dump_Variant(&varresult);
7134 if (pVarResult)
7136 VariantClear(pVarResult);
7137 *pVarResult = varresult;
7139 else
7140 VariantClear(&varresult);
7143 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7144 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7145 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7146 (pDispParams->cArgs != 0))
7148 if (V_VT(pVarResult) == VT_DISPATCH)
7150 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7151 /* Note: not VariantClear; we still need the dispatch
7152 * pointer to be valid */
7153 VariantInit(pVarResult);
7154 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7155 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7156 pDispParams, pVarResult, pExcepInfo, pArgErr);
7157 IDispatch_Release(pDispatch);
7159 else
7161 VariantClear(pVarResult);
7162 hres = DISP_E_NOTACOLLECTION;
7166 func_fail:
7167 heap_free(buffer);
7168 break;
7170 case FUNC_DISPATCH: {
7171 IDispatch *disp;
7173 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7174 if (SUCCEEDED(hres)) {
7175 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7176 hres = IDispatch_Invoke(
7177 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7178 pVarResult,pExcepInfo,pArgErr
7180 if (FAILED(hres))
7181 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7182 IDispatch_Release(disp);
7183 } else
7184 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7185 break;
7187 default:
7188 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7189 hres = E_FAIL;
7190 break;
7193 TRACE("-- 0x%08x\n", hres);
7194 return hres;
7196 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7197 VARDESC *var_desc;
7199 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7200 if(FAILED(hres)) return hres;
7202 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7203 dump_VARDESC(var_desc);
7204 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7205 return E_NOTIMPL;
7208 /* not found, look for it in inherited interfaces */
7209 ITypeInfo2_GetTypeKind(iface, &type_kind);
7210 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7211 if(This->impltypes) {
7212 /* recursive search */
7213 ITypeInfo *pTInfo;
7214 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7215 if(SUCCEEDED(hres)){
7216 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7217 ITypeInfo_Release(pTInfo);
7218 return hres;
7220 WARN("Could not search inherited interface!\n");
7223 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7224 return DISP_E_MEMBERNOTFOUND;
7227 /* ITypeInfo::GetDocumentation
7229 * Retrieves the documentation string, the complete Help file name and path,
7230 * and the context ID for the Help topic for a specified type description.
7232 * (Can be tested by the Visual Basic Editor in Word for instance.)
7234 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7235 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7236 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7238 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7239 const TLBFuncDesc *pFDesc;
7240 const TLBVarDesc *pVDesc;
7241 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7242 " HelpContext(%p) HelpFile(%p)\n",
7243 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7244 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7245 if(pBstrName)
7246 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7247 if(pBstrDocString)
7248 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7249 if(pdwHelpContext)
7250 *pdwHelpContext=This->dwHelpContext;
7251 if(pBstrHelpFile)
7252 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7253 return S_OK;
7254 }else {/* for a member */
7255 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7256 if(pFDesc){
7257 if(pBstrName)
7258 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7259 if(pBstrDocString)
7260 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7261 if(pdwHelpContext)
7262 *pdwHelpContext=pFDesc->helpcontext;
7263 if(pBstrHelpFile)
7264 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7265 return S_OK;
7267 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7268 if(pVDesc){
7269 if(pBstrName)
7270 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7271 if(pBstrDocString)
7272 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7273 if(pdwHelpContext)
7274 *pdwHelpContext=pVDesc->HelpContext;
7275 if(pBstrHelpFile)
7276 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7277 return S_OK;
7281 if(This->impltypes &&
7282 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7283 /* recursive search */
7284 ITypeInfo *pTInfo;
7285 HRESULT result;
7286 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7287 if(SUCCEEDED(result)) {
7288 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7289 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7290 ITypeInfo_Release(pTInfo);
7291 return result;
7293 WARN("Could not search inherited interface!\n");
7296 WARN("member %d not found\n", memid);
7297 return TYPE_E_ELEMENTNOTFOUND;
7300 /* ITypeInfo::GetDllEntry
7302 * Retrieves a description or specification of an entry point for a function
7303 * in a DLL.
7305 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7306 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7307 WORD *pwOrdinal)
7309 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7310 const TLBFuncDesc *pFDesc;
7312 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7314 if (pBstrDllName) *pBstrDllName = NULL;
7315 if (pBstrName) *pBstrName = NULL;
7316 if (pwOrdinal) *pwOrdinal = 0;
7318 if (This->typekind != TKIND_MODULE)
7319 return TYPE_E_BADMODULEKIND;
7321 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7322 if(pFDesc){
7323 dump_TypeInfo(This);
7324 if (TRACE_ON(ole))
7325 dump_TLBFuncDescOne(pFDesc);
7327 if (pBstrDllName)
7328 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7330 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7331 if (pBstrName)
7332 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7333 if (pwOrdinal)
7334 *pwOrdinal = -1;
7335 return S_OK;
7337 if (pBstrName)
7338 *pBstrName = NULL;
7339 if (pwOrdinal)
7340 *pwOrdinal = LOWORD(pFDesc->Entry);
7341 return S_OK;
7343 return TYPE_E_ELEMENTNOTFOUND;
7346 /* internal function to make the inherited interfaces' methods appear
7347 * part of the interface */
7348 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7349 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7351 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7352 HRESULT hr;
7354 TRACE("%p, 0x%x\n", iface, *hRefType);
7356 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7358 ITypeInfo *pSubTypeInfo;
7360 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7361 if (FAILED(hr))
7362 return hr;
7364 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7365 hRefType, ppTInfo);
7366 ITypeInfo_Release(pSubTypeInfo);
7367 if (SUCCEEDED(hr))
7368 return hr;
7370 *hRefType -= DISPATCH_HREF_OFFSET;
7372 if (!(*hRefType & DISPATCH_HREF_MASK))
7373 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7374 else
7375 return E_FAIL;
7378 /* ITypeInfo::GetRefTypeInfo
7380 * If a type description references other type descriptions, it retrieves
7381 * the referenced type descriptions.
7383 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7384 ITypeInfo2 *iface,
7385 HREFTYPE hRefType,
7386 ITypeInfo **ppTInfo)
7388 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7389 HRESULT result = E_FAIL;
7391 if(!ppTInfo)
7392 return E_INVALIDARG;
7394 if ((INT)hRefType < 0) {
7395 ITypeInfoImpl *pTypeInfoImpl;
7397 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7398 !(This->typekind == TKIND_INTERFACE ||
7399 This->typekind == TKIND_DISPATCH))
7400 return TYPE_E_ELEMENTNOTFOUND;
7402 /* when we meet a DUAL typeinfo, we must create the alternate
7403 * version of it.
7405 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7407 *pTypeInfoImpl = *This;
7408 pTypeInfoImpl->ref = 0;
7410 if (This->typekind == TKIND_INTERFACE)
7411 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7412 else
7413 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7415 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7416 /* the AddRef implicitly adds a reference to the parent typelib, which
7417 * stops the copied data from being destroyed until the new typeinfo's
7418 * refcount goes to zero, but we need to signal to the new instance to
7419 * not free its data structures when it is destroyed */
7420 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7422 ITypeInfo_AddRef(*ppTInfo);
7424 result = S_OK;
7425 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7426 (This->typekind == TKIND_DISPATCH))
7428 HREFTYPE href_dispatch = hRefType;
7429 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7430 } else {
7431 TLBRefType *ref_type;
7432 ITypeLib *pTLib = NULL;
7433 UINT i;
7435 if(!(hRefType & 0x1)){
7436 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7438 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7440 result = S_OK;
7441 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7442 ITypeInfo_AddRef(*ppTInfo);
7443 goto end;
7446 result = TYPE_E_ELEMENTNOTFOUND;
7447 goto end;
7450 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7452 if(ref_type->reference == (hRefType & (~0x3)))
7453 break;
7455 if(&ref_type->entry == &This->pTypeLib->ref_list)
7457 FIXME("Can't find pRefType for ref %x\n", hRefType);
7458 goto end;
7461 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7462 UINT Index;
7463 TRACE("internal reference\n");
7464 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7465 } else {
7466 if(ref_type->pImpTLInfo->pImpTypeLib) {
7467 TRACE("typeinfo in imported typelib that is already loaded\n");
7468 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7469 ITypeLib_AddRef(pTLib);
7470 result = S_OK;
7471 } else {
7472 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7473 result = LoadRegTypeLib( TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7474 ref_type->pImpTLInfo->wVersionMajor,
7475 ref_type->pImpTLInfo->wVersionMinor,
7476 ref_type->pImpTLInfo->lcid,
7477 &pTLib);
7479 if(FAILED(result)) {
7480 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7481 result=LoadTypeLib(libnam, &pTLib);
7482 SysFreeString(libnam);
7484 if(SUCCEEDED(result)) {
7485 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7486 ITypeLib_AddRef(pTLib);
7490 if(SUCCEEDED(result)) {
7491 if(ref_type->index == TLB_REF_USE_GUID)
7492 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7493 else
7494 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7496 if (pTLib != NULL)
7497 ITypeLib_Release(pTLib);
7500 end:
7501 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7502 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7503 return result;
7506 /* ITypeInfo::AddressOfMember
7508 * Retrieves the addresses of static functions or variables, such as those
7509 * defined in a DLL.
7511 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7512 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7514 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7515 HRESULT hr;
7516 BSTR dll, entry;
7517 WORD ordinal;
7518 HMODULE module;
7520 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7522 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7523 if (FAILED(hr))
7524 return hr;
7526 module = LoadLibraryW(dll);
7527 if (!module)
7529 ERR("couldn't load %s\n", debugstr_w(dll));
7530 SysFreeString(dll);
7531 SysFreeString(entry);
7532 return STG_E_FILENOTFOUND;
7534 /* FIXME: store library somewhere where we can free it */
7536 if (entry)
7538 LPSTR entryA;
7539 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7540 entryA = heap_alloc(len);
7541 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7543 *ppv = GetProcAddress(module, entryA);
7544 if (!*ppv)
7545 ERR("function not found %s\n", debugstr_a(entryA));
7547 heap_free(entryA);
7549 else
7551 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7552 if (!*ppv)
7553 ERR("function not found %d\n", ordinal);
7556 SysFreeString(dll);
7557 SysFreeString(entry);
7559 if (!*ppv)
7560 return TYPE_E_DLLFUNCTIONNOTFOUND;
7562 return S_OK;
7565 /* ITypeInfo::CreateInstance
7567 * Creates a new instance of a type that describes a component object class
7568 * (coclass).
7570 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7571 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7573 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7574 HRESULT hr;
7575 TYPEATTR *pTA;
7577 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7579 *ppvObj = NULL;
7581 if(pOuterUnk)
7583 WARN("Not able to aggregate\n");
7584 return CLASS_E_NOAGGREGATION;
7587 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7588 if(FAILED(hr)) return hr;
7590 if(pTA->typekind != TKIND_COCLASS)
7592 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7593 hr = E_INVALIDARG;
7594 goto end;
7597 hr = S_FALSE;
7598 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7600 IUnknown *pUnk;
7601 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7602 TRACE("GetActiveObject rets %08x\n", hr);
7603 if(hr == S_OK)
7605 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7606 IUnknown_Release(pUnk);
7610 if(hr != S_OK)
7611 hr = CoCreateInstance(&pTA->guid, NULL,
7612 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7613 riid, ppvObj);
7615 end:
7616 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7617 return hr;
7620 /* ITypeInfo::GetMops
7622 * Retrieves marshalling information.
7624 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7625 BSTR *pBstrMops)
7627 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7628 FIXME("(%p %d) stub!\n", This, memid);
7629 *pBstrMops = NULL;
7630 return S_OK;
7633 /* ITypeInfo::GetContainingTypeLib
7635 * Retrieves the containing type library and the index of the type description
7636 * within that type library.
7638 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7639 ITypeLib * *ppTLib, UINT *pIndex)
7641 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7643 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7644 if (pIndex) {
7645 *pIndex=This->index;
7646 TRACE("returning pIndex=%d\n", *pIndex);
7649 if (ppTLib) {
7650 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7651 ITypeLib_AddRef(*ppTLib);
7652 TRACE("returning ppTLib=%p\n", *ppTLib);
7655 return S_OK;
7658 /* ITypeInfo::ReleaseTypeAttr
7660 * Releases a TYPEATTR previously returned by Get
7663 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7664 TYPEATTR* pTypeAttr)
7666 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7667 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7668 heap_free(pTypeAttr);
7671 /* ITypeInfo::ReleaseFuncDesc
7673 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7675 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7676 ITypeInfo2 *iface,
7677 FUNCDESC *pFuncDesc)
7679 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7680 SHORT i;
7682 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7684 for (i = 0; i < pFuncDesc->cParams; i++)
7685 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7686 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7688 SysFreeString((BSTR)pFuncDesc);
7691 /* ITypeInfo::ReleaseVarDesc
7693 * Releases a VARDESC previously returned by GetVarDesc.
7695 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7696 VARDESC *pVarDesc)
7698 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7699 TRACE("(%p)->(%p)\n", This, pVarDesc);
7701 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7702 if (pVarDesc->varkind == VAR_CONST)
7703 VariantClear(pVarDesc->u.lpvarValue);
7704 SysFreeString((BSTR)pVarDesc);
7707 /* ITypeInfo2::GetTypeKind
7709 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7712 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7713 TYPEKIND *pTypeKind)
7715 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7716 *pTypeKind=This->typekind;
7717 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7718 return S_OK;
7721 /* ITypeInfo2::GetTypeFlags
7723 * Returns the type flags without any allocations. This returns a DWORD type
7724 * flag, which expands the type flags without growing the TYPEATTR (type
7725 * attribute).
7728 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7730 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7731 *pTypeFlags=This->wTypeFlags;
7732 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7733 return S_OK;
7736 /* ITypeInfo2::GetFuncIndexOfMemId
7737 * Binds to a specific member based on a known DISPID, where the member name
7738 * is not known (for example, when binding to a default member).
7741 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7742 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7744 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7745 UINT fdc;
7746 HRESULT result;
7748 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7749 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7750 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7751 break;
7753 if(fdc < This->cFuncs) {
7754 *pFuncIndex = fdc;
7755 result = S_OK;
7756 } else
7757 result = TYPE_E_ELEMENTNOTFOUND;
7759 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7760 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7761 return result;
7764 /* TypeInfo2::GetVarIndexOfMemId
7766 * Binds to a specific member based on a known DISPID, where the member name
7767 * is not known (for example, when binding to a default member).
7770 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7771 MEMBERID memid, UINT *pVarIndex)
7773 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7774 TLBVarDesc *pVarInfo;
7776 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7778 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7779 if(!pVarInfo)
7780 return TYPE_E_ELEMENTNOTFOUND;
7782 *pVarIndex = (pVarInfo - This->vardescs);
7784 return S_OK;
7787 /* ITypeInfo2::GetCustData
7789 * Gets the custom data
7791 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7792 ITypeInfo2 * iface,
7793 REFGUID guid,
7794 VARIANT *pVarVal)
7796 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7797 TLBCustData *pCData;
7799 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7801 if(!guid || !pVarVal)
7802 return E_INVALIDARG;
7804 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7806 VariantInit( pVarVal);
7807 if (pCData)
7808 VariantCopy( pVarVal, &pCData->data);
7809 else
7810 VariantClear( pVarVal );
7811 return S_OK;
7814 /* ITypeInfo2::GetFuncCustData
7816 * Gets the custom data
7818 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7819 ITypeInfo2 * iface,
7820 UINT index,
7821 REFGUID guid,
7822 VARIANT *pVarVal)
7824 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7825 TLBCustData *pCData;
7826 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7828 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7830 if(index >= This->cFuncs)
7831 return TYPE_E_ELEMENTNOTFOUND;
7833 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7834 if(!pCData)
7835 return TYPE_E_ELEMENTNOTFOUND;
7837 VariantInit(pVarVal);
7838 VariantCopy(pVarVal, &pCData->data);
7840 return S_OK;
7843 /* ITypeInfo2::GetParamCustData
7845 * Gets the custom data
7847 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7848 ITypeInfo2 * iface,
7849 UINT indexFunc,
7850 UINT indexParam,
7851 REFGUID guid,
7852 VARIANT *pVarVal)
7854 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7855 TLBCustData *pCData;
7856 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7858 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7859 debugstr_guid(guid), pVarVal);
7861 if(indexFunc >= This->cFuncs)
7862 return TYPE_E_ELEMENTNOTFOUND;
7864 if(indexParam >= pFDesc->funcdesc.cParams)
7865 return TYPE_E_ELEMENTNOTFOUND;
7867 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7868 if(!pCData)
7869 return TYPE_E_ELEMENTNOTFOUND;
7871 VariantInit(pVarVal);
7872 VariantCopy(pVarVal, &pCData->data);
7874 return S_OK;
7877 /* ITypeInfo2::GetVarCustData
7879 * Gets the custom data
7881 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7882 ITypeInfo2 * iface,
7883 UINT index,
7884 REFGUID guid,
7885 VARIANT *pVarVal)
7887 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7888 TLBCustData *pCData;
7889 TLBVarDesc *pVDesc = &This->vardescs[index];
7891 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7893 if(index >= This->cVars)
7894 return TYPE_E_ELEMENTNOTFOUND;
7896 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7897 if(!pCData)
7898 return TYPE_E_ELEMENTNOTFOUND;
7900 VariantInit(pVarVal);
7901 VariantCopy(pVarVal, &pCData->data);
7903 return S_OK;
7906 /* ITypeInfo2::GetImplCustData
7908 * Gets the custom data
7910 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7911 ITypeInfo2 * iface,
7912 UINT index,
7913 REFGUID guid,
7914 VARIANT *pVarVal)
7916 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7917 TLBCustData *pCData;
7918 TLBImplType *pRDesc = &This->impltypes[index];
7920 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7922 if(index >= This->cImplTypes)
7923 return TYPE_E_ELEMENTNOTFOUND;
7925 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7926 if(!pCData)
7927 return TYPE_E_ELEMENTNOTFOUND;
7929 VariantInit(pVarVal);
7930 VariantCopy(pVarVal, &pCData->data);
7932 return S_OK;
7935 /* ITypeInfo2::GetDocumentation2
7937 * Retrieves the documentation string, the complete Help file name and path,
7938 * the localization context to use, and the context ID for the library Help
7939 * topic in the Help file.
7942 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7943 ITypeInfo2 * iface,
7944 MEMBERID memid,
7945 LCID lcid,
7946 BSTR *pbstrHelpString,
7947 DWORD *pdwHelpStringContext,
7948 BSTR *pbstrHelpStringDll)
7950 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7951 const TLBFuncDesc *pFDesc;
7952 const TLBVarDesc *pVDesc;
7953 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7954 "HelpStringContext(%p) HelpStringDll(%p)\n",
7955 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7956 pbstrHelpStringDll );
7957 /* the help string should be obtained from the helpstringdll,
7958 * using the _DLLGetDocumentation function, based on the supplied
7959 * lcid. Nice to do sometime...
7961 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7962 if(pbstrHelpString)
7963 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
7964 if(pdwHelpStringContext)
7965 *pdwHelpStringContext=This->dwHelpStringContext;
7966 if(pbstrHelpStringDll)
7967 *pbstrHelpStringDll=
7968 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7969 return S_OK;
7970 }else {/* for a member */
7971 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7972 if(pFDesc){
7973 if(pbstrHelpString)
7974 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7975 if(pdwHelpStringContext)
7976 *pdwHelpStringContext=pFDesc->HelpStringContext;
7977 if(pbstrHelpStringDll)
7978 *pbstrHelpStringDll=
7979 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7980 return S_OK;
7982 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7983 if(pVDesc){
7984 if(pbstrHelpString)
7985 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7986 if(pdwHelpStringContext)
7987 *pdwHelpStringContext=pVDesc->HelpStringContext;
7988 if(pbstrHelpStringDll)
7989 *pbstrHelpStringDll=
7990 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7991 return S_OK;
7994 return TYPE_E_ELEMENTNOTFOUND;
7997 /* ITypeInfo2::GetAllCustData
7999 * Gets all custom data items for the Type info.
8002 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8003 ITypeInfo2 * iface,
8004 CUSTDATA *pCustData)
8006 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8008 TRACE("%p %p\n", This, pCustData);
8010 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
8013 /* ITypeInfo2::GetAllFuncCustData
8015 * Gets all custom data items for the specified Function
8018 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8019 ITypeInfo2 * iface,
8020 UINT index,
8021 CUSTDATA *pCustData)
8023 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8024 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8026 TRACE("%p %u %p\n", This, index, pCustData);
8028 if(index >= This->cFuncs)
8029 return TYPE_E_ELEMENTNOTFOUND;
8031 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8034 /* ITypeInfo2::GetAllParamCustData
8036 * Gets all custom data items for the Functions
8039 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8040 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8042 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8043 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8045 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8047 if(indexFunc >= This->cFuncs)
8048 return TYPE_E_ELEMENTNOTFOUND;
8050 if(indexParam >= pFDesc->funcdesc.cParams)
8051 return TYPE_E_ELEMENTNOTFOUND;
8053 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8056 /* ITypeInfo2::GetAllVarCustData
8058 * Gets all custom data items for the specified Variable
8061 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8062 UINT index, CUSTDATA *pCustData)
8064 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8065 TLBVarDesc * pVDesc = &This->vardescs[index];
8067 TRACE("%p %u %p\n", This, index, pCustData);
8069 if(index >= This->cVars)
8070 return TYPE_E_ELEMENTNOTFOUND;
8072 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8075 /* ITypeInfo2::GetAllImplCustData
8077 * Gets all custom data items for the specified implementation type
8080 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8081 ITypeInfo2 * iface,
8082 UINT index,
8083 CUSTDATA *pCustData)
8085 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8086 TLBImplType *pRDesc = &This->impltypes[index];
8088 TRACE("%p %u %p\n", This, index, pCustData);
8090 if(index >= This->cImplTypes)
8091 return TYPE_E_ELEMENTNOTFOUND;
8093 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8096 static const ITypeInfo2Vtbl tinfvt =
8099 ITypeInfo_fnQueryInterface,
8100 ITypeInfo_fnAddRef,
8101 ITypeInfo_fnRelease,
8103 ITypeInfo_fnGetTypeAttr,
8104 ITypeInfo_fnGetTypeComp,
8105 ITypeInfo_fnGetFuncDesc,
8106 ITypeInfo_fnGetVarDesc,
8107 ITypeInfo_fnGetNames,
8108 ITypeInfo_fnGetRefTypeOfImplType,
8109 ITypeInfo_fnGetImplTypeFlags,
8110 ITypeInfo_fnGetIDsOfNames,
8111 ITypeInfo_fnInvoke,
8112 ITypeInfo_fnGetDocumentation,
8113 ITypeInfo_fnGetDllEntry,
8114 ITypeInfo_fnGetRefTypeInfo,
8115 ITypeInfo_fnAddressOfMember,
8116 ITypeInfo_fnCreateInstance,
8117 ITypeInfo_fnGetMops,
8118 ITypeInfo_fnGetContainingTypeLib,
8119 ITypeInfo_fnReleaseTypeAttr,
8120 ITypeInfo_fnReleaseFuncDesc,
8121 ITypeInfo_fnReleaseVarDesc,
8123 ITypeInfo2_fnGetTypeKind,
8124 ITypeInfo2_fnGetTypeFlags,
8125 ITypeInfo2_fnGetFuncIndexOfMemId,
8126 ITypeInfo2_fnGetVarIndexOfMemId,
8127 ITypeInfo2_fnGetCustData,
8128 ITypeInfo2_fnGetFuncCustData,
8129 ITypeInfo2_fnGetParamCustData,
8130 ITypeInfo2_fnGetVarCustData,
8131 ITypeInfo2_fnGetImplTypeCustData,
8132 ITypeInfo2_fnGetDocumentation2,
8133 ITypeInfo2_fnGetAllCustData,
8134 ITypeInfo2_fnGetAllFuncCustData,
8135 ITypeInfo2_fnGetAllParamCustData,
8136 ITypeInfo2_fnGetAllVarCustData,
8137 ITypeInfo2_fnGetAllImplTypeCustData,
8140 /******************************************************************************
8141 * CreateDispTypeInfo [OLEAUT32.31]
8143 * Build type information for an object so it can be called through an
8144 * IDispatch interface.
8146 * RETURNS
8147 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8148 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8150 * NOTES
8151 * This call allows an objects methods to be accessed through IDispatch, by
8152 * building an ITypeInfo object that IDispatch can use to call through.
8154 HRESULT WINAPI CreateDispTypeInfo(
8155 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8156 LCID lcid, /* [I] Locale Id */
8157 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8159 ITypeInfoImpl *pTIClass, *pTIIface;
8160 ITypeLibImpl *pTypeLibImpl;
8161 unsigned int param, func;
8162 TLBFuncDesc *pFuncDesc;
8163 TLBRefType *ref;
8165 TRACE("\n");
8166 pTypeLibImpl = TypeLibImpl_Constructor();
8167 if (!pTypeLibImpl) return E_FAIL;
8169 pTypeLibImpl->TypeInfoCount = 2;
8170 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8172 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8173 pTIIface->pTypeLib = pTypeLibImpl;
8174 pTIIface->index = 0;
8175 pTIIface->Name = NULL;
8176 pTIIface->dwHelpContext = -1;
8177 pTIIface->guid = NULL;
8178 pTIIface->lcid = lcid;
8179 pTIIface->typekind = TKIND_INTERFACE;
8180 pTIIface->wMajorVerNum = 0;
8181 pTIIface->wMinorVerNum = 0;
8182 pTIIface->cbAlignment = 2;
8183 pTIIface->cbSizeInstance = -1;
8184 pTIIface->cbSizeVft = -1;
8185 pTIIface->cFuncs = 0;
8186 pTIIface->cImplTypes = 0;
8187 pTIIface->cVars = 0;
8188 pTIIface->wTypeFlags = 0;
8189 pTIIface->hreftype = 0;
8191 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8192 pFuncDesc = pTIIface->funcdescs;
8193 for(func = 0; func < pidata->cMembers; func++) {
8194 METHODDATA *md = pidata->pmethdata + func;
8195 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8196 pFuncDesc->funcdesc.memid = md->dispid;
8197 pFuncDesc->funcdesc.lprgscode = NULL;
8198 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8199 pFuncDesc->funcdesc.invkind = md->wFlags;
8200 pFuncDesc->funcdesc.callconv = md->cc;
8201 pFuncDesc->funcdesc.cParams = md->cArgs;
8202 pFuncDesc->funcdesc.cParamsOpt = 0;
8203 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8204 pFuncDesc->funcdesc.cScodes = 0;
8205 pFuncDesc->funcdesc.wFuncFlags = 0;
8206 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8207 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8208 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8209 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8210 md->cArgs * sizeof(ELEMDESC));
8211 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8212 for(param = 0; param < md->cArgs; param++) {
8213 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8214 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8216 pFuncDesc->helpcontext = 0;
8217 pFuncDesc->HelpStringContext = 0;
8218 pFuncDesc->HelpString = NULL;
8219 pFuncDesc->Entry = NULL;
8220 list_init(&pFuncDesc->custdata_list);
8221 pTIIface->cFuncs++;
8222 ++pFuncDesc;
8225 dump_TypeInfo(pTIIface);
8227 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8228 pTIClass->pTypeLib = pTypeLibImpl;
8229 pTIClass->index = 1;
8230 pTIClass->Name = NULL;
8231 pTIClass->dwHelpContext = -1;
8232 pTIClass->guid = NULL;
8233 pTIClass->lcid = lcid;
8234 pTIClass->typekind = TKIND_COCLASS;
8235 pTIClass->wMajorVerNum = 0;
8236 pTIClass->wMinorVerNum = 0;
8237 pTIClass->cbAlignment = 2;
8238 pTIClass->cbSizeInstance = -1;
8239 pTIClass->cbSizeVft = -1;
8240 pTIClass->cFuncs = 0;
8241 pTIClass->cImplTypes = 1;
8242 pTIClass->cVars = 0;
8243 pTIClass->wTypeFlags = 0;
8244 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8246 pTIClass->impltypes = TLBImplType_Alloc(1);
8248 ref = heap_alloc_zero(sizeof(*ref));
8249 ref->pImpTLInfo = TLB_REF_INTERNAL;
8250 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8252 dump_TypeInfo(pTIClass);
8254 *pptinfo = (ITypeInfo*)pTIClass;
8256 ITypeInfo_AddRef(*pptinfo);
8257 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8259 return S_OK;
8263 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8265 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8267 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
8270 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8272 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8274 return ITypeInfo_AddRef((ITypeInfo *)This);
8277 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8279 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8281 return ITypeInfo_Release((ITypeInfo *)This);
8284 static HRESULT WINAPI ITypeComp_fnBind(
8285 ITypeComp * iface,
8286 OLECHAR * szName,
8287 ULONG lHash,
8288 WORD wFlags,
8289 ITypeInfo ** ppTInfo,
8290 DESCKIND * pDescKind,
8291 BINDPTR * pBindPtr)
8293 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8294 const TLBFuncDesc *pFDesc;
8295 const TLBVarDesc *pVDesc;
8296 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8297 UINT fdc;
8299 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8301 *pDescKind = DESCKIND_NONE;
8302 pBindPtr->lpfuncdesc = NULL;
8303 *ppTInfo = NULL;
8305 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8306 pFDesc = &This->funcdescs[fdc];
8307 if (!strcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8308 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8309 break;
8310 else
8311 /* name found, but wrong flags */
8312 hr = TYPE_E_TYPEMISMATCH;
8316 if (fdc < This->cFuncs)
8318 HRESULT hr = TLB_AllocAndInitFuncDesc(
8319 &pFDesc->funcdesc,
8320 &pBindPtr->lpfuncdesc,
8321 This->typekind == TKIND_DISPATCH);
8322 if (FAILED(hr))
8323 return hr;
8324 *pDescKind = DESCKIND_FUNCDESC;
8325 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8326 ITypeInfo_AddRef(*ppTInfo);
8327 return S_OK;
8328 } else {
8329 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8330 if(pVDesc){
8331 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8332 if (FAILED(hr))
8333 return hr;
8334 *pDescKind = DESCKIND_VARDESC;
8335 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8336 ITypeInfo_AddRef(*ppTInfo);
8337 return S_OK;
8340 /* FIXME: search each inherited interface, not just the first */
8341 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8342 /* recursive search */
8343 ITypeInfo *pTInfo;
8344 ITypeComp *pTComp;
8345 HRESULT hr;
8346 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8347 if (SUCCEEDED(hr))
8349 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8350 ITypeInfo_Release(pTInfo);
8352 if (SUCCEEDED(hr))
8354 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8355 ITypeComp_Release(pTComp);
8356 return hr;
8358 WARN("Could not search inherited interface!\n");
8360 if (hr == DISP_E_MEMBERNOTFOUND)
8361 hr = S_OK;
8362 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8363 return hr;
8366 static HRESULT WINAPI ITypeComp_fnBindType(
8367 ITypeComp * iface,
8368 OLECHAR * szName,
8369 ULONG lHash,
8370 ITypeInfo ** ppTInfo,
8371 ITypeComp ** ppTComp)
8373 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8375 /* strange behaviour (does nothing) but like the
8376 * original */
8378 if (!ppTInfo || !ppTComp)
8379 return E_POINTER;
8381 *ppTInfo = NULL;
8382 *ppTComp = NULL;
8384 return S_OK;
8387 static const ITypeCompVtbl tcompvt =
8390 ITypeComp_fnQueryInterface,
8391 ITypeComp_fnAddRef,
8392 ITypeComp_fnRelease,
8394 ITypeComp_fnBind,
8395 ITypeComp_fnBindType
8398 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8399 REFIID riid, void **object)
8401 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8403 return ITypeLib2_QueryInterface((ITypeLib2*)This, riid, object);
8406 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8408 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8410 return ITypeLib2_AddRef((ITypeLib2*)This);
8413 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8415 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8417 return ITypeLib2_Release((ITypeLib2*)This);
8420 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8421 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8423 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8424 ITypeInfoImpl *info;
8425 HRESULT hres;
8427 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8429 if (!ctinfo || !name)
8430 return E_INVALIDARG;
8432 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8433 if (info)
8434 return TYPE_E_NAMECONFLICT;
8436 if (This->typeinfos)
8437 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8438 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8439 else
8440 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8442 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8444 info->pTypeLib = This;
8445 info->Name = TLB_append_str(&This->name_list, name);
8446 info->index = This->TypeInfoCount;
8447 info->typekind = kind;
8448 info->cbAlignment = 4;
8450 switch(info->typekind) {
8451 case TKIND_ENUM:
8452 case TKIND_INTERFACE:
8453 case TKIND_DISPATCH:
8454 case TKIND_COCLASS:
8455 info->cbSizeInstance = 4;
8456 break;
8457 case TKIND_RECORD:
8458 case TKIND_UNION:
8459 info->cbSizeInstance = 0;
8460 break;
8461 case TKIND_MODULE:
8462 info->cbSizeInstance = 2;
8463 break;
8464 case TKIND_ALIAS:
8465 info->cbSizeInstance = -0x75;
8466 break;
8467 default:
8468 FIXME("unrecognized typekind %d\n", info->typekind);
8469 info->cbSizeInstance = 0xdeadbeef;
8470 break;
8473 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8474 &IID_ICreateTypeInfo, (void **)ctinfo);
8475 if (FAILED(hres)) {
8476 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8477 return hres;
8480 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8482 ++This->TypeInfoCount;
8484 return S_OK;
8487 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8488 LPOLESTR name)
8490 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8492 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8494 if (!name)
8495 return E_INVALIDARG;
8497 This->Name = TLB_append_str(&This->name_list, name);
8499 return S_OK;
8502 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8503 WORD majorVerNum, WORD minorVerNum)
8505 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8507 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8509 This->ver_major = majorVerNum;
8510 This->ver_minor = minorVerNum;
8512 return S_OK;
8515 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8516 REFGUID guid)
8518 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8520 TRACE("%p %s\n", This, debugstr_guid(guid));
8522 This->guid = TLB_append_guid(&This->guid_list, guid);
8524 return S_OK;
8527 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8528 LPOLESTR doc)
8530 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8532 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8534 if (!doc)
8535 return E_INVALIDARG;
8537 This->DocString = TLB_append_str(&This->string_list, doc);
8539 return S_OK;
8542 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8543 LPOLESTR helpFileName)
8545 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8547 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8549 if (!helpFileName)
8550 return E_INVALIDARG;
8552 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8554 return S_OK;
8557 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8558 DWORD helpContext)
8560 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8562 TRACE("%p %d\n", This, helpContext);
8564 This->dwHelpContext = helpContext;
8566 return S_OK;
8569 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8570 LCID lcid)
8572 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8574 TRACE("%p %x\n", This, lcid);
8576 This->set_lcid = lcid;
8578 return S_OK;
8581 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8582 UINT libFlags)
8584 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8586 TRACE("%p %x\n", This, libFlags);
8588 This->libflags = libFlags;
8590 return S_OK;
8593 typedef struct tagWMSFT_SegContents {
8594 DWORD len;
8595 void *data;
8596 } WMSFT_SegContents;
8598 typedef struct tagWMSFT_TLBFile {
8599 MSFT_Header header;
8600 WMSFT_SegContents typeinfo_seg;
8601 WMSFT_SegContents impfile_seg;
8602 WMSFT_SegContents impinfo_seg;
8603 WMSFT_SegContents ref_seg;
8604 WMSFT_SegContents lib_seg;
8605 WMSFT_SegContents guid_seg;
8606 WMSFT_SegContents res07_seg;
8607 WMSFT_SegContents name_seg;
8608 WMSFT_SegContents string_seg;
8609 WMSFT_SegContents typdesc_seg;
8610 WMSFT_SegContents arraydesc_seg;
8611 WMSFT_SegContents custdata_seg;
8612 WMSFT_SegContents cdguids_seg;
8613 MSFT_SegDir segdir;
8614 WMSFT_SegContents aux_seg;
8615 } WMSFT_TLBFile;
8617 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8618 WMSFT_TLBFile *file)
8620 TLBString *str;
8621 UINT last_offs;
8622 char *data;
8624 file->string_seg.len = 0;
8625 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8626 int size;
8628 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8629 if (size == 0)
8630 return E_UNEXPECTED;
8632 size += sizeof(INT16);
8633 if (size % 4)
8634 size = (size + 4) & ~0x3;
8635 if (size < 8)
8636 size = 8;
8638 file->string_seg.len += size;
8640 /* temporarily use str->offset to store the length of the aligned,
8641 * converted string */
8642 str->offset = size;
8645 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8647 last_offs = 0;
8648 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8649 int size;
8651 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8652 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8653 if (size == 0) {
8654 heap_free(file->string_seg.data);
8655 return E_UNEXPECTED;
8658 *((INT16*)data) = size;
8660 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8662 size = str->offset;
8663 data += size;
8664 str->offset = last_offs;
8665 last_offs += size;
8668 return S_OK;
8671 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8672 WMSFT_TLBFile *file)
8674 TLBString *str;
8675 UINT last_offs;
8676 char *data;
8677 MSFT_NameIntro *last_intro = NULL;
8679 file->header.nametablecount = 0;
8680 file->header.nametablechars = 0;
8682 file->name_seg.len = 0;
8683 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8684 int size;
8686 size = strlenW(str->str);
8687 file->header.nametablechars += size;
8688 file->header.nametablecount++;
8690 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8691 if (size == 0)
8692 return E_UNEXPECTED;
8694 size += sizeof(MSFT_NameIntro);
8695 if (size % 4)
8696 size = (size + 4) & ~0x3;
8697 if (size < 8)
8698 size = 8;
8700 file->name_seg.len += size;
8702 /* temporarily use str->offset to store the length of the aligned,
8703 * converted string */
8704 str->offset = size;
8707 file->name_seg.data = data = heap_alloc(file->name_seg.len);
8709 last_offs = 0;
8710 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8711 int size;
8712 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8714 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8715 data + sizeof(MSFT_NameIntro),
8716 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8717 if (size == 0) {
8718 heap_free(file->name_seg.data);
8719 return E_UNEXPECTED;
8721 data[sizeof(MSFT_NameIntro) + size] = '\0';
8723 intro->hreftype = -1; /* TODO? */
8724 intro->next_hash = -1;
8725 intro->namelen = size & 0xFF;
8726 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8727 intro->namelen |= LHashValOfNameSysA(This->syskind,
8728 This->lcid, data + sizeof(MSFT_NameIntro)) << 16;
8730 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8731 str->offset - size - sizeof(MSFT_NameIntro));
8733 /* update str->offset to actual value to use in other
8734 * compilation functions that require positions within
8735 * the string table */
8736 last_intro = intro;
8737 size = str->offset;
8738 data += size;
8739 str->offset = last_offs;
8740 last_offs += size;
8743 if(last_intro)
8744 last_intro->hreftype = 0; /* last one is 0? */
8746 return S_OK;
8749 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8751 TLBGuid *guid;
8752 MSFT_GuidEntry *entry;
8753 DWORD offs;
8755 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8756 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8758 entry = file->guid_seg.data;
8759 offs = 0;
8760 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
8761 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
8762 entry->hreftype = 0xFFFFFFFF; /* TODO */
8763 entry->next_hash = 0xFFFFFFFF; /* TODO? */
8765 guid->offset = offs;
8767 offs += sizeof(MSFT_GuidEntry);
8768 ++entry;
8771 --entry;
8772 entry->next_hash = 0; /* last one has 0? */
8774 return S_OK;
8777 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
8779 VARIANT v = *value;
8780 VARTYPE arg_type = V_VT(value);
8781 int mask = 0;
8782 HRESULT hres;
8783 DWORD ret = file->custdata_seg.len;
8785 if(arg_type == VT_INT)
8786 arg_type = VT_I4;
8787 if(arg_type == VT_UINT)
8788 arg_type = VT_UI4;
8790 v = *value;
8791 if(V_VT(value) != arg_type) {
8792 hres = VariantChangeType(&v, value, 0, arg_type);
8793 if(FAILED(hres)){
8794 ERR("VariantChangeType failed: %08x\n", hres);
8795 return -1;
8799 /* Check if default value can be stored in-place */
8800 switch(arg_type){
8801 case VT_I4:
8802 case VT_UI4:
8803 mask = 0x3ffffff;
8804 if(V_UI4(&v) > 0x3ffffff)
8805 break;
8806 /* fall through */
8807 case VT_I1:
8808 case VT_UI1:
8809 case VT_BOOL:
8810 if(!mask)
8811 mask = 0xff;
8812 /* fall through */
8813 case VT_I2:
8814 case VT_UI2:
8815 if(!mask)
8816 mask = 0xffff;
8817 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
8820 /* have to allocate space in custdata_seg */
8821 switch(arg_type) {
8822 case VT_I4:
8823 case VT_R4:
8824 case VT_UI4:
8825 case VT_INT:
8826 case VT_UINT:
8827 case VT_HRESULT:
8828 case VT_PTR: {
8829 /* Construct the data to be allocated */
8830 int *data;
8832 if(file->custdata_seg.data){
8833 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
8834 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
8835 file->custdata_seg.len += sizeof(int) * 2;
8836 }else{
8837 file->custdata_seg.len = sizeof(int) * 2;
8838 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8841 data[0] = V_VT(value) + (V_UI4(&v) << 16);
8842 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
8844 /* TODO: Check if the encoded data is already present in custdata_seg */
8846 return ret;
8849 case VT_BSTR: {
8850 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
8851 char *data;
8853 if(file->custdata_seg.data){
8854 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
8855 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
8856 file->custdata_seg.len += len;
8857 }else{
8858 file->custdata_seg.len = len;
8859 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8862 *((unsigned short *)data) = V_VT(value);
8863 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
8864 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
8865 if(V_BSTR(&v)[i] <= 0x7f)
8866 data[i+6] = V_BSTR(&v)[i];
8867 else
8868 data[i+6] = '?';
8870 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
8871 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
8872 data[i] = 0x57;
8874 /* TODO: Check if the encoded data is already present in custdata_seg */
8876 return ret;
8878 default:
8879 FIXME("Argument type not yet handled\n");
8880 return -1;
8884 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
8886 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
8888 DWORD offs = file->arraydesc_seg.len;
8889 DWORD *encoded;
8890 USHORT i;
8892 /* TODO: we should check for duplicates, but that's harder because each
8893 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8894 * at the library-level) */
8896 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
8897 if(!file->arraydesc_seg.data)
8898 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
8899 else
8900 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
8901 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
8903 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
8904 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
8905 for(i = 0; i < desc->cDims; ++i){
8906 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
8907 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
8910 return offs;
8913 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
8915 DWORD junk;
8916 INT16 junk2;
8917 DWORD offs = 0;
8918 DWORD encoded[2];
8919 VARTYPE vt = desc->vt & VT_TYPEMASK, subtype;
8920 char *data;
8922 if(!out_mix)
8923 out_mix = &junk;
8924 if(!out_size)
8925 out_size = &junk2;
8927 switch(vt){
8928 case VT_INT:
8929 subtype = VT_I4;
8930 break;
8931 case VT_UINT:
8932 subtype = VT_UI4;
8933 break;
8934 case VT_VOID:
8935 subtype = VT_EMPTY;
8936 break;
8937 default:
8938 subtype = vt;
8939 break;
8942 switch(vt){
8943 case VT_INT:
8944 case VT_UINT:
8945 case VT_I1:
8946 case VT_UI1:
8947 case VT_I2:
8948 case VT_UI2:
8949 case VT_I4:
8950 case VT_UI4:
8951 case VT_BOOL:
8952 case VT_R4:
8953 case VT_ERROR:
8954 case VT_BSTR:
8955 case VT_HRESULT:
8956 case VT_CY:
8957 case VT_VOID:
8958 case VT_VARIANT:
8959 *out_mix = subtype;
8960 return 0x80000000 | (subtype << 16) | desc->vt;
8963 if(vt == VT_PTR || vt == VT_SAFEARRAY){
8964 DWORD mix;
8965 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
8966 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
8967 *out_mix = 0x7FFF;
8968 *out_size += 2 * sizeof(DWORD);
8969 }else if(vt == VT_CARRAY){
8970 encoded[0] = desc->vt | (0x7FFE << 16);
8971 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
8972 *out_mix = 0x7FFE;
8973 }else if(vt == VT_USERDEFINED){
8974 encoded[0] = desc->vt | (0x7FFF << 16);
8975 encoded[1] = desc->u.hreftype;
8976 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
8977 }else{
8978 FIXME("Don't know what to do! VT: 0x%x\n", desc->vt);
8979 *out_mix = desc->vt;
8980 return 0x80000000 | (desc->vt << 16) | desc->vt;
8983 data = file->typdesc_seg.data;
8984 while(offs < file->typdesc_seg.len){
8985 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
8986 return offs;
8987 offs += sizeof(encoded);
8990 file->typdesc_seg.len += sizeof(encoded);
8991 if(!file->typdesc_seg.data)
8992 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
8993 else
8994 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
8996 memcpy(&data[offs], encoded, sizeof(encoded));
8998 return offs;
9001 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9003 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9004 DWORD ret = cdguids_seg->len, offs;
9005 MSFT_CDGuid *cdguid = cdguids_seg->data;
9006 TLBCustData *cd;
9008 if(list_empty(custdata_list))
9009 return -1;
9011 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9012 if(!cdguids_seg->data){
9013 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9014 }else
9015 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9017 offs = ret + sizeof(MSFT_CDGuid);
9018 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9019 cdguid->GuidOffset = cd->guid->offset;
9020 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9021 cdguid->next = offs;
9022 offs += sizeof(MSFT_CDGuid);
9023 ++cdguid;
9026 --cdguid;
9027 cdguid->next = -1;
9029 return ret;
9032 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9033 WMSFT_TLBFile *file)
9035 WMSFT_SegContents *aux_seg = &file->aux_seg;
9036 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9037 MSFT_VarRecord *varrecord;
9038 MSFT_FuncRecord *funcrecord;
9039 MEMBERID *memid;
9040 DWORD *name, *offsets, offs;
9042 for(i = 0; i < info->cFuncs; ++i){
9043 TLBFuncDesc *desc = &info->funcdescs[i];
9045 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9047 /* optional fields */
9048 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9049 if(!list_empty(&desc->custdata_list))
9050 recorded_size += 7 * sizeof(INT);
9051 else if(desc->HelpStringContext != 0)
9052 recorded_size += 6 * sizeof(INT);
9053 /* res9? resA? */
9054 else if(desc->Entry)
9055 recorded_size += 3 * sizeof(INT);
9056 else if(desc->HelpString)
9057 recorded_size += 2 * sizeof(INT);
9058 else if(desc->helpcontext)
9059 recorded_size += sizeof(INT);
9061 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9063 for(j = 0; j < desc->funcdesc.cParams; ++j){
9064 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9065 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9066 break;
9070 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9073 for(i = 0; i < info->cVars; ++i){
9074 TLBVarDesc *desc = &info->vardescs[i];
9076 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9078 /* optional fields */
9079 if(desc->HelpStringContext != 0)
9080 recorded_size += 5 * sizeof(INT);
9081 else if(!list_empty(&desc->custdata_list))
9082 recorded_size += 4 * sizeof(INT);
9083 /* res9? */
9084 else if(desc->HelpString)
9085 recorded_size += 2 * sizeof(INT);
9086 else if(desc->HelpContext != 0)
9087 recorded_size += sizeof(INT);
9089 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9092 if(!recorded_size && !extra_size)
9093 return ret;
9095 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9097 aux_seg->len += recorded_size + extra_size;
9099 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9101 if(aux_seg->data)
9102 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9103 else
9104 aux_seg->data = heap_alloc(aux_seg->len);
9106 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9108 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9109 offs = 0;
9111 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9112 for(i = 0; i < info->cFuncs; ++i){
9113 TLBFuncDesc *desc = &info->funcdescs[i];
9114 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9116 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9117 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9118 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9119 funcrecord->VtableOffset = desc->funcdesc.oVft;
9121 /* FKCCIC:
9122 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9123 * ^^^funckind
9124 * ^^^ ^invkind
9125 * ^has_cust_data
9126 * ^^^^callconv
9127 * ^has_param_defaults
9128 * ^oEntry_is_intresource
9130 funcrecord->FKCCIC =
9131 desc->funcdesc.funckind |
9132 (desc->funcdesc.invkind << 3) |
9133 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9134 (desc->funcdesc.callconv << 8);
9136 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9137 funcrecord->FKCCIC |= 0x2000;
9139 for(j = 0; j < desc->funcdesc.cParams; ++j){
9140 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9141 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9142 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9145 if(paramdefault_size > 0)
9146 funcrecord->FKCCIC |= 0x1000;
9148 funcrecord->nrargs = desc->funcdesc.cParams;
9149 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9151 /* optional fields */
9152 /* res9? resA? */
9153 if(!list_empty(&desc->custdata_list)){
9154 size += 7 * sizeof(INT);
9155 funcrecord->HelpContext = desc->helpcontext;
9156 if(desc->HelpString)
9157 funcrecord->oHelpString = desc->HelpString->offset;
9158 else
9159 funcrecord->oHelpString = -1;
9160 if(!desc->Entry)
9161 funcrecord->oEntry = -1;
9162 else if(IS_INTRESOURCE(desc->Entry))
9163 funcrecord->oEntry = LOWORD(desc->Entry);
9164 else
9165 funcrecord->oEntry = desc->Entry->offset;
9166 funcrecord->res9 = -1;
9167 funcrecord->resA = -1;
9168 funcrecord->HelpStringContext = desc->HelpStringContext;
9169 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9170 }else if(desc->HelpStringContext != 0){
9171 size += 6 * sizeof(INT);
9172 funcrecord->HelpContext = desc->helpcontext;
9173 if(desc->HelpString)
9174 funcrecord->oHelpString = desc->HelpString->offset;
9175 else
9176 funcrecord->oHelpString = -1;
9177 if(!desc->Entry)
9178 funcrecord->oEntry = -1;
9179 else if(IS_INTRESOURCE(desc->Entry))
9180 funcrecord->oEntry = LOWORD(desc->Entry);
9181 else
9182 funcrecord->oEntry = desc->Entry->offset;
9183 funcrecord->res9 = -1;
9184 funcrecord->resA = -1;
9185 funcrecord->HelpStringContext = desc->HelpStringContext;
9186 }else if(desc->Entry){
9187 size += 3 * sizeof(INT);
9188 funcrecord->HelpContext = desc->helpcontext;
9189 if(desc->HelpString)
9190 funcrecord->oHelpString = desc->HelpString->offset;
9191 else
9192 funcrecord->oHelpString = -1;
9193 if(!desc->Entry)
9194 funcrecord->oEntry = -1;
9195 else if(IS_INTRESOURCE(desc->Entry))
9196 funcrecord->oEntry = LOWORD(desc->Entry);
9197 else
9198 funcrecord->oEntry = desc->Entry->offset;
9199 }else if(desc->HelpString){
9200 size += 2 * sizeof(INT);
9201 funcrecord->HelpContext = desc->helpcontext;
9202 funcrecord->oHelpString = desc->HelpString->offset;
9203 }else if(desc->helpcontext){
9204 size += sizeof(INT);
9205 funcrecord->HelpContext = desc->helpcontext;
9208 paramdefault = (DWORD*)((char *)funcrecord + size);
9209 size += paramdefault_size;
9211 for(j = 0; j < desc->funcdesc.cParams; ++j){
9212 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9214 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9215 if(desc->pParamDesc[j].Name)
9216 info->oName = desc->pParamDesc[j].Name->offset;
9217 else
9218 info->oName = -1;
9219 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9221 if(paramdefault_size){
9222 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9223 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9224 else if(paramdefault_size)
9225 *paramdefault = -1;
9226 ++paramdefault;
9229 size += sizeof(MSFT_ParameterInfo);
9232 funcrecord->Info = size | (i << 16); /* is it just the index? */
9234 *offsets = offs;
9235 offs += size;
9236 ++offsets;
9238 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9241 varrecord = (MSFT_VarRecord*)funcrecord;
9242 for(i = 0; i < info->cVars; ++i){
9243 TLBVarDesc *desc = &info->vardescs[i];
9244 DWORD size = 5 * sizeof(INT);
9246 varrecord->vardescsize = sizeof(desc->vardesc);
9247 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9248 varrecord->Flags = desc->vardesc.wVarFlags;
9249 varrecord->VarKind = desc->vardesc.varkind;
9251 if(desc->vardesc.varkind == VAR_CONST){
9252 varrecord->vardescsize += sizeof(VARIANT);
9253 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9254 }else
9255 varrecord->OffsValue = desc->vardesc.u.oInst;
9257 /* res9? */
9258 if(desc->HelpStringContext != 0){
9259 size += 5 * sizeof(INT);
9260 varrecord->HelpContext = desc->HelpContext;
9261 if(desc->HelpString)
9262 varrecord->HelpString = desc->HelpString->offset;
9263 else
9264 varrecord->HelpString = -1;
9265 varrecord->res9 = -1;
9266 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9267 varrecord->HelpStringContext = desc->HelpStringContext;
9268 }else if(!list_empty(&desc->custdata_list)){
9269 size += 4 * sizeof(INT);
9270 varrecord->HelpContext = desc->HelpContext;
9271 if(desc->HelpString)
9272 varrecord->HelpString = desc->HelpString->offset;
9273 else
9274 varrecord->HelpString = -1;
9275 varrecord->res9 = -1;
9276 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9277 }else if(desc->HelpString){
9278 size += 2 * sizeof(INT);
9279 varrecord->HelpContext = desc->HelpContext;
9280 if(desc->HelpString)
9281 varrecord->HelpString = desc->HelpString->offset;
9282 else
9283 varrecord->HelpString = -1;
9284 }else if(desc->HelpContext != 0){
9285 size += sizeof(INT);
9286 varrecord->HelpContext = desc->HelpContext;
9289 varrecord->Info = size | (i << 16);
9291 *offsets = offs;
9292 offs += size;
9293 ++offsets;
9295 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9298 memid = (MEMBERID*)varrecord;
9299 for(i = 0; i < info->cFuncs; ++i){
9300 TLBFuncDesc *desc = &info->funcdescs[i];
9301 *memid = desc->funcdesc.memid;
9302 ++memid;
9304 for(i = 0; i < info->cVars; ++i){
9305 TLBVarDesc *desc = &info->vardescs[i];
9306 *memid = desc->vardesc.memid;
9307 ++memid;
9310 name = (UINT*)memid;
9311 for(i = 0; i < info->cFuncs; ++i){
9312 TLBFuncDesc *desc = &info->funcdescs[i];
9313 if(desc->Name)
9314 *name = desc->Name->offset;
9315 else
9316 *name = -1;
9317 ++name;
9319 for(i = 0; i < info->cVars; ++i){
9320 TLBVarDesc *desc = &info->vardescs[i];
9321 if(desc->Name)
9322 *name = desc->Name->offset;
9323 else
9324 *name = -1;
9325 ++name;
9328 return ret;
9331 typedef struct tagWMSFT_RefChunk {
9332 DWORD href;
9333 DWORD res04;
9334 DWORD res08;
9335 DWORD next;
9336 } WMSFT_RefChunk;
9338 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9340 DWORD offs = file->ref_seg.len, i;
9341 WMSFT_RefChunk *chunk;
9343 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9344 if(!file->ref_seg.data)
9345 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9346 else
9347 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9349 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9351 for(i = 0; i < info->cImplTypes; ++i){
9352 chunk->href = info->impltypes[i].hRef;
9353 chunk->res04 = info->impltypes[i].implflags;
9354 chunk->res08 = -1;
9355 if(i < info->cImplTypes - 1)
9356 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9357 else
9358 chunk->next = -1;
9359 ++chunk;
9362 return offs;
9365 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9367 DWORD size;
9369 size = sizeof(MSFT_TypeInfoBase);
9371 if(data){
9372 MSFT_TypeInfoBase *base = (void*)data;
9373 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9374 base->typekind = TKIND_DISPATCH;
9375 else
9376 base->typekind = info->typekind;
9377 base->typekind |= index << 16; /* TODO: There are some other flags here */
9378 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9379 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9380 base->res2 = 0;
9381 base->res3 = 0;
9382 base->res4 = 3;
9383 base->res5 = 0;
9384 base->cElement = (info->cVars << 16) | info->cFuncs;
9385 base->res7 = 0;
9386 base->res8 = 0;
9387 base->res9 = 0;
9388 base->resA = 0;
9389 if(info->guid)
9390 base->posguid = info->guid->offset;
9391 else
9392 base->posguid = -1;
9393 base->flags = info->wTypeFlags;
9394 if(info->Name)
9395 base->NameOffset = info->Name->offset;
9396 else
9397 base->NameOffset = -1;
9398 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9399 if(info->DocString)
9400 base->docstringoffs = info->DocString->offset;
9401 else
9402 base->docstringoffs = -1;
9403 base->helpstringcontext = info->dwHelpStringContext;
9404 base->helpcontext = info->dwHelpContext;
9405 base->oCustData = WMSFT_compile_custdata(&info->custdata_list, file);
9406 base->cImplTypes = info->cImplTypes;
9407 base->cbSizeVft = info->cbSizeVft;
9408 base->size = info->cbSizeInstance;
9409 if(info->typekind == TKIND_COCLASS){
9410 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9411 }else if(info->typekind == TKIND_ALIAS){
9412 base->datatype1 = WMSFT_append_typedesc(&info->tdescAlias, file, NULL, NULL);
9413 }else if(info->typekind == TKIND_MODULE){
9414 if(info->DllName)
9415 base->datatype1 = info->DllName->offset;
9416 else
9417 base->datatype1 = -1;
9418 }else{
9419 if(info->cImplTypes > 0)
9420 base->datatype1 = info->impltypes[0].hRef;
9421 else
9422 base->datatype1 = -1;
9424 base->datatype2 = index; /* FIXME: i think there's more here */
9425 base->res18 = 0;
9426 base->res19 = -1;
9429 return size;
9432 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9434 UINT i;
9436 file->typeinfo_seg.len = 0;
9437 for(i = 0; i < This->TypeInfoCount; ++i){
9438 ITypeInfoImpl *info = This->typeinfos[i];
9439 *junk = file->typeinfo_seg.len;
9440 ++junk;
9441 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9444 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9445 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9447 file->aux_seg.len = 0;
9448 file->aux_seg.data = NULL;
9450 file->typeinfo_seg.len = 0;
9451 for(i = 0; i < This->TypeInfoCount; ++i){
9452 ITypeInfoImpl *info = This->typeinfos[i];
9453 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9454 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9458 typedef struct tagWMSFT_ImpFile {
9459 INT guid_offs;
9460 LCID lcid;
9461 DWORD version;
9462 } WMSFT_ImpFile;
9464 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9466 TLBImpLib *implib;
9467 WMSFT_ImpFile *impfile;
9468 char *data;
9469 DWORD last_offs = 0;
9471 file->impfile_seg.len = 0;
9472 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9473 int size = 0;
9475 if(implib->name){
9476 WCHAR *path = strrchrW(implib->name, '\\');
9477 if(path)
9478 ++path;
9479 else
9480 path = implib->name;
9481 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9482 if (size == 0)
9483 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9486 size += sizeof(INT16);
9487 if (size % 4)
9488 size = (size + 4) & ~0x3;
9489 if (size < 8)
9490 size = 8;
9492 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9495 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9497 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9498 int strlen = 0, size;
9500 impfile = (WMSFT_ImpFile*)data;
9501 impfile->guid_offs = implib->guid->offset;
9502 impfile->lcid = implib->lcid;
9503 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9505 data += sizeof(WMSFT_ImpFile);
9507 if(implib->name){
9508 WCHAR *path= strrchrW(implib->name, '\\');
9509 if(path)
9510 ++path;
9511 else
9512 path = implib->name;
9513 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9514 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9515 if (strlen == 0)
9516 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9519 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9521 size = strlen + sizeof(INT16);
9522 if (size % 4)
9523 size = (size + 4) & ~0x3;
9524 if (size < 8)
9525 size = 8;
9526 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9528 data += size;
9529 implib->offset = last_offs;
9530 last_offs += size + sizeof(WMSFT_ImpFile);
9534 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9536 MSFT_ImpInfo *info;
9537 TLBRefType *ref_type;
9538 UINT i = 0;
9540 WMSFT_compile_impfile(This, file);
9542 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9543 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9545 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9546 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9547 if(ref_type->index == TLB_REF_USE_GUID){
9548 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9549 info->oGuid = ref_type->guid->offset;
9550 }else
9551 info->oGuid = ref_type->index;
9552 info->oImpFile = ref_type->pImpTLInfo->offset;
9553 ++i;
9554 ++info;
9558 static void WMSFT_compile_lib(ITypeLibImpl *This, WMSFT_TLBFile *file)
9560 /* TODO: What actually goes here? */
9561 file->lib_seg.len = 0x80;
9562 file->lib_seg.data = heap_alloc(file->lib_seg.len);
9563 memset(file->lib_seg.data, 0xFF, file->lib_seg.len);
9565 #if 0
9566 /* sometimes, first element is offset to last guid, for some reason */
9567 if(This->guid)
9568 *(DWORD*)file->lib_seg.data =
9569 (list_count(&This->guid_list) - 1) * sizeof(MSFT_GuidEntry);
9570 #endif
9573 static void WMSFT_compile_res07(ITypeLibImpl *This, WMSFT_TLBFile *file)
9575 /* TODO: What actually goes here?
9576 * Wild speculation:
9577 * It's something to do with the Name table (and string table?). When you
9578 * add a new name, the offset to that name from within the Name table gets
9579 * stuck somewhere in res07, apparently starting at the end of the segment
9580 * then moving backwards at a rate of 3 bytes per char in the Name. */
9581 file->res07_seg.len = 0x200;
9582 file->res07_seg.data = heap_alloc(file->res07_seg.len);
9583 memset(file->res07_seg.data, 0xFF, file->res07_seg.len);
9586 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9588 if(contents && contents->len){
9589 segdir->offset = *running_offset;
9590 segdir->length = contents->len;
9591 *running_offset += segdir->length;
9592 }else{
9593 segdir->offset = -1;
9594 segdir->length = 0;
9597 /* TODO: do these ever change? */
9598 segdir->res08 = -1;
9599 segdir->res0c = 0xf;
9602 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9604 DWORD written;
9605 if(segment)
9606 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9609 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9610 DWORD file_len)
9612 DWORD i;
9613 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9615 for(i = 0; i < This->TypeInfoCount; ++i){
9616 base->memoffset += file_len;
9617 ++base;
9620 return S_OK;
9623 static void WMSFT_free_file(WMSFT_TLBFile *file)
9625 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9626 HeapFree(GetProcessHeap(), 0, file->lib_seg.data);
9627 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9628 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9629 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9630 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9631 HeapFree(GetProcessHeap(), 0, file->res07_seg.data);
9632 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9633 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9634 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9635 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9636 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9637 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9638 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9641 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9643 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9644 WMSFT_TLBFile file;
9645 DWORD written, junk_size, junk_offs, running_offset;
9646 BOOL br;
9647 HANDLE outfile;
9648 HRESULT hres;
9649 DWORD *junk;
9651 TRACE("%p\n", This);
9653 memset(&file, 0, sizeof(file));
9655 file.header.magic1 = 0x5446534D;
9656 file.header.magic2 = 0x00010002;
9657 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9658 file.header.lcid2 = This->set_lcid;
9659 file.header.varflags = 0x41; /* TODO?? */
9660 if (This->HelpFile)
9661 file.header.varflags |= 0x10;
9662 if (This->HelpStringDll)
9663 file.header.varflags |= HELPDLLFLAG;
9664 file.header.version = (This->ver_major << 16) | This->ver_minor;
9665 file.header.flags = This->libflags;
9666 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9667 file.header.helpcontext = This->dwHelpContext;
9668 file.header.res44 = 0x20;
9669 file.header.res48 = 0x80;
9670 file.header.dispatchpos = This->dispatch_href;
9672 /* do name and string compilation to get offsets for other compilations */
9673 hres = WMSFT_compile_names(This, &file);
9674 if (FAILED(hres)){
9675 WMSFT_free_file(&file);
9676 return hres;
9679 hres = WMSFT_compile_strings(This, &file);
9680 if (FAILED(hres)){
9681 WMSFT_free_file(&file);
9682 return hres;
9685 hres = WMSFT_compile_guids(This, &file);
9686 if (FAILED(hres)){
9687 WMSFT_free_file(&file);
9688 return hres;
9691 if(This->HelpFile)
9692 file.header.helpfile = This->HelpFile->offset;
9693 else
9694 file.header.helpfile = -1;
9696 if(This->DocString)
9697 file.header.helpstring = This->DocString->offset;
9698 else
9699 file.header.helpstring = -1;
9701 /* do some more segment compilation */
9702 file.header.nimpinfos = list_count(&This->ref_list);
9703 file.header.nrtypeinfos = This->TypeInfoCount;
9705 if(This->Name)
9706 file.header.NameOffset = This->Name->offset;
9707 else
9708 file.header.NameOffset = -1;
9710 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9712 if(This->guid)
9713 file.header.posguid = This->guid->offset;
9714 else
9715 file.header.posguid = -1;
9717 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9718 if(file.header.varflags & HELPDLLFLAG)
9719 junk_size += sizeof(DWORD);
9720 if(junk_size){
9721 junk = heap_alloc_zero(junk_size);
9722 if(file.header.varflags & HELPDLLFLAG){
9723 *junk = This->HelpStringDll->offset;
9724 junk_offs = 1;
9725 }else
9726 junk_offs = 0;
9727 }else{
9728 junk = NULL;
9729 junk_offs = 0;
9732 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9733 WMSFT_compile_impinfo(This, &file);
9734 WMSFT_compile_lib(This, &file);
9735 WMSFT_compile_res07(This, &file);
9737 running_offset = 0;
9739 TRACE("header at: 0x%x\n", running_offset);
9740 running_offset += sizeof(file.header);
9742 TRACE("junk at: 0x%x\n", running_offset);
9743 running_offset += junk_size;
9745 TRACE("segdir at: 0x%x\n", running_offset);
9746 running_offset += sizeof(file.segdir);
9748 TRACE("typeinfo at: 0x%x\n", running_offset);
9749 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9751 TRACE("libtab at: 0x%x\n", running_offset);
9752 tmp_fill_segdir_seg(&file.segdir.pLibtab, &file.lib_seg, &running_offset);
9754 TRACE("guidtab at: 0x%x\n", running_offset);
9755 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9757 TRACE("reftab at: 0x%x\n", running_offset);
9758 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9760 TRACE("impinfo at: 0x%x\n", running_offset);
9761 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9763 TRACE("impfiles at: 0x%x\n", running_offset);
9764 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9766 TRACE("res07 at: 0x%x\n", running_offset);
9767 tmp_fill_segdir_seg(&file.segdir.res07, &file.res07_seg, &running_offset);
9769 TRACE("nametab at: 0x%x\n", running_offset);
9770 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9772 TRACE("stringtab at: 0x%x\n", running_offset);
9773 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9775 TRACE("typdesc at: 0x%x\n", running_offset);
9776 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9778 TRACE("arraydescriptions at: 0x%x\n", running_offset);
9779 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
9781 TRACE("custdata at: 0x%x\n", running_offset);
9782 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
9784 TRACE("cdguids at: 0x%x\n", running_offset);
9785 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
9787 TRACE("res0e at: 0x%x\n", running_offset);
9788 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
9790 TRACE("res0f at: 0x%x\n", running_offset);
9791 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
9793 TRACE("aux_seg at: 0x%x\n", running_offset);
9795 WMSFT_fixup_typeinfos(This, &file, running_offset);
9797 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
9798 FILE_ATTRIBUTE_NORMAL, 0);
9799 if (outfile == INVALID_HANDLE_VALUE){
9800 WMSFT_free_file(&file);
9801 return TYPE_E_IOERROR;
9804 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
9805 if (!br) {
9806 WMSFT_free_file(&file);
9807 CloseHandle(outfile);
9808 return TYPE_E_IOERROR;
9811 br = WriteFile(outfile, junk, junk_size, &written, NULL);
9812 if (!br) {
9813 WMSFT_free_file(&file);
9814 CloseHandle(outfile);
9815 return TYPE_E_IOERROR;
9818 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
9819 if (!br) {
9820 WMSFT_free_file(&file);
9821 CloseHandle(outfile);
9822 return TYPE_E_IOERROR;
9825 WMSFT_write_segment(outfile, &file.typeinfo_seg);
9826 WMSFT_write_segment(outfile, &file.lib_seg);
9827 WMSFT_write_segment(outfile, &file.guid_seg);
9828 WMSFT_write_segment(outfile, &file.ref_seg);
9829 WMSFT_write_segment(outfile, &file.impinfo_seg);
9830 WMSFT_write_segment(outfile, &file.impfile_seg);
9831 WMSFT_write_segment(outfile, &file.res07_seg);
9832 WMSFT_write_segment(outfile, &file.name_seg);
9833 WMSFT_write_segment(outfile, &file.string_seg);
9834 WMSFT_write_segment(outfile, &file.typdesc_seg);
9835 WMSFT_write_segment(outfile, &file.arraydesc_seg);
9836 WMSFT_write_segment(outfile, &file.custdata_seg);
9837 WMSFT_write_segment(outfile, &file.cdguids_seg);
9838 WMSFT_write_segment(outfile, &file.aux_seg);
9840 WMSFT_free_file(&file);
9842 CloseHandle(outfile);
9844 return S_OK;
9847 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
9848 LPOLESTR name)
9850 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9851 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
9852 return E_NOTIMPL;
9855 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
9856 REFGUID guid, VARIANT *varVal)
9858 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9859 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
9860 return E_NOTIMPL;
9863 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
9864 ULONG helpStringContext)
9866 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9867 FIXME("%p %u - stub\n", This, helpStringContext);
9868 return E_NOTIMPL;
9871 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
9872 LPOLESTR filename)
9874 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9875 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
9877 if (!filename)
9878 return E_INVALIDARG;
9880 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
9882 return S_OK;
9885 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
9886 ICreateTypeLib2_fnQueryInterface,
9887 ICreateTypeLib2_fnAddRef,
9888 ICreateTypeLib2_fnRelease,
9889 ICreateTypeLib2_fnCreateTypeInfo,
9890 ICreateTypeLib2_fnSetName,
9891 ICreateTypeLib2_fnSetVersion,
9892 ICreateTypeLib2_fnSetGuid,
9893 ICreateTypeLib2_fnSetDocString,
9894 ICreateTypeLib2_fnSetHelpFileName,
9895 ICreateTypeLib2_fnSetHelpContext,
9896 ICreateTypeLib2_fnSetLcid,
9897 ICreateTypeLib2_fnSetLibFlags,
9898 ICreateTypeLib2_fnSaveAllChanges,
9899 ICreateTypeLib2_fnDeleteTypeInfo,
9900 ICreateTypeLib2_fnSetCustData,
9901 ICreateTypeLib2_fnSetHelpStringContext,
9902 ICreateTypeLib2_fnSetHelpStringDll
9905 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
9906 REFIID riid, void **object)
9908 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9910 return ITypeInfo2_QueryInterface((ITypeInfo2*)This, riid, object);
9913 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
9915 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9917 return ITypeInfo2_AddRef((ITypeInfo2*)This);
9920 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
9922 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9924 return ITypeInfo2_Release((ITypeInfo2*)This);
9927 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
9928 REFGUID guid)
9930 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9932 TRACE("%p %s\n", This, debugstr_guid(guid));
9934 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
9936 return S_OK;
9939 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
9940 UINT typeFlags)
9942 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9943 WORD old_flags;
9944 HRESULT hres;
9946 TRACE("%p %x\n", This, typeFlags);
9948 if (typeFlags & TYPEFLAG_FDUAL) {
9949 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9950 ITypeLib *stdole;
9951 ITypeInfo *dispatch;
9952 HREFTYPE hreftype;
9953 HRESULT hres;
9955 hres = LoadTypeLib(stdole2tlb, &stdole);
9956 if(FAILED(hres))
9957 return hres;
9959 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
9960 ITypeLib_Release(stdole);
9961 if(FAILED(hres))
9962 return hres;
9964 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
9965 ITypeInfo_Release(dispatch);
9966 if(FAILED(hres))
9967 return hres;
9970 old_flags = This->wTypeFlags;
9971 This->wTypeFlags = typeFlags;
9973 hres = ICreateTypeInfo2_LayOut(iface);
9974 if (FAILED(hres)) {
9975 This->wTypeFlags = old_flags;
9976 return hres;
9979 return S_OK;
9982 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
9983 LPOLESTR doc)
9985 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9987 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9989 if (!doc)
9990 return E_INVALIDARG;
9992 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
9994 return S_OK;
9997 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
9998 DWORD helpContext)
10000 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10002 TRACE("%p %d\n", This, helpContext);
10004 This->dwHelpContext = helpContext;
10006 return S_OK;
10009 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10010 WORD majorVerNum, WORD minorVerNum)
10012 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10014 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10016 This->wMajorVerNum = majorVerNum;
10017 This->wMinorVerNum = minorVerNum;
10019 return S_OK;
10022 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10023 ITypeInfo *typeInfo, HREFTYPE *refType)
10025 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10026 UINT index;
10027 ITypeLib *container;
10028 TLBRefType *ref_type;
10029 TLBImpLib *implib;
10030 TYPEATTR *typeattr;
10031 TLIBATTR *libattr;
10032 HRESULT hres;
10034 TRACE("%p %p %p\n", This, typeInfo, refType);
10036 if (!typeInfo || !refType)
10037 return E_INVALIDARG;
10039 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10040 if (FAILED(hres))
10041 return hres;
10043 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10044 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10046 ITypeLib_Release(container);
10048 *refType = target->hreftype;
10050 return S_OK;
10053 hres = ITypeLib_GetLibAttr(container, &libattr);
10054 if (FAILED(hres)) {
10055 ITypeLib_Release(container);
10056 return hres;
10059 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10060 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10061 implib->lcid == libattr->lcid &&
10062 implib->wVersionMajor == libattr->wMajorVerNum &&
10063 implib->wVersionMinor == libattr->wMinorVerNum)
10064 break;
10067 if(&implib->entry == &This->pTypeLib->implib_list){
10068 implib = heap_alloc_zero(sizeof(TLBImpLib));
10070 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10071 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10072 implib->name = SysAllocString(our_container->path);
10073 }else{
10074 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10075 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10076 if(FAILED(hres)){
10077 implib->name = NULL;
10078 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10082 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid);
10083 implib->lcid = libattr->lcid;
10084 implib->wVersionMajor = libattr->wMajorVerNum;
10085 implib->wVersionMinor = libattr->wMinorVerNum;
10087 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10090 ITypeLib_ReleaseTLibAttr(container, libattr);
10091 ITypeLib_Release(container);
10093 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10094 if (FAILED(hres))
10095 return hres;
10097 index = 0;
10098 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10099 if(ref_type->index == TLB_REF_USE_GUID &&
10100 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10101 ref_type->tkind == typeattr->typekind)
10102 break;
10103 ++index;
10106 if(&ref_type->entry == &This->pTypeLib->ref_list){
10107 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10109 ref_type->tkind = typeattr->typekind;
10110 ref_type->pImpTLInfo = implib;
10111 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10113 ref_type->index = TLB_REF_USE_GUID;
10115 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid);
10117 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10120 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10122 *refType = ref_type->reference | 0x1;
10124 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10125 This->pTypeLib->dispatch_href = *refType;
10127 return S_OK;
10130 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10131 UINT index, FUNCDESC *funcDesc)
10133 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10134 TLBFuncDesc tmp_func_desc, *func_desc;
10135 int buf_size, i;
10136 char *buffer;
10137 HRESULT hres;
10139 TRACE("%p %u %p\n", This, index, funcDesc);
10141 if (!funcDesc || funcDesc->oVft & 3)
10142 return E_INVALIDARG;
10144 switch (This->typekind) {
10145 case TKIND_MODULE:
10146 if (funcDesc->funckind != FUNC_STATIC)
10147 return TYPE_E_BADMODULEKIND;
10148 break;
10149 case TKIND_DISPATCH:
10150 if (funcDesc->funckind != FUNC_DISPATCH)
10151 return TYPE_E_BADMODULEKIND;
10152 break;
10153 default:
10154 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10155 return TYPE_E_BADMODULEKIND;
10158 if (index > This->cFuncs)
10159 return TYPE_E_ELEMENTNOTFOUND;
10161 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10162 !funcDesc->cParams)
10163 return TYPE_E_INCONSISTENTPROPFUNCS;
10165 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10166 TLBFuncDesc_Constructor(&tmp_func_desc);
10168 tmp_func_desc.funcdesc = *funcDesc;
10170 if (tmp_func_desc.funcdesc.oVft != 0)
10171 tmp_func_desc.funcdesc.oVft |= 1;
10173 if (funcDesc->cScodes) {
10174 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10175 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10176 } else
10177 tmp_func_desc.funcdesc.lprgscode = NULL;
10179 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10180 for (i = 0; i < funcDesc->cParams; ++i) {
10181 buf_size += sizeof(ELEMDESC);
10182 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10184 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10185 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10187 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10188 if (FAILED(hres)) {
10189 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10190 heap_free(tmp_func_desc.funcdesc.lprgscode);
10191 return hres;
10194 for (i = 0; i < funcDesc->cParams; ++i) {
10195 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10196 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10197 if (FAILED(hres)) {
10198 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10199 heap_free(tmp_func_desc.funcdesc.lprgscode);
10200 return hres;
10202 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10203 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10204 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10205 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10206 if (FAILED(hres)) {
10207 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10208 heap_free(tmp_func_desc.funcdesc.lprgscode);
10209 return hres;
10214 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10216 if (This->funcdescs) {
10217 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10218 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10220 if (index < This->cFuncs) {
10221 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10222 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10223 func_desc = This->funcdescs + index;
10224 } else
10225 func_desc = This->funcdescs + This->cFuncs;
10227 /* move custdata lists to the new memory location */
10228 for(i = 0; i < This->cFuncs + 1; ++i){
10229 if(index != i){
10230 TLBFuncDesc *fd = &This->funcdescs[i];
10231 if(fd->custdata_list.prev == fd->custdata_list.next)
10232 list_init(&fd->custdata_list);
10233 else{
10234 fd->custdata_list.prev->next = &fd->custdata_list;
10235 fd->custdata_list.next->prev = &fd->custdata_list;
10239 } else
10240 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10242 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10243 list_init(&func_desc->custdata_list);
10245 ++This->cFuncs;
10247 This->needs_layout = TRUE;
10249 return S_OK;
10252 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10253 UINT index, HREFTYPE refType)
10255 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10256 TLBImplType *impl_type;
10257 HRESULT hres;
10259 TRACE("%p %u %d\n", This, index, refType);
10261 switch(This->typekind){
10262 case TKIND_COCLASS: {
10263 if (index == -1) {
10264 FIXME("Unhandled index: -1\n");
10265 return E_NOTIMPL;
10268 if(index != This->cImplTypes)
10269 return TYPE_E_ELEMENTNOTFOUND;
10271 break;
10273 case TKIND_INTERFACE:
10274 case TKIND_DISPATCH:
10275 if (index != 0 || This->cImplTypes)
10276 return TYPE_E_ELEMENTNOTFOUND;
10277 break;
10278 default:
10279 FIXME("Unimplemented typekind: %d\n", This->typekind);
10280 return E_NOTIMPL;
10283 if (This->impltypes){
10284 UINT i;
10286 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10287 sizeof(TLBImplType) * (This->cImplTypes + 1));
10289 if (index < This->cImplTypes) {
10290 memmove(This->impltypes + index + 1, This->impltypes + index,
10291 (This->cImplTypes - index) * sizeof(TLBImplType));
10292 impl_type = This->impltypes + index;
10293 } else
10294 impl_type = This->impltypes + This->cImplTypes;
10296 /* move custdata lists to the new memory location */
10297 for(i = 0; i < This->cImplTypes + 1; ++i){
10298 if(index != i){
10299 TLBImplType *it = &This->impltypes[i];
10300 if(it->custdata_list.prev == it->custdata_list.next)
10301 list_init(&it->custdata_list);
10302 else{
10303 it->custdata_list.prev->next = &it->custdata_list;
10304 it->custdata_list.next->prev = &it->custdata_list;
10308 } else
10309 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10311 memset(impl_type, 0, sizeof(TLBImplType));
10312 TLBImplType_Constructor(impl_type);
10313 impl_type->hRef = refType;
10315 ++This->cImplTypes;
10317 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10318 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10320 hres = ICreateTypeInfo2_LayOut(iface);
10321 if (FAILED(hres))
10322 return hres;
10324 return S_OK;
10327 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10328 UINT index, INT implTypeFlags)
10330 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10331 TLBImplType *impl_type = &This->impltypes[index];
10333 TRACE("%p %u %x\n", This, index, implTypeFlags);
10335 if (This->typekind != TKIND_COCLASS)
10336 return TYPE_E_BADMODULEKIND;
10338 if (index >= This->cImplTypes)
10339 return TYPE_E_ELEMENTNOTFOUND;
10341 impl_type->implflags = implTypeFlags;
10343 return S_OK;
10346 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10347 WORD alignment)
10349 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10351 TRACE("%p %d\n", This, alignment);
10353 This->cbAlignment = alignment;
10355 return S_OK;
10358 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10359 LPOLESTR schema)
10361 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10363 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10365 if (!schema)
10366 return E_INVALIDARG;
10368 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10370 This->lpstrSchema = This->Schema->str;
10372 return S_OK;
10375 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10376 UINT index, VARDESC *varDesc)
10378 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10379 TLBVarDesc *var_desc;
10381 TRACE("%p %u %p\n", This, index, varDesc);
10383 if (This->vardescs){
10384 UINT i;
10386 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10387 sizeof(TLBVarDesc) * (This->cVars + 1));
10389 if (index < This->cVars) {
10390 memmove(This->vardescs + index + 1, This->vardescs + index,
10391 (This->cVars - index) * sizeof(TLBVarDesc));
10392 var_desc = This->vardescs + index;
10393 } else
10394 var_desc = This->vardescs + This->cVars;
10396 /* move custdata lists to the new memory location */
10397 for(i = 0; i < This->cVars + 1; ++i){
10398 if(index != i){
10399 TLBVarDesc *var = &This->vardescs[i];
10400 if(var->custdata_list.prev == var->custdata_list.next)
10401 list_init(&var->custdata_list);
10402 else{
10403 var->custdata_list.prev->next = &var->custdata_list;
10404 var->custdata_list.next->prev = &var->custdata_list;
10408 } else
10409 var_desc = This->vardescs = heap_alloc(sizeof(TLBVarDesc));
10411 memset(var_desc, 0, sizeof(TLBVarDesc));
10412 TLBVarDesc_Constructor(var_desc);
10413 var_desc->vardesc = *varDesc;
10415 ++This->cVars;
10417 This->needs_layout = TRUE;
10419 return S_OK;
10422 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10423 UINT index, LPOLESTR *names, UINT numNames)
10425 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10426 TLBFuncDesc *func_desc = &This->funcdescs[index];
10427 int i;
10429 TRACE("%p %u %p %u\n", This, index, names, numNames);
10431 if (!names)
10432 return E_INVALIDARG;
10434 if (index >= This->cFuncs || numNames == 0)
10435 return TYPE_E_ELEMENTNOTFOUND;
10437 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10438 if(numNames > func_desc->funcdesc.cParams)
10439 return TYPE_E_ELEMENTNOTFOUND;
10440 } else
10441 if(numNames > func_desc->funcdesc.cParams + 1)
10442 return TYPE_E_ELEMENTNOTFOUND;
10444 for(i = 0; i < This->cFuncs; ++i) {
10445 TLBFuncDesc *iter = &This->funcdescs[i];
10446 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10447 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10448 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10449 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10450 continue;
10451 return TYPE_E_AMBIGUOUSNAME;
10455 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10457 for (i = 1; i < numNames; ++i) {
10458 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10459 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10462 return S_OK;
10465 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10466 UINT index, LPOLESTR name)
10468 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10469 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
10470 return E_NOTIMPL;
10473 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10474 TYPEDESC *tdescAlias)
10476 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10477 FIXME("%p %p - stub\n", This, tdescAlias);
10478 return E_NOTIMPL;
10481 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10482 UINT index, LPOLESTR dllName, LPOLESTR procName)
10484 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10485 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10486 return E_NOTIMPL;
10489 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10490 UINT index, LPOLESTR docString)
10492 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10493 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
10494 return E_NOTIMPL;
10497 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10498 UINT index, LPOLESTR docString)
10500 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10501 TLBVarDesc *var_desc = &This->vardescs[index];
10503 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10505 if(!docString)
10506 return E_INVALIDARG;
10508 if(index >= This->cVars)
10509 return TYPE_E_ELEMENTNOTFOUND;
10511 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10513 return S_OK;
10516 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10517 UINT index, DWORD helpContext)
10519 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10520 TLBFuncDesc *func_desc = &This->funcdescs[index];
10522 TRACE("%p %u %d\n", This, index, helpContext);
10524 if(index >= This->cFuncs)
10525 return TYPE_E_ELEMENTNOTFOUND;
10527 func_desc->helpcontext = helpContext;
10529 return S_OK;
10532 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10533 UINT index, DWORD helpContext)
10535 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10536 TLBVarDesc *var_desc = &This->vardescs[index];
10538 TRACE("%p %u %d\n", This, index, helpContext);
10540 if(index >= This->cVars)
10541 return TYPE_E_ELEMENTNOTFOUND;
10543 var_desc->HelpContext = helpContext;
10545 return S_OK;
10548 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10549 UINT index, BSTR bstrMops)
10551 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10552 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10553 return E_NOTIMPL;
10556 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10557 IDLDESC *idlDesc)
10559 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10561 TRACE("%p %p\n", This, idlDesc);
10563 if (!idlDesc)
10564 return E_INVALIDARG;
10566 This->idldescType.dwReserved = idlDesc->dwReserved;
10567 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10569 return S_OK;
10572 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10574 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10575 ITypeInfo *tinfo;
10576 TLBFuncDesc *func_desc;
10577 UINT user_vft = 0, i, depth = 0;
10578 HRESULT hres = S_OK;
10580 TRACE("%p\n", This);
10582 This->needs_layout = FALSE;
10584 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10585 if (FAILED(hres))
10586 return hres;
10588 if (This->typekind == TKIND_INTERFACE) {
10589 ITypeInfo *inh;
10590 TYPEATTR *attr;
10591 HREFTYPE inh_href;
10593 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10595 if (SUCCEEDED(hres)) {
10596 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10598 if (SUCCEEDED(hres)) {
10599 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10600 if (FAILED(hres)) {
10601 ITypeInfo_Release(inh);
10602 ITypeInfo_Release(tinfo);
10603 return hres;
10605 This->cbSizeVft = attr->cbSizeVft * 4 / sizeof(void*);
10606 ITypeInfo_ReleaseTypeAttr(inh, attr);
10609 ++depth;
10610 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10611 if(SUCCEEDED(hres)){
10612 ITypeInfo *next;
10613 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10614 if(SUCCEEDED(hres)){
10615 ITypeInfo_Release(inh);
10616 inh = next;
10619 }while(SUCCEEDED(hres));
10620 hres = S_OK;
10622 ITypeInfo_Release(inh);
10623 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10624 This->cbSizeVft = 0;
10625 hres = S_OK;
10626 } else {
10627 ITypeInfo_Release(tinfo);
10628 return hres;
10630 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10631 This->cbSizeVft = 0;
10632 hres = S_OK;
10633 } else {
10634 ITypeInfo_Release(tinfo);
10635 return hres;
10637 } else if (This->typekind == TKIND_DISPATCH)
10638 This->cbSizeVft = 7 * sizeof(void*);
10639 else
10640 This->cbSizeVft = 0;
10642 func_desc = This->funcdescs;
10643 i = 0;
10644 while (i < This->cFuncs) {
10645 if (!(func_desc->funcdesc.oVft & 0x1))
10646 func_desc->funcdesc.oVft = This->cbSizeVft;
10648 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10649 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10651 This->cbSizeVft += sizeof(void*);
10653 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10654 TLBFuncDesc *iter;
10655 UINT j = 0;
10656 BOOL reset = FALSE;
10658 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10660 iter = This->funcdescs;
10661 while (j < This->cFuncs) {
10662 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10663 if (!reset) {
10664 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10665 reset = TRUE;
10666 } else
10667 ++func_desc->funcdesc.memid;
10668 iter = This->funcdescs;
10669 j = 0;
10670 } else {
10671 ++iter;
10672 ++j;
10677 ++func_desc;
10678 ++i;
10681 if (user_vft > This->cbSizeVft)
10682 This->cbSizeVft = user_vft + sizeof(void*);
10684 ITypeInfo_Release(tinfo);
10685 return hres;
10688 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10689 UINT index)
10691 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10692 FIXME("%p %u - stub\n", This, index);
10693 return E_NOTIMPL;
10696 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10697 MEMBERID memid, INVOKEKIND invKind)
10699 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10700 FIXME("%p %x %d - stub\n", This, memid, invKind);
10701 return E_NOTIMPL;
10704 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
10705 UINT index)
10707 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10708 FIXME("%p %u - stub\n", This, index);
10709 return E_NOTIMPL;
10712 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
10713 MEMBERID memid)
10715 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10716 FIXME("%p %x - stub\n", This, memid);
10717 return E_NOTIMPL;
10720 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
10721 UINT index)
10723 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10724 FIXME("%p %u - stub\n", This, index);
10725 return E_NOTIMPL;
10728 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
10729 REFGUID guid, VARIANT *varVal)
10731 TLBGuid *tlbguid;
10733 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10735 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10737 if (!guid || !varVal)
10738 return E_INVALIDARG;
10740 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
10742 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10745 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
10746 UINT index, REFGUID guid, VARIANT *varVal)
10748 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10749 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10750 return E_NOTIMPL;
10753 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
10754 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
10756 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10757 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
10758 return E_NOTIMPL;
10761 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
10762 UINT index, REFGUID guid, VARIANT *varVal)
10764 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10765 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10766 return E_NOTIMPL;
10769 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
10770 UINT index, REFGUID guid, VARIANT *varVal)
10772 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10773 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10774 return E_NOTIMPL;
10777 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
10778 ULONG helpStringContext)
10780 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10782 TRACE("%p %u\n", This, helpStringContext);
10784 This->dwHelpStringContext = helpStringContext;
10786 return S_OK;
10789 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
10790 UINT index, ULONG helpStringContext)
10792 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10793 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10794 return E_NOTIMPL;
10797 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
10798 UINT index, ULONG helpStringContext)
10800 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10801 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10802 return E_NOTIMPL;
10805 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
10807 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10808 FIXME("%p - stub\n", This);
10809 return E_NOTIMPL;
10812 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
10813 LPOLESTR name)
10815 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10817 TRACE("%p %s\n", This, wine_dbgstr_w(name));
10819 if (!name)
10820 return E_INVALIDARG;
10822 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
10824 return S_OK;
10827 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
10828 ICreateTypeInfo2_fnQueryInterface,
10829 ICreateTypeInfo2_fnAddRef,
10830 ICreateTypeInfo2_fnRelease,
10831 ICreateTypeInfo2_fnSetGuid,
10832 ICreateTypeInfo2_fnSetTypeFlags,
10833 ICreateTypeInfo2_fnSetDocString,
10834 ICreateTypeInfo2_fnSetHelpContext,
10835 ICreateTypeInfo2_fnSetVersion,
10836 ICreateTypeInfo2_fnAddRefTypeInfo,
10837 ICreateTypeInfo2_fnAddFuncDesc,
10838 ICreateTypeInfo2_fnAddImplType,
10839 ICreateTypeInfo2_fnSetImplTypeFlags,
10840 ICreateTypeInfo2_fnSetAlignment,
10841 ICreateTypeInfo2_fnSetSchema,
10842 ICreateTypeInfo2_fnAddVarDesc,
10843 ICreateTypeInfo2_fnSetFuncAndParamNames,
10844 ICreateTypeInfo2_fnSetVarName,
10845 ICreateTypeInfo2_fnSetTypeDescAlias,
10846 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
10847 ICreateTypeInfo2_fnSetFuncDocString,
10848 ICreateTypeInfo2_fnSetVarDocString,
10849 ICreateTypeInfo2_fnSetFuncHelpContext,
10850 ICreateTypeInfo2_fnSetVarHelpContext,
10851 ICreateTypeInfo2_fnSetMops,
10852 ICreateTypeInfo2_fnSetTypeIdldesc,
10853 ICreateTypeInfo2_fnLayOut,
10854 ICreateTypeInfo2_fnDeleteFuncDesc,
10855 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
10856 ICreateTypeInfo2_fnDeleteVarDesc,
10857 ICreateTypeInfo2_fnDeleteVarDescByMemId,
10858 ICreateTypeInfo2_fnDeleteImplType,
10859 ICreateTypeInfo2_fnSetCustData,
10860 ICreateTypeInfo2_fnSetFuncCustData,
10861 ICreateTypeInfo2_fnSetParamCustData,
10862 ICreateTypeInfo2_fnSetVarCustData,
10863 ICreateTypeInfo2_fnSetImplTypeCustData,
10864 ICreateTypeInfo2_fnSetHelpStringContext,
10865 ICreateTypeInfo2_fnSetFuncHelpStringContext,
10866 ICreateTypeInfo2_fnSetVarHelpStringContext,
10867 ICreateTypeInfo2_fnInvalidate,
10868 ICreateTypeInfo2_fnSetName