oleaut32: Implement ICreateTypeInfo::SetVarDocString.
[wine.git] / dlls / oleaut32 / typelib.c
blobd52d46119cbf66b2b3513e3207a59f7a657bd563
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 TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1739 TLBVarDesc *ret;
1741 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1742 if(!ret)
1743 return NULL;
1745 while(n){
1746 list_init(&ret[n-1].custdata_list);
1747 --n;
1750 return ret;
1753 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1755 TLBParDesc *ret;
1757 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1758 if(!ret)
1759 return NULL;
1761 while(n){
1762 list_init(&ret[n-1].custdata_list);
1763 --n;
1766 return ret;
1769 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1771 list_init(&func_desc->custdata_list);
1774 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1776 TLBFuncDesc *ret;
1778 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1779 if(!ret)
1780 return NULL;
1782 while(n){
1783 TLBFuncDesc_Constructor(&ret[n-1]);
1784 --n;
1787 return ret;
1790 static void TLBImplType_Constructor(TLBImplType *impl)
1792 list_init(&impl->custdata_list);
1795 static TLBImplType *TLBImplType_Alloc(UINT n)
1797 TLBImplType *ret;
1799 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1800 if(!ret)
1801 return NULL;
1803 while(n){
1804 TLBImplType_Constructor(&ret[n-1]);
1805 --n;
1808 return ret;
1811 static TLBGuid *TLB_append_guid(struct list *guid_list, const GUID *new_guid)
1813 TLBGuid *guid;
1815 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1816 if (IsEqualGUID(&guid->guid, new_guid))
1817 return guid;
1820 guid = heap_alloc(sizeof(TLBGuid));
1821 if (!guid)
1822 return NULL;
1824 memcpy(&guid->guid, new_guid, sizeof(GUID));
1826 list_add_tail(guid_list, &guid->entry);
1828 return guid;
1831 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1833 TLBCustData *cust_data;
1835 switch(V_VT(var)){
1836 case VT_I4:
1837 case VT_R4:
1838 case VT_UI4:
1839 case VT_INT:
1840 case VT_UINT:
1841 case VT_HRESULT:
1842 case VT_BSTR:
1843 break;
1844 default:
1845 return DISP_E_BADVARTYPE;
1848 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1850 if (!cust_data) {
1851 cust_data = heap_alloc(sizeof(TLBCustData));
1852 if (!cust_data)
1853 return E_OUTOFMEMORY;
1855 cust_data->guid = tlbguid;
1856 VariantInit(&cust_data->data);
1858 list_add_tail(custdata_list, &cust_data->entry);
1859 }else
1860 VariantClear(&cust_data->data);
1862 return VariantCopy(&cust_data->data, var);
1865 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1867 TLBString *str;
1869 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1870 if (strcmpW(str->str, new_str) == 0)
1871 return str;
1874 str = heap_alloc(sizeof(TLBString));
1875 if (!str)
1876 return NULL;
1878 str->str = SysAllocString(new_str);
1879 if (!str->str) {
1880 heap_free(str);
1881 return NULL;
1884 list_add_tail(string_list, &str->entry);
1886 return str;
1889 /**********************************************************************
1891 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1893 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1895 return pcx->pos;
1898 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1900 if (where != DO_NOT_SEEK)
1902 where += pcx->oStart;
1903 if (where > pcx->length)
1905 /* FIXME */
1906 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1907 TLB_abort();
1909 pcx->pos = where;
1913 /* read function */
1914 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1916 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1917 pcx->pos, count, pcx->oStart, pcx->length, where);
1919 MSFT_Seek(pcx, where);
1920 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1921 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1922 pcx->pos += count;
1923 return count;
1926 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1927 LONG where )
1929 DWORD ret;
1931 ret = MSFT_Read(buffer, count, pcx, where);
1932 FromLEDWords(buffer, ret);
1934 return ret;
1937 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1938 LONG where )
1940 DWORD ret;
1942 ret = MSFT_Read(buffer, count, pcx, where);
1943 FromLEWords(buffer, ret);
1945 return ret;
1948 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
1950 TLBGuid *guid;
1951 MSFT_GuidEntry entry;
1952 int offs = 0;
1954 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
1955 while (1) {
1956 if (offs >= pcx->pTblDir->pGuidTab.length)
1957 return S_OK;
1959 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
1961 guid = heap_alloc(sizeof(TLBGuid));
1963 guid->offset = offs;
1964 guid->guid = entry.guid;
1966 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
1968 offs += sizeof(MSFT_GuidEntry);
1972 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
1974 TLBGuid *ret;
1976 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
1977 if(ret->offset == offset){
1978 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
1979 return ret;
1983 return NULL;
1986 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1988 MSFT_NameIntro niName;
1990 if (offset < 0)
1992 ERR_(typelib)("bad offset %d\n", offset);
1993 return -1;
1996 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1997 pcx->pTblDir->pNametab.offset+offset);
1999 return niName.hreftype;
2002 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2004 char *string;
2005 MSFT_NameIntro intro;
2006 INT16 len_piece;
2007 int offs = 0, lengthInChars;
2009 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2010 while (1) {
2011 TLBString *tlbstr;
2013 if (offs >= pcx->pTblDir->pNametab.length)
2014 return S_OK;
2016 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2017 intro.namelen &= 0xFF;
2018 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2019 if(len_piece % 4)
2020 len_piece = (len_piece + 4) & ~0x3;
2021 if(len_piece < 8)
2022 len_piece = 8;
2024 string = heap_alloc(len_piece + 1);
2025 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2026 string[intro.namelen] = '\0';
2028 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2029 string, -1, NULL, 0);
2030 if (!lengthInChars) {
2031 heap_free(string);
2032 return E_UNEXPECTED;
2035 tlbstr = heap_alloc(sizeof(TLBString));
2037 tlbstr->offset = offs;
2038 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2039 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2041 heap_free(string);
2043 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2045 offs += len_piece;
2049 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2051 TLBString *tlbstr;
2053 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2054 if (tlbstr->offset == offset) {
2055 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2056 return tlbstr;
2060 return NULL;
2063 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2065 TLBString *tlbstr;
2067 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2068 if (tlbstr->offset == offset) {
2069 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2070 return tlbstr;
2074 return NULL;
2078 * read a value and fill a VARIANT structure
2080 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2082 int size;
2084 TRACE_(typelib)("\n");
2086 if(offset <0) { /* data are packed in here */
2087 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2088 V_I4(pVar) = offset & 0x3ffffff;
2089 return;
2091 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2092 pcx->pTblDir->pCustData.offset + offset );
2093 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2094 switch (V_VT(pVar)){
2095 case VT_EMPTY: /* FIXME: is this right? */
2096 case VT_NULL: /* FIXME: is this right? */
2097 case VT_I2 : /* this should not happen */
2098 case VT_I4 :
2099 case VT_R4 :
2100 case VT_ERROR :
2101 case VT_BOOL :
2102 case VT_I1 :
2103 case VT_UI1 :
2104 case VT_UI2 :
2105 case VT_UI4 :
2106 case VT_INT :
2107 case VT_UINT :
2108 case VT_VOID : /* FIXME: is this right? */
2109 case VT_HRESULT :
2110 size=4; break;
2111 case VT_R8 :
2112 case VT_CY :
2113 case VT_DATE :
2114 case VT_I8 :
2115 case VT_UI8 :
2116 case VT_DECIMAL : /* FIXME: is this right? */
2117 case VT_FILETIME :
2118 size=8;break;
2119 /* pointer types with known behaviour */
2120 case VT_BSTR :{
2121 char * ptr;
2122 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2123 if(size < 0) {
2124 char next;
2125 DWORD origPos = MSFT_Tell(pcx), nullPos;
2127 do {
2128 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
2129 } while (next);
2130 nullPos = MSFT_Tell(pcx);
2131 size = nullPos - origPos;
2132 MSFT_Seek(pcx, origPos);
2134 ptr = heap_alloc_zero(size);/* allocate temp buffer */
2135 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
2136 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2137 /* FIXME: do we need a AtoW conversion here? */
2138 V_UNION(pVar, bstrVal[size])='\0';
2139 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2140 heap_free(ptr);
2142 size=-4; break;
2143 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2144 case VT_DISPATCH :
2145 case VT_VARIANT :
2146 case VT_UNKNOWN :
2147 case VT_PTR :
2148 case VT_SAFEARRAY :
2149 case VT_CARRAY :
2150 case VT_USERDEFINED :
2151 case VT_LPSTR :
2152 case VT_LPWSTR :
2153 case VT_BLOB :
2154 case VT_STREAM :
2155 case VT_STORAGE :
2156 case VT_STREAMED_OBJECT :
2157 case VT_STORED_OBJECT :
2158 case VT_BLOB_OBJECT :
2159 case VT_CF :
2160 case VT_CLSID :
2161 default:
2162 size=0;
2163 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2164 V_VT(pVar));
2167 if(size>0) /* (big|small) endian correct? */
2168 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2169 return;
2172 * create a linked list with custom data
2174 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2176 MSFT_CDGuid entry;
2177 TLBCustData* pNew;
2178 int count=0;
2180 TRACE_(typelib)("\n");
2182 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2184 while(offset >=0){
2185 count++;
2186 pNew=heap_alloc_zero(sizeof(TLBCustData));
2187 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2188 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2189 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2190 list_add_head(custdata_list, &pNew->entry);
2191 offset = entry.next;
2193 return count;
2196 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
2197 ITypeInfoImpl *pTI)
2199 if(type <0)
2200 pTd->vt=type & VT_TYPEMASK;
2201 else
2202 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2204 if(pTd->vt == VT_USERDEFINED)
2205 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
2207 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2210 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
2212 /* resolve referenced type if any */
2213 while (lpTypeDesc)
2215 switch (lpTypeDesc->vt)
2217 case VT_PTR:
2218 lpTypeDesc = lpTypeDesc->u.lptdesc;
2219 break;
2221 case VT_CARRAY:
2222 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
2223 break;
2225 case VT_USERDEFINED:
2226 MSFT_DoRefType(pcx, pTI->pTypeLib,
2227 lpTypeDesc->u.hreftype);
2229 lpTypeDesc = NULL;
2230 break;
2232 default:
2233 lpTypeDesc = NULL;
2238 static void
2239 MSFT_DoFuncs(TLBContext* pcx,
2240 ITypeInfoImpl* pTI,
2241 int cFuncs,
2242 int cVars,
2243 int offset,
2244 TLBFuncDesc** pptfd)
2247 * member information is stored in a data structure at offset
2248 * indicated by the memoffset field of the typeinfo structure
2249 * There are several distinctive parts.
2250 * The first part starts with a field that holds the total length
2251 * of this (first) part excluding this field. Then follow the records,
2252 * for each member there is one record.
2254 * The first entry is always the length of the record (including this
2255 * length word).
2256 * The rest of the record depends on the type of the member. If there is
2257 * a field indicating the member type (function, variable, interface, etc)
2258 * I have not found it yet. At this time we depend on the information
2259 * in the type info and the usual order how things are stored.
2261 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2262 * for each member;
2264 * Third is an equal sized array with file offsets to the name entry
2265 * of each member.
2267 * The fourth and last (?) part is an array with offsets to the records
2268 * in the first part of this file segment.
2271 int infolen, nameoffset, reclength, i;
2272 int recoffset = offset + sizeof(INT);
2274 char *recbuf = heap_alloc(0xffff);
2275 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2276 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2278 TRACE_(typelib)("\n");
2280 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2282 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2283 ptfd = *pptfd;
2284 for ( i = 0; i < cFuncs ; i++ )
2286 int optional;
2288 /* name, eventually add to a hash table */
2289 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2290 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2292 /* nameoffset is sometimes -1 on the second half of a propget/propput
2293 * pair of functions */
2294 if ((nameoffset == -1) && (i > 0))
2295 ptfd->Name = ptfd_prev->Name;
2296 else
2297 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2299 /* read the function information record */
2300 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2302 reclength &= 0xffff;
2304 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2306 /* size without argument data */
2307 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2309 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2310 ptfd->helpcontext = pFuncRec->HelpContext;
2312 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2313 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2315 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2317 if (pFuncRec->FKCCIC & 0x2000 )
2319 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2320 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2321 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2323 else
2324 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2326 else
2327 ptfd->Entry = (TLBString*)-1;
2329 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2330 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2332 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2333 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2335 /* fill the FuncDesc Structure */
2336 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2337 offset + infolen + ( i + 1) * sizeof(INT));
2339 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2340 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2341 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2342 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2343 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2344 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2345 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2347 MSFT_GetTdesc(pcx,
2348 pFuncRec->DataType,
2349 &ptfd->funcdesc.elemdescFunc.tdesc,
2350 pTI);
2351 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2353 /* do the parameters/arguments */
2354 if(pFuncRec->nrargs)
2356 int j = 0;
2357 MSFT_ParameterInfo paraminfo;
2359 ptfd->funcdesc.lprgelemdescParam =
2360 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2362 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2364 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2365 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2367 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2369 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2371 MSFT_GetTdesc(pcx,
2372 paraminfo.DataType,
2373 &elemdesc->tdesc,
2374 pTI);
2376 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2378 /* name */
2379 if (paraminfo.oName == -1)
2380 /* this occurs for [propput] or [propget] methods, so
2381 * we should just set the name of the parameter to the
2382 * name of the method. */
2383 ptfd->pParamDesc[j].Name = ptfd->Name;
2384 else
2385 ptfd->pParamDesc[j].Name =
2386 MSFT_ReadName( pcx, paraminfo.oName );
2387 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2389 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2391 /* default value */
2392 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2393 (pFuncRec->FKCCIC & 0x1000) )
2395 INT* pInt = (INT *)((char *)pFuncRec +
2396 reclength -
2397 (pFuncRec->nrargs * 4) * sizeof(INT) );
2399 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2401 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2402 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2404 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2405 pInt[j], pcx);
2407 else
2408 elemdesc->u.paramdesc.pparamdescex = NULL;
2410 /* custom info */
2411 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2412 j*sizeof(pFuncRec->oArgCustData[0])) &&
2413 pFuncRec->FKCCIC & 0x80 )
2415 MSFT_CustData(pcx,
2416 pFuncRec->oArgCustData[j],
2417 &ptfd->pParamDesc[j].custdata_list);
2420 /* SEEK value = jump to offset,
2421 * from there jump to the end of record,
2422 * go back by (j-1) arguments
2424 MSFT_ReadLEDWords( &paraminfo ,
2425 sizeof(MSFT_ParameterInfo), pcx,
2426 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2427 * sizeof(MSFT_ParameterInfo)));
2431 /* scode is not used: archaic win16 stuff FIXME: right? */
2432 ptfd->funcdesc.cScodes = 0 ;
2433 ptfd->funcdesc.lprgscode = NULL ;
2435 ptfd_prev = ptfd;
2436 ++ptfd;
2437 recoffset += reclength;
2439 heap_free(recbuf);
2442 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2443 int cVars, int offset, TLBVarDesc ** pptvd)
2445 int infolen, nameoffset, reclength;
2446 char recbuf[256];
2447 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2448 TLBVarDesc *ptvd;
2449 int i;
2450 int recoffset;
2452 TRACE_(typelib)("\n");
2454 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2455 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2456 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2457 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2458 recoffset += offset+sizeof(INT);
2459 for(i=0;i<cVars;i++, ++ptvd){
2460 /* name, eventually add to a hash table */
2461 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2462 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2463 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2464 /* read the variable information record */
2465 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2466 reclength &= 0xff;
2467 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2469 /* optional data */
2470 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2471 ptvd->HelpContext = pVarRec->HelpContext;
2473 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2474 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2476 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2477 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2479 /* fill the VarDesc Structure */
2480 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2481 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2482 ptvd->vardesc.varkind = pVarRec->VarKind;
2483 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2484 MSFT_GetTdesc(pcx, pVarRec->DataType,
2485 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2486 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2487 if(pVarRec->VarKind == VAR_CONST ){
2488 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2489 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2490 pVarRec->OffsValue, pcx);
2491 } else
2492 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2493 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2494 recoffset += reclength;
2498 /* fill in data for a hreftype (offset). When the referenced type is contained
2499 * in the typelib, it's just an (file) offset in the type info base dir.
2500 * If comes from import, it's an offset+1 in the ImpInfo table
2501 * */
2502 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2503 int offset)
2505 TLBRefType *ref;
2507 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2509 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2511 if(ref->reference == offset) return;
2514 ref = heap_alloc_zero(sizeof(TLBRefType));
2515 list_add_tail(&pTL->ref_list, &ref->entry);
2517 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2518 /* external typelib */
2519 MSFT_ImpInfo impinfo;
2520 TLBImpLib *pImpLib;
2522 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2524 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2525 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2527 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2528 if(pImpLib->offset==impinfo.oImpFile)
2529 break;
2531 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2532 ref->reference = offset & (~0x3);
2533 ref->pImpTLInfo = pImpLib;
2534 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2535 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2536 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2537 ref->index = TLB_REF_USE_GUID;
2538 } else
2539 ref->index = impinfo.oGuid;
2540 }else{
2541 ERR("Cannot find a reference\n");
2542 ref->reference = -1;
2543 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2545 }else{
2546 /* in this typelib */
2547 ref->index = MSFT_HREFTYPE_INDEX(offset);
2548 ref->reference = offset;
2549 ref->pImpTLInfo = TLB_REF_INTERNAL;
2553 /* process Implemented Interfaces of a com class */
2554 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2555 int offset)
2557 int i;
2558 MSFT_RefRecord refrec;
2559 TLBImplType *pImpl;
2561 TRACE_(typelib)("\n");
2563 pTI->impltypes = TLBImplType_Alloc(count);
2564 pImpl = pTI->impltypes;
2565 for(i=0;i<count;i++){
2566 if(offset<0) break; /* paranoia */
2567 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2568 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2569 pImpl->hRef = refrec.reftype;
2570 pImpl->implflags=refrec.flags;
2571 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2572 offset=refrec.onext;
2573 ++pImpl;
2577 * process a typeinfo record
2579 static ITypeInfoImpl * MSFT_DoTypeInfo(
2580 TLBContext *pcx,
2581 int count,
2582 ITypeLibImpl * pLibInfo)
2584 MSFT_TypeInfoBase tiBase;
2585 ITypeInfoImpl *ptiRet;
2587 TRACE_(typelib)("count=%u\n", count);
2589 ptiRet = ITypeInfoImpl_Constructor();
2590 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2591 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2593 /* this is where we are coming from */
2594 ptiRet->pTypeLib = pLibInfo;
2595 ptiRet->index=count;
2597 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2598 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2599 ptiRet->lpstrSchema=NULL; /* reserved */
2600 ptiRet->cbSizeInstance=tiBase.size;
2601 ptiRet->typekind=tiBase.typekind & 0xF;
2602 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2603 ptiRet->cVars=HIWORD(tiBase.cElement);
2604 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2605 ptiRet->wTypeFlags=tiBase.flags;
2606 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2607 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2608 ptiRet->cImplTypes=tiBase.cImplTypes;
2609 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2610 if(ptiRet->typekind == TKIND_ALIAS)
2611 MSFT_GetTdesc(pcx, tiBase.datatype1,
2612 &ptiRet->tdescAlias, ptiRet);
2614 /* FIXME: */
2615 /* IDLDESC idldescType; *//* never saw this one != zero */
2617 /* name, eventually add to a hash table */
2618 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2619 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2620 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2621 /* help info */
2622 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2623 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2624 ptiRet->dwHelpContext=tiBase.helpcontext;
2626 if (ptiRet->typekind == TKIND_MODULE)
2627 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2629 /* note: InfoType's Help file and HelpStringDll come from the containing
2630 * library. Further HelpString and Docstring appear to be the same thing :(
2632 /* functions */
2633 if(ptiRet->cFuncs >0 )
2634 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2635 ptiRet->cVars,
2636 tiBase.memoffset, &ptiRet->funcdescs);
2637 /* variables */
2638 if(ptiRet->cVars >0 )
2639 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2640 ptiRet->cVars,
2641 tiBase.memoffset, &ptiRet->vardescs);
2642 if(ptiRet->cImplTypes >0 ) {
2643 switch(ptiRet->typekind)
2645 case TKIND_COCLASS:
2646 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2647 tiBase.datatype1);
2648 break;
2649 case TKIND_DISPATCH:
2650 /* This is not -1 when the interface is a non-base dual interface or
2651 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2652 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2653 not this interface.
2656 if (tiBase.datatype1 != -1)
2658 ptiRet->impltypes = TLBImplType_Alloc(1);
2659 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2660 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2662 break;
2663 default:
2664 ptiRet->impltypes = TLBImplType_Alloc(1);
2665 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2666 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2667 break;
2670 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2672 TRACE_(typelib)("%s guid: %s kind:%s\n",
2673 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2674 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2675 typekind_desc[ptiRet->typekind]);
2676 if (TRACE_ON(typelib))
2677 dump_TypeInfo(ptiRet);
2679 return ptiRet;
2682 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2684 char *string;
2685 INT16 len_str, len_piece;
2686 int offs = 0, lengthInChars;
2688 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2689 while (1) {
2690 TLBString *tlbstr;
2692 if (offs >= pcx->pTblDir->pStringtab.length)
2693 return S_OK;
2695 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2696 len_piece = len_str + sizeof(INT16);
2697 if(len_piece % 4)
2698 len_piece = (len_piece + 4) & ~0x3;
2699 if(len_piece < 8)
2700 len_piece = 8;
2702 string = heap_alloc(len_piece + 1);
2703 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2704 string[len_str] = '\0';
2706 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2707 string, -1, NULL, 0);
2708 if (!lengthInChars) {
2709 heap_free(string);
2710 return E_UNEXPECTED;
2713 tlbstr = heap_alloc(sizeof(TLBString));
2715 tlbstr->offset = offs;
2716 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2717 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2719 heap_free(string);
2721 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2723 offs += len_piece;
2727 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2728 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2729 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2730 * tradeoff here.
2732 static struct list tlb_cache = LIST_INIT(tlb_cache);
2733 static CRITICAL_SECTION cache_section;
2734 static CRITICAL_SECTION_DEBUG cache_section_debug =
2736 0, 0, &cache_section,
2737 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2738 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2740 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2743 typedef struct TLB_PEFile
2745 IUnknown IUnknown_iface;
2746 LONG refs;
2747 HMODULE dll;
2748 HRSRC typelib_resource;
2749 HGLOBAL typelib_global;
2750 LPVOID typelib_base;
2751 } TLB_PEFile;
2753 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2755 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2758 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2760 if (IsEqualIID(riid, &IID_IUnknown))
2762 *ppv = iface;
2763 IUnknown_AddRef(iface);
2764 return S_OK;
2766 *ppv = NULL;
2767 return E_NOINTERFACE;
2770 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2772 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2773 return InterlockedIncrement(&This->refs);
2776 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2778 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2779 ULONG refs = InterlockedDecrement(&This->refs);
2780 if (!refs)
2782 if (This->typelib_global)
2783 FreeResource(This->typelib_global);
2784 if (This->dll)
2785 FreeLibrary(This->dll);
2786 heap_free(This);
2788 return refs;
2791 static const IUnknownVtbl TLB_PEFile_Vtable =
2793 TLB_PEFile_QueryInterface,
2794 TLB_PEFile_AddRef,
2795 TLB_PEFile_Release
2798 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2800 TLB_PEFile *This;
2801 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2803 This = heap_alloc(sizeof(TLB_PEFile));
2804 if (!This)
2805 return E_OUTOFMEMORY;
2807 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2808 This->refs = 1;
2809 This->dll = NULL;
2810 This->typelib_resource = NULL;
2811 This->typelib_global = NULL;
2812 This->typelib_base = NULL;
2814 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2815 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2817 if (This->dll)
2819 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2820 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2821 if (This->typelib_resource)
2823 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2824 if (This->typelib_global)
2826 This->typelib_base = LockResource(This->typelib_global);
2828 if (This->typelib_base)
2830 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2831 *ppBase = This->typelib_base;
2832 *ppFile = &This->IUnknown_iface;
2833 return S_OK;
2838 TRACE("No TYPELIB resource found\n");
2839 hr = E_FAIL;
2842 TLB_PEFile_Release(&This->IUnknown_iface);
2843 return hr;
2846 typedef struct TLB_NEFile
2848 IUnknown IUnknown_iface;
2849 LONG refs;
2850 LPVOID typelib_base;
2851 } TLB_NEFile;
2853 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2855 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2858 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2860 if (IsEqualIID(riid, &IID_IUnknown))
2862 *ppv = iface;
2863 IUnknown_AddRef(iface);
2864 return S_OK;
2866 *ppv = NULL;
2867 return E_NOINTERFACE;
2870 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2872 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2873 return InterlockedIncrement(&This->refs);
2876 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2878 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2879 ULONG refs = InterlockedDecrement(&This->refs);
2880 if (!refs)
2882 heap_free(This->typelib_base);
2883 heap_free(This);
2885 return refs;
2888 static const IUnknownVtbl TLB_NEFile_Vtable =
2890 TLB_NEFile_QueryInterface,
2891 TLB_NEFile_AddRef,
2892 TLB_NEFile_Release
2895 /***********************************************************************
2896 * read_xx_header [internal]
2898 static int read_xx_header( HFILE lzfd )
2900 IMAGE_DOS_HEADER mzh;
2901 char magic[3];
2903 LZSeek( lzfd, 0, SEEK_SET );
2904 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2905 return 0;
2906 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2907 return 0;
2909 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2910 if ( 2 != LZRead( lzfd, magic, 2 ) )
2911 return 0;
2913 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2915 if ( magic[0] == 'N' && magic[1] == 'E' )
2916 return IMAGE_OS2_SIGNATURE;
2917 if ( magic[0] == 'P' && magic[1] == 'E' )
2918 return IMAGE_NT_SIGNATURE;
2920 magic[2] = '\0';
2921 WARN("Can't handle %s files.\n", magic );
2922 return 0;
2926 /***********************************************************************
2927 * find_ne_resource [internal]
2929 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2930 DWORD *resLen, DWORD *resOff )
2932 IMAGE_OS2_HEADER nehd;
2933 NE_TYPEINFO *typeInfo;
2934 NE_NAMEINFO *nameInfo;
2935 DWORD nehdoffset;
2936 LPBYTE resTab;
2937 DWORD resTabSize;
2938 int count;
2940 /* Read in NE header */
2941 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2942 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2944 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2945 if ( !resTabSize )
2947 TRACE("No resources in NE dll\n" );
2948 return FALSE;
2951 /* Read in resource table */
2952 resTab = heap_alloc( resTabSize );
2953 if ( !resTab ) return FALSE;
2955 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2956 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2958 heap_free( resTab );
2959 return FALSE;
2962 /* Find resource */
2963 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2965 if (!IS_INTRESOURCE(typeid)) /* named type */
2967 BYTE len = strlen( typeid );
2968 while (typeInfo->type_id)
2970 if (!(typeInfo->type_id & 0x8000))
2972 BYTE *p = resTab + typeInfo->type_id;
2973 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2975 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2976 typeInfo->count * sizeof(NE_NAMEINFO));
2979 else /* numeric type id */
2981 WORD id = LOWORD(typeid) | 0x8000;
2982 while (typeInfo->type_id)
2984 if (typeInfo->type_id == id) goto found_type;
2985 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2986 typeInfo->count * sizeof(NE_NAMEINFO));
2989 TRACE("No typeid entry found for %p\n", typeid );
2990 heap_free( resTab );
2991 return FALSE;
2993 found_type:
2994 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2996 if (!IS_INTRESOURCE(resid)) /* named resource */
2998 BYTE len = strlen( resid );
2999 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3001 BYTE *p = resTab + nameInfo->id;
3002 if (nameInfo->id & 0x8000) continue;
3003 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3006 else /* numeric resource id */
3008 WORD id = LOWORD(resid) | 0x8000;
3009 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3010 if (nameInfo->id == id) goto found_name;
3012 TRACE("No resid entry found for %p\n", typeid );
3013 heap_free( resTab );
3014 return FALSE;
3016 found_name:
3017 /* Return resource data */
3018 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3019 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3021 heap_free( resTab );
3022 return TRUE;
3025 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3027 HFILE lzfd = -1;
3028 OFSTRUCT ofs;
3029 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3030 TLB_NEFile *This;
3032 This = heap_alloc(sizeof(TLB_NEFile));
3033 if (!This) return E_OUTOFMEMORY;
3035 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3036 This->refs = 1;
3037 This->typelib_base = NULL;
3039 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3040 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3042 DWORD reslen, offset;
3043 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3045 This->typelib_base = heap_alloc(reslen);
3046 if( !This->typelib_base )
3047 hr = E_OUTOFMEMORY;
3048 else
3050 LZSeek( lzfd, offset, SEEK_SET );
3051 reslen = LZRead( lzfd, This->typelib_base, reslen );
3052 LZClose( lzfd );
3053 *ppBase = This->typelib_base;
3054 *pdwTLBLength = reslen;
3055 *ppFile = &This->IUnknown_iface;
3056 return S_OK;
3061 if( lzfd >= 0) LZClose( lzfd );
3062 TLB_NEFile_Release(&This->IUnknown_iface);
3063 return hr;
3066 typedef struct TLB_Mapping
3068 IUnknown IUnknown_iface;
3069 LONG refs;
3070 HANDLE file;
3071 HANDLE mapping;
3072 LPVOID typelib_base;
3073 } TLB_Mapping;
3075 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3077 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3080 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3082 if (IsEqualIID(riid, &IID_IUnknown))
3084 *ppv = iface;
3085 IUnknown_AddRef(iface);
3086 return S_OK;
3088 *ppv = NULL;
3089 return E_NOINTERFACE;
3092 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3094 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3095 return InterlockedIncrement(&This->refs);
3098 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3100 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3101 ULONG refs = InterlockedDecrement(&This->refs);
3102 if (!refs)
3104 if (This->typelib_base)
3105 UnmapViewOfFile(This->typelib_base);
3106 if (This->mapping)
3107 CloseHandle(This->mapping);
3108 if (This->file != INVALID_HANDLE_VALUE)
3109 CloseHandle(This->file);
3110 heap_free(This);
3112 return refs;
3115 static const IUnknownVtbl TLB_Mapping_Vtable =
3117 TLB_Mapping_QueryInterface,
3118 TLB_Mapping_AddRef,
3119 TLB_Mapping_Release
3122 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3124 TLB_Mapping *This;
3126 This = heap_alloc(sizeof(TLB_Mapping));
3127 if (!This)
3128 return E_OUTOFMEMORY;
3130 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3131 This->refs = 1;
3132 This->file = INVALID_HANDLE_VALUE;
3133 This->mapping = NULL;
3134 This->typelib_base = NULL;
3136 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3137 if (INVALID_HANDLE_VALUE != This->file)
3139 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3140 if (This->mapping)
3142 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3143 if(This->typelib_base)
3145 /* retrieve file size */
3146 *pdwTLBLength = GetFileSize(This->file, NULL);
3147 *ppBase = This->typelib_base;
3148 *ppFile = &This->IUnknown_iface;
3149 return S_OK;
3154 IUnknown_Release(&This->IUnknown_iface);
3155 return TYPE_E_CANTLOADLIBRARY;
3158 /****************************************************************************
3159 * TLB_ReadTypeLib
3161 * find the type of the typelib file and map the typelib resource into
3162 * the memory
3165 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3166 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3168 ITypeLibImpl *entry;
3169 HRESULT ret;
3170 INT index = 1;
3171 LPWSTR index_str, file = (LPWSTR)pszFileName;
3172 LPVOID pBase = NULL;
3173 DWORD dwTLBLength = 0;
3174 IUnknown *pFile = NULL;
3176 *ppTypeLib = NULL;
3178 index_str = strrchrW(pszFileName, '\\');
3179 if(index_str && *++index_str != '\0')
3181 LPWSTR end_ptr;
3182 LONG idx = strtolW(index_str, &end_ptr, 10);
3183 if(*end_ptr == '\0')
3185 int str_len = index_str - pszFileName - 1;
3186 index = idx;
3187 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3188 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3189 file[str_len] = 0;
3193 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3195 if(strchrW(file, '\\'))
3197 lstrcpyW(pszPath, file);
3199 else
3201 int len = GetSystemDirectoryW(pszPath, cchPath);
3202 pszPath[len] = '\\';
3203 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3207 if(file != pszFileName) heap_free(file);
3209 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3211 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3212 EnterCriticalSection(&cache_section);
3213 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3215 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3217 TRACE("cache hit\n");
3218 *ppTypeLib = &entry->ITypeLib2_iface;
3219 ITypeLib2_AddRef(*ppTypeLib);
3220 LeaveCriticalSection(&cache_section);
3221 return S_OK;
3224 LeaveCriticalSection(&cache_section);
3226 /* now actually load and parse the typelib */
3228 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3229 if (ret == TYPE_E_CANTLOADLIBRARY)
3230 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3231 if (ret == TYPE_E_CANTLOADLIBRARY)
3232 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3233 if (SUCCEEDED(ret))
3235 if (dwTLBLength >= 4)
3237 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3238 if (dwSignature == MSFT_SIGNATURE)
3239 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3240 else if (dwSignature == SLTG_SIGNATURE)
3241 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3242 else
3244 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3245 ret = TYPE_E_CANTLOADLIBRARY;
3248 else
3249 ret = TYPE_E_CANTLOADLIBRARY;
3250 IUnknown_Release(pFile);
3253 if(*ppTypeLib) {
3254 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3256 TRACE("adding to cache\n");
3257 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3258 lstrcpyW(impl->path, pszPath);
3259 /* We should really canonicalise the path here. */
3260 impl->index = index;
3262 /* FIXME: check if it has added already in the meantime */
3263 EnterCriticalSection(&cache_section);
3264 list_add_head(&tlb_cache, &impl->entry);
3265 LeaveCriticalSection(&cache_section);
3266 ret = S_OK;
3268 else
3270 if(ret != E_FAIL)
3271 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3273 ret = TYPE_E_CANTLOADLIBRARY;
3277 return ret;
3280 /*================== ITypeLib(2) Methods ===================================*/
3282 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3284 ITypeLibImpl* pTypeLibImpl;
3286 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3287 if (!pTypeLibImpl) return NULL;
3289 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3290 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3291 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3292 pTypeLibImpl->ref = 1;
3294 list_init(&pTypeLibImpl->implib_list);
3295 list_init(&pTypeLibImpl->custdata_list);
3296 list_init(&pTypeLibImpl->name_list);
3297 list_init(&pTypeLibImpl->string_list);
3298 list_init(&pTypeLibImpl->guid_list);
3299 list_init(&pTypeLibImpl->ref_list);
3300 pTypeLibImpl->dispatch_href = -1;
3302 return pTypeLibImpl;
3305 /****************************************************************************
3306 * ITypeLib2_Constructor_MSFT
3308 * loading an MSFT typelib from an in-memory image
3310 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3312 TLBContext cx;
3313 LONG lPSegDir;
3314 MSFT_Header tlbHeader;
3315 MSFT_SegDir tlbSegDir;
3316 ITypeLibImpl * pTypeLibImpl;
3318 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3320 pTypeLibImpl = TypeLibImpl_Constructor();
3321 if (!pTypeLibImpl) return NULL;
3323 /* get pointer to beginning of typelib data */
3324 cx.pos = 0;
3325 cx.oStart=0;
3326 cx.mapping = pLib;
3327 cx.pLibInfo = pTypeLibImpl;
3328 cx.length = dwTLBLength;
3330 /* read header */
3331 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3332 TRACE_(typelib)("header:\n");
3333 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3334 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3335 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3336 return NULL;
3338 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3340 /* there is a small amount of information here until the next important
3341 * part:
3342 * the segment directory . Try to calculate the amount of data */
3343 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3345 /* now read the segment directory */
3346 TRACE("read segment directory (at %d)\n",lPSegDir);
3347 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3348 cx.pTblDir = &tlbSegDir;
3350 /* just check two entries */
3351 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3353 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3354 heap_free(pTypeLibImpl);
3355 return NULL;
3358 MSFT_ReadAllNames(&cx);
3359 MSFT_ReadAllStrings(&cx);
3360 MSFT_ReadAllGuids(&cx);
3362 /* now fill our internal data */
3363 /* TLIBATTR fields */
3364 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3366 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3367 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3368 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3369 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3371 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3372 pTypeLibImpl->lcid = tlbHeader.lcid;
3374 /* name, eventually add to a hash table */
3375 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3377 /* help info */
3378 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3379 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3381 if( tlbHeader.varflags & HELPDLLFLAG)
3383 int offset;
3384 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3385 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3388 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3390 /* custom data */
3391 if(tlbHeader.CustomDataOffset >= 0)
3393 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3396 /* fill in type descriptions */
3397 if(tlbSegDir.pTypdescTab.length > 0)
3399 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3400 INT16 td[4];
3401 pTypeLibImpl->ctTypeDesc = cTD;
3402 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3403 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3404 for(i=0; i<cTD; )
3406 /* FIXME: add several sanity checks here */
3407 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3408 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3410 /* FIXME: check safearray */
3411 if(td[3] < 0)
3412 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3413 else
3414 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3416 else if(td[0] == VT_CARRAY)
3418 /* array descr table here */
3419 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3421 else if(td[0] == VT_USERDEFINED)
3423 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3425 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3428 /* second time around to fill the array subscript info */
3429 for(i=0;i<cTD;i++)
3431 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3432 if(tlbSegDir.pArrayDescriptions.offset>0)
3434 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3435 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3437 if(td[1]<0)
3438 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3439 else
3440 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3442 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3444 for(j = 0; j<td[2]; j++)
3446 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3447 sizeof(INT), &cx, DO_NOT_SEEK);
3448 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3449 sizeof(INT), &cx, DO_NOT_SEEK);
3452 else
3454 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3455 ERR("didn't find array description data\n");
3460 /* imported type libs */
3461 if(tlbSegDir.pImpFiles.offset>0)
3463 TLBImpLib *pImpLib;
3464 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3465 UINT16 size;
3467 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3469 char *name;
3471 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3472 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3473 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3475 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3476 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3477 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3478 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3480 size >>= 2;
3481 name = heap_alloc_zero(size+1);
3482 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3483 pImpLib->name = TLB_MultiByteToBSTR(name);
3484 heap_free(name);
3486 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3487 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3489 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3493 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3494 if(pTypeLibImpl->dispatch_href != -1)
3495 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3497 /* type infos */
3498 if(tlbHeader.nrtypeinfos >= 0 )
3500 ITypeInfoImpl **ppTI;
3501 int i;
3503 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3505 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3507 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3509 ++ppTI;
3510 (pTypeLibImpl->TypeInfoCount)++;
3514 TRACE("(%p)\n", pTypeLibImpl);
3515 return &pTypeLibImpl->ITypeLib2_iface;
3519 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3521 char b[3];
3522 int i;
3523 short s;
3525 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3526 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3527 return FALSE;
3530 guid->Data4[0] = s >> 8;
3531 guid->Data4[1] = s & 0xff;
3533 b[2] = '\0';
3534 for(i = 0; i < 6; i++) {
3535 memcpy(b, str + 24 + 2 * i, 2);
3536 guid->Data4[i + 2] = strtol(b, NULL, 16);
3538 return TRUE;
3541 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3543 WORD bytelen;
3544 DWORD len;
3545 BSTR tmp_str;
3547 *pStr = NULL;
3548 bytelen = *(const WORD*)ptr;
3549 if(bytelen == 0xffff) return 2;
3551 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3552 tmp_str = SysAllocStringLen(NULL, len);
3553 if (*tmp_str) {
3554 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3555 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3556 SysFreeString(tmp_str);
3558 return bytelen + 2;
3561 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3563 WORD bytelen;
3565 *str = NULL;
3566 bytelen = *(const WORD*)ptr;
3567 if(bytelen == 0xffff) return 2;
3568 *str = heap_alloc(bytelen + 1);
3569 memcpy(*str, ptr + 2, bytelen);
3570 (*str)[bytelen] = '\0';
3571 return bytelen + 2;
3574 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3576 BSTR tmp_str;
3577 TLBString *tlbstr;
3579 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3580 if (tlbstr->offset == offset)
3581 return tlbstr;
3584 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3585 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3586 SysFreeString(tmp_str);
3588 return tlbstr;
3591 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3593 char *ptr = pLibBlk;
3594 WORD w;
3596 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3597 FIXME("libblk magic = %04x\n", w);
3598 return 0;
3601 ptr += 6;
3602 if((w = *(WORD*)ptr) != 0xffff) {
3603 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3604 ptr += w;
3606 ptr += 2;
3608 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3610 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3612 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3613 ptr += 4;
3615 pTypeLibImpl->syskind = *(WORD*)ptr;
3616 ptr += 2;
3618 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3619 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3620 else
3621 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3622 ptr += 2;
3624 ptr += 4; /* skip res12 */
3626 pTypeLibImpl->libflags = *(WORD*)ptr;
3627 ptr += 2;
3629 pTypeLibImpl->ver_major = *(WORD*)ptr;
3630 ptr += 2;
3632 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3633 ptr += 2;
3635 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr);
3636 ptr += sizeof(GUID);
3638 return ptr - (char*)pLibBlk;
3641 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3642 typedef struct
3644 unsigned int num;
3645 HREFTYPE refs[1];
3646 } sltg_ref_lookup_t;
3648 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3649 HREFTYPE *typelib_ref)
3651 if(table && typeinfo_ref < table->num)
3653 *typelib_ref = table->refs[typeinfo_ref];
3654 return S_OK;
3657 ERR_(typelib)("Unable to find reference\n");
3658 *typelib_ref = -1;
3659 return E_FAIL;
3662 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3664 BOOL done = FALSE;
3666 while(!done) {
3667 if((*pType & 0xe00) == 0xe00) {
3668 pTD->vt = VT_PTR;
3669 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3670 pTD = pTD->u.lptdesc;
3672 switch(*pType & 0x3f) {
3673 case VT_PTR:
3674 pTD->vt = VT_PTR;
3675 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3676 pTD = pTD->u.lptdesc;
3677 break;
3679 case VT_USERDEFINED:
3680 pTD->vt = VT_USERDEFINED;
3681 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3682 done = TRUE;
3683 break;
3685 case VT_CARRAY:
3687 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3688 array */
3690 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3692 pTD->vt = VT_CARRAY;
3693 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3694 pTD->u.lpadesc->cDims = pSA->cDims;
3695 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3696 pSA->cDims * sizeof(SAFEARRAYBOUND));
3698 pTD = &pTD->u.lpadesc->tdescElem;
3699 break;
3702 case VT_SAFEARRAY:
3704 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3705 useful? */
3707 pType++;
3708 pTD->vt = VT_SAFEARRAY;
3709 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3710 pTD = pTD->u.lptdesc;
3711 break;
3713 default:
3714 pTD->vt = *pType & 0x3f;
3715 done = TRUE;
3716 break;
3718 pType++;
3720 return pType;
3723 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3724 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3726 /* Handle [in/out] first */
3727 if((*pType & 0xc000) == 0xc000)
3728 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3729 else if(*pType & 0x8000)
3730 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3731 else if(*pType & 0x4000)
3732 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3733 else
3734 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3736 if(*pType & 0x2000)
3737 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3739 if(*pType & 0x80)
3740 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3742 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3746 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3747 char *pNameTable)
3749 unsigned int ref;
3750 char *name;
3751 TLBRefType *ref_type;
3752 sltg_ref_lookup_t *table;
3753 HREFTYPE typelib_ref;
3755 if(pRef->magic != SLTG_REF_MAGIC) {
3756 FIXME("Ref magic = %x\n", pRef->magic);
3757 return NULL;
3759 name = ( (char*)pRef->names + pRef->number);
3761 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3762 table->num = pRef->number >> 3;
3764 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3766 /* We don't want the first href to be 0 */
3767 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3769 for(ref = 0; ref < pRef->number >> 3; ref++) {
3770 char *refname;
3771 unsigned int lib_offs, type_num;
3773 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3775 name += SLTG_ReadStringA(name, &refname);
3776 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3777 FIXME_(typelib)("Can't sscanf ref\n");
3778 if(lib_offs != 0xffff) {
3779 TLBImpLib *import;
3781 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3782 if(import->offset == lib_offs)
3783 break;
3785 if(&import->entry == &pTL->implib_list) {
3786 char fname[MAX_PATH+1];
3787 int len;
3788 GUID tmpguid;
3790 import = heap_alloc_zero(sizeof(*import));
3791 import->offset = lib_offs;
3792 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3793 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid);
3794 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3795 &import->wVersionMajor,
3796 &import->wVersionMinor,
3797 &import->lcid, fname) != 4) {
3798 FIXME_(typelib)("can't sscanf ref %s\n",
3799 pNameTable + lib_offs + 40);
3801 len = strlen(fname);
3802 if(fname[len-1] != '#')
3803 FIXME("fname = %s\n", fname);
3804 fname[len-1] = '\0';
3805 import->name = TLB_MultiByteToBSTR(fname);
3806 list_add_tail(&pTL->implib_list, &import->entry);
3808 ref_type->pImpTLInfo = import;
3810 /* Store a reference to IDispatch */
3811 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3812 pTL->dispatch_href = typelib_ref;
3814 } else { /* internal ref */
3815 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3817 ref_type->reference = typelib_ref;
3818 ref_type->index = type_num;
3820 heap_free(refname);
3821 list_add_tail(&pTL->ref_list, &ref_type->entry);
3823 table->refs[ref] = typelib_ref;
3824 typelib_ref += 4;
3826 if((BYTE)*name != SLTG_REF_MAGIC)
3827 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3828 dump_TLBRefType(pTL);
3829 return table;
3832 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3833 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3835 SLTG_ImplInfo *info;
3836 TLBImplType *pImplType;
3837 /* I don't really get this structure, usually it's 0x16 bytes
3838 long, but iuser.tlb contains some that are 0x18 bytes long.
3839 That's ok because we can use the next ptr to jump to the next
3840 one. But how do we know the length of the last one? The WORD
3841 at offs 0x8 might be the clue. For now I'm just assuming that
3842 the last one is the regular 0x16 bytes. */
3844 info = (SLTG_ImplInfo*)pBlk;
3845 while(1){
3846 pTI->cImplTypes++;
3847 if(info->next == 0xffff)
3848 break;
3849 info = (SLTG_ImplInfo*)(pBlk + info->next);
3852 info = (SLTG_ImplInfo*)pBlk;
3853 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
3854 pImplType = pTI->impltypes;
3855 while(1) {
3856 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3857 pImplType->implflags = info->impltypeflags;
3858 ++pImplType;
3860 if(info->next == 0xffff)
3861 break;
3862 if(OneOnly)
3863 FIXME_(typelib)("Interface inheriting more than one interface\n");
3864 info = (SLTG_ImplInfo*)(pBlk + info->next);
3866 info++; /* see comment at top of function */
3867 return (char*)info;
3870 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3871 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3873 TLBVarDesc *pVarDesc;
3874 const TLBString *prevName = NULL;
3875 SLTG_Variable *pItem;
3876 unsigned short i;
3877 WORD *pType;
3879 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3881 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3882 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3884 pVarDesc->vardesc.memid = pItem->memid;
3886 if (pItem->magic != SLTG_VAR_MAGIC &&
3887 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3888 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3889 return;
3892 if (pItem->name == 0xfffe)
3893 pVarDesc->Name = prevName;
3894 else
3895 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
3897 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
3898 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3899 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3901 if(pItem->flags & 0x02)
3902 pType = &pItem->type;
3903 else
3904 pType = (WORD*)(pBlk + pItem->type);
3906 if (pItem->flags & ~0xda)
3907 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3909 SLTG_DoElem(pType, pBlk,
3910 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3912 if (TRACE_ON(typelib)) {
3913 char buf[300];
3914 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3915 TRACE_(typelib)("elemdescVar: %s\n", buf);
3918 if (pItem->flags & 0x40) {
3919 TRACE_(typelib)("VAR_DISPATCH\n");
3920 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3922 else if (pItem->flags & 0x10) {
3923 TRACE_(typelib)("VAR_CONST\n");
3924 pVarDesc->vardesc.varkind = VAR_CONST;
3925 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3926 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3927 if (pItem->flags & 0x08)
3928 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3929 else {
3930 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3932 case VT_LPSTR:
3933 case VT_LPWSTR:
3934 case VT_BSTR:
3936 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3937 BSTR str;
3938 TRACE_(typelib)("len = %u\n", len);
3939 if (len == 0xffff) {
3940 str = NULL;
3941 } else {
3942 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3943 str = SysAllocStringLen(NULL, alloc_len);
3944 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3946 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3947 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3948 break;
3950 case VT_I2:
3951 case VT_UI2:
3952 case VT_I4:
3953 case VT_UI4:
3954 case VT_INT:
3955 case VT_UINT:
3956 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3957 *(INT*)(pBlk + pItem->byte_offs);
3958 break;
3959 default:
3960 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3964 else {
3965 TRACE_(typelib)("VAR_PERINSTANCE\n");
3966 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3967 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3970 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3971 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3973 if (pItem->flags & 0x80)
3974 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3976 prevName = pVarDesc->Name;
3978 pTI->cVars = cVars;
3981 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3982 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3984 SLTG_Function *pFunc;
3985 unsigned short i;
3986 TLBFuncDesc *pFuncDesc;
3988 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
3990 pFuncDesc = pTI->funcdescs;
3991 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3992 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3994 int param;
3995 WORD *pType, *pArg;
3997 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3998 case SLTG_FUNCTION_MAGIC:
3999 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4000 break;
4001 case SLTG_DISPATCH_FUNCTION_MAGIC:
4002 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4003 break;
4004 case SLTG_STATIC_FUNCTION_MAGIC:
4005 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4006 break;
4007 default:
4008 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4009 continue;
4011 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4013 pFuncDesc->funcdesc.memid = pFunc->dispid;
4014 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4015 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4016 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4017 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4018 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4020 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4021 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4023 if(pFunc->retnextopt & 0x80)
4024 pType = &pFunc->rettype;
4025 else
4026 pType = (WORD*)(pBlk + pFunc->rettype);
4028 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4030 pFuncDesc->funcdesc.lprgelemdescParam =
4031 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4032 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4034 pArg = (WORD*)(pBlk + pFunc->arg_off);
4036 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4037 char *paramName = pNameTable + *pArg;
4038 BOOL HaveOffs;
4039 /* If arg type follows then paramName points to the 2nd
4040 letter of the name, else the next WORD is an offset to
4041 the arg type and paramName points to the first letter.
4042 So let's take one char off paramName and see if we're
4043 pointing at an alpha-numeric char. However if *pArg is
4044 0xffff or 0xfffe then the param has no name, the former
4045 meaning that the next WORD is the type, the latter
4046 meaning that the next WORD is an offset to the type. */
4048 HaveOffs = FALSE;
4049 if(*pArg == 0xffff)
4050 paramName = NULL;
4051 else if(*pArg == 0xfffe) {
4052 paramName = NULL;
4053 HaveOffs = TRUE;
4055 else if(paramName[-1] && !isalnum(paramName[-1]))
4056 HaveOffs = TRUE;
4058 pArg++;
4060 if(HaveOffs) { /* the next word is an offset to type */
4061 pType = (WORD*)(pBlk + *pArg);
4062 SLTG_DoElem(pType, pBlk,
4063 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4064 pArg++;
4065 } else {
4066 if(paramName)
4067 paramName--;
4068 pArg = SLTG_DoElem(pArg, pBlk,
4069 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4072 /* Are we an optional param ? */
4073 if(pFuncDesc->funcdesc.cParams - param <=
4074 pFuncDesc->funcdesc.cParamsOpt)
4075 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4077 if(paramName) {
4078 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4079 paramName - pNameTable, pTI->pTypeLib);
4080 } else {
4081 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4085 pTI->cFuncs = cFuncs;
4088 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4089 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4090 SLTG_TypeInfoTail *pTITail)
4092 char *pFirstItem;
4093 sltg_ref_lookup_t *ref_lookup = NULL;
4095 if(pTIHeader->href_table != 0xffffffff) {
4096 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4097 pNameTable);
4100 pFirstItem = pBlk;
4102 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4103 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4105 heap_free(ref_lookup);
4109 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4110 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4111 const SLTG_TypeInfoTail *pTITail)
4113 char *pFirstItem;
4114 sltg_ref_lookup_t *ref_lookup = NULL;
4116 if(pTIHeader->href_table != 0xffffffff) {
4117 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4118 pNameTable);
4121 pFirstItem = pBlk;
4123 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4124 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4127 if (pTITail->funcs_off != 0xffff)
4128 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4130 heap_free(ref_lookup);
4132 if (TRACE_ON(typelib))
4133 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4136 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4137 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4138 const SLTG_TypeInfoTail *pTITail)
4140 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4143 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4144 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4145 const SLTG_TypeInfoTail *pTITail)
4147 WORD *pType;
4148 sltg_ref_lookup_t *ref_lookup = NULL;
4150 if (pTITail->simple_alias) {
4151 /* if simple alias, no more processing required */
4152 pTI->tdescAlias.vt = pTITail->tdescalias_vt;
4153 return;
4156 if(pTIHeader->href_table != 0xffffffff) {
4157 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4158 pNameTable);
4161 /* otherwise it is an offset to a type */
4162 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4164 SLTG_DoType(pType, pBlk, &pTI->tdescAlias, ref_lookup);
4166 heap_free(ref_lookup);
4169 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4170 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4171 const SLTG_TypeInfoTail *pTITail)
4173 sltg_ref_lookup_t *ref_lookup = NULL;
4174 if (pTIHeader->href_table != 0xffffffff)
4175 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4176 pNameTable);
4178 if (pTITail->vars_off != 0xffff)
4179 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4181 if (pTITail->funcs_off != 0xffff)
4182 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4184 if (pTITail->impls_off != 0xffff)
4185 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4187 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4188 * of dispinterface functions including the IDispatch ones, so
4189 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4190 pTI->cbSizeVft = pTI->cFuncs * sizeof(void *);
4192 heap_free(ref_lookup);
4193 if (TRACE_ON(typelib))
4194 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4197 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4198 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4199 const SLTG_TypeInfoTail *pTITail)
4201 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4204 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4205 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4206 const SLTG_TypeInfoTail *pTITail)
4208 sltg_ref_lookup_t *ref_lookup = NULL;
4209 if (pTIHeader->href_table != 0xffffffff)
4210 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4211 pNameTable);
4213 if (pTITail->vars_off != 0xffff)
4214 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4216 if (pTITail->funcs_off != 0xffff)
4217 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4218 heap_free(ref_lookup);
4219 if (TRACE_ON(typelib))
4220 dump_TypeInfo(pTI);
4223 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4224 manageable copy of it into this */
4225 typedef struct {
4226 WORD small_no;
4227 char *index_name;
4228 char *other_name;
4229 WORD res1a;
4230 WORD name_offs;
4231 WORD more_bytes;
4232 char *extra;
4233 WORD res20;
4234 DWORD helpcontext;
4235 WORD res26;
4236 GUID uuid;
4237 } SLTG_InternalOtherTypeInfo;
4239 /****************************************************************************
4240 * ITypeLib2_Constructor_SLTG
4242 * loading a SLTG typelib from an in-memory image
4244 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4246 ITypeLibImpl *pTypeLibImpl;
4247 SLTG_Header *pHeader;
4248 SLTG_BlkEntry *pBlkEntry;
4249 SLTG_Magic *pMagic;
4250 SLTG_Index *pIndex;
4251 SLTG_Pad9 *pPad9;
4252 LPVOID pBlk, pFirstBlk;
4253 SLTG_LibBlk *pLibBlk;
4254 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4255 char *pAfterOTIBlks = NULL;
4256 char *pNameTable, *ptr;
4257 int i;
4258 DWORD len, order;
4259 ITypeInfoImpl **ppTypeInfoImpl;
4261 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4264 pTypeLibImpl = TypeLibImpl_Constructor();
4265 if (!pTypeLibImpl) return NULL;
4267 pHeader = pLib;
4269 TRACE_(typelib)("header:\n");
4270 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4271 pHeader->nrOfFileBlks );
4272 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4273 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4274 pHeader->SLTG_magic);
4275 return NULL;
4278 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4279 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4281 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4282 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4284 /* Next we have a magic block */
4285 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4287 /* Let's see if we're still in sync */
4288 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4289 sizeof(SLTG_COMPOBJ_MAGIC))) {
4290 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4291 return NULL;
4293 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4294 sizeof(SLTG_DIR_MAGIC))) {
4295 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4296 return NULL;
4299 pIndex = (SLTG_Index*)(pMagic+1);
4301 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4303 pFirstBlk = pPad9 + 1;
4305 /* We'll set up a ptr to the main library block, which is the last one. */
4307 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4308 pBlkEntry[order].next != 0;
4309 order = pBlkEntry[order].next - 1, i++) {
4310 pBlk = (char*)pBlk + pBlkEntry[order].len;
4312 pLibBlk = pBlk;
4314 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4316 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4317 interspersed */
4319 len += 0x40;
4321 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4323 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4326 ptr = (char*)pLibBlk + len;
4328 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4329 WORD w, extra;
4330 len = 0;
4332 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4334 w = *(WORD*)(ptr + 2);
4335 if(w != 0xffff) {
4336 len += w;
4337 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4338 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4339 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4341 w = *(WORD*)(ptr + 4 + len);
4342 if(w != 0xffff) {
4343 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4344 len += w;
4345 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4346 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4347 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4349 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4350 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4351 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4352 if(extra) {
4353 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4354 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4355 len += extra;
4357 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4358 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4359 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4360 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4361 len += sizeof(SLTG_OtherTypeInfo);
4362 ptr += len;
4365 pAfterOTIBlks = ptr;
4367 /* Skip this WORD and get the next DWORD */
4368 len = *(DWORD*)(pAfterOTIBlks + 2);
4370 /* Now add this to pLibBLk look at what we're pointing at and
4371 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4372 dust and we should be pointing at the beginning of the name
4373 table */
4375 pNameTable = (char*)pLibBlk + len;
4377 switch(*(WORD*)pNameTable) {
4378 case 0xffff:
4379 break;
4380 case 0x0200:
4381 pNameTable += 0x20;
4382 break;
4383 default:
4384 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4385 break;
4388 pNameTable += 0x216;
4390 pNameTable += 2;
4392 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4394 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4397 /* Hopefully we now have enough ptrs set up to actually read in
4398 some TypeInfos. It's not clear which order to do them in, so
4399 I'll just follow the links along the BlkEntry chain and read
4400 them in the order in which they are in the file */
4402 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4403 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4405 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4406 pBlkEntry[order].next != 0;
4407 order = pBlkEntry[order].next - 1, i++) {
4409 SLTG_TypeInfoHeader *pTIHeader;
4410 SLTG_TypeInfoTail *pTITail;
4411 SLTG_MemberHeader *pMemHeader;
4413 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4414 FIXME_(typelib)("Index strings don't match\n");
4415 heap_free(pOtherTypeInfoBlks);
4416 return NULL;
4419 pTIHeader = pBlk;
4420 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4421 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4422 heap_free(pOtherTypeInfoBlks);
4423 return NULL;
4425 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4426 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4427 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4429 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4430 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4431 (*ppTypeInfoImpl)->index = i;
4432 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4433 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4434 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid);
4435 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4436 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4437 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4438 (*ppTypeInfoImpl)->wTypeFlags =
4439 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4441 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4442 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4444 if((pTIHeader->typeflags1 & 7) != 2)
4445 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4446 if(pTIHeader->typeflags3 != 2)
4447 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4449 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4450 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4451 typekind_desc[pTIHeader->typekind],
4452 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4453 (*ppTypeInfoImpl)->wTypeFlags);
4455 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4457 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4459 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4460 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4461 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4463 switch(pTIHeader->typekind) {
4464 case TKIND_ENUM:
4465 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4466 pTIHeader, pTITail);
4467 break;
4469 case TKIND_RECORD:
4470 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4471 pTIHeader, pTITail);
4472 break;
4474 case TKIND_INTERFACE:
4475 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4476 pTIHeader, pTITail);
4477 break;
4479 case TKIND_COCLASS:
4480 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4481 pTIHeader, pTITail);
4482 break;
4484 case TKIND_ALIAS:
4485 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4486 pTIHeader, pTITail);
4487 break;
4489 case TKIND_DISPATCH:
4490 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4491 pTIHeader, pTITail);
4492 break;
4494 case TKIND_MODULE:
4495 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4496 pTIHeader, pTITail);
4497 break;
4499 default:
4500 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4501 break;
4505 /* could get cFuncs, cVars and cImplTypes from here
4506 but we've already set those */
4507 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4508 X(06);
4509 X(16);
4510 X(18);
4511 X(1a);
4512 X(1e);
4513 X(24);
4514 X(26);
4515 X(2a);
4516 X(2c);
4517 X(2e);
4518 X(30);
4519 X(32);
4520 X(34);
4521 #undef X
4522 ++ppTypeInfoImpl;
4523 pBlk = (char*)pBlk + pBlkEntry[order].len;
4526 if(i != pTypeLibImpl->TypeInfoCount) {
4527 FIXME("Somehow processed %d TypeInfos\n", i);
4528 heap_free(pOtherTypeInfoBlks);
4529 return NULL;
4532 heap_free(pOtherTypeInfoBlks);
4533 return &pTypeLibImpl->ITypeLib2_iface;
4536 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4538 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4540 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4542 if(IsEqualIID(riid, &IID_IUnknown) ||
4543 IsEqualIID(riid,&IID_ITypeLib)||
4544 IsEqualIID(riid,&IID_ITypeLib2))
4546 *ppv = &This->ITypeLib2_iface;
4548 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4549 IsEqualIID(riid, &IID_ICreateTypeLib2))
4551 *ppv = &This->ICreateTypeLib2_iface;
4553 else
4555 *ppv = NULL;
4556 TRACE("-- Interface: E_NOINTERFACE\n");
4557 return E_NOINTERFACE;
4560 IUnknown_AddRef((IUnknown*)*ppv);
4561 return S_OK;
4564 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4566 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4567 ULONG ref = InterlockedIncrement(&This->ref);
4569 TRACE("(%p) ref=%u\n", This, ref);
4571 return ref;
4574 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4576 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4577 ULONG ref = InterlockedDecrement(&This->ref);
4579 TRACE("(%p) ref=%u\n",This, ref);
4581 if (!ref)
4583 TLBImpLib *pImpLib, *pImpLibNext;
4584 TLBRefType *ref_type;
4585 TLBString *tlbstr, *tlbstr_next;
4586 void *cursor2;
4587 int i;
4589 /* remove cache entry */
4590 if(This->path)
4592 TRACE("removing from cache list\n");
4593 EnterCriticalSection(&cache_section);
4594 if(This->entry.next)
4595 list_remove(&This->entry);
4596 LeaveCriticalSection(&cache_section);
4597 heap_free(This->path);
4599 TRACE(" destroying ITypeLib(%p)\n",This);
4601 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4602 list_remove(&tlbstr->entry);
4603 heap_free(tlbstr);
4606 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4607 list_remove(&tlbstr->entry);
4608 heap_free(tlbstr);
4611 TLB_FreeCustData(&This->custdata_list);
4613 for (i = 0; i < This->ctTypeDesc; i++)
4614 if (This->pTypeDesc[i].vt == VT_CARRAY)
4615 heap_free(This->pTypeDesc[i].u.lpadesc);
4617 heap_free(This->pTypeDesc);
4619 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4621 if (pImpLib->pImpTypeLib)
4622 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4623 SysFreeString(pImpLib->name);
4625 list_remove(&pImpLib->entry);
4626 heap_free(pImpLib);
4629 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4631 list_remove(&ref_type->entry);
4632 heap_free(ref_type);
4635 for (i = 0; i < This->TypeInfoCount; ++i)
4636 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4637 heap_free(This->typeinfos);
4638 heap_free(This);
4639 return 0;
4642 return ref;
4645 /* ITypeLib::GetTypeInfoCount
4647 * Returns the number of type descriptions in the type library
4649 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4651 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4652 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4653 return This->TypeInfoCount;
4656 /* ITypeLib::GetTypeInfo
4658 * retrieves the specified type description in the library.
4660 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4661 ITypeLib2 *iface,
4662 UINT index,
4663 ITypeInfo **ppTInfo)
4665 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4667 TRACE("%p %u %p\n", This, index, ppTInfo);
4669 if(!ppTInfo)
4670 return E_INVALIDARG;
4672 if(index >= This->TypeInfoCount)
4673 return TYPE_E_ELEMENTNOTFOUND;
4675 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4676 ITypeInfo_AddRef(*ppTInfo);
4678 return S_OK;
4682 /* ITypeLibs::GetTypeInfoType
4684 * Retrieves the type of a type description.
4686 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4687 ITypeLib2 *iface,
4688 UINT index,
4689 TYPEKIND *pTKind)
4691 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4693 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4695 if(!pTKind)
4696 return E_INVALIDARG;
4698 if(index >= This->TypeInfoCount)
4699 return TYPE_E_ELEMENTNOTFOUND;
4701 *pTKind = This->typeinfos[index]->typekind;
4703 return S_OK;
4706 /* ITypeLib::GetTypeInfoOfGuid
4708 * Retrieves the type description that corresponds to the specified GUID.
4711 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4712 ITypeLib2 *iface,
4713 REFGUID guid,
4714 ITypeInfo **ppTInfo)
4716 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4717 int i;
4719 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4721 for(i = 0; i < This->TypeInfoCount; ++i){
4722 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4723 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4724 ITypeInfo_AddRef(*ppTInfo);
4725 return S_OK;
4729 return TYPE_E_ELEMENTNOTFOUND;
4732 /* ITypeLib::GetLibAttr
4734 * Retrieves the structure that contains the library's attributes.
4737 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4738 ITypeLib2 *iface,
4739 LPTLIBATTR *attr)
4741 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4743 TRACE("(%p, %p)\n", This, attr);
4745 if (!attr) return E_INVALIDARG;
4747 *attr = heap_alloc(sizeof(**attr));
4748 if (!*attr) return E_OUTOFMEMORY;
4750 (*attr)->guid = *TLB_get_guid_null(This->guid);
4751 (*attr)->lcid = This->set_lcid;
4752 (*attr)->syskind = This->syskind;
4753 (*attr)->wMajorVerNum = This->ver_major;
4754 (*attr)->wMinorVerNum = This->ver_minor;
4755 (*attr)->wLibFlags = This->libflags;
4757 return S_OK;
4760 /* ITypeLib::GetTypeComp
4762 * Enables a client compiler to bind to a library's types, variables,
4763 * constants, and global functions.
4766 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4767 ITypeLib2 *iface,
4768 ITypeComp **ppTComp)
4770 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4772 TRACE("(%p)->(%p)\n",This,ppTComp);
4773 *ppTComp = &This->ITypeComp_iface;
4774 ITypeComp_AddRef(*ppTComp);
4776 return S_OK;
4779 /* ITypeLib::GetDocumentation
4781 * Retrieves the library's documentation string, the complete Help file name
4782 * and path, and the context identifier for the library Help topic in the Help
4783 * file.
4785 * On a successful return all non-null BSTR pointers will have been set,
4786 * possibly to NULL.
4788 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4789 ITypeLib2 *iface,
4790 INT index,
4791 BSTR *pBstrName,
4792 BSTR *pBstrDocString,
4793 DWORD *pdwHelpContext,
4794 BSTR *pBstrHelpFile)
4796 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4797 HRESULT result = E_INVALIDARG;
4798 ITypeInfo *pTInfo;
4800 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4801 This, index,
4802 pBstrName, pBstrDocString,
4803 pdwHelpContext, pBstrHelpFile);
4805 if(index<0)
4807 /* documentation for the typelib */
4808 if(pBstrName)
4810 if (This->Name)
4812 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4813 goto memerr1;
4815 else
4816 *pBstrName = NULL;
4818 if(pBstrDocString)
4820 if (This->DocString)
4822 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4823 goto memerr2;
4825 else if (This->Name)
4827 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->Name))))
4828 goto memerr2;
4830 else
4831 *pBstrDocString = NULL;
4833 if(pdwHelpContext)
4835 *pdwHelpContext = This->dwHelpContext;
4837 if(pBstrHelpFile)
4839 if (This->HelpFile)
4841 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4842 goto memerr3;
4844 else
4845 *pBstrHelpFile = NULL;
4848 result = S_OK;
4850 else
4852 /* for a typeinfo */
4853 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4855 if(SUCCEEDED(result))
4857 result = ITypeInfo_GetDocumentation(pTInfo,
4858 MEMBERID_NIL,
4859 pBstrName,
4860 pBstrDocString,
4861 pdwHelpContext, pBstrHelpFile);
4863 ITypeInfo_Release(pTInfo);
4866 return result;
4867 memerr3:
4868 if (pBstrDocString) SysFreeString (*pBstrDocString);
4869 memerr2:
4870 if (pBstrName) SysFreeString (*pBstrName);
4871 memerr1:
4872 return STG_E_INSUFFICIENTMEMORY;
4875 /* ITypeLib::IsName
4877 * Indicates whether a passed-in string contains the name of a type or member
4878 * described in the library.
4881 static HRESULT WINAPI ITypeLib2_fnIsName(
4882 ITypeLib2 *iface,
4883 LPOLESTR szNameBuf,
4884 ULONG lHashVal,
4885 BOOL *pfName)
4887 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4888 int tic;
4889 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4891 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4892 pfName);
4894 *pfName=TRUE;
4895 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4896 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4897 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4898 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4899 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4900 int pc;
4901 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4902 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
4903 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
4904 goto ITypeLib2_fnIsName_exit;
4907 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
4908 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4909 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4913 *pfName=FALSE;
4915 ITypeLib2_fnIsName_exit:
4916 TRACE("(%p)slow! search for %s: %s found!\n", This,
4917 debugstr_w(szNameBuf), *pfName?"NOT":"");
4919 return S_OK;
4922 /* ITypeLib::FindName
4924 * Finds occurrences of a type description in a type library. This may be used
4925 * to quickly verify that a name exists in a type library.
4928 static HRESULT WINAPI ITypeLib2_fnFindName(
4929 ITypeLib2 *iface,
4930 LPOLESTR name,
4931 ULONG hash,
4932 ITypeInfo **ppTInfo,
4933 MEMBERID *memid,
4934 UINT16 *found)
4936 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4937 int tic;
4938 UINT count = 0;
4939 UINT len;
4941 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4943 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4944 return E_INVALIDARG;
4946 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4947 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4948 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4949 TLBVarDesc *var;
4950 UINT fdc;
4952 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4953 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4954 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4955 int pc;
4957 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4958 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4959 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
4960 goto ITypeLib2_fnFindName_exit;
4964 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
4965 if (var)
4966 goto ITypeLib2_fnFindName_exit;
4968 continue;
4969 ITypeLib2_fnFindName_exit:
4970 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4971 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4972 count++;
4974 TRACE("found %d typeinfos\n", count);
4976 *found = count;
4978 return S_OK;
4981 /* ITypeLib::ReleaseTLibAttr
4983 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4986 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4987 ITypeLib2 *iface,
4988 TLIBATTR *pTLibAttr)
4990 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4991 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4992 heap_free(pTLibAttr);
4995 /* ITypeLib2::GetCustData
4997 * gets the custom data
4999 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5000 ITypeLib2 * iface,
5001 REFGUID guid,
5002 VARIANT *pVarVal)
5004 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5005 TLBCustData *pCData;
5007 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5009 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5010 if(!pCData)
5011 return TYPE_E_ELEMENTNOTFOUND;
5013 VariantInit(pVarVal);
5014 VariantCopy(pVarVal, &pCData->data);
5016 return S_OK;
5019 /* ITypeLib2::GetLibStatistics
5021 * Returns statistics about a type library that are required for efficient
5022 * sizing of hash tables.
5025 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5026 ITypeLib2 * iface,
5027 ULONG *pcUniqueNames,
5028 ULONG *pcchUniqueNames)
5030 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5032 FIXME("(%p): stub!\n", This);
5034 if(pcUniqueNames) *pcUniqueNames=1;
5035 if(pcchUniqueNames) *pcchUniqueNames=1;
5036 return S_OK;
5039 /* ITypeLib2::GetDocumentation2
5041 * Retrieves the library's documentation string, the complete Help file name
5042 * and path, the localization context to use, and the context ID for the
5043 * library Help topic in the Help file.
5046 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5047 ITypeLib2 * iface,
5048 INT index,
5049 LCID lcid,
5050 BSTR *pbstrHelpString,
5051 DWORD *pdwHelpStringContext,
5052 BSTR *pbstrHelpStringDll)
5054 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5055 HRESULT result;
5056 ITypeInfo *pTInfo;
5058 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5060 /* the help string should be obtained from the helpstringdll,
5061 * using the _DLLGetDocumentation function, based on the supplied
5062 * lcid. Nice to do sometime...
5064 if(index<0)
5066 /* documentation for the typelib */
5067 if(pbstrHelpString)
5068 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5069 if(pdwHelpStringContext)
5070 *pdwHelpStringContext=This->dwHelpContext;
5071 if(pbstrHelpStringDll)
5072 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5074 result = S_OK;
5076 else
5078 /* for a typeinfo */
5079 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5081 if(SUCCEEDED(result))
5083 ITypeInfo2 * pTInfo2;
5084 result = ITypeInfo_QueryInterface(pTInfo,
5085 &IID_ITypeInfo2,
5086 (LPVOID*) &pTInfo2);
5088 if(SUCCEEDED(result))
5090 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5091 MEMBERID_NIL,
5092 lcid,
5093 pbstrHelpString,
5094 pdwHelpStringContext,
5095 pbstrHelpStringDll);
5097 ITypeInfo2_Release(pTInfo2);
5100 ITypeInfo_Release(pTInfo);
5103 return result;
5106 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5108 TLBCustData *pCData;
5109 unsigned int ct;
5110 CUSTDATAITEM *cdi;
5112 ct = list_count(custdata_list);
5114 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5115 if(!pCustData->prgCustData)
5116 return E_OUTOFMEMORY;
5118 pCustData->cCustData = ct;
5120 cdi = pCustData->prgCustData;
5121 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5122 cdi->guid = *TLB_get_guid_null(pCData->guid);
5123 VariantCopy(&cdi->varValue, &pCData->data);
5124 ++cdi;
5127 return S_OK;
5131 /* ITypeLib2::GetAllCustData
5133 * Gets all custom data items for the library.
5136 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5137 ITypeLib2 * iface,
5138 CUSTDATA *pCustData)
5140 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5141 TRACE("(%p)->(%p)\n", This, pCustData);
5142 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5145 static const ITypeLib2Vtbl tlbvt = {
5146 ITypeLib2_fnQueryInterface,
5147 ITypeLib2_fnAddRef,
5148 ITypeLib2_fnRelease,
5149 ITypeLib2_fnGetTypeInfoCount,
5150 ITypeLib2_fnGetTypeInfo,
5151 ITypeLib2_fnGetTypeInfoType,
5152 ITypeLib2_fnGetTypeInfoOfGuid,
5153 ITypeLib2_fnGetLibAttr,
5154 ITypeLib2_fnGetTypeComp,
5155 ITypeLib2_fnGetDocumentation,
5156 ITypeLib2_fnIsName,
5157 ITypeLib2_fnFindName,
5158 ITypeLib2_fnReleaseTLibAttr,
5160 ITypeLib2_fnGetCustData,
5161 ITypeLib2_fnGetLibStatistics,
5162 ITypeLib2_fnGetDocumentation2,
5163 ITypeLib2_fnGetAllCustData
5167 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5169 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5171 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5174 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5176 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5178 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5181 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5183 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5185 return ITypeLib2_Release(&This->ITypeLib2_iface);
5188 static HRESULT WINAPI ITypeLibComp_fnBind(
5189 ITypeComp * iface,
5190 OLECHAR * szName,
5191 ULONG lHash,
5192 WORD wFlags,
5193 ITypeInfo ** ppTInfo,
5194 DESCKIND * pDescKind,
5195 BINDPTR * pBindPtr)
5197 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5198 int typemismatch=0, i;
5200 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5202 *pDescKind = DESCKIND_NONE;
5203 pBindPtr->lptcomp = NULL;
5204 *ppTInfo = NULL;
5206 for(i = 0; i < This->TypeInfoCount; ++i){
5207 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5208 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5210 /* FIXME: check wFlags here? */
5211 /* FIXME: we should use a hash table to look this info up using lHash
5212 * instead of an O(n) search */
5213 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5214 (pTypeInfo->typekind == TKIND_MODULE))
5216 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5218 *pDescKind = DESCKIND_TYPECOMP;
5219 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5220 ITypeComp_AddRef(pBindPtr->lptcomp);
5221 TRACE("module or enum: %s\n", debugstr_w(szName));
5222 return S_OK;
5226 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5227 (pTypeInfo->typekind == TKIND_ENUM))
5229 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5230 HRESULT hr;
5232 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5233 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5235 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5236 return S_OK;
5238 else if (hr == TYPE_E_TYPEMISMATCH)
5239 typemismatch = 1;
5242 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5243 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5245 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5246 HRESULT hr;
5247 ITypeInfo *subtypeinfo;
5248 BINDPTR subbindptr;
5249 DESCKIND subdesckind;
5251 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5252 &subtypeinfo, &subdesckind, &subbindptr);
5253 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5255 TYPEDESC tdesc_appobject;
5256 const VARDESC vardesc_appobject =
5258 -2, /* memid */
5259 NULL, /* lpstrSchema */
5261 0 /* oInst */
5264 /* ELEMDESC */
5266 /* TYPEDESC */
5268 &tdesc_appobject
5270 VT_PTR
5273 0, /* wVarFlags */
5274 VAR_STATIC /* varkind */
5277 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5278 tdesc_appobject.vt = VT_USERDEFINED;
5280 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5282 /* cleanup things filled in by Bind call so we can put our
5283 * application object data in there instead */
5284 switch (subdesckind)
5286 case DESCKIND_FUNCDESC:
5287 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5288 break;
5289 case DESCKIND_VARDESC:
5290 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5291 break;
5292 default:
5293 break;
5295 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5297 if (pTypeInfo->hreftype == -1)
5298 FIXME("no hreftype for interface %p\n", pTypeInfo);
5300 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5301 if (FAILED(hr))
5302 return hr;
5304 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5305 *ppTInfo = (ITypeInfo *)pTypeInfo;
5306 ITypeInfo_AddRef(*ppTInfo);
5307 return S_OK;
5309 else if (hr == TYPE_E_TYPEMISMATCH)
5310 typemismatch = 1;
5314 if (typemismatch)
5316 TRACE("type mismatch %s\n", debugstr_w(szName));
5317 return TYPE_E_TYPEMISMATCH;
5319 else
5321 TRACE("name not found %s\n", debugstr_w(szName));
5322 return S_OK;
5326 static HRESULT WINAPI ITypeLibComp_fnBindType(
5327 ITypeComp * iface,
5328 OLECHAR * szName,
5329 ULONG lHash,
5330 ITypeInfo ** ppTInfo,
5331 ITypeComp ** ppTComp)
5333 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5334 ITypeInfoImpl *info;
5336 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5338 if(!szName || !ppTInfo || !ppTComp)
5339 return E_INVALIDARG;
5341 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5342 if(!info){
5343 *ppTInfo = NULL;
5344 *ppTComp = NULL;
5345 return S_OK;
5348 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5349 ITypeInfo_AddRef(*ppTInfo);
5350 *ppTComp = &info->ITypeComp_iface;
5351 ITypeComp_AddRef(*ppTComp);
5353 return S_OK;
5356 static const ITypeCompVtbl tlbtcvt =
5359 ITypeLibComp_fnQueryInterface,
5360 ITypeLibComp_fnAddRef,
5361 ITypeLibComp_fnRelease,
5363 ITypeLibComp_fnBind,
5364 ITypeLibComp_fnBindType
5367 /*================== ITypeInfo(2) Methods ===================================*/
5368 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5370 ITypeInfoImpl *pTypeInfoImpl;
5372 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5373 if (pTypeInfoImpl)
5375 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5376 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5377 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5378 pTypeInfoImpl->ref = 0;
5379 pTypeInfoImpl->hreftype = -1;
5380 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5381 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5382 list_init(&pTypeInfoImpl->custdata_list);
5384 TRACE("(%p)\n", pTypeInfoImpl);
5385 return pTypeInfoImpl;
5388 /* ITypeInfo::QueryInterface
5390 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5391 ITypeInfo2 *iface,
5392 REFIID riid,
5393 VOID **ppvObject)
5395 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5397 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5399 *ppvObject=NULL;
5400 if(IsEqualIID(riid, &IID_IUnknown) ||
5401 IsEqualIID(riid,&IID_ITypeInfo)||
5402 IsEqualIID(riid,&IID_ITypeInfo2))
5403 *ppvObject = This;
5404 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5405 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5406 *ppvObject = &This->ICreateTypeInfo2_iface;
5408 if(*ppvObject){
5409 ITypeInfo2_AddRef(iface);
5410 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5411 return S_OK;
5413 TRACE("-- Interface: E_NOINTERFACE\n");
5414 return E_NOINTERFACE;
5417 /* ITypeInfo::AddRef
5419 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5421 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5422 ULONG ref = InterlockedIncrement(&This->ref);
5424 TRACE("(%p)->ref is %u\n",This, ref);
5426 if (ref == 1 /* incremented from 0 */)
5427 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5429 return ref;
5432 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5434 UINT i;
5436 TRACE("destroying ITypeInfo(%p)\n",This);
5438 for (i = 0; i < This->cFuncs; ++i)
5440 int j;
5441 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5442 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5444 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5445 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5447 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5448 heap_free(elemdesc->u.paramdesc.pparamdescex);
5450 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5452 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5453 heap_free(pFInfo->pParamDesc);
5454 TLB_FreeCustData(&pFInfo->custdata_list);
5456 heap_free(This->funcdescs);
5458 for(i = 0; i < This->cVars; ++i)
5460 TLBVarDesc *pVInfo = &This->vardescs[i];
5461 if (pVInfo->vardesc.varkind == VAR_CONST)
5463 VariantClear(pVInfo->vardesc.u.lpvarValue);
5464 heap_free(pVInfo->vardesc.u.lpvarValue);
5466 TLB_FreeCustData(&pVInfo->custdata_list);
5468 heap_free(This->vardescs);
5470 if(This->impltypes){
5471 for (i = 0; i < This->cImplTypes; ++i){
5472 TLBImplType *pImpl = &This->impltypes[i];
5473 TLB_FreeCustData(&pImpl->custdata_list);
5475 heap_free(This->impltypes);
5478 TLB_FreeCustData(&This->custdata_list);
5480 heap_free(This);
5483 /* ITypeInfo::Release
5485 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5487 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5488 ULONG ref = InterlockedDecrement(&This->ref);
5490 TRACE("(%p)->(%u)\n",This, ref);
5492 if (!ref)
5494 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5495 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5496 if (not_attached_to_typelib)
5497 heap_free(This);
5498 /* otherwise This will be freed when typelib is freed */
5501 return ref;
5504 /* ITypeInfo::GetTypeAttr
5506 * Retrieves a TYPEATTR structure that contains the attributes of the type
5507 * description.
5510 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5511 LPTYPEATTR *ppTypeAttr)
5513 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5514 SIZE_T size;
5516 TRACE("(%p)\n",This);
5518 size = sizeof(**ppTypeAttr);
5519 if (This->typekind == TKIND_ALIAS)
5520 size += TLB_SizeTypeDesc(&This->tdescAlias, FALSE);
5522 *ppTypeAttr = heap_alloc(size);
5523 if (!*ppTypeAttr)
5524 return E_OUTOFMEMORY;
5526 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5527 (*ppTypeAttr)->lcid = This->lcid;
5528 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5529 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5530 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5531 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5532 (*ppTypeAttr)->typekind = This->typekind;
5533 (*ppTypeAttr)->cFuncs = This->cFuncs;
5534 (*ppTypeAttr)->cVars = This->cVars;
5535 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5536 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5537 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5538 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5539 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5540 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5541 (*ppTypeAttr)->tdescAlias = This->tdescAlias;
5542 (*ppTypeAttr)->idldescType = This->idldescType;
5544 if (This->typekind == TKIND_ALIAS)
5545 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5546 &This->tdescAlias, *ppTypeAttr + 1);
5548 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5549 /* This should include all the inherited funcs */
5550 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5551 /* This is always the size of IDispatch's vtbl */
5552 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5553 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5555 return S_OK;
5558 /* ITypeInfo::GetTypeComp
5560 * Retrieves the ITypeComp interface for the type description, which enables a
5561 * client compiler to bind to the type description's members.
5564 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5565 ITypeComp * *ppTComp)
5567 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5569 TRACE("(%p)->(%p)\n", This, ppTComp);
5571 *ppTComp = &This->ITypeComp_iface;
5572 ITypeComp_AddRef(*ppTComp);
5573 return S_OK;
5576 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5578 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5579 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5580 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5581 return size;
5584 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5586 *dest = *src;
5587 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5588 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5590 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5591 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5592 *buffer += sizeof(PARAMDESCEX);
5593 *pparamdescex_dest = *pparamdescex_src;
5594 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5595 VariantInit(&pparamdescex_dest->varDefaultValue);
5596 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5597 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5599 else
5600 dest->u.paramdesc.pparamdescex = NULL;
5601 return S_OK;
5604 static HRESULT TLB_SanitizeBSTR(BSTR str)
5606 UINT len = SysStringLen(str), i;
5607 for (i = 0; i < len; ++i)
5608 if (str[i] > 0x7f)
5609 str[i] = '?';
5610 return S_OK;
5613 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5615 if (V_VT(var) == VT_INT)
5616 return VariantChangeType(var, var, 0, VT_I4);
5617 else if (V_VT(var) == VT_UINT)
5618 return VariantChangeType(var, var, 0, VT_UI4);
5619 else if (V_VT(var) == VT_BSTR)
5620 return TLB_SanitizeBSTR(V_BSTR(var));
5622 return S_OK;
5625 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5627 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5628 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5631 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5633 FUNCDESC *dest;
5634 char *buffer;
5635 SIZE_T size = sizeof(*src);
5636 SHORT i;
5637 HRESULT hr;
5639 size += sizeof(*src->lprgscode) * src->cScodes;
5640 size += TLB_SizeElemDesc(&src->elemdescFunc);
5641 for (i = 0; i < src->cParams; i++)
5643 size += sizeof(ELEMDESC);
5644 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5647 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5648 if (!dest) return E_OUTOFMEMORY;
5650 *dest = *src;
5651 if (dispinterface) /* overwrite funckind */
5652 dest->funckind = FUNC_DISPATCH;
5653 buffer = (char *)(dest + 1);
5655 dest->oVft = dest->oVft & 0xFFFC;
5657 if (dest->cScodes) {
5658 dest->lprgscode = (SCODE *)buffer;
5659 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5660 buffer += sizeof(*src->lprgscode) * src->cScodes;
5661 } else
5662 dest->lprgscode = NULL;
5664 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5665 if (FAILED(hr))
5667 SysFreeString((BSTR)dest);
5668 return hr;
5671 if (dest->cParams) {
5672 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5673 buffer += sizeof(ELEMDESC) * src->cParams;
5674 for (i = 0; i < src->cParams; i++)
5676 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5677 if (FAILED(hr))
5678 break;
5680 if (FAILED(hr))
5682 /* undo the above actions */
5683 for (i = i - 1; i >= 0; i--)
5684 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5685 TLB_FreeElemDesc(&dest->elemdescFunc);
5686 SysFreeString((BSTR)dest);
5687 return hr;
5689 } else
5690 dest->lprgelemdescParam = NULL;
5692 /* special treatment for dispinterfaces: this makes functions appear
5693 * to return their [retval] value when it is really returning an
5694 * HRESULT */
5695 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5697 if (dest->cParams &&
5698 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5700 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5701 if (elemdesc->tdesc.vt != VT_PTR)
5703 ERR("elemdesc should have started with VT_PTR instead of:\n");
5704 if (ERR_ON(ole))
5705 dump_ELEMDESC(elemdesc);
5706 return E_UNEXPECTED;
5709 /* copy last parameter to the return value. we are using a flat
5710 * buffer so there is no danger of leaking memory in
5711 * elemdescFunc */
5712 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5714 /* remove the last parameter */
5715 dest->cParams--;
5717 else
5718 /* otherwise this function is made to appear to have no return
5719 * value */
5720 dest->elemdescFunc.tdesc.vt = VT_VOID;
5724 *dest_ptr = dest;
5725 return S_OK;
5728 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5730 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5732 if (index >= This->cFuncs)
5733 return TYPE_E_ELEMENTNOTFOUND;
5735 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5736 return S_OK;
5739 /* internal function to make the inherited interfaces' methods appear
5740 * part of the interface */
5741 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5742 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5744 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5745 HRESULT hr;
5746 UINT implemented_funcs = 0;
5748 if (funcs)
5749 *funcs = 0;
5750 else
5751 *hrefoffset = DISPATCH_HREF_OFFSET;
5753 if(This->impltypes)
5755 ITypeInfo *pSubTypeInfo;
5756 UINT sub_funcs;
5758 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5759 if (FAILED(hr))
5760 return hr;
5762 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5763 index,
5764 ppFuncDesc,
5765 &sub_funcs, hrefoffset);
5766 implemented_funcs += sub_funcs;
5767 ITypeInfo_Release(pSubTypeInfo);
5768 if (SUCCEEDED(hr))
5769 return hr;
5770 *hrefoffset += DISPATCH_HREF_OFFSET;
5773 if (funcs)
5774 *funcs = implemented_funcs + This->cFuncs;
5775 else
5776 *hrefoffset = 0;
5778 if (index < implemented_funcs)
5779 return E_INVALIDARG;
5780 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5781 ppFuncDesc);
5784 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5786 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5787 while (TRUE)
5789 switch (pTypeDesc->vt)
5791 case VT_USERDEFINED:
5792 pTypeDesc->u.hreftype += hrefoffset;
5793 return;
5794 case VT_PTR:
5795 case VT_SAFEARRAY:
5796 pTypeDesc = pTypeDesc->u.lptdesc;
5797 break;
5798 case VT_CARRAY:
5799 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5800 break;
5801 default:
5802 return;
5807 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5809 SHORT i;
5810 for (i = 0; i < pFuncDesc->cParams; i++)
5811 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5812 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5815 /* ITypeInfo::GetFuncDesc
5817 * Retrieves the FUNCDESC structure that contains information about a
5818 * specified function.
5821 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5822 LPFUNCDESC *ppFuncDesc)
5824 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5825 const FUNCDESC *internal_funcdesc;
5826 HRESULT hr;
5827 UINT hrefoffset = 0;
5829 TRACE("(%p) index %d\n", This, index);
5831 if (!ppFuncDesc)
5832 return E_INVALIDARG;
5834 if (This->needs_layout)
5835 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5837 if (This->typekind == TKIND_DISPATCH)
5838 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5839 &internal_funcdesc, NULL,
5840 &hrefoffset);
5841 else
5842 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5843 &internal_funcdesc);
5844 if (FAILED(hr))
5846 WARN("description for function %d not found\n", index);
5847 return hr;
5850 hr = TLB_AllocAndInitFuncDesc(
5851 internal_funcdesc,
5852 ppFuncDesc,
5853 This->typekind == TKIND_DISPATCH);
5855 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
5856 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5858 TRACE("-- 0x%08x\n", hr);
5859 return hr;
5862 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5864 VARDESC *dest;
5865 char *buffer;
5866 SIZE_T size = sizeof(*src);
5867 HRESULT hr;
5869 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5870 if (src->varkind == VAR_CONST)
5871 size += sizeof(VARIANT);
5872 size += TLB_SizeElemDesc(&src->elemdescVar);
5874 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5875 if (!dest) return E_OUTOFMEMORY;
5877 *dest = *src;
5878 buffer = (char *)(dest + 1);
5879 if (src->lpstrSchema)
5881 int len;
5882 dest->lpstrSchema = (LPOLESTR)buffer;
5883 len = strlenW(src->lpstrSchema);
5884 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5885 buffer += (len + 1) * sizeof(WCHAR);
5888 if (src->varkind == VAR_CONST)
5890 HRESULT hr;
5892 dest->u.lpvarValue = (VARIANT *)buffer;
5893 *dest->u.lpvarValue = *src->u.lpvarValue;
5894 buffer += sizeof(VARIANT);
5895 VariantInit(dest->u.lpvarValue);
5896 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5897 if (FAILED(hr))
5899 SysFreeString((BSTR)dest);
5900 return hr;
5903 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5904 if (FAILED(hr))
5906 if (src->varkind == VAR_CONST)
5907 VariantClear(dest->u.lpvarValue);
5908 SysFreeString((BSTR)dest);
5909 return hr;
5911 *dest_ptr = dest;
5912 return S_OK;
5915 /* ITypeInfo::GetVarDesc
5917 * Retrieves a VARDESC structure that describes the specified variable.
5920 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5921 LPVARDESC *ppVarDesc)
5923 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5924 const TLBVarDesc *pVDesc = &This->vardescs[index];
5926 TRACE("(%p) index %d\n", This, index);
5928 if(index >= This->cVars)
5929 return TYPE_E_ELEMENTNOTFOUND;
5931 if (This->needs_layout)
5932 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5934 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5937 /* ITypeInfo_GetNames
5939 * Retrieves the variable with the specified member ID (or the name of the
5940 * property or method and its parameters) that correspond to the specified
5941 * function ID.
5943 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5944 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5946 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5947 const TLBFuncDesc *pFDesc;
5948 const TLBVarDesc *pVDesc;
5949 int i;
5950 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5951 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
5952 if(pFDesc)
5954 /* function found, now return function and parameter names */
5955 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5957 if(!i)
5958 *rgBstrNames=SysAllocString(TLB_get_bstr(pFDesc->Name));
5959 else
5960 rgBstrNames[i]=SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i-1].Name));
5962 *pcNames=i;
5964 else
5966 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
5967 if(pVDesc)
5969 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
5970 *pcNames=1;
5972 else
5974 if(This->impltypes &&
5975 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
5976 /* recursive search */
5977 ITypeInfo *pTInfo;
5978 HRESULT result;
5979 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5980 if(SUCCEEDED(result))
5982 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5983 ITypeInfo_Release(pTInfo);
5984 return result;
5986 WARN("Could not search inherited interface!\n");
5988 else
5990 WARN("no names found\n");
5992 *pcNames=0;
5993 return TYPE_E_ELEMENTNOTFOUND;
5996 return S_OK;
6000 /* ITypeInfo::GetRefTypeOfImplType
6002 * If a type description describes a COM class, it retrieves the type
6003 * description of the implemented interface types. For an interface,
6004 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6005 * if any exist.
6008 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6009 ITypeInfo2 *iface,
6010 UINT index,
6011 HREFTYPE *pRefType)
6013 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6014 HRESULT hr = S_OK;
6016 TRACE("(%p) index %d\n", This, index);
6017 if (TRACE_ON(ole)) dump_TypeInfo(This);
6019 if(index==(UINT)-1)
6021 /* only valid on dual interfaces;
6022 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6025 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6027 *pRefType = -2;
6029 else
6031 hr = TYPE_E_ELEMENTNOTFOUND;
6034 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6036 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6037 *pRefType = This->pTypeLib->dispatch_href;
6039 else
6041 if(index >= This->cImplTypes)
6042 hr = TYPE_E_ELEMENTNOTFOUND;
6043 else
6044 *pRefType = This->impltypes[index].hRef;
6047 if(TRACE_ON(ole))
6049 if(SUCCEEDED(hr))
6050 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6051 else
6052 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6055 return hr;
6058 /* ITypeInfo::GetImplTypeFlags
6060 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6061 * or base interface in a type description.
6063 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6064 UINT index, INT *pImplTypeFlags)
6066 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6068 TRACE("(%p) index %d\n", This, index);
6070 if(!pImplTypeFlags)
6071 return E_INVALIDARG;
6073 if(This->typekind == TKIND_DISPATCH && index == 0){
6074 *pImplTypeFlags = 0;
6075 return S_OK;
6078 if(index >= This->cImplTypes)
6079 return TYPE_E_ELEMENTNOTFOUND;
6081 *pImplTypeFlags = This->impltypes[index].implflags;
6083 return S_OK;
6086 /* GetIDsOfNames
6087 * Maps between member names and member IDs, and parameter names and
6088 * parameter IDs.
6090 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6091 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6093 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6094 const TLBVarDesc *pVDesc;
6095 HRESULT ret=S_OK;
6096 UINT i, fdc;
6098 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6099 cNames);
6101 /* init out parameters in case of failure */
6102 for (i = 0; i < cNames; i++)
6103 pMemId[i] = MEMBERID_NIL;
6105 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6106 int j;
6107 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6108 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6109 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6110 for(i=1; i < cNames; i++){
6111 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6112 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6113 break;
6114 if( j<pFDesc->funcdesc.cParams)
6115 pMemId[i]=j;
6116 else
6117 ret=DISP_E_UNKNOWNNAME;
6119 TRACE("-- 0x%08x\n", ret);
6120 return ret;
6123 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6124 if(pVDesc){
6125 if(cNames)
6126 *pMemId = pVDesc->vardesc.memid;
6127 return ret;
6129 /* not found, see if it can be found in an inherited interface */
6130 if(This->impltypes) {
6131 /* recursive search */
6132 ITypeInfo *pTInfo;
6133 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6134 if(SUCCEEDED(ret)){
6135 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6136 ITypeInfo_Release(pTInfo);
6137 return ret;
6139 WARN("Could not search inherited interface!\n");
6140 } else
6141 WARN("no names found\n");
6142 return DISP_E_UNKNOWNNAME;
6146 #ifdef __i386__
6148 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6149 __ASM_GLOBAL_FUNC( call_method,
6150 "pushl %ebp\n\t"
6151 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6152 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6153 "movl %esp,%ebp\n\t"
6154 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6155 "pushl %esi\n\t"
6156 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6157 "pushl %edi\n\t"
6158 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6159 "movl 12(%ebp),%edx\n\t"
6160 "movl %esp,%edi\n\t"
6161 "shll $2,%edx\n\t"
6162 "jz 1f\n\t"
6163 "subl %edx,%edi\n\t"
6164 "andl $~15,%edi\n\t"
6165 "movl %edi,%esp\n\t"
6166 "movl 12(%ebp),%ecx\n\t"
6167 "movl 16(%ebp),%esi\n\t"
6168 "cld\n\t"
6169 "rep; movsl\n"
6170 "1:\tcall *8(%ebp)\n\t"
6171 "subl %esp,%edi\n\t"
6172 "movl 20(%ebp),%ecx\n\t"
6173 "movl %edi,(%ecx)\n\t"
6174 "leal -8(%ebp),%esp\n\t"
6175 "popl %edi\n\t"
6176 __ASM_CFI(".cfi_same_value %edi\n\t")
6177 "popl %esi\n\t"
6178 __ASM_CFI(".cfi_same_value %esi\n\t")
6179 "popl %ebp\n\t"
6180 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6181 __ASM_CFI(".cfi_same_value %ebp\n\t")
6182 "ret" )
6184 /* same function but returning floating point */
6185 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6187 /* ITypeInfo::Invoke
6189 * Invokes a method, or accesses a property of an object, that implements the
6190 * interface described by the type description.
6192 DWORD
6193 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6194 DWORD res;
6195 int stack_offset;
6197 if (TRACE_ON(ole)) {
6198 int i;
6199 TRACE("Calling %p(",func);
6200 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6201 if (nrargs > 30) TRACE("...");
6202 TRACE(")\n");
6205 switch (callconv) {
6206 case CC_STDCALL:
6207 case CC_CDECL:
6208 res = call_method( func, nrargs, args, &stack_offset );
6209 break;
6210 default:
6211 FIXME("unsupported calling convention %d\n",callconv);
6212 res = -1;
6213 break;
6215 TRACE("returns %08x\n",res);
6216 return res;
6219 #elif defined(__x86_64__)
6221 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6222 __ASM_GLOBAL_FUNC( call_method,
6223 "pushq %rbp\n\t"
6224 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6225 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6226 "movq %rsp,%rbp\n\t"
6227 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6228 "pushq %rsi\n\t"
6229 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6230 "pushq %rdi\n\t"
6231 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6232 "movq %rcx,%rax\n\t"
6233 "movq $4,%rcx\n\t"
6234 "cmp %rcx,%rdx\n\t"
6235 "cmovgq %rdx,%rcx\n\t"
6236 "leaq 0(,%rcx,8),%rdx\n\t"
6237 "subq %rdx,%rsp\n\t"
6238 "andq $~15,%rsp\n\t"
6239 "movq %rsp,%rdi\n\t"
6240 "movq %r8,%rsi\n\t"
6241 "rep; movsq\n\t"
6242 "movq 0(%rsp),%rcx\n\t"
6243 "movq 8(%rsp),%rdx\n\t"
6244 "movq 16(%rsp),%r8\n\t"
6245 "movq 24(%rsp),%r9\n\t"
6246 "movq %rcx,%xmm0\n\t"
6247 "movq %rdx,%xmm1\n\t"
6248 "movq %r8,%xmm2\n\t"
6249 "movq %r9,%xmm3\n\t"
6250 "callq *%rax\n\t"
6251 "leaq -16(%rbp),%rsp\n\t"
6252 "popq %rdi\n\t"
6253 __ASM_CFI(".cfi_same_value %rdi\n\t")
6254 "popq %rsi\n\t"
6255 __ASM_CFI(".cfi_same_value %rsi\n\t")
6256 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6257 "popq %rbp\n\t"
6258 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6259 __ASM_CFI(".cfi_same_value %rbp\n\t")
6260 "ret")
6262 /* same function but returning floating point */
6263 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6265 #endif /* __x86_64__ */
6267 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6269 HRESULT hr = S_OK;
6270 ITypeInfo *tinfo2 = NULL;
6271 TYPEATTR *tattr = NULL;
6273 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6274 if (hr)
6276 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6277 "hr = 0x%08x\n",
6278 tdesc->u.hreftype, hr);
6279 return hr;
6281 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6282 if (hr)
6284 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6285 ITypeInfo_Release(tinfo2);
6286 return hr;
6289 switch (tattr->typekind)
6291 case TKIND_ENUM:
6292 *vt |= VT_I4;
6293 break;
6295 case TKIND_ALIAS:
6296 tdesc = &tattr->tdescAlias;
6297 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6298 break;
6300 case TKIND_INTERFACE:
6301 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6302 *vt |= VT_DISPATCH;
6303 else
6304 *vt |= VT_UNKNOWN;
6305 break;
6307 case TKIND_DISPATCH:
6308 *vt |= VT_DISPATCH;
6309 break;
6311 case TKIND_COCLASS:
6312 *vt |= VT_DISPATCH;
6313 break;
6315 case TKIND_RECORD:
6316 FIXME("TKIND_RECORD unhandled.\n");
6317 hr = E_NOTIMPL;
6318 break;
6320 case TKIND_UNION:
6321 FIXME("TKIND_UNION unhandled.\n");
6322 hr = E_NOTIMPL;
6323 break;
6325 default:
6326 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6327 hr = E_NOTIMPL;
6328 break;
6330 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6331 ITypeInfo_Release(tinfo2);
6332 return hr;
6335 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6337 HRESULT hr = S_OK;
6339 /* enforce only one level of pointer indirection */
6340 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6342 tdesc = tdesc->u.lptdesc;
6344 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6345 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6346 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6347 if ((tdesc->vt == VT_USERDEFINED) ||
6348 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6350 VARTYPE vt_userdefined = 0;
6351 const TYPEDESC *tdesc_userdefined = tdesc;
6352 if (tdesc->vt == VT_PTR)
6354 vt_userdefined = VT_BYREF;
6355 tdesc_userdefined = tdesc->u.lptdesc;
6357 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6358 if ((hr == S_OK) &&
6359 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6360 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6362 *vt |= vt_userdefined;
6363 return S_OK;
6366 *vt = VT_BYREF;
6369 switch (tdesc->vt)
6371 case VT_HRESULT:
6372 *vt |= VT_ERROR;
6373 break;
6374 case VT_USERDEFINED:
6375 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6376 break;
6377 case VT_VOID:
6378 case VT_CARRAY:
6379 case VT_PTR:
6380 case VT_LPSTR:
6381 case VT_LPWSTR:
6382 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6383 hr = DISP_E_BADVARTYPE;
6384 break;
6385 case VT_SAFEARRAY:
6386 *vt |= VT_ARRAY;
6387 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6388 break;
6389 case VT_INT:
6390 *vt |= VT_I4;
6391 break;
6392 case VT_UINT:
6393 *vt |= VT_UI4;
6394 break;
6395 default:
6396 *vt |= tdesc->vt;
6397 break;
6399 return hr;
6402 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6404 ITypeInfo *tinfo2;
6405 TYPEATTR *tattr;
6406 HRESULT hres;
6408 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6409 if(FAILED(hres))
6410 return hres;
6412 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6413 if(FAILED(hres)) {
6414 ITypeInfo_Release(tinfo2);
6415 return hres;
6418 switch(tattr->typekind) {
6419 case TKIND_ALIAS:
6420 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6421 break;
6423 case TKIND_INTERFACE:
6424 case TKIND_DISPATCH:
6425 *guid = tattr->guid;
6426 break;
6428 default:
6429 ERR("Unexpected typekind %d\n", tattr->typekind);
6430 hres = E_UNEXPECTED;
6433 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6434 ITypeInfo_Release(tinfo2);
6435 return hres;
6438 /***********************************************************************
6439 * DispCallFunc (OLEAUT32.@)
6441 * Invokes a function of the specified calling convention, passing the
6442 * specified arguments and returns the result.
6444 * PARAMS
6445 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6446 * oVft [I] The offset in the vtable. See notes.
6447 * cc [I] Calling convention of the function to call.
6448 * vtReturn [I] The return type of the function.
6449 * cActuals [I] Number of parameters.
6450 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6451 * prgpvarg [I] The arguments to pass.
6452 * pvargResult [O] The return value of the function. Can be NULL.
6454 * RETURNS
6455 * Success: S_OK.
6456 * Failure: HRESULT code.
6458 * NOTES
6459 * The HRESULT return value of this function is not affected by the return
6460 * value of the user supplied function, which is returned in pvargResult.
6462 * If pvInstance is NULL then a non-object function is to be called and oVft
6463 * is the address of the function to call.
6465 * The cc parameter can be one of the following values:
6466 *|CC_FASTCALL
6467 *|CC_CDECL
6468 *|CC_PASCAL
6469 *|CC_STDCALL
6470 *|CC_FPFASTCALL
6471 *|CC_SYSCALL
6472 *|CC_MPWCDECL
6473 *|CC_MPWPASCAL
6476 HRESULT WINAPI
6477 DispCallFunc(
6478 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6479 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6481 #ifdef __i386__
6482 int argspos, stack_offset;
6483 void *func;
6484 UINT i;
6485 DWORD *args;
6487 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6488 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6489 pvargResult, V_VT(pvargResult));
6491 if (cc != CC_STDCALL && cc != CC_CDECL)
6493 FIXME("unsupported calling convention %d\n",cc);
6494 return E_INVALIDARG;
6497 /* maximum size for an argument is sizeof(VARIANT) */
6498 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6500 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6501 argspos = 1;
6502 if (pvInstance)
6504 const FARPROC *vtable = *(FARPROC **)pvInstance;
6505 func = vtable[oVft/sizeof(void *)];
6506 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6508 else func = (void *)oVft;
6510 for (i = 0; i < cActuals; i++)
6512 VARIANT *arg = prgpvarg[i];
6514 switch (prgvt[i])
6516 case VT_EMPTY:
6517 break;
6518 case VT_I8:
6519 case VT_UI8:
6520 case VT_R8:
6521 case VT_DATE:
6522 case VT_CY:
6523 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6524 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6525 break;
6526 case VT_DECIMAL:
6527 case VT_VARIANT:
6528 memcpy( &args[argspos], arg, sizeof(*arg) );
6529 argspos += sizeof(*arg) / sizeof(DWORD);
6530 break;
6531 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6532 args[argspos++] = V_BOOL(arg);
6533 break;
6534 default:
6535 args[argspos++] = V_UI4(arg);
6536 break;
6538 TRACE("arg %u: type %d\n",i,prgvt[i]);
6539 dump_Variant(arg);
6542 switch (vtReturn)
6544 case VT_EMPTY:
6545 call_method( func, argspos - 1, args + 1, &stack_offset );
6546 break;
6547 case VT_R4:
6548 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6549 break;
6550 case VT_R8:
6551 case VT_DATE:
6552 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6553 break;
6554 case VT_DECIMAL:
6555 case VT_VARIANT:
6556 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6557 call_method( func, argspos, args, &stack_offset );
6558 break;
6559 case VT_I8:
6560 case VT_UI8:
6561 case VT_CY:
6562 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6563 break;
6564 case VT_HRESULT:
6565 WARN("invalid return type %u\n", vtReturn);
6566 heap_free( args );
6567 return E_INVALIDARG;
6568 default:
6569 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6570 break;
6572 heap_free( args );
6573 if (stack_offset && cc == CC_STDCALL)
6575 WARN( "stack pointer off by %d\n", stack_offset );
6576 return DISP_E_BADCALLEE;
6578 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6579 TRACE("retval: "); dump_Variant(pvargResult);
6580 return S_OK;
6582 #elif defined(__x86_64__)
6583 int argspos;
6584 UINT i;
6585 DWORD_PTR *args;
6586 void *func;
6588 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6589 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6590 pvargResult, V_VT(pvargResult));
6592 if (cc != CC_STDCALL && cc != CC_CDECL)
6594 FIXME("unsupported calling convention %d\n",cc);
6595 return E_INVALIDARG;
6598 /* maximum size for an argument is sizeof(DWORD_PTR) */
6599 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6601 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6602 argspos = 1;
6603 if (pvInstance)
6605 const FARPROC *vtable = *(FARPROC **)pvInstance;
6606 func = vtable[oVft/sizeof(void *)];
6607 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6609 else func = (void *)oVft;
6611 for (i = 0; i < cActuals; i++)
6613 VARIANT *arg = prgpvarg[i];
6615 switch (prgvt[i])
6617 case VT_DECIMAL:
6618 case VT_VARIANT:
6619 args[argspos++] = (ULONG_PTR)arg;
6620 break;
6621 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6622 args[argspos++] = V_BOOL(arg);
6623 break;
6624 default:
6625 args[argspos++] = V_UI8(arg);
6626 break;
6628 TRACE("arg %u: type %d\n",i,prgvt[i]);
6629 dump_Variant(arg);
6632 switch (vtReturn)
6634 case VT_R4:
6635 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6636 break;
6637 case VT_R8:
6638 case VT_DATE:
6639 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6640 break;
6641 case VT_DECIMAL:
6642 case VT_VARIANT:
6643 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6644 call_method( func, argspos, args );
6645 break;
6646 case VT_HRESULT:
6647 WARN("invalid return type %u\n", vtReturn);
6648 heap_free( args );
6649 return E_INVALIDARG;
6650 default:
6651 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6652 break;
6654 heap_free( args );
6655 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6656 TRACE("retval: "); dump_Variant(pvargResult);
6657 return S_OK;
6659 #else
6660 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6661 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6662 return E_NOTIMPL;
6663 #endif
6666 static inline BOOL func_restricted( const FUNCDESC *desc )
6668 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6671 #define INVBUF_ELEMENT_SIZE \
6672 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6673 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6674 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6675 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6676 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6677 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6678 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6679 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6681 static HRESULT WINAPI ITypeInfo_fnInvoke(
6682 ITypeInfo2 *iface,
6683 VOID *pIUnk,
6684 MEMBERID memid,
6685 UINT16 wFlags,
6686 DISPPARAMS *pDispParams,
6687 VARIANT *pVarResult,
6688 EXCEPINFO *pExcepInfo,
6689 UINT *pArgErr)
6691 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6692 int i;
6693 unsigned int var_index;
6694 TYPEKIND type_kind;
6695 HRESULT hres;
6696 const TLBFuncDesc *pFuncInfo;
6697 UINT fdc;
6699 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6700 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6703 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6704 return DISP_E_MEMBERNOTFOUND;
6706 if (!pDispParams)
6708 ERR("NULL pDispParams not allowed\n");
6709 return E_INVALIDARG;
6712 dump_DispParms(pDispParams);
6714 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6716 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6717 pDispParams->cNamedArgs, pDispParams->cArgs);
6718 return E_INVALIDARG;
6721 /* we do this instead of using GetFuncDesc since it will return a fake
6722 * FUNCDESC for dispinterfaces and we want the real function description */
6723 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6724 pFuncInfo = &This->funcdescs[fdc];
6725 if ((memid == pFuncInfo->funcdesc.memid) &&
6726 (wFlags & pFuncInfo->funcdesc.invkind) &&
6727 !func_restricted( &pFuncInfo->funcdesc ))
6728 break;
6731 if (fdc < This->cFuncs) {
6732 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6734 if (TRACE_ON(ole))
6736 TRACE("invoking:\n");
6737 dump_TLBFuncDescOne(pFuncInfo);
6740 switch (func_desc->funckind) {
6741 case FUNC_PUREVIRTUAL:
6742 case FUNC_VIRTUAL: {
6743 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6744 VARIANT varresult;
6745 VARIANT retval; /* pointer for storing byref retvals in */
6746 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6747 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6748 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6749 UINT cNamedArgs = pDispParams->cNamedArgs;
6750 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6751 UINT vargs_converted=0;
6753 hres = S_OK;
6755 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6757 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6759 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6760 hres = DISP_E_PARAMNOTFOUND;
6761 goto func_fail;
6765 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6767 ERR("functions with the vararg attribute do not support named arguments\n");
6768 hres = DISP_E_NONAMEDARGS;
6769 goto func_fail;
6772 for (i = 0; i < func_desc->cParams; i++)
6774 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6775 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6776 if (FAILED(hres))
6777 goto func_fail;
6780 TRACE("changing args\n");
6781 for (i = 0; i < func_desc->cParams; i++)
6783 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6784 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6785 VARIANTARG *src_arg;
6787 if (wParamFlags & PARAMFLAG_FLCID)
6789 VARIANTARG *arg;
6790 arg = prgpvarg[i] = &rgvarg[i];
6791 V_VT(arg) = VT_I4;
6792 V_I4(arg) = This->pTypeLib->lcid;
6793 continue;
6796 src_arg = NULL;
6798 if (cNamedArgs)
6800 USHORT j;
6801 for (j = 0; j < cNamedArgs; j++)
6802 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6804 src_arg = &pDispParams->rgvarg[j];
6805 break;
6809 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6811 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6812 vargs_converted++;
6815 if (wParamFlags & PARAMFLAG_FRETVAL)
6817 /* under most conditions the caller is not allowed to
6818 * pass in a dispparam arg in the index of what would be
6819 * the retval parameter. however, there is an exception
6820 * where the extra parameter is used in an extra
6821 * IDispatch::Invoke below */
6822 if ((i < pDispParams->cArgs) &&
6823 ((func_desc->cParams != 1) || !pVarResult ||
6824 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6826 hres = DISP_E_BADPARAMCOUNT;
6827 break;
6830 /* note: this check is placed so that if the caller passes
6831 * in a VARIANTARG for the retval we just ignore it, like
6832 * native does */
6833 if (i == func_desc->cParams - 1)
6835 VARIANTARG *arg;
6836 arg = prgpvarg[i] = &rgvarg[i];
6837 memset(arg, 0, sizeof(*arg));
6838 V_VT(arg) = rgvt[i];
6839 memset(&retval, 0, sizeof(retval));
6840 V_BYREF(arg) = &retval;
6842 else
6844 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6845 hres = E_UNEXPECTED;
6846 break;
6849 else if (src_arg)
6851 dump_Variant(src_arg);
6853 if(rgvt[i]!=V_VT(src_arg))
6855 if (rgvt[i] == VT_VARIANT)
6856 hres = VariantCopy(&rgvarg[i], src_arg);
6857 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6859 if (rgvt[i] == V_VT(src_arg))
6860 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6861 else
6863 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6864 if (wParamFlags & PARAMFLAG_FIN)
6865 hres = VariantCopy(&missing_arg[i], src_arg);
6866 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6868 V_VT(&rgvarg[i]) = rgvt[i];
6870 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6872 SAFEARRAY *a;
6873 SAFEARRAYBOUND bound;
6874 VARIANT *v;
6875 LONG j;
6876 bound.lLbound = 0;
6877 bound.cElements = pDispParams->cArgs-i;
6878 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6880 ERR("SafeArrayCreate failed\n");
6881 break;
6883 hres = SafeArrayAccessData(a, (LPVOID)&v);
6884 if (hres != S_OK)
6886 ERR("SafeArrayAccessData failed with %x\n", hres);
6887 SafeArrayDestroy(a);
6888 break;
6890 for (j = 0; j < bound.cElements; j++)
6891 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6892 hres = SafeArrayUnaccessData(a);
6893 if (hres != S_OK)
6895 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6896 SafeArrayDestroy(a);
6897 break;
6899 V_ARRAY(&rgvarg[i]) = a;
6900 V_VT(&rgvarg[i]) = rgvt[i];
6902 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6904 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6905 if (wParamFlags & PARAMFLAG_FIN)
6906 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6907 else
6908 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6909 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6910 V_VT(&rgvarg[i]) = rgvt[i];
6912 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6914 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6915 V_VT(&rgvarg[i]) = rgvt[i];
6917 else
6919 /* FIXME: this doesn't work for VT_BYREF arguments if
6920 * they are not the same type as in the paramdesc */
6921 V_VT(&rgvarg[i]) = V_VT(src_arg);
6922 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6923 V_VT(&rgvarg[i]) = rgvt[i];
6926 if (FAILED(hres))
6928 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6929 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6930 debugstr_VT(src_arg), debugstr_VF(src_arg));
6931 break;
6933 prgpvarg[i] = &rgvarg[i];
6935 else
6937 prgpvarg[i] = src_arg;
6940 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6941 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6942 && V_UNKNOWN(prgpvarg[i])) {
6943 IUnknown *userdefined_iface;
6944 GUID guid;
6946 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6947 if(FAILED(hres))
6948 break;
6950 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6951 if(FAILED(hres)) {
6952 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6953 break;
6956 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6957 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6960 else if (wParamFlags & PARAMFLAG_FOPT)
6962 VARIANTARG *arg;
6963 arg = prgpvarg[i] = &rgvarg[i];
6964 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6966 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6967 if (FAILED(hres))
6968 break;
6970 else
6972 VARIANTARG *missing_arg;
6973 /* if the function wants a pointer to a variant then
6974 * set that up, otherwise just pass the VT_ERROR in
6975 * the argument by value */
6976 if (rgvt[i] & VT_BYREF)
6978 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6979 V_VT(arg) = VT_VARIANT | VT_BYREF;
6980 V_VARIANTREF(arg) = missing_arg;
6982 else
6983 missing_arg = arg;
6984 V_VT(missing_arg) = VT_ERROR;
6985 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6988 else
6990 hres = DISP_E_BADPARAMCOUNT;
6991 break;
6994 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6996 /* VT_VOID is a special case for return types, so it is not
6997 * handled in the general function */
6998 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6999 V_VT(&varresult) = VT_EMPTY;
7000 else
7002 V_VT(&varresult) = 0;
7003 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7004 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7007 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7008 V_VT(&varresult), func_desc->cParams, rgvt,
7009 prgpvarg, &varresult);
7011 vargs_converted = 0;
7013 for (i = 0; i < func_desc->cParams; i++)
7015 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7016 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7018 if (wParamFlags & PARAMFLAG_FLCID)
7019 continue;
7020 else if (wParamFlags & PARAMFLAG_FRETVAL)
7022 if (TRACE_ON(ole))
7024 TRACE("[retval] value: ");
7025 dump_Variant(prgpvarg[i]);
7028 if (pVarResult)
7030 VariantInit(pVarResult);
7031 /* deref return value */
7032 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7035 VARIANT_ClearInd(prgpvarg[i]);
7037 else if (vargs_converted < pDispParams->cArgs)
7039 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7040 if (wParamFlags & PARAMFLAG_FOUT)
7042 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7044 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7046 if (FAILED(hres))
7048 ERR("failed to convert param %d to vt %d\n", i,
7049 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7050 break;
7054 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7055 func_desc->cParamsOpt < 0 &&
7056 i == func_desc->cParams-1)
7058 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7059 LONG j, ubound;
7060 VARIANT *v;
7061 hres = SafeArrayGetUBound(a, 1, &ubound);
7062 if (hres != S_OK)
7064 ERR("SafeArrayGetUBound failed with %x\n", hres);
7065 break;
7067 hres = SafeArrayAccessData(a, (LPVOID)&v);
7068 if (hres != S_OK)
7070 ERR("SafeArrayAccessData failed with %x\n", hres);
7071 break;
7073 for (j = 0; j <= ubound; j++)
7074 VariantClear(&v[j]);
7075 hres = SafeArrayUnaccessData(a);
7076 if (hres != S_OK)
7078 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7079 break;
7082 VariantClear(&rgvarg[i]);
7083 vargs_converted++;
7085 else if (wParamFlags & PARAMFLAG_FOPT)
7087 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7088 VariantClear(&rgvarg[i]);
7091 VariantClear(&missing_arg[i]);
7094 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7096 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7097 hres = DISP_E_EXCEPTION;
7098 if (pExcepInfo)
7100 IErrorInfo *pErrorInfo;
7101 pExcepInfo->scode = V_ERROR(&varresult);
7102 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7104 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7105 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7106 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7107 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7109 IErrorInfo_Release(pErrorInfo);
7113 if (V_VT(&varresult) != VT_ERROR)
7115 TRACE("varresult value: ");
7116 dump_Variant(&varresult);
7118 if (pVarResult)
7120 VariantClear(pVarResult);
7121 *pVarResult = varresult;
7123 else
7124 VariantClear(&varresult);
7127 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7128 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7129 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7130 (pDispParams->cArgs != 0))
7132 if (V_VT(pVarResult) == VT_DISPATCH)
7134 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7135 /* Note: not VariantClear; we still need the dispatch
7136 * pointer to be valid */
7137 VariantInit(pVarResult);
7138 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7139 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7140 pDispParams, pVarResult, pExcepInfo, pArgErr);
7141 IDispatch_Release(pDispatch);
7143 else
7145 VariantClear(pVarResult);
7146 hres = DISP_E_NOTACOLLECTION;
7150 func_fail:
7151 heap_free(buffer);
7152 break;
7154 case FUNC_DISPATCH: {
7155 IDispatch *disp;
7157 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7158 if (SUCCEEDED(hres)) {
7159 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7160 hres = IDispatch_Invoke(
7161 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7162 pVarResult,pExcepInfo,pArgErr
7164 if (FAILED(hres))
7165 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7166 IDispatch_Release(disp);
7167 } else
7168 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7169 break;
7171 default:
7172 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7173 hres = E_FAIL;
7174 break;
7177 TRACE("-- 0x%08x\n", hres);
7178 return hres;
7180 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7181 VARDESC *var_desc;
7183 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7184 if(FAILED(hres)) return hres;
7186 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7187 dump_VARDESC(var_desc);
7188 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7189 return E_NOTIMPL;
7192 /* not found, look for it in inherited interfaces */
7193 ITypeInfo2_GetTypeKind(iface, &type_kind);
7194 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7195 if(This->impltypes) {
7196 /* recursive search */
7197 ITypeInfo *pTInfo;
7198 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7199 if(SUCCEEDED(hres)){
7200 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7201 ITypeInfo_Release(pTInfo);
7202 return hres;
7204 WARN("Could not search inherited interface!\n");
7207 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7208 return DISP_E_MEMBERNOTFOUND;
7211 /* ITypeInfo::GetDocumentation
7213 * Retrieves the documentation string, the complete Help file name and path,
7214 * and the context ID for the Help topic for a specified type description.
7216 * (Can be tested by the Visual Basic Editor in Word for instance.)
7218 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7219 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7220 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7222 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7223 const TLBFuncDesc *pFDesc;
7224 const TLBVarDesc *pVDesc;
7225 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7226 " HelpContext(%p) HelpFile(%p)\n",
7227 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7228 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7229 if(pBstrName)
7230 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7231 if(pBstrDocString)
7232 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7233 if(pdwHelpContext)
7234 *pdwHelpContext=This->dwHelpContext;
7235 if(pBstrHelpFile)
7236 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7237 return S_OK;
7238 }else {/* for a member */
7239 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7240 if(pFDesc){
7241 if(pBstrName)
7242 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7243 if(pBstrDocString)
7244 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7245 if(pdwHelpContext)
7246 *pdwHelpContext=pFDesc->helpcontext;
7247 if(pBstrHelpFile)
7248 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7249 return S_OK;
7251 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7252 if(pVDesc){
7253 if(pBstrName)
7254 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7255 if(pBstrDocString)
7256 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7257 if(pdwHelpContext)
7258 *pdwHelpContext=pVDesc->HelpContext;
7259 if(pBstrHelpFile)
7260 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7261 return S_OK;
7265 if(This->impltypes &&
7266 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7267 /* recursive search */
7268 ITypeInfo *pTInfo;
7269 HRESULT result;
7270 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7271 if(SUCCEEDED(result)) {
7272 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7273 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7274 ITypeInfo_Release(pTInfo);
7275 return result;
7277 WARN("Could not search inherited interface!\n");
7280 WARN("member %d not found\n", memid);
7281 return TYPE_E_ELEMENTNOTFOUND;
7284 /* ITypeInfo::GetDllEntry
7286 * Retrieves a description or specification of an entry point for a function
7287 * in a DLL.
7289 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7290 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7291 WORD *pwOrdinal)
7293 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7294 const TLBFuncDesc *pFDesc;
7296 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7298 if (pBstrDllName) *pBstrDllName = NULL;
7299 if (pBstrName) *pBstrName = NULL;
7300 if (pwOrdinal) *pwOrdinal = 0;
7302 if (This->typekind != TKIND_MODULE)
7303 return TYPE_E_BADMODULEKIND;
7305 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7306 if(pFDesc){
7307 dump_TypeInfo(This);
7308 if (TRACE_ON(ole))
7309 dump_TLBFuncDescOne(pFDesc);
7311 if (pBstrDllName)
7312 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7314 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7315 if (pBstrName)
7316 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7317 if (pwOrdinal)
7318 *pwOrdinal = -1;
7319 return S_OK;
7321 if (pBstrName)
7322 *pBstrName = NULL;
7323 if (pwOrdinal)
7324 *pwOrdinal = LOWORD(pFDesc->Entry);
7325 return S_OK;
7327 return TYPE_E_ELEMENTNOTFOUND;
7330 /* internal function to make the inherited interfaces' methods appear
7331 * part of the interface */
7332 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7333 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7335 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7336 HRESULT hr;
7338 TRACE("%p, 0x%x\n", iface, *hRefType);
7340 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7342 ITypeInfo *pSubTypeInfo;
7344 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7345 if (FAILED(hr))
7346 return hr;
7348 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7349 hRefType, ppTInfo);
7350 ITypeInfo_Release(pSubTypeInfo);
7351 if (SUCCEEDED(hr))
7352 return hr;
7354 *hRefType -= DISPATCH_HREF_OFFSET;
7356 if (!(*hRefType & DISPATCH_HREF_MASK))
7357 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7358 else
7359 return E_FAIL;
7362 /* ITypeInfo::GetRefTypeInfo
7364 * If a type description references other type descriptions, it retrieves
7365 * the referenced type descriptions.
7367 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7368 ITypeInfo2 *iface,
7369 HREFTYPE hRefType,
7370 ITypeInfo **ppTInfo)
7372 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7373 HRESULT result = E_FAIL;
7375 if(!ppTInfo)
7376 return E_INVALIDARG;
7378 if ((INT)hRefType < 0) {
7379 ITypeInfoImpl *pTypeInfoImpl;
7381 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7382 !(This->typekind == TKIND_INTERFACE ||
7383 This->typekind == TKIND_DISPATCH))
7384 return TYPE_E_ELEMENTNOTFOUND;
7386 /* when we meet a DUAL typeinfo, we must create the alternate
7387 * version of it.
7389 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7391 *pTypeInfoImpl = *This;
7392 pTypeInfoImpl->ref = 0;
7394 if (This->typekind == TKIND_INTERFACE)
7395 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7396 else
7397 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7399 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7400 /* the AddRef implicitly adds a reference to the parent typelib, which
7401 * stops the copied data from being destroyed until the new typeinfo's
7402 * refcount goes to zero, but we need to signal to the new instance to
7403 * not free its data structures when it is destroyed */
7404 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7406 ITypeInfo_AddRef(*ppTInfo);
7408 result = S_OK;
7409 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7410 (This->typekind == TKIND_DISPATCH))
7412 HREFTYPE href_dispatch = hRefType;
7413 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7414 } else {
7415 TLBRefType *ref_type;
7416 ITypeLib *pTLib = NULL;
7417 UINT i;
7419 if(!(hRefType & 0x1)){
7420 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7422 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7424 result = S_OK;
7425 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7426 ITypeInfo_AddRef(*ppTInfo);
7427 goto end;
7430 result = TYPE_E_ELEMENTNOTFOUND;
7431 goto end;
7434 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7436 if(ref_type->reference == (hRefType & (~0x3)))
7437 break;
7439 if(&ref_type->entry == &This->pTypeLib->ref_list)
7441 FIXME("Can't find pRefType for ref %x\n", hRefType);
7442 goto end;
7445 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7446 UINT Index;
7447 TRACE("internal reference\n");
7448 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7449 } else {
7450 if(ref_type->pImpTLInfo->pImpTypeLib) {
7451 TRACE("typeinfo in imported typelib that is already loaded\n");
7452 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7453 ITypeLib_AddRef(pTLib);
7454 result = S_OK;
7455 } else {
7456 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7457 result = LoadRegTypeLib( TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7458 ref_type->pImpTLInfo->wVersionMajor,
7459 ref_type->pImpTLInfo->wVersionMinor,
7460 ref_type->pImpTLInfo->lcid,
7461 &pTLib);
7463 if(FAILED(result)) {
7464 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7465 result=LoadTypeLib(libnam, &pTLib);
7466 SysFreeString(libnam);
7468 if(SUCCEEDED(result)) {
7469 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7470 ITypeLib_AddRef(pTLib);
7474 if(SUCCEEDED(result)) {
7475 if(ref_type->index == TLB_REF_USE_GUID)
7476 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7477 else
7478 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7480 if (pTLib != NULL)
7481 ITypeLib_Release(pTLib);
7484 end:
7485 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7486 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7487 return result;
7490 /* ITypeInfo::AddressOfMember
7492 * Retrieves the addresses of static functions or variables, such as those
7493 * defined in a DLL.
7495 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7496 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7498 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7499 HRESULT hr;
7500 BSTR dll, entry;
7501 WORD ordinal;
7502 HMODULE module;
7504 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7506 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7507 if (FAILED(hr))
7508 return hr;
7510 module = LoadLibraryW(dll);
7511 if (!module)
7513 ERR("couldn't load %s\n", debugstr_w(dll));
7514 SysFreeString(dll);
7515 SysFreeString(entry);
7516 return STG_E_FILENOTFOUND;
7518 /* FIXME: store library somewhere where we can free it */
7520 if (entry)
7522 LPSTR entryA;
7523 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7524 entryA = heap_alloc(len);
7525 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7527 *ppv = GetProcAddress(module, entryA);
7528 if (!*ppv)
7529 ERR("function not found %s\n", debugstr_a(entryA));
7531 heap_free(entryA);
7533 else
7535 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7536 if (!*ppv)
7537 ERR("function not found %d\n", ordinal);
7540 SysFreeString(dll);
7541 SysFreeString(entry);
7543 if (!*ppv)
7544 return TYPE_E_DLLFUNCTIONNOTFOUND;
7546 return S_OK;
7549 /* ITypeInfo::CreateInstance
7551 * Creates a new instance of a type that describes a component object class
7552 * (coclass).
7554 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7555 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7557 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7558 HRESULT hr;
7559 TYPEATTR *pTA;
7561 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7563 *ppvObj = NULL;
7565 if(pOuterUnk)
7567 WARN("Not able to aggregate\n");
7568 return CLASS_E_NOAGGREGATION;
7571 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7572 if(FAILED(hr)) return hr;
7574 if(pTA->typekind != TKIND_COCLASS)
7576 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7577 hr = E_INVALIDARG;
7578 goto end;
7581 hr = S_FALSE;
7582 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7584 IUnknown *pUnk;
7585 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7586 TRACE("GetActiveObject rets %08x\n", hr);
7587 if(hr == S_OK)
7589 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7590 IUnknown_Release(pUnk);
7594 if(hr != S_OK)
7595 hr = CoCreateInstance(&pTA->guid, NULL,
7596 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7597 riid, ppvObj);
7599 end:
7600 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7601 return hr;
7604 /* ITypeInfo::GetMops
7606 * Retrieves marshalling information.
7608 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7609 BSTR *pBstrMops)
7611 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7612 FIXME("(%p %d) stub!\n", This, memid);
7613 *pBstrMops = NULL;
7614 return S_OK;
7617 /* ITypeInfo::GetContainingTypeLib
7619 * Retrieves the containing type library and the index of the type description
7620 * within that type library.
7622 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7623 ITypeLib * *ppTLib, UINT *pIndex)
7625 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7627 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7628 if (pIndex) {
7629 *pIndex=This->index;
7630 TRACE("returning pIndex=%d\n", *pIndex);
7633 if (ppTLib) {
7634 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7635 ITypeLib_AddRef(*ppTLib);
7636 TRACE("returning ppTLib=%p\n", *ppTLib);
7639 return S_OK;
7642 /* ITypeInfo::ReleaseTypeAttr
7644 * Releases a TYPEATTR previously returned by Get
7647 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7648 TYPEATTR* pTypeAttr)
7650 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7651 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7652 heap_free(pTypeAttr);
7655 /* ITypeInfo::ReleaseFuncDesc
7657 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7659 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7660 ITypeInfo2 *iface,
7661 FUNCDESC *pFuncDesc)
7663 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7664 SHORT i;
7666 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7668 for (i = 0; i < pFuncDesc->cParams; i++)
7669 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7670 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7672 SysFreeString((BSTR)pFuncDesc);
7675 /* ITypeInfo::ReleaseVarDesc
7677 * Releases a VARDESC previously returned by GetVarDesc.
7679 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7680 VARDESC *pVarDesc)
7682 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7683 TRACE("(%p)->(%p)\n", This, pVarDesc);
7685 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7686 if (pVarDesc->varkind == VAR_CONST)
7687 VariantClear(pVarDesc->u.lpvarValue);
7688 SysFreeString((BSTR)pVarDesc);
7691 /* ITypeInfo2::GetTypeKind
7693 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7696 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7697 TYPEKIND *pTypeKind)
7699 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7700 *pTypeKind=This->typekind;
7701 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7702 return S_OK;
7705 /* ITypeInfo2::GetTypeFlags
7707 * Returns the type flags without any allocations. This returns a DWORD type
7708 * flag, which expands the type flags without growing the TYPEATTR (type
7709 * attribute).
7712 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7714 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7715 *pTypeFlags=This->wTypeFlags;
7716 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7717 return S_OK;
7720 /* ITypeInfo2::GetFuncIndexOfMemId
7721 * Binds to a specific member based on a known DISPID, where the member name
7722 * is not known (for example, when binding to a default member).
7725 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7726 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7728 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7729 UINT fdc;
7730 HRESULT result;
7732 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7733 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7734 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7735 break;
7737 if(fdc < This->cFuncs) {
7738 *pFuncIndex = fdc;
7739 result = S_OK;
7740 } else
7741 result = TYPE_E_ELEMENTNOTFOUND;
7743 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7744 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7745 return result;
7748 /* TypeInfo2::GetVarIndexOfMemId
7750 * Binds to a specific member based on a known DISPID, where the member name
7751 * is not known (for example, when binding to a default member).
7754 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7755 MEMBERID memid, UINT *pVarIndex)
7757 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7758 TLBVarDesc *pVarInfo;
7760 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7762 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7763 if(!pVarInfo)
7764 return TYPE_E_ELEMENTNOTFOUND;
7766 *pVarIndex = (pVarInfo - This->vardescs);
7768 return S_OK;
7771 /* ITypeInfo2::GetCustData
7773 * Gets the custom data
7775 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7776 ITypeInfo2 * iface,
7777 REFGUID guid,
7778 VARIANT *pVarVal)
7780 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7781 TLBCustData *pCData;
7783 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7785 if(!guid || !pVarVal)
7786 return E_INVALIDARG;
7788 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7790 VariantInit( pVarVal);
7791 if (pCData)
7792 VariantCopy( pVarVal, &pCData->data);
7793 else
7794 VariantClear( pVarVal );
7795 return S_OK;
7798 /* ITypeInfo2::GetFuncCustData
7800 * Gets the custom data
7802 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7803 ITypeInfo2 * iface,
7804 UINT index,
7805 REFGUID guid,
7806 VARIANT *pVarVal)
7808 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7809 TLBCustData *pCData;
7810 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7812 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7814 if(index >= This->cFuncs)
7815 return TYPE_E_ELEMENTNOTFOUND;
7817 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7818 if(!pCData)
7819 return TYPE_E_ELEMENTNOTFOUND;
7821 VariantInit(pVarVal);
7822 VariantCopy(pVarVal, &pCData->data);
7824 return S_OK;
7827 /* ITypeInfo2::GetParamCustData
7829 * Gets the custom data
7831 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7832 ITypeInfo2 * iface,
7833 UINT indexFunc,
7834 UINT indexParam,
7835 REFGUID guid,
7836 VARIANT *pVarVal)
7838 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7839 TLBCustData *pCData;
7840 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7842 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7843 debugstr_guid(guid), pVarVal);
7845 if(indexFunc >= This->cFuncs)
7846 return TYPE_E_ELEMENTNOTFOUND;
7848 if(indexParam >= pFDesc->funcdesc.cParams)
7849 return TYPE_E_ELEMENTNOTFOUND;
7851 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7852 if(!pCData)
7853 return TYPE_E_ELEMENTNOTFOUND;
7855 VariantInit(pVarVal);
7856 VariantCopy(pVarVal, &pCData->data);
7858 return S_OK;
7861 /* ITypeInfo2::GetVarCustData
7863 * Gets the custom data
7865 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7866 ITypeInfo2 * iface,
7867 UINT index,
7868 REFGUID guid,
7869 VARIANT *pVarVal)
7871 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7872 TLBCustData *pCData;
7873 TLBVarDesc *pVDesc = &This->vardescs[index];
7875 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7877 if(index >= This->cVars)
7878 return TYPE_E_ELEMENTNOTFOUND;
7880 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7881 if(!pCData)
7882 return TYPE_E_ELEMENTNOTFOUND;
7884 VariantInit(pVarVal);
7885 VariantCopy(pVarVal, &pCData->data);
7887 return S_OK;
7890 /* ITypeInfo2::GetImplCustData
7892 * Gets the custom data
7894 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7895 ITypeInfo2 * iface,
7896 UINT index,
7897 REFGUID guid,
7898 VARIANT *pVarVal)
7900 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7901 TLBCustData *pCData;
7902 TLBImplType *pRDesc = &This->impltypes[index];
7904 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7906 if(index >= This->cImplTypes)
7907 return TYPE_E_ELEMENTNOTFOUND;
7909 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7910 if(!pCData)
7911 return TYPE_E_ELEMENTNOTFOUND;
7913 VariantInit(pVarVal);
7914 VariantCopy(pVarVal, &pCData->data);
7916 return S_OK;
7919 /* ITypeInfo2::GetDocumentation2
7921 * Retrieves the documentation string, the complete Help file name and path,
7922 * the localization context to use, and the context ID for the library Help
7923 * topic in the Help file.
7926 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7927 ITypeInfo2 * iface,
7928 MEMBERID memid,
7929 LCID lcid,
7930 BSTR *pbstrHelpString,
7931 DWORD *pdwHelpStringContext,
7932 BSTR *pbstrHelpStringDll)
7934 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7935 const TLBFuncDesc *pFDesc;
7936 const TLBVarDesc *pVDesc;
7937 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7938 "HelpStringContext(%p) HelpStringDll(%p)\n",
7939 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7940 pbstrHelpStringDll );
7941 /* the help string should be obtained from the helpstringdll,
7942 * using the _DLLGetDocumentation function, based on the supplied
7943 * lcid. Nice to do sometime...
7945 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7946 if(pbstrHelpString)
7947 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
7948 if(pdwHelpStringContext)
7949 *pdwHelpStringContext=This->dwHelpStringContext;
7950 if(pbstrHelpStringDll)
7951 *pbstrHelpStringDll=
7952 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7953 return S_OK;
7954 }else {/* for a member */
7955 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7956 if(pFDesc){
7957 if(pbstrHelpString)
7958 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7959 if(pdwHelpStringContext)
7960 *pdwHelpStringContext=pFDesc->HelpStringContext;
7961 if(pbstrHelpStringDll)
7962 *pbstrHelpStringDll=
7963 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7964 return S_OK;
7966 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7967 if(pVDesc){
7968 if(pbstrHelpString)
7969 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7970 if(pdwHelpStringContext)
7971 *pdwHelpStringContext=pVDesc->HelpStringContext;
7972 if(pbstrHelpStringDll)
7973 *pbstrHelpStringDll=
7974 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7975 return S_OK;
7978 return TYPE_E_ELEMENTNOTFOUND;
7981 /* ITypeInfo2::GetAllCustData
7983 * Gets all custom data items for the Type info.
7986 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7987 ITypeInfo2 * iface,
7988 CUSTDATA *pCustData)
7990 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7992 TRACE("%p %p\n", This, pCustData);
7994 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7997 /* ITypeInfo2::GetAllFuncCustData
7999 * Gets all custom data items for the specified Function
8002 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8003 ITypeInfo2 * iface,
8004 UINT index,
8005 CUSTDATA *pCustData)
8007 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8008 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8010 TRACE("%p %u %p\n", This, index, pCustData);
8012 if(index >= This->cFuncs)
8013 return TYPE_E_ELEMENTNOTFOUND;
8015 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8018 /* ITypeInfo2::GetAllParamCustData
8020 * Gets all custom data items for the Functions
8023 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8024 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8026 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8027 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8029 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8031 if(indexFunc >= This->cFuncs)
8032 return TYPE_E_ELEMENTNOTFOUND;
8034 if(indexParam >= pFDesc->funcdesc.cParams)
8035 return TYPE_E_ELEMENTNOTFOUND;
8037 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8040 /* ITypeInfo2::GetAllVarCustData
8042 * Gets all custom data items for the specified Variable
8045 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8046 UINT index, CUSTDATA *pCustData)
8048 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8049 TLBVarDesc * pVDesc = &This->vardescs[index];
8051 TRACE("%p %u %p\n", This, index, pCustData);
8053 if(index >= This->cVars)
8054 return TYPE_E_ELEMENTNOTFOUND;
8056 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8059 /* ITypeInfo2::GetAllImplCustData
8061 * Gets all custom data items for the specified implementation type
8064 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8065 ITypeInfo2 * iface,
8066 UINT index,
8067 CUSTDATA *pCustData)
8069 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8070 TLBImplType *pRDesc = &This->impltypes[index];
8072 TRACE("%p %u %p\n", This, index, pCustData);
8074 if(index >= This->cImplTypes)
8075 return TYPE_E_ELEMENTNOTFOUND;
8077 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8080 static const ITypeInfo2Vtbl tinfvt =
8083 ITypeInfo_fnQueryInterface,
8084 ITypeInfo_fnAddRef,
8085 ITypeInfo_fnRelease,
8087 ITypeInfo_fnGetTypeAttr,
8088 ITypeInfo_fnGetTypeComp,
8089 ITypeInfo_fnGetFuncDesc,
8090 ITypeInfo_fnGetVarDesc,
8091 ITypeInfo_fnGetNames,
8092 ITypeInfo_fnGetRefTypeOfImplType,
8093 ITypeInfo_fnGetImplTypeFlags,
8094 ITypeInfo_fnGetIDsOfNames,
8095 ITypeInfo_fnInvoke,
8096 ITypeInfo_fnGetDocumentation,
8097 ITypeInfo_fnGetDllEntry,
8098 ITypeInfo_fnGetRefTypeInfo,
8099 ITypeInfo_fnAddressOfMember,
8100 ITypeInfo_fnCreateInstance,
8101 ITypeInfo_fnGetMops,
8102 ITypeInfo_fnGetContainingTypeLib,
8103 ITypeInfo_fnReleaseTypeAttr,
8104 ITypeInfo_fnReleaseFuncDesc,
8105 ITypeInfo_fnReleaseVarDesc,
8107 ITypeInfo2_fnGetTypeKind,
8108 ITypeInfo2_fnGetTypeFlags,
8109 ITypeInfo2_fnGetFuncIndexOfMemId,
8110 ITypeInfo2_fnGetVarIndexOfMemId,
8111 ITypeInfo2_fnGetCustData,
8112 ITypeInfo2_fnGetFuncCustData,
8113 ITypeInfo2_fnGetParamCustData,
8114 ITypeInfo2_fnGetVarCustData,
8115 ITypeInfo2_fnGetImplTypeCustData,
8116 ITypeInfo2_fnGetDocumentation2,
8117 ITypeInfo2_fnGetAllCustData,
8118 ITypeInfo2_fnGetAllFuncCustData,
8119 ITypeInfo2_fnGetAllParamCustData,
8120 ITypeInfo2_fnGetAllVarCustData,
8121 ITypeInfo2_fnGetAllImplTypeCustData,
8124 /******************************************************************************
8125 * CreateDispTypeInfo [OLEAUT32.31]
8127 * Build type information for an object so it can be called through an
8128 * IDispatch interface.
8130 * RETURNS
8131 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8132 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8134 * NOTES
8135 * This call allows an objects methods to be accessed through IDispatch, by
8136 * building an ITypeInfo object that IDispatch can use to call through.
8138 HRESULT WINAPI CreateDispTypeInfo(
8139 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8140 LCID lcid, /* [I] Locale Id */
8141 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8143 ITypeInfoImpl *pTIClass, *pTIIface;
8144 ITypeLibImpl *pTypeLibImpl;
8145 unsigned int param, func;
8146 TLBFuncDesc *pFuncDesc;
8147 TLBRefType *ref;
8149 TRACE("\n");
8150 pTypeLibImpl = TypeLibImpl_Constructor();
8151 if (!pTypeLibImpl) return E_FAIL;
8153 pTypeLibImpl->TypeInfoCount = 2;
8154 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8156 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8157 pTIIface->pTypeLib = pTypeLibImpl;
8158 pTIIface->index = 0;
8159 pTIIface->Name = NULL;
8160 pTIIface->dwHelpContext = -1;
8161 pTIIface->guid = NULL;
8162 pTIIface->lcid = lcid;
8163 pTIIface->typekind = TKIND_INTERFACE;
8164 pTIIface->wMajorVerNum = 0;
8165 pTIIface->wMinorVerNum = 0;
8166 pTIIface->cbAlignment = 2;
8167 pTIIface->cbSizeInstance = -1;
8168 pTIIface->cbSizeVft = -1;
8169 pTIIface->cFuncs = 0;
8170 pTIIface->cImplTypes = 0;
8171 pTIIface->cVars = 0;
8172 pTIIface->wTypeFlags = 0;
8173 pTIIface->hreftype = 0;
8175 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8176 pFuncDesc = pTIIface->funcdescs;
8177 for(func = 0; func < pidata->cMembers; func++) {
8178 METHODDATA *md = pidata->pmethdata + func;
8179 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8180 pFuncDesc->funcdesc.memid = md->dispid;
8181 pFuncDesc->funcdesc.lprgscode = NULL;
8182 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8183 pFuncDesc->funcdesc.invkind = md->wFlags;
8184 pFuncDesc->funcdesc.callconv = md->cc;
8185 pFuncDesc->funcdesc.cParams = md->cArgs;
8186 pFuncDesc->funcdesc.cParamsOpt = 0;
8187 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8188 pFuncDesc->funcdesc.cScodes = 0;
8189 pFuncDesc->funcdesc.wFuncFlags = 0;
8190 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8191 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8192 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8193 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8194 md->cArgs * sizeof(ELEMDESC));
8195 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8196 for(param = 0; param < md->cArgs; param++) {
8197 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8198 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8200 pFuncDesc->helpcontext = 0;
8201 pFuncDesc->HelpStringContext = 0;
8202 pFuncDesc->HelpString = NULL;
8203 pFuncDesc->Entry = NULL;
8204 list_init(&pFuncDesc->custdata_list);
8205 pTIIface->cFuncs++;
8206 ++pFuncDesc;
8209 dump_TypeInfo(pTIIface);
8211 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8212 pTIClass->pTypeLib = pTypeLibImpl;
8213 pTIClass->index = 1;
8214 pTIClass->Name = NULL;
8215 pTIClass->dwHelpContext = -1;
8216 pTIClass->guid = NULL;
8217 pTIClass->lcid = lcid;
8218 pTIClass->typekind = TKIND_COCLASS;
8219 pTIClass->wMajorVerNum = 0;
8220 pTIClass->wMinorVerNum = 0;
8221 pTIClass->cbAlignment = 2;
8222 pTIClass->cbSizeInstance = -1;
8223 pTIClass->cbSizeVft = -1;
8224 pTIClass->cFuncs = 0;
8225 pTIClass->cImplTypes = 1;
8226 pTIClass->cVars = 0;
8227 pTIClass->wTypeFlags = 0;
8228 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8230 pTIClass->impltypes = TLBImplType_Alloc(1);
8232 ref = heap_alloc_zero(sizeof(*ref));
8233 ref->pImpTLInfo = TLB_REF_INTERNAL;
8234 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8236 dump_TypeInfo(pTIClass);
8238 *pptinfo = (ITypeInfo*)pTIClass;
8240 ITypeInfo_AddRef(*pptinfo);
8241 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8243 return S_OK;
8247 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8249 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8251 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
8254 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8256 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8258 return ITypeInfo_AddRef((ITypeInfo *)This);
8261 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8263 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8265 return ITypeInfo_Release((ITypeInfo *)This);
8268 static HRESULT WINAPI ITypeComp_fnBind(
8269 ITypeComp * iface,
8270 OLECHAR * szName,
8271 ULONG lHash,
8272 WORD wFlags,
8273 ITypeInfo ** ppTInfo,
8274 DESCKIND * pDescKind,
8275 BINDPTR * pBindPtr)
8277 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8278 const TLBFuncDesc *pFDesc;
8279 const TLBVarDesc *pVDesc;
8280 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8281 UINT fdc;
8283 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8285 *pDescKind = DESCKIND_NONE;
8286 pBindPtr->lpfuncdesc = NULL;
8287 *ppTInfo = NULL;
8289 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8290 pFDesc = &This->funcdescs[fdc];
8291 if (!strcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8292 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8293 break;
8294 else
8295 /* name found, but wrong flags */
8296 hr = TYPE_E_TYPEMISMATCH;
8300 if (fdc < This->cFuncs)
8302 HRESULT hr = TLB_AllocAndInitFuncDesc(
8303 &pFDesc->funcdesc,
8304 &pBindPtr->lpfuncdesc,
8305 This->typekind == TKIND_DISPATCH);
8306 if (FAILED(hr))
8307 return hr;
8308 *pDescKind = DESCKIND_FUNCDESC;
8309 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8310 ITypeInfo_AddRef(*ppTInfo);
8311 return S_OK;
8312 } else {
8313 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8314 if(pVDesc){
8315 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8316 if (FAILED(hr))
8317 return hr;
8318 *pDescKind = DESCKIND_VARDESC;
8319 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8320 ITypeInfo_AddRef(*ppTInfo);
8321 return S_OK;
8324 /* FIXME: search each inherited interface, not just the first */
8325 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8326 /* recursive search */
8327 ITypeInfo *pTInfo;
8328 ITypeComp *pTComp;
8329 HRESULT hr;
8330 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8331 if (SUCCEEDED(hr))
8333 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8334 ITypeInfo_Release(pTInfo);
8336 if (SUCCEEDED(hr))
8338 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8339 ITypeComp_Release(pTComp);
8340 return hr;
8342 WARN("Could not search inherited interface!\n");
8344 if (hr == DISP_E_MEMBERNOTFOUND)
8345 hr = S_OK;
8346 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8347 return hr;
8350 static HRESULT WINAPI ITypeComp_fnBindType(
8351 ITypeComp * iface,
8352 OLECHAR * szName,
8353 ULONG lHash,
8354 ITypeInfo ** ppTInfo,
8355 ITypeComp ** ppTComp)
8357 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8359 /* strange behaviour (does nothing) but like the
8360 * original */
8362 if (!ppTInfo || !ppTComp)
8363 return E_POINTER;
8365 *ppTInfo = NULL;
8366 *ppTComp = NULL;
8368 return S_OK;
8371 static const ITypeCompVtbl tcompvt =
8374 ITypeComp_fnQueryInterface,
8375 ITypeComp_fnAddRef,
8376 ITypeComp_fnRelease,
8378 ITypeComp_fnBind,
8379 ITypeComp_fnBindType
8382 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8383 REFIID riid, void **object)
8385 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8387 return ITypeLib2_QueryInterface((ITypeLib2*)This, riid, object);
8390 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8392 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8394 return ITypeLib2_AddRef((ITypeLib2*)This);
8397 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8399 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8401 return ITypeLib2_Release((ITypeLib2*)This);
8404 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8405 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8407 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8408 ITypeInfoImpl *info;
8409 HRESULT hres;
8411 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8413 if (!ctinfo || !name)
8414 return E_INVALIDARG;
8416 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8417 if (info)
8418 return TYPE_E_NAMECONFLICT;
8420 if (This->typeinfos)
8421 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8422 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8423 else
8424 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8426 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8428 info->pTypeLib = This;
8429 info->Name = TLB_append_str(&This->name_list, name);
8430 info->index = This->TypeInfoCount;
8431 info->typekind = kind;
8432 info->cbAlignment = 4;
8434 switch(info->typekind) {
8435 case TKIND_ENUM:
8436 case TKIND_INTERFACE:
8437 case TKIND_DISPATCH:
8438 case TKIND_COCLASS:
8439 info->cbSizeInstance = 4;
8440 break;
8441 case TKIND_RECORD:
8442 case TKIND_UNION:
8443 info->cbSizeInstance = 0;
8444 break;
8445 case TKIND_MODULE:
8446 info->cbSizeInstance = 2;
8447 break;
8448 case TKIND_ALIAS:
8449 info->cbSizeInstance = -0x75;
8450 break;
8451 default:
8452 FIXME("unrecognized typekind %d\n", info->typekind);
8453 info->cbSizeInstance = 0xdeadbeef;
8454 break;
8457 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8458 &IID_ICreateTypeInfo, (void **)ctinfo);
8459 if (FAILED(hres)) {
8460 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8461 return hres;
8464 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8466 ++This->TypeInfoCount;
8468 return S_OK;
8471 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8472 LPOLESTR name)
8474 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8476 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8478 if (!name)
8479 return E_INVALIDARG;
8481 This->Name = TLB_append_str(&This->name_list, name);
8483 return S_OK;
8486 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8487 WORD majorVerNum, WORD minorVerNum)
8489 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8491 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8493 This->ver_major = majorVerNum;
8494 This->ver_minor = minorVerNum;
8496 return S_OK;
8499 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8500 REFGUID guid)
8502 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8504 TRACE("%p %s\n", This, debugstr_guid(guid));
8506 This->guid = TLB_append_guid(&This->guid_list, guid);
8508 return S_OK;
8511 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8512 LPOLESTR doc)
8514 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8516 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8518 if (!doc)
8519 return E_INVALIDARG;
8521 This->DocString = TLB_append_str(&This->string_list, doc);
8523 return S_OK;
8526 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8527 LPOLESTR helpFileName)
8529 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8531 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8533 if (!helpFileName)
8534 return E_INVALIDARG;
8536 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8538 return S_OK;
8541 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8542 DWORD helpContext)
8544 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8546 TRACE("%p %d\n", This, helpContext);
8548 This->dwHelpContext = helpContext;
8550 return S_OK;
8553 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8554 LCID lcid)
8556 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8558 TRACE("%p %x\n", This, lcid);
8560 This->set_lcid = lcid;
8562 return S_OK;
8565 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8566 UINT libFlags)
8568 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8570 TRACE("%p %x\n", This, libFlags);
8572 This->libflags = libFlags;
8574 return S_OK;
8577 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
8579 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8580 FIXME("%p - stub\n", This);
8581 return E_NOTIMPL;
8584 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
8585 LPOLESTR name)
8587 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8588 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
8589 return E_NOTIMPL;
8592 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
8593 REFGUID guid, VARIANT *varVal)
8595 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8596 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
8597 return E_NOTIMPL;
8600 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
8601 ULONG helpStringContext)
8603 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8604 FIXME("%p %u - stub\n", This, helpStringContext);
8605 return E_NOTIMPL;
8608 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
8609 LPOLESTR filename)
8611 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8612 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
8614 if (!filename)
8615 return E_INVALIDARG;
8617 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
8619 return S_OK;
8622 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
8623 ICreateTypeLib2_fnQueryInterface,
8624 ICreateTypeLib2_fnAddRef,
8625 ICreateTypeLib2_fnRelease,
8626 ICreateTypeLib2_fnCreateTypeInfo,
8627 ICreateTypeLib2_fnSetName,
8628 ICreateTypeLib2_fnSetVersion,
8629 ICreateTypeLib2_fnSetGuid,
8630 ICreateTypeLib2_fnSetDocString,
8631 ICreateTypeLib2_fnSetHelpFileName,
8632 ICreateTypeLib2_fnSetHelpContext,
8633 ICreateTypeLib2_fnSetLcid,
8634 ICreateTypeLib2_fnSetLibFlags,
8635 ICreateTypeLib2_fnSaveAllChanges,
8636 ICreateTypeLib2_fnDeleteTypeInfo,
8637 ICreateTypeLib2_fnSetCustData,
8638 ICreateTypeLib2_fnSetHelpStringContext,
8639 ICreateTypeLib2_fnSetHelpStringDll
8642 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
8643 REFIID riid, void **object)
8645 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8647 return ITypeInfo2_QueryInterface((ITypeInfo2*)This, riid, object);
8650 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
8652 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8654 return ITypeInfo2_AddRef((ITypeInfo2*)This);
8657 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
8659 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8661 return ITypeInfo2_Release((ITypeInfo2*)This);
8664 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
8665 REFGUID guid)
8667 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8669 TRACE("%p %s\n", This, debugstr_guid(guid));
8671 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
8673 return S_OK;
8676 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
8677 UINT typeFlags)
8679 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8680 WORD old_flags;
8681 HRESULT hres;
8683 TRACE("%p %x\n", This, typeFlags);
8685 if (typeFlags & TYPEFLAG_FDUAL) {
8686 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
8687 ITypeLib *stdole;
8688 ITypeInfo *dispatch;
8689 HREFTYPE hreftype;
8690 HRESULT hres;
8692 hres = LoadTypeLib(stdole2tlb, &stdole);
8693 if(FAILED(hres))
8694 return hres;
8696 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
8697 ITypeLib_Release(stdole);
8698 if(FAILED(hres))
8699 return hres;
8701 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
8702 ITypeInfo_Release(dispatch);
8703 if(FAILED(hres))
8704 return hres;
8707 old_flags = This->wTypeFlags;
8708 This->wTypeFlags = typeFlags;
8710 hres = ICreateTypeInfo2_LayOut(iface);
8711 if (FAILED(hres)) {
8712 This->wTypeFlags = old_flags;
8713 return hres;
8716 return S_OK;
8719 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
8720 LPOLESTR doc)
8722 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8724 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8726 if (!doc)
8727 return E_INVALIDARG;
8729 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
8731 return S_OK;
8734 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
8735 DWORD helpContext)
8737 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8739 TRACE("%p %d\n", This, helpContext);
8741 This->dwHelpContext = helpContext;
8743 return S_OK;
8746 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
8747 WORD majorVerNum, WORD minorVerNum)
8749 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8751 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8753 This->wMajorVerNum = majorVerNum;
8754 This->wMinorVerNum = minorVerNum;
8756 return S_OK;
8759 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
8760 ITypeInfo *typeInfo, HREFTYPE *refType)
8762 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8763 UINT index;
8764 ITypeLib *container;
8765 TLBRefType *ref_type;
8766 TLBImpLib *implib;
8767 TYPEATTR *typeattr;
8768 TLIBATTR *libattr;
8769 HRESULT hres;
8771 TRACE("%p %p %p\n", This, typeInfo, refType);
8773 if (!typeInfo || !refType)
8774 return E_INVALIDARG;
8776 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
8777 if (FAILED(hres))
8778 return hres;
8780 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
8781 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
8783 ITypeLib_Release(container);
8785 *refType = target->hreftype;
8787 return S_OK;
8790 hres = ITypeLib_GetLibAttr(container, &libattr);
8791 if (FAILED(hres)) {
8792 ITypeLib_Release(container);
8793 return hres;
8796 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
8797 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
8798 implib->lcid == libattr->lcid &&
8799 implib->wVersionMajor == libattr->wMajorVerNum &&
8800 implib->wVersionMinor == libattr->wMinorVerNum)
8801 break;
8804 if(&implib->entry == &This->pTypeLib->implib_list){
8805 implib = heap_alloc_zero(sizeof(TLBImpLib));
8807 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
8808 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
8809 implib->name = SysAllocString(our_container->path);
8810 }else{
8811 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
8812 libattr->wMinorVerNum, libattr->lcid, &implib->name);
8813 if(FAILED(hres)){
8814 implib->name = NULL;
8815 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
8819 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid);
8820 implib->lcid = libattr->lcid;
8821 implib->wVersionMajor = libattr->wMajorVerNum;
8822 implib->wVersionMinor = libattr->wMinorVerNum;
8824 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
8827 ITypeLib_ReleaseTLibAttr(container, libattr);
8828 ITypeLib_Release(container);
8830 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
8831 if (FAILED(hres))
8832 return hres;
8834 index = 0;
8835 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
8836 if(ref_type->index == TLB_REF_USE_GUID &&
8837 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
8838 ref_type->tkind == typeattr->typekind)
8839 break;
8840 ++index;
8843 if(&ref_type->entry == &This->pTypeLib->ref_list){
8844 ref_type = heap_alloc_zero(sizeof(TLBRefType));
8846 ref_type->tkind = typeattr->typekind;
8847 ref_type->pImpTLInfo = implib;
8848 ref_type->reference = index * sizeof(MSFT_ImpInfo);
8850 ref_type->index = TLB_REF_USE_GUID;
8852 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid);
8854 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
8857 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
8859 *refType = ref_type->reference | 0x1;
8861 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
8862 This->pTypeLib->dispatch_href = *refType;
8864 return S_OK;
8867 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
8868 UINT index, FUNCDESC *funcDesc)
8870 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8871 TLBFuncDesc tmp_func_desc, *func_desc;
8872 int buf_size, i;
8873 char *buffer;
8874 HRESULT hres;
8876 TRACE("%p %u %p\n", This, index, funcDesc);
8878 if (!funcDesc || funcDesc->oVft & 3)
8879 return E_INVALIDARG;
8881 switch (This->typekind) {
8882 case TKIND_MODULE:
8883 if (funcDesc->funckind != FUNC_STATIC)
8884 return TYPE_E_BADMODULEKIND;
8885 break;
8886 case TKIND_DISPATCH:
8887 if (funcDesc->funckind != FUNC_DISPATCH)
8888 return TYPE_E_BADMODULEKIND;
8889 break;
8890 default:
8891 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
8892 return TYPE_E_BADMODULEKIND;
8895 if (index > This->cFuncs)
8896 return TYPE_E_ELEMENTNOTFOUND;
8898 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
8899 !funcDesc->cParams)
8900 return TYPE_E_INCONSISTENTPROPFUNCS;
8902 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
8903 TLBFuncDesc_Constructor(&tmp_func_desc);
8905 tmp_func_desc.funcdesc = *funcDesc;
8907 if (tmp_func_desc.funcdesc.oVft != 0)
8908 tmp_func_desc.funcdesc.oVft |= 1;
8910 if (funcDesc->cScodes) {
8911 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
8912 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
8913 } else
8914 tmp_func_desc.funcdesc.lprgscode = NULL;
8916 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
8917 for (i = 0; i < funcDesc->cParams; ++i) {
8918 buf_size += sizeof(ELEMDESC);
8919 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
8921 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
8922 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
8924 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
8925 if (FAILED(hres)) {
8926 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8927 heap_free(tmp_func_desc.funcdesc.lprgscode);
8928 return hres;
8931 for (i = 0; i < funcDesc->cParams; ++i) {
8932 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
8933 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
8934 if (FAILED(hres)) {
8935 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8936 heap_free(tmp_func_desc.funcdesc.lprgscode);
8937 return hres;
8939 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
8940 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
8941 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
8942 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
8943 if (FAILED(hres)) {
8944 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8945 heap_free(tmp_func_desc.funcdesc.lprgscode);
8946 return hres;
8951 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
8953 if (This->funcdescs) {
8954 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
8955 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
8957 if (index < This->cFuncs) {
8958 memmove(This->funcdescs + index + 1, This->funcdescs + index,
8959 (This->cFuncs - index) * sizeof(TLBFuncDesc));
8960 func_desc = This->funcdescs + index;
8961 } else
8962 func_desc = This->funcdescs + This->cFuncs;
8964 /* move custdata lists to the new memory location */
8965 for(i = 0; i < This->cFuncs + 1; ++i){
8966 if(index != i){
8967 TLBFuncDesc *fd = &This->funcdescs[i];
8968 if(fd->custdata_list.prev == fd->custdata_list.next)
8969 list_init(&fd->custdata_list);
8970 else{
8971 fd->custdata_list.prev->next = &fd->custdata_list;
8972 fd->custdata_list.next->prev = &fd->custdata_list;
8976 } else
8977 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
8979 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
8980 list_init(&func_desc->custdata_list);
8982 ++This->cFuncs;
8984 This->needs_layout = TRUE;
8986 return S_OK;
8989 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
8990 UINT index, HREFTYPE refType)
8992 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8993 TLBImplType *impl_type;
8994 HRESULT hres;
8996 TRACE("%p %u %d\n", This, index, refType);
8998 switch(This->typekind){
8999 case TKIND_COCLASS: {
9000 if (index == -1) {
9001 FIXME("Unhandled index: -1\n");
9002 return E_NOTIMPL;
9005 if(index != This->cImplTypes)
9006 return TYPE_E_ELEMENTNOTFOUND;
9008 break;
9010 case TKIND_INTERFACE:
9011 case TKIND_DISPATCH:
9012 if (index != 0 || This->cImplTypes)
9013 return TYPE_E_ELEMENTNOTFOUND;
9014 break;
9015 default:
9016 FIXME("Unimplemented typekind: %d\n", This->typekind);
9017 return E_NOTIMPL;
9020 if (This->impltypes){
9021 UINT i;
9023 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
9024 sizeof(TLBImplType) * (This->cImplTypes + 1));
9026 if (index < This->cImplTypes) {
9027 memmove(This->impltypes + index + 1, This->impltypes + index,
9028 (This->cImplTypes - index) * sizeof(TLBImplType));
9029 impl_type = This->impltypes + index;
9030 } else
9031 impl_type = This->impltypes + This->cImplTypes;
9033 /* move custdata lists to the new memory location */
9034 for(i = 0; i < This->cImplTypes + 1; ++i){
9035 if(index != i){
9036 TLBImplType *it = &This->impltypes[i];
9037 if(it->custdata_list.prev == it->custdata_list.next)
9038 list_init(&it->custdata_list);
9039 else{
9040 it->custdata_list.prev->next = &it->custdata_list;
9041 it->custdata_list.next->prev = &it->custdata_list;
9045 } else
9046 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
9048 memset(impl_type, 0, sizeof(TLBImplType));
9049 TLBImplType_Constructor(impl_type);
9050 impl_type->hRef = refType;
9052 ++This->cImplTypes;
9054 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
9055 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
9057 hres = ICreateTypeInfo2_LayOut(iface);
9058 if (FAILED(hres))
9059 return hres;
9061 return S_OK;
9064 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
9065 UINT index, INT implTypeFlags)
9067 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9068 TLBImplType *impl_type = &This->impltypes[index];
9070 TRACE("%p %u %x\n", This, index, implTypeFlags);
9072 if (This->typekind != TKIND_COCLASS)
9073 return TYPE_E_BADMODULEKIND;
9075 if (index >= This->cImplTypes)
9076 return TYPE_E_ELEMENTNOTFOUND;
9078 impl_type->implflags = implTypeFlags;
9080 return S_OK;
9083 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
9084 WORD alignment)
9086 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9088 TRACE("%p %d\n", This, alignment);
9090 This->cbAlignment = alignment;
9092 return S_OK;
9095 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
9096 LPOLESTR schema)
9098 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9100 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
9102 if (!schema)
9103 return E_INVALIDARG;
9105 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
9107 This->lpstrSchema = This->Schema->str;
9109 return S_OK;
9112 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
9113 UINT index, VARDESC *varDesc)
9115 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9116 FIXME("%p %u %p - stub\n", This, index, varDesc);
9117 return E_NOTIMPL;
9120 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
9121 UINT index, LPOLESTR *names, UINT numNames)
9123 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9124 TLBFuncDesc *func_desc = &This->funcdescs[index];
9125 int i;
9127 TRACE("%p %u %p %u\n", This, index, names, numNames);
9129 if (!names)
9130 return E_INVALIDARG;
9132 if (index >= This->cFuncs || numNames == 0)
9133 return TYPE_E_ELEMENTNOTFOUND;
9135 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
9136 if(numNames > func_desc->funcdesc.cParams)
9137 return TYPE_E_ELEMENTNOTFOUND;
9138 } else
9139 if(numNames > func_desc->funcdesc.cParams + 1)
9140 return TYPE_E_ELEMENTNOTFOUND;
9142 for(i = 0; i < This->cFuncs; ++i) {
9143 TLBFuncDesc *iter = &This->funcdescs[i];
9144 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
9145 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
9146 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
9147 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
9148 continue;
9149 return TYPE_E_AMBIGUOUSNAME;
9153 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
9155 for (i = 1; i < numNames; ++i) {
9156 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
9157 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
9160 return S_OK;
9163 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
9164 UINT index, LPOLESTR name)
9166 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9167 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
9168 return E_NOTIMPL;
9171 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
9172 TYPEDESC *tdescAlias)
9174 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9175 FIXME("%p %p - stub\n", This, tdescAlias);
9176 return E_NOTIMPL;
9179 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
9180 UINT index, LPOLESTR dllName, LPOLESTR procName)
9182 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9183 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
9184 return E_NOTIMPL;
9187 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
9188 UINT index, LPOLESTR docString)
9190 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9191 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
9192 return E_NOTIMPL;
9195 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
9196 UINT index, LPOLESTR docString)
9198 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9199 TLBVarDesc *var_desc = &This->vardescs[index];
9201 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
9203 if(!docString)
9204 return E_INVALIDARG;
9206 if(index >= This->cVars)
9207 return TYPE_E_ELEMENTNOTFOUND;
9209 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
9211 return S_OK;
9214 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
9215 UINT index, DWORD helpContext)
9217 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9218 TLBFuncDesc *func_desc = &This->funcdescs[index];
9220 TRACE("%p %u %d\n", This, index, helpContext);
9222 if(index >= This->cFuncs)
9223 return TYPE_E_ELEMENTNOTFOUND;
9225 func_desc->helpcontext = helpContext;
9227 return S_OK;
9230 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
9231 UINT index, DWORD helpContext)
9233 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9234 TLBVarDesc *var_desc = &This->vardescs[index];
9236 TRACE("%p %u %d\n", This, index, helpContext);
9238 if(index >= This->cVars)
9239 return TYPE_E_ELEMENTNOTFOUND;
9241 var_desc->HelpContext = helpContext;
9243 return S_OK;
9246 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
9247 UINT index, BSTR bstrMops)
9249 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9250 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
9251 return E_NOTIMPL;
9254 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
9255 IDLDESC *idlDesc)
9257 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9259 TRACE("%p %p\n", This, idlDesc);
9261 if (!idlDesc)
9262 return E_INVALIDARG;
9264 This->idldescType.dwReserved = idlDesc->dwReserved;
9265 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
9267 return S_OK;
9270 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
9272 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9273 ITypeInfo *tinfo;
9274 TLBFuncDesc *func_desc;
9275 UINT user_vft = 0, i, depth = 0;
9276 HRESULT hres = S_OK;
9278 TRACE("%p\n", This);
9280 This->needs_layout = FALSE;
9282 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
9283 if (FAILED(hres))
9284 return hres;
9286 if (This->typekind == TKIND_INTERFACE) {
9287 ITypeInfo *inh;
9288 TYPEATTR *attr;
9289 HREFTYPE inh_href;
9291 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
9293 if (SUCCEEDED(hres)) {
9294 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
9296 if (SUCCEEDED(hres)) {
9297 hres = ITypeInfo_GetTypeAttr(inh, &attr);
9298 if (FAILED(hres)) {
9299 ITypeInfo_Release(inh);
9300 ITypeInfo_Release(tinfo);
9301 return hres;
9303 This->cbSizeVft = attr->cbSizeVft * 4 / sizeof(void*);
9304 ITypeInfo_ReleaseTypeAttr(inh, attr);
9307 ++depth;
9308 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
9309 if(SUCCEEDED(hres)){
9310 ITypeInfo *next;
9311 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
9312 if(SUCCEEDED(hres)){
9313 ITypeInfo_Release(inh);
9314 inh = next;
9317 }while(SUCCEEDED(hres));
9318 hres = S_OK;
9320 ITypeInfo_Release(inh);
9321 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
9322 This->cbSizeVft = 0;
9323 hres = S_OK;
9324 } else {
9325 ITypeInfo_Release(tinfo);
9326 return hres;
9328 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
9329 This->cbSizeVft = 0;
9330 hres = S_OK;
9331 } else {
9332 ITypeInfo_Release(tinfo);
9333 return hres;
9335 } else if (This->typekind == TKIND_DISPATCH)
9336 This->cbSizeVft = 7 * sizeof(void*);
9337 else
9338 This->cbSizeVft = 0;
9340 func_desc = This->funcdescs;
9341 i = 0;
9342 while (i < This->cFuncs) {
9343 if (!(func_desc->funcdesc.oVft & 0x1))
9344 func_desc->funcdesc.oVft = This->cbSizeVft;
9346 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
9347 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
9349 This->cbSizeVft += sizeof(void*);
9351 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
9352 TLBFuncDesc *iter;
9353 UINT j = 0;
9354 BOOL reset = FALSE;
9356 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
9358 iter = This->funcdescs;
9359 while (j < This->cFuncs) {
9360 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
9361 if (!reset) {
9362 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
9363 reset = TRUE;
9364 } else
9365 ++func_desc->funcdesc.memid;
9366 iter = This->funcdescs;
9367 j = 0;
9368 } else {
9369 ++iter;
9370 ++j;
9375 ++func_desc;
9376 ++i;
9379 if (user_vft > This->cbSizeVft)
9380 This->cbSizeVft = user_vft + sizeof(void*);
9382 ITypeInfo_Release(tinfo);
9383 return hres;
9386 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
9387 UINT index)
9389 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9390 FIXME("%p %u - stub\n", This, index);
9391 return E_NOTIMPL;
9394 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
9395 MEMBERID memid, INVOKEKIND invKind)
9397 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9398 FIXME("%p %x %d - stub\n", This, memid, invKind);
9399 return E_NOTIMPL;
9402 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
9403 UINT index)
9405 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9406 FIXME("%p %u - stub\n", This, index);
9407 return E_NOTIMPL;
9410 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
9411 MEMBERID memid)
9413 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9414 FIXME("%p %x - stub\n", This, memid);
9415 return E_NOTIMPL;
9418 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
9419 UINT index)
9421 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9422 FIXME("%p %u - stub\n", This, index);
9423 return E_NOTIMPL;
9426 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
9427 REFGUID guid, VARIANT *varVal)
9429 TLBGuid *tlbguid;
9431 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9433 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
9435 if (!guid || !varVal)
9436 return E_INVALIDARG;
9438 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
9440 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
9443 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
9444 UINT index, REFGUID guid, VARIANT *varVal)
9446 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9447 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9448 return E_NOTIMPL;
9451 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
9452 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
9454 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9455 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
9456 return E_NOTIMPL;
9459 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
9460 UINT index, REFGUID guid, VARIANT *varVal)
9462 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9463 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9464 return E_NOTIMPL;
9467 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
9468 UINT index, REFGUID guid, VARIANT *varVal)
9470 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9471 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9472 return E_NOTIMPL;
9475 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
9476 ULONG helpStringContext)
9478 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9480 TRACE("%p %u\n", This, helpStringContext);
9482 This->dwHelpStringContext = helpStringContext;
9484 return S_OK;
9487 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
9488 UINT index, ULONG helpStringContext)
9490 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9491 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
9492 return E_NOTIMPL;
9495 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
9496 UINT index, ULONG helpStringContext)
9498 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9499 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
9500 return E_NOTIMPL;
9503 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
9505 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9506 FIXME("%p - stub\n", This);
9507 return E_NOTIMPL;
9510 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
9511 LPOLESTR name)
9513 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9515 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9517 if (!name)
9518 return E_INVALIDARG;
9520 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
9522 return S_OK;
9525 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
9526 ICreateTypeInfo2_fnQueryInterface,
9527 ICreateTypeInfo2_fnAddRef,
9528 ICreateTypeInfo2_fnRelease,
9529 ICreateTypeInfo2_fnSetGuid,
9530 ICreateTypeInfo2_fnSetTypeFlags,
9531 ICreateTypeInfo2_fnSetDocString,
9532 ICreateTypeInfo2_fnSetHelpContext,
9533 ICreateTypeInfo2_fnSetVersion,
9534 ICreateTypeInfo2_fnAddRefTypeInfo,
9535 ICreateTypeInfo2_fnAddFuncDesc,
9536 ICreateTypeInfo2_fnAddImplType,
9537 ICreateTypeInfo2_fnSetImplTypeFlags,
9538 ICreateTypeInfo2_fnSetAlignment,
9539 ICreateTypeInfo2_fnSetSchema,
9540 ICreateTypeInfo2_fnAddVarDesc,
9541 ICreateTypeInfo2_fnSetFuncAndParamNames,
9542 ICreateTypeInfo2_fnSetVarName,
9543 ICreateTypeInfo2_fnSetTypeDescAlias,
9544 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
9545 ICreateTypeInfo2_fnSetFuncDocString,
9546 ICreateTypeInfo2_fnSetVarDocString,
9547 ICreateTypeInfo2_fnSetFuncHelpContext,
9548 ICreateTypeInfo2_fnSetVarHelpContext,
9549 ICreateTypeInfo2_fnSetMops,
9550 ICreateTypeInfo2_fnSetTypeIdldesc,
9551 ICreateTypeInfo2_fnLayOut,
9552 ICreateTypeInfo2_fnDeleteFuncDesc,
9553 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
9554 ICreateTypeInfo2_fnDeleteVarDesc,
9555 ICreateTypeInfo2_fnDeleteVarDescByMemId,
9556 ICreateTypeInfo2_fnDeleteImplType,
9557 ICreateTypeInfo2_fnSetCustData,
9558 ICreateTypeInfo2_fnSetFuncCustData,
9559 ICreateTypeInfo2_fnSetParamCustData,
9560 ICreateTypeInfo2_fnSetVarCustData,
9561 ICreateTypeInfo2_fnSetImplTypeCustData,
9562 ICreateTypeInfo2_fnSetHelpStringContext,
9563 ICreateTypeInfo2_fnSetFuncHelpStringContext,
9564 ICreateTypeInfo2_fnSetVarHelpStringContext,
9565 ICreateTypeInfo2_fnInvalidate,
9566 ICreateTypeInfo2_fnSetName