oleaut32: Implement ICreateTypeInfo::SetCustData.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob7fa395ae590e389fa5116deebbeba9ae4d8b6875
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 tagTLBCustData
960 GUID guid;
961 VARIANT data;
962 struct list entry;
963 } TLBCustData;
965 /* data structure for import typelibs */
966 typedef struct tagTLBImpLib
968 int offset; /* offset in the file (MSFT)
969 offset in nametable (SLTG)
970 just used to identify library while reading
971 data from file */
972 GUID guid; /* libid */
973 BSTR name; /* name */
975 LCID lcid; /* lcid of imported typelib */
977 WORD wVersionMajor; /* major version number */
978 WORD wVersionMinor; /* minor version number */
980 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
981 NULL if not yet loaded */
982 struct list entry;
983 } TLBImpLib;
985 /* internal ITypeLib data */
986 typedef struct tagITypeLibImpl
988 ITypeLib2 ITypeLib2_iface;
989 ITypeComp ITypeComp_iface;
990 ICreateTypeLib2 ICreateTypeLib2_iface;
991 LONG ref;
992 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
993 LCID lcid;
995 /* strings can be stored in tlb as multibyte strings BUT they are *always*
996 * exported to the application as a UNICODE string.
998 BSTR Name;
999 BSTR DocString;
1000 BSTR HelpFile;
1001 BSTR HelpStringDll;
1002 DWORD dwHelpContext;
1003 int TypeInfoCount; /* nr of typeinfo's in librarry */
1004 struct tagITypeInfoImpl **typeinfos;
1005 struct list custdata_list;
1006 struct list implib_list;
1007 int ctTypeDesc; /* number of items in type desc array */
1008 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1009 library. Only used while reading MSFT
1010 typelibs */
1011 struct list ref_list; /* list of ref types in this typelib */
1012 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1015 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1016 struct list entry;
1017 WCHAR *path;
1018 INT index;
1019 } ITypeLibImpl;
1021 static const ITypeLib2Vtbl tlbvt;
1022 static const ITypeCompVtbl tlbtcvt;
1023 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1025 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1027 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1030 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1032 return impl_from_ITypeLib2((ITypeLib2*)iface);
1035 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1037 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1040 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1042 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1045 /* ITypeLib methods */
1046 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1047 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1049 /*======================= ITypeInfo implementation =======================*/
1051 /* data for referenced types */
1052 typedef struct tagTLBRefType
1054 INT index; /* Type index for internal ref or for external ref
1055 it the format is SLTG. -2 indicates to
1056 use guid */
1058 TYPEKIND tkind;
1059 GUID guid; /* guid of the referenced type */
1060 /* if index == TLB_REF_USE_GUID */
1062 HREFTYPE reference; /* The href of this ref */
1063 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1064 TLB_REF_INTERNAL for internal refs
1065 TLB_REF_NOT_FOUND for broken refs */
1067 struct list entry;
1068 } TLBRefType;
1070 #define TLB_REF_USE_GUID -2
1072 #define TLB_REF_INTERNAL (void*)-2
1073 #define TLB_REF_NOT_FOUND (void*)-1
1075 /* internal Parameter data */
1076 typedef struct tagTLBParDesc
1078 BSTR Name;
1079 struct list custdata_list;
1080 } TLBParDesc;
1082 /* internal Function data */
1083 typedef struct tagTLBFuncDesc
1085 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1086 BSTR Name; /* the name of this function */
1087 TLBParDesc *pParamDesc; /* array with param names and custom data */
1088 int helpcontext;
1089 int HelpStringContext;
1090 BSTR HelpString;
1091 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1092 struct list custdata_list;
1093 } TLBFuncDesc;
1095 /* internal Variable data */
1096 typedef struct tagTLBVarDesc
1098 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1099 BSTR Name; /* the name of this variable */
1100 int HelpContext;
1101 int HelpStringContext;
1102 BSTR HelpString;
1103 struct list custdata_list;
1104 } TLBVarDesc;
1106 /* internal implemented interface data */
1107 typedef struct tagTLBImplType
1109 HREFTYPE hRef; /* hRef of interface */
1110 int implflags; /* IMPLFLAG_*s */
1111 struct list custdata_list;
1112 } TLBImplType;
1114 /* internal TypeInfo data */
1115 typedef struct tagITypeInfoImpl
1117 ITypeInfo2 ITypeInfo2_iface;
1118 ITypeComp ITypeComp_iface;
1119 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1120 LONG ref;
1121 BOOL not_attached_to_typelib;
1122 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1123 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1124 int index; /* index in this typelib; */
1125 HREFTYPE hreftype; /* hreftype for app object binding */
1126 /* type libs seem to store the doc strings in ascii
1127 * so why should we do it in unicode?
1129 BSTR Name;
1130 BSTR DocString;
1131 BSTR DllName;
1132 DWORD dwHelpContext;
1133 DWORD dwHelpStringContext;
1135 /* functions */
1136 TLBFuncDesc *funcdescs;
1138 /* variables */
1139 TLBVarDesc *vardescs;
1141 /* Implemented Interfaces */
1142 TLBImplType *impltypes;
1144 struct list custdata_list;
1145 } ITypeInfoImpl;
1147 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1149 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1152 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1154 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1157 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1159 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1162 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1164 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1167 static const ITypeInfo2Vtbl tinfvt;
1168 static const ITypeCompVtbl tcompvt;
1169 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1171 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1172 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1174 typedef struct tagTLBContext
1176 unsigned int oStart; /* start of TLB in file */
1177 unsigned int pos; /* current pos */
1178 unsigned int length; /* total length */
1179 void *mapping; /* memory mapping */
1180 MSFT_SegDir * pTblDir;
1181 ITypeLibImpl* pLibInfo;
1182 } TLBContext;
1185 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1188 debug
1190 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1191 if (pTD->vt & VT_RESERVED)
1192 szVarType += strlen(strcpy(szVarType, "reserved | "));
1193 if (pTD->vt & VT_BYREF)
1194 szVarType += strlen(strcpy(szVarType, "ref to "));
1195 if (pTD->vt & VT_ARRAY)
1196 szVarType += strlen(strcpy(szVarType, "array of "));
1197 if (pTD->vt & VT_VECTOR)
1198 szVarType += strlen(strcpy(szVarType, "vector of "));
1199 switch(pTD->vt & VT_TYPEMASK) {
1200 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1201 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1202 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1203 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1204 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1205 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1206 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1207 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1208 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1209 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1210 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1211 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1212 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1213 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1214 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1215 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1216 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1217 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1218 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1219 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1220 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1221 pTD->u.hreftype); break;
1222 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1223 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1224 case VT_PTR: sprintf(szVarType, "ptr to ");
1225 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1226 break;
1227 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1228 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1229 break;
1230 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1231 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1232 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1233 break;
1235 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1239 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1240 char buf[200];
1241 USHORT flags = edesc->u.paramdesc.wParamFlags;
1242 dump_TypeDesc(&edesc->tdesc,buf);
1243 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1244 MESSAGE("\t\tu.paramdesc.wParamFlags");
1245 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1246 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1247 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1248 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1249 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1250 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1251 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1252 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1253 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1255 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1256 int i;
1257 MESSAGE("memid is %08x\n",funcdesc->memid);
1258 for (i=0;i<funcdesc->cParams;i++) {
1259 MESSAGE("Param %d:\n",i);
1260 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1262 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1263 switch (funcdesc->funckind) {
1264 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1265 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1266 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1267 case FUNC_STATIC: MESSAGE("static");break;
1268 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1269 default: MESSAGE("unknown");break;
1271 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1272 switch (funcdesc->invkind) {
1273 case INVOKE_FUNC: MESSAGE("func");break;
1274 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1275 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1276 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1278 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1279 switch (funcdesc->callconv) {
1280 case CC_CDECL: MESSAGE("cdecl");break;
1281 case CC_PASCAL: MESSAGE("pascal");break;
1282 case CC_STDCALL: MESSAGE("stdcall");break;
1283 case CC_SYSCALL: MESSAGE("syscall");break;
1284 default:break;
1286 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1287 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1288 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1290 MESSAGE("\telemdescFunc (return value type):\n");
1291 dump_ELEMDESC(&funcdesc->elemdescFunc);
1294 static const char * const typekind_desc[] =
1296 "TKIND_ENUM",
1297 "TKIND_RECORD",
1298 "TKIND_MODULE",
1299 "TKIND_INTERFACE",
1300 "TKIND_DISPATCH",
1301 "TKIND_COCLASS",
1302 "TKIND_ALIAS",
1303 "TKIND_UNION",
1304 "TKIND_MAX"
1307 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1309 int i;
1310 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1311 for (i=0;i<pfd->funcdesc.cParams;i++)
1312 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1315 dump_FUNCDESC(&(pfd->funcdesc));
1317 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1318 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1320 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1322 while (n)
1324 dump_TLBFuncDescOne(pfd);
1325 ++pfd;
1326 --n;
1329 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1331 while (n)
1333 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1334 ++pvd;
1335 --n;
1339 static void dump_TLBImpLib(const TLBImpLib *import)
1341 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1342 debugstr_w(import->name));
1343 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1344 import->wVersionMinor, import->lcid, import->offset);
1347 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1349 TLBRefType *ref;
1351 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1353 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1354 if(ref->index == -1)
1355 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1356 else
1357 TRACE_(typelib)("type no: %d\n", ref->index);
1359 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1361 TRACE_(typelib)("in lib\n");
1362 dump_TLBImpLib(ref->pImpTLInfo);
1367 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1369 if(!impl)
1370 return;
1371 while (n) {
1372 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1373 impl->hRef, impl->implflags);
1374 ++impl;
1375 --n;
1379 static void dump_Variant(const VARIANT * pvar)
1381 SYSTEMTIME st;
1383 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1385 if (pvar)
1387 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1388 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1390 TRACE(",%p", V_BYREF(pvar));
1392 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1394 TRACE(",%p", V_ARRAY(pvar));
1396 else switch (V_TYPE(pvar))
1398 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1399 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1400 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1401 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1402 case VT_INT:
1403 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1404 case VT_UINT:
1405 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1406 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1407 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1408 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1409 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1410 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1411 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1412 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1413 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1414 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1415 V_CY(pvar).s.Lo); break;
1416 case VT_DATE:
1417 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1418 TRACE(",<invalid>");
1419 else
1420 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1421 st.wHour, st.wMinute, st.wSecond);
1422 break;
1423 case VT_ERROR:
1424 case VT_VOID:
1425 case VT_USERDEFINED:
1426 case VT_EMPTY:
1427 case VT_NULL: break;
1428 default: TRACE(",?"); break;
1431 TRACE("}\n");
1434 static void dump_DispParms(const DISPPARAMS * pdp)
1436 unsigned int index;
1438 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1440 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1442 TRACE("named args:\n");
1443 for (index = 0; index < pdp->cNamedArgs; index++)
1444 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1447 if (pdp->cArgs && pdp->rgvarg)
1449 TRACE("args:\n");
1450 for (index = 0; index < pdp->cArgs; index++)
1451 dump_Variant( &pdp->rgvarg[index] );
1455 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1457 TRACE("%p ref=%u\n", pty, pty->ref);
1458 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1459 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1460 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1461 TRACE("fct:%u var:%u impl:%u\n",
1462 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1463 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1464 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1465 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1466 if (TRACE_ON(ole))
1467 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1468 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1469 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1472 static void dump_VARDESC(const VARDESC *v)
1474 MESSAGE("memid %d\n",v->memid);
1475 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1476 MESSAGE("oInst %d\n",v->u.oInst);
1477 dump_ELEMDESC(&(v->elemdescVar));
1478 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1479 MESSAGE("varkind %d\n",v->varkind);
1482 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1484 /* VT_LPWSTR is largest type that, may appear in type description */
1485 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1486 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1487 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1488 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1489 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1490 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1491 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1492 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1495 static void TLB_abort(void)
1497 DebugBreak();
1500 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1502 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1503 if (!ret) ERR("cannot allocate memory\n");
1504 return ret;
1507 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1509 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1510 if (!ret) ERR("cannot allocate memory\n");
1511 return ret;
1514 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1516 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1519 void heap_free(void *ptr)
1521 HeapFree(GetProcessHeap(), 0, ptr);
1524 /* returns the size required for a deep copy of a typedesc into a
1525 * flat buffer */
1526 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1528 SIZE_T size = 0;
1530 if (alloc_initial_space)
1531 size += sizeof(TYPEDESC);
1533 switch (tdesc->vt)
1535 case VT_PTR:
1536 case VT_SAFEARRAY:
1537 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1538 break;
1539 case VT_CARRAY:
1540 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1541 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1542 break;
1544 return size;
1547 /* deep copy a typedesc into a flat buffer */
1548 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1550 if (!dest)
1552 dest = buffer;
1553 buffer = (char *)buffer + sizeof(TYPEDESC);
1556 *dest = *src;
1558 switch (src->vt)
1560 case VT_PTR:
1561 case VT_SAFEARRAY:
1562 dest->u.lptdesc = buffer;
1563 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1564 break;
1565 case VT_CARRAY:
1566 dest->u.lpadesc = buffer;
1567 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1568 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1569 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1570 break;
1572 return buffer;
1575 /* free custom data allocated by MSFT_CustData */
1576 static inline void TLB_FreeCustData(struct list *custdata_list)
1578 TLBCustData *cd, *cdn;
1579 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1581 list_remove(&cd->entry);
1582 VariantClear(&cd->data);
1583 heap_free(cd);
1587 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1589 DWORD len;
1590 BSTR ret;
1592 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1593 ret = SysAllocStringLen(NULL, len - 1);
1594 if (!ret) return ret;
1595 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1596 return ret;
1599 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1600 UINT n, MEMBERID memid)
1602 while(n){
1603 if(funcdescs->funcdesc.memid == memid)
1604 return funcdescs;
1605 ++funcdescs;
1606 --n;
1608 return NULL;
1611 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1612 UINT n, const OLECHAR *name)
1614 while(n){
1615 if(!lstrcmpiW(funcdescs->Name, name))
1616 return funcdescs;
1617 ++funcdescs;
1618 --n;
1620 return NULL;
1623 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1624 UINT n, MEMBERID memid)
1626 while(n){
1627 if(vardescs->vardesc.memid == memid)
1628 return vardescs;
1629 ++vardescs;
1630 --n;
1632 return NULL;
1635 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1636 UINT n, const OLECHAR *name)
1638 while(n){
1639 if(!lstrcmpiW(vardescs->Name, name))
1640 return vardescs;
1641 ++vardescs;
1642 --n;
1644 return NULL;
1647 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1649 TLBCustData *cust_data;
1650 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1651 if(IsEqualIID(&cust_data->guid, guid))
1652 return cust_data;
1653 return NULL;
1656 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1657 UINT n, const OLECHAR *name)
1659 while(n){
1660 if(!lstrcmpiW((*typeinfos)->Name, name))
1661 return *typeinfos;
1662 ++typeinfos;
1663 --n;
1665 return NULL;
1668 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1670 TLBVarDesc *ret;
1672 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1673 if(!ret)
1674 return NULL;
1676 while(n){
1677 list_init(&ret[n-1].custdata_list);
1678 --n;
1681 return ret;
1684 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1686 TLBParDesc *ret;
1688 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1689 if(!ret)
1690 return NULL;
1692 while(n){
1693 list_init(&ret[n-1].custdata_list);
1694 --n;
1697 return ret;
1700 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1702 list_init(&func_desc->custdata_list);
1705 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1707 TLBFuncDesc *ret;
1709 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1710 if(!ret)
1711 return NULL;
1713 while(n){
1714 TLBFuncDesc_Constructor(&ret[n-1]);
1715 --n;
1718 return ret;
1721 static void TLBImplType_Constructor(TLBImplType *impl)
1723 list_init(&impl->custdata_list);
1726 static TLBImplType *TLBImplType_Alloc(UINT n)
1728 TLBImplType *ret;
1730 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1731 if(!ret)
1732 return NULL;
1734 while(n){
1735 TLBImplType_Constructor(&ret[n-1]);
1736 --n;
1739 return ret;
1742 static HRESULT TLB_set_custdata(struct list *custdata_list, REFGUID guid, VARIANT *var)
1744 TLBCustData *cust_data;
1746 switch(V_VT(var)){
1747 case VT_I4:
1748 case VT_R4:
1749 case VT_UI4:
1750 case VT_INT:
1751 case VT_UINT:
1752 case VT_HRESULT:
1753 case VT_BSTR:
1754 break;
1755 default:
1756 return DISP_E_BADVARTYPE;
1759 cust_data = TLB_get_custdata_by_guid(custdata_list, guid);
1761 if (!cust_data) {
1762 cust_data = heap_alloc(sizeof(TLBCustData));
1763 if (!cust_data)
1764 return E_OUTOFMEMORY;
1766 cust_data->guid = *guid;
1767 VariantInit(&cust_data->data);
1769 list_add_tail(custdata_list, &cust_data->entry);
1770 }else
1771 VariantClear(&cust_data->data);
1773 return VariantCopy(&cust_data->data, var);
1776 /**********************************************************************
1778 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1780 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1782 return pcx->pos;
1785 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1787 if (where != DO_NOT_SEEK)
1789 where += pcx->oStart;
1790 if (where > pcx->length)
1792 /* FIXME */
1793 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1794 TLB_abort();
1796 pcx->pos = where;
1800 /* read function */
1801 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1803 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1804 pcx->pos, count, pcx->oStart, pcx->length, where);
1806 MSFT_Seek(pcx, where);
1807 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1808 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1809 pcx->pos += count;
1810 return count;
1813 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1814 LONG where )
1816 DWORD ret;
1818 ret = MSFT_Read(buffer, count, pcx, where);
1819 FromLEDWords(buffer, ret);
1821 return ret;
1824 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1825 LONG where )
1827 DWORD ret;
1829 ret = MSFT_Read(buffer, count, pcx, where);
1830 FromLEWords(buffer, ret);
1832 return ret;
1835 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1837 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1838 memset(pGuid,0, sizeof(GUID));
1839 return;
1841 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1842 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1843 pGuid->Data2 = FromLEWord(pGuid->Data2);
1844 pGuid->Data3 = FromLEWord(pGuid->Data3);
1845 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1848 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1850 MSFT_NameIntro niName;
1852 if (offset < 0)
1854 ERR_(typelib)("bad offset %d\n", offset);
1855 return -1;
1858 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1859 pcx->pTblDir->pNametab.offset+offset);
1861 return niName.hreftype;
1864 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1866 char * name;
1867 MSFT_NameIntro niName;
1868 int lengthInChars;
1869 BSTR bstrName = NULL;
1871 if (offset < 0)
1873 ERR_(typelib)("bad offset %d\n", offset);
1874 return NULL;
1876 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1877 pcx->pTblDir->pNametab.offset+offset);
1878 niName.namelen &= 0xFF; /* FIXME: correct ? */
1879 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1880 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1881 name[niName.namelen & 0xff]='\0';
1883 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1884 name, -1, NULL, 0);
1886 /* no invalid characters in string */
1887 if (lengthInChars)
1889 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1891 /* don't check for invalid character since this has been done previously */
1892 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1894 heap_free(name);
1896 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1897 return bstrName;
1900 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1902 char * string;
1903 INT16 length;
1904 int lengthInChars;
1905 BSTR bstr = NULL;
1907 if(offset<0) return NULL;
1908 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1909 if(length <= 0) return 0;
1910 string = heap_alloc_zero(length +1);
1911 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1912 string[length]='\0';
1914 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1915 string, -1, NULL, 0);
1917 /* no invalid characters in string */
1918 if (lengthInChars)
1920 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1922 /* don't check for invalid character since this has been done previously */
1923 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1925 heap_free(string);
1927 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1928 return bstr;
1931 * read a value and fill a VARIANT structure
1933 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1935 int size;
1937 TRACE_(typelib)("\n");
1939 if(offset <0) { /* data are packed in here */
1940 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1941 V_I4(pVar) = offset & 0x3ffffff;
1942 return;
1944 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1945 pcx->pTblDir->pCustData.offset + offset );
1946 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1947 switch (V_VT(pVar)){
1948 case VT_EMPTY: /* FIXME: is this right? */
1949 case VT_NULL: /* FIXME: is this right? */
1950 case VT_I2 : /* this should not happen */
1951 case VT_I4 :
1952 case VT_R4 :
1953 case VT_ERROR :
1954 case VT_BOOL :
1955 case VT_I1 :
1956 case VT_UI1 :
1957 case VT_UI2 :
1958 case VT_UI4 :
1959 case VT_INT :
1960 case VT_UINT :
1961 case VT_VOID : /* FIXME: is this right? */
1962 case VT_HRESULT :
1963 size=4; break;
1964 case VT_R8 :
1965 case VT_CY :
1966 case VT_DATE :
1967 case VT_I8 :
1968 case VT_UI8 :
1969 case VT_DECIMAL : /* FIXME: is this right? */
1970 case VT_FILETIME :
1971 size=8;break;
1972 /* pointer types with known behaviour */
1973 case VT_BSTR :{
1974 char * ptr;
1975 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1976 if(size < 0) {
1977 char next;
1978 DWORD origPos = MSFT_Tell(pcx), nullPos;
1980 do {
1981 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1982 } while (next);
1983 nullPos = MSFT_Tell(pcx);
1984 size = nullPos - origPos;
1985 MSFT_Seek(pcx, origPos);
1987 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1988 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1989 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1990 /* FIXME: do we need a AtoW conversion here? */
1991 V_UNION(pVar, bstrVal[size])='\0';
1992 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1993 heap_free(ptr);
1995 size=-4; break;
1996 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1997 case VT_DISPATCH :
1998 case VT_VARIANT :
1999 case VT_UNKNOWN :
2000 case VT_PTR :
2001 case VT_SAFEARRAY :
2002 case VT_CARRAY :
2003 case VT_USERDEFINED :
2004 case VT_LPSTR :
2005 case VT_LPWSTR :
2006 case VT_BLOB :
2007 case VT_STREAM :
2008 case VT_STORAGE :
2009 case VT_STREAMED_OBJECT :
2010 case VT_STORED_OBJECT :
2011 case VT_BLOB_OBJECT :
2012 case VT_CF :
2013 case VT_CLSID :
2014 default:
2015 size=0;
2016 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2017 V_VT(pVar));
2020 if(size>0) /* (big|small) endian correct? */
2021 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2022 return;
2025 * create a linked list with custom data
2027 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2029 MSFT_CDGuid entry;
2030 TLBCustData* pNew;
2031 int count=0;
2033 TRACE_(typelib)("\n");
2035 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2037 while(offset >=0){
2038 count++;
2039 pNew=heap_alloc_zero(sizeof(TLBCustData));
2040 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2041 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
2042 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2043 list_add_head(custdata_list, &pNew->entry);
2044 offset = entry.next;
2046 return count;
2049 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
2050 ITypeInfoImpl *pTI)
2052 if(type <0)
2053 pTd->vt=type & VT_TYPEMASK;
2054 else
2055 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2057 if(pTd->vt == VT_USERDEFINED)
2058 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
2060 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2063 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
2065 /* resolve referenced type if any */
2066 while (lpTypeDesc)
2068 switch (lpTypeDesc->vt)
2070 case VT_PTR:
2071 lpTypeDesc = lpTypeDesc->u.lptdesc;
2072 break;
2074 case VT_CARRAY:
2075 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
2076 break;
2078 case VT_USERDEFINED:
2079 MSFT_DoRefType(pcx, pTI->pTypeLib,
2080 lpTypeDesc->u.hreftype);
2082 lpTypeDesc = NULL;
2083 break;
2085 default:
2086 lpTypeDesc = NULL;
2091 static void
2092 MSFT_DoFuncs(TLBContext* pcx,
2093 ITypeInfoImpl* pTI,
2094 int cFuncs,
2095 int cVars,
2096 int offset,
2097 TLBFuncDesc** pptfd)
2100 * member information is stored in a data structure at offset
2101 * indicated by the memoffset field of the typeinfo structure
2102 * There are several distinctive parts.
2103 * The first part starts with a field that holds the total length
2104 * of this (first) part excluding this field. Then follow the records,
2105 * for each member there is one record.
2107 * The first entry is always the length of the record (including this
2108 * length word).
2109 * The rest of the record depends on the type of the member. If there is
2110 * a field indicating the member type (function, variable, interface, etc)
2111 * I have not found it yet. At this time we depend on the information
2112 * in the type info and the usual order how things are stored.
2114 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2115 * for each member;
2117 * Third is an equal sized array with file offsets to the name entry
2118 * of each member.
2120 * The fourth and last (?) part is an array with offsets to the records
2121 * in the first part of this file segment.
2124 int infolen, nameoffset, reclength, i;
2125 int recoffset = offset + sizeof(INT);
2127 char *recbuf = heap_alloc(0xffff);
2128 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2129 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2131 TRACE_(typelib)("\n");
2133 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2135 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2136 ptfd = *pptfd;
2137 for ( i = 0; i < cFuncs ; i++ )
2139 int optional;
2141 /* name, eventually add to a hash table */
2142 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2143 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2145 /* nameoffset is sometimes -1 on the second half of a propget/propput
2146 * pair of functions */
2147 if ((nameoffset == -1) && (i > 0))
2148 ptfd->Name = SysAllocString(ptfd_prev->Name);
2149 else
2150 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2152 /* read the function information record */
2153 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2155 reclength &= 0xffff;
2157 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2159 /* size without argument data */
2160 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2162 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2163 ptfd->helpcontext = pFuncRec->HelpContext;
2165 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2166 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2168 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2170 if (pFuncRec->FKCCIC & 0x2000 )
2172 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2173 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2174 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2176 else
2177 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2179 else
2180 ptfd->Entry = (BSTR)-1;
2182 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2183 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2185 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2186 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2188 /* fill the FuncDesc Structure */
2189 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2190 offset + infolen + ( i + 1) * sizeof(INT));
2192 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2193 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2194 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2195 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2196 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2197 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2198 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2200 MSFT_GetTdesc(pcx,
2201 pFuncRec->DataType,
2202 &ptfd->funcdesc.elemdescFunc.tdesc,
2203 pTI);
2204 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2206 /* do the parameters/arguments */
2207 if(pFuncRec->nrargs)
2209 int j = 0;
2210 MSFT_ParameterInfo paraminfo;
2212 ptfd->funcdesc.lprgelemdescParam =
2213 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2215 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2217 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2218 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2220 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2222 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2224 MSFT_GetTdesc(pcx,
2225 paraminfo.DataType,
2226 &elemdesc->tdesc,
2227 pTI);
2229 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2231 /* name */
2232 if (paraminfo.oName == -1)
2233 /* this occurs for [propput] or [propget] methods, so
2234 * we should just set the name of the parameter to the
2235 * name of the method. */
2236 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2237 else
2238 ptfd->pParamDesc[j].Name =
2239 MSFT_ReadName( pcx, paraminfo.oName );
2240 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2242 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2244 /* default value */
2245 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2246 (pFuncRec->FKCCIC & 0x1000) )
2248 INT* pInt = (INT *)((char *)pFuncRec +
2249 reclength -
2250 (pFuncRec->nrargs * 4) * sizeof(INT) );
2252 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2254 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2255 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2257 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2258 pInt[j], pcx);
2260 else
2261 elemdesc->u.paramdesc.pparamdescex = NULL;
2263 /* custom info */
2264 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2265 j*sizeof(pFuncRec->oArgCustData[0])) &&
2266 pFuncRec->FKCCIC & 0x80 )
2268 MSFT_CustData(pcx,
2269 pFuncRec->oArgCustData[j],
2270 &ptfd->pParamDesc[j].custdata_list);
2273 /* SEEK value = jump to offset,
2274 * from there jump to the end of record,
2275 * go back by (j-1) arguments
2277 MSFT_ReadLEDWords( &paraminfo ,
2278 sizeof(MSFT_ParameterInfo), pcx,
2279 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2280 * sizeof(MSFT_ParameterInfo)));
2284 /* scode is not used: archaic win16 stuff FIXME: right? */
2285 ptfd->funcdesc.cScodes = 0 ;
2286 ptfd->funcdesc.lprgscode = NULL ;
2288 ptfd_prev = ptfd;
2289 ++ptfd;
2290 recoffset += reclength;
2292 heap_free(recbuf);
2295 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2296 int cVars, int offset, TLBVarDesc ** pptvd)
2298 int infolen, nameoffset, reclength;
2299 char recbuf[256];
2300 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2301 TLBVarDesc *ptvd;
2302 int i;
2303 int recoffset;
2305 TRACE_(typelib)("\n");
2307 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2308 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2309 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2310 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2311 recoffset += offset+sizeof(INT);
2312 for(i=0;i<cVars;i++, ++ptvd){
2313 /* name, eventually add to a hash table */
2314 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2315 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2316 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2317 /* read the variable information record */
2318 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2319 reclength &= 0xff;
2320 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2322 /* optional data */
2323 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2324 ptvd->HelpContext = pVarRec->HelpContext;
2326 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2327 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2329 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2330 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2332 /* fill the VarDesc Structure */
2333 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2334 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2335 ptvd->vardesc.varkind = pVarRec->VarKind;
2336 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2337 MSFT_GetTdesc(pcx, pVarRec->DataType,
2338 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2339 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2340 if(pVarRec->VarKind == VAR_CONST ){
2341 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2342 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2343 pVarRec->OffsValue, pcx);
2344 } else
2345 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2346 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2347 recoffset += reclength;
2351 /* fill in data for a hreftype (offset). When the referenced type is contained
2352 * in the typelib, it's just an (file) offset in the type info base dir.
2353 * If comes from import, it's an offset+1 in the ImpInfo table
2354 * */
2355 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2356 int offset)
2358 TLBRefType *ref;
2360 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2362 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2364 if(ref->reference == offset) return;
2367 ref = heap_alloc_zero(sizeof(TLBRefType));
2368 list_add_tail(&pTL->ref_list, &ref->entry);
2370 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2371 /* external typelib */
2372 MSFT_ImpInfo impinfo;
2373 TLBImpLib *pImpLib;
2375 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2377 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2378 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2380 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2381 if(pImpLib->offset==impinfo.oImpFile)
2382 break;
2384 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2385 ref->reference = offset & (~0x3);
2386 ref->pImpTLInfo = pImpLib;
2387 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2388 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2389 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2390 ref->index = TLB_REF_USE_GUID;
2391 } else
2392 ref->index = impinfo.oGuid;
2393 }else{
2394 ERR("Cannot find a reference\n");
2395 ref->reference = -1;
2396 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2398 }else{
2399 /* in this typelib */
2400 ref->index = MSFT_HREFTYPE_INDEX(offset);
2401 ref->reference = offset;
2402 ref->pImpTLInfo = TLB_REF_INTERNAL;
2406 /* process Implemented Interfaces of a com class */
2407 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2408 int offset)
2410 int i;
2411 MSFT_RefRecord refrec;
2412 TLBImplType *pImpl;
2414 TRACE_(typelib)("\n");
2416 pTI->impltypes = TLBImplType_Alloc(count);
2417 pImpl = pTI->impltypes;
2418 for(i=0;i<count;i++){
2419 if(offset<0) break; /* paranoia */
2420 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2421 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2422 pImpl->hRef = refrec.reftype;
2423 pImpl->implflags=refrec.flags;
2424 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2425 offset=refrec.onext;
2426 ++pImpl;
2430 * process a typeinfo record
2432 static ITypeInfoImpl * MSFT_DoTypeInfo(
2433 TLBContext *pcx,
2434 int count,
2435 ITypeLibImpl * pLibInfo)
2437 MSFT_TypeInfoBase tiBase;
2438 ITypeInfoImpl *ptiRet;
2440 TRACE_(typelib)("count=%u\n", count);
2442 ptiRet = ITypeInfoImpl_Constructor();
2443 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2444 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2446 /* this is where we are coming from */
2447 ptiRet->pTypeLib = pLibInfo;
2448 ptiRet->index=count;
2449 /* fill in the typeattr fields */
2451 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2452 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2453 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2454 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2455 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2456 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2457 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2458 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2459 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2460 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2461 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2462 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2463 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2464 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2465 MSFT_GetTdesc(pcx, tiBase.datatype1,
2466 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2468 /* FIXME: */
2469 /* IDLDESC idldescType; *//* never saw this one != zero */
2471 /* name, eventually add to a hash table */
2472 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2473 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2474 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2475 /* help info */
2476 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2477 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2478 ptiRet->dwHelpContext=tiBase.helpcontext;
2480 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2481 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2483 /* note: InfoType's Help file and HelpStringDll come from the containing
2484 * library. Further HelpString and Docstring appear to be the same thing :(
2486 /* functions */
2487 if(ptiRet->TypeAttr.cFuncs >0 )
2488 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2489 ptiRet->TypeAttr.cVars,
2490 tiBase.memoffset, &ptiRet->funcdescs);
2491 /* variables */
2492 if(ptiRet->TypeAttr.cVars >0 )
2493 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2494 ptiRet->TypeAttr.cVars,
2495 tiBase.memoffset, &ptiRet->vardescs);
2496 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2497 switch(ptiRet->TypeAttr.typekind)
2499 case TKIND_COCLASS:
2500 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2501 tiBase.datatype1);
2502 break;
2503 case TKIND_DISPATCH:
2504 /* This is not -1 when the interface is a non-base dual interface or
2505 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2506 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2507 not this interface.
2510 if (tiBase.datatype1 != -1)
2512 ptiRet->impltypes = TLBImplType_Alloc(1);
2513 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2514 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2516 break;
2517 default:
2518 ptiRet->impltypes = TLBImplType_Alloc(1);
2519 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2520 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2521 break;
2524 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2526 TRACE_(typelib)("%s guid: %s kind:%s\n",
2527 debugstr_w(ptiRet->Name),
2528 debugstr_guid(&ptiRet->TypeAttr.guid),
2529 typekind_desc[ptiRet->TypeAttr.typekind]);
2530 if (TRACE_ON(typelib))
2531 dump_TypeInfo(ptiRet);
2533 return ptiRet;
2536 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2537 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2538 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2539 * tradeoff here.
2541 static struct list tlb_cache = LIST_INIT(tlb_cache);
2542 static CRITICAL_SECTION cache_section;
2543 static CRITICAL_SECTION_DEBUG cache_section_debug =
2545 0, 0, &cache_section,
2546 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2547 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2549 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2552 typedef struct TLB_PEFile
2554 IUnknown IUnknown_iface;
2555 LONG refs;
2556 HMODULE dll;
2557 HRSRC typelib_resource;
2558 HGLOBAL typelib_global;
2559 LPVOID typelib_base;
2560 } TLB_PEFile;
2562 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2564 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2567 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2569 if (IsEqualIID(riid, &IID_IUnknown))
2571 *ppv = iface;
2572 IUnknown_AddRef(iface);
2573 return S_OK;
2575 *ppv = NULL;
2576 return E_NOINTERFACE;
2579 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2581 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2582 return InterlockedIncrement(&This->refs);
2585 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2587 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2588 ULONG refs = InterlockedDecrement(&This->refs);
2589 if (!refs)
2591 if (This->typelib_global)
2592 FreeResource(This->typelib_global);
2593 if (This->dll)
2594 FreeLibrary(This->dll);
2595 heap_free(This);
2597 return refs;
2600 static const IUnknownVtbl TLB_PEFile_Vtable =
2602 TLB_PEFile_QueryInterface,
2603 TLB_PEFile_AddRef,
2604 TLB_PEFile_Release
2607 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2609 TLB_PEFile *This;
2610 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2612 This = heap_alloc(sizeof(TLB_PEFile));
2613 if (!This)
2614 return E_OUTOFMEMORY;
2616 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2617 This->refs = 1;
2618 This->dll = NULL;
2619 This->typelib_resource = NULL;
2620 This->typelib_global = NULL;
2621 This->typelib_base = NULL;
2623 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2624 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2626 if (This->dll)
2628 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2629 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2630 if (This->typelib_resource)
2632 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2633 if (This->typelib_global)
2635 This->typelib_base = LockResource(This->typelib_global);
2637 if (This->typelib_base)
2639 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2640 *ppBase = This->typelib_base;
2641 *ppFile = &This->IUnknown_iface;
2642 return S_OK;
2647 TRACE("No TYPELIB resource found\n");
2648 hr = E_FAIL;
2651 TLB_PEFile_Release(&This->IUnknown_iface);
2652 return hr;
2655 typedef struct TLB_NEFile
2657 IUnknown IUnknown_iface;
2658 LONG refs;
2659 LPVOID typelib_base;
2660 } TLB_NEFile;
2662 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2664 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2667 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2669 if (IsEqualIID(riid, &IID_IUnknown))
2671 *ppv = iface;
2672 IUnknown_AddRef(iface);
2673 return S_OK;
2675 *ppv = NULL;
2676 return E_NOINTERFACE;
2679 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2681 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2682 return InterlockedIncrement(&This->refs);
2685 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2687 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2688 ULONG refs = InterlockedDecrement(&This->refs);
2689 if (!refs)
2691 heap_free(This->typelib_base);
2692 heap_free(This);
2694 return refs;
2697 static const IUnknownVtbl TLB_NEFile_Vtable =
2699 TLB_NEFile_QueryInterface,
2700 TLB_NEFile_AddRef,
2701 TLB_NEFile_Release
2704 /***********************************************************************
2705 * read_xx_header [internal]
2707 static int read_xx_header( HFILE lzfd )
2709 IMAGE_DOS_HEADER mzh;
2710 char magic[3];
2712 LZSeek( lzfd, 0, SEEK_SET );
2713 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2714 return 0;
2715 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2716 return 0;
2718 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2719 if ( 2 != LZRead( lzfd, magic, 2 ) )
2720 return 0;
2722 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2724 if ( magic[0] == 'N' && magic[1] == 'E' )
2725 return IMAGE_OS2_SIGNATURE;
2726 if ( magic[0] == 'P' && magic[1] == 'E' )
2727 return IMAGE_NT_SIGNATURE;
2729 magic[2] = '\0';
2730 WARN("Can't handle %s files.\n", magic );
2731 return 0;
2735 /***********************************************************************
2736 * find_ne_resource [internal]
2738 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2739 DWORD *resLen, DWORD *resOff )
2741 IMAGE_OS2_HEADER nehd;
2742 NE_TYPEINFO *typeInfo;
2743 NE_NAMEINFO *nameInfo;
2744 DWORD nehdoffset;
2745 LPBYTE resTab;
2746 DWORD resTabSize;
2747 int count;
2749 /* Read in NE header */
2750 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2751 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2753 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2754 if ( !resTabSize )
2756 TRACE("No resources in NE dll\n" );
2757 return FALSE;
2760 /* Read in resource table */
2761 resTab = heap_alloc( resTabSize );
2762 if ( !resTab ) return FALSE;
2764 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2765 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2767 heap_free( resTab );
2768 return FALSE;
2771 /* Find resource */
2772 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2774 if (!IS_INTRESOURCE(typeid)) /* named type */
2776 BYTE len = strlen( typeid );
2777 while (typeInfo->type_id)
2779 if (!(typeInfo->type_id & 0x8000))
2781 BYTE *p = resTab + typeInfo->type_id;
2782 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2784 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2785 typeInfo->count * sizeof(NE_NAMEINFO));
2788 else /* numeric type id */
2790 WORD id = LOWORD(typeid) | 0x8000;
2791 while (typeInfo->type_id)
2793 if (typeInfo->type_id == id) goto found_type;
2794 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2795 typeInfo->count * sizeof(NE_NAMEINFO));
2798 TRACE("No typeid entry found for %p\n", typeid );
2799 heap_free( resTab );
2800 return FALSE;
2802 found_type:
2803 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2805 if (!IS_INTRESOURCE(resid)) /* named resource */
2807 BYTE len = strlen( resid );
2808 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2810 BYTE *p = resTab + nameInfo->id;
2811 if (nameInfo->id & 0x8000) continue;
2812 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2815 else /* numeric resource id */
2817 WORD id = LOWORD(resid) | 0x8000;
2818 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2819 if (nameInfo->id == id) goto found_name;
2821 TRACE("No resid entry found for %p\n", typeid );
2822 heap_free( resTab );
2823 return FALSE;
2825 found_name:
2826 /* Return resource data */
2827 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2828 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2830 heap_free( resTab );
2831 return TRUE;
2834 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2836 HFILE lzfd = -1;
2837 OFSTRUCT ofs;
2838 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2839 TLB_NEFile *This;
2841 This = heap_alloc(sizeof(TLB_NEFile));
2842 if (!This) return E_OUTOFMEMORY;
2844 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
2845 This->refs = 1;
2846 This->typelib_base = NULL;
2848 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2849 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2851 DWORD reslen, offset;
2852 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2854 This->typelib_base = heap_alloc(reslen);
2855 if( !This->typelib_base )
2856 hr = E_OUTOFMEMORY;
2857 else
2859 LZSeek( lzfd, offset, SEEK_SET );
2860 reslen = LZRead( lzfd, This->typelib_base, reslen );
2861 LZClose( lzfd );
2862 *ppBase = This->typelib_base;
2863 *pdwTLBLength = reslen;
2864 *ppFile = &This->IUnknown_iface;
2865 return S_OK;
2870 if( lzfd >= 0) LZClose( lzfd );
2871 TLB_NEFile_Release(&This->IUnknown_iface);
2872 return hr;
2875 typedef struct TLB_Mapping
2877 IUnknown IUnknown_iface;
2878 LONG refs;
2879 HANDLE file;
2880 HANDLE mapping;
2881 LPVOID typelib_base;
2882 } TLB_Mapping;
2884 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
2886 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
2889 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2891 if (IsEqualIID(riid, &IID_IUnknown))
2893 *ppv = iface;
2894 IUnknown_AddRef(iface);
2895 return S_OK;
2897 *ppv = NULL;
2898 return E_NOINTERFACE;
2901 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2903 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
2904 return InterlockedIncrement(&This->refs);
2907 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2909 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
2910 ULONG refs = InterlockedDecrement(&This->refs);
2911 if (!refs)
2913 if (This->typelib_base)
2914 UnmapViewOfFile(This->typelib_base);
2915 if (This->mapping)
2916 CloseHandle(This->mapping);
2917 if (This->file != INVALID_HANDLE_VALUE)
2918 CloseHandle(This->file);
2919 heap_free(This);
2921 return refs;
2924 static const IUnknownVtbl TLB_Mapping_Vtable =
2926 TLB_Mapping_QueryInterface,
2927 TLB_Mapping_AddRef,
2928 TLB_Mapping_Release
2931 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2933 TLB_Mapping *This;
2935 This = heap_alloc(sizeof(TLB_Mapping));
2936 if (!This)
2937 return E_OUTOFMEMORY;
2939 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
2940 This->refs = 1;
2941 This->file = INVALID_HANDLE_VALUE;
2942 This->mapping = NULL;
2943 This->typelib_base = NULL;
2945 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2946 if (INVALID_HANDLE_VALUE != This->file)
2948 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2949 if (This->mapping)
2951 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2952 if(This->typelib_base)
2954 /* retrieve file size */
2955 *pdwTLBLength = GetFileSize(This->file, NULL);
2956 *ppBase = This->typelib_base;
2957 *ppFile = &This->IUnknown_iface;
2958 return S_OK;
2963 IUnknown_Release(&This->IUnknown_iface);
2964 return TYPE_E_CANTLOADLIBRARY;
2967 /****************************************************************************
2968 * TLB_ReadTypeLib
2970 * find the type of the typelib file and map the typelib resource into
2971 * the memory
2974 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2975 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2977 ITypeLibImpl *entry;
2978 HRESULT ret;
2979 INT index = 1;
2980 LPWSTR index_str, file = (LPWSTR)pszFileName;
2981 LPVOID pBase = NULL;
2982 DWORD dwTLBLength = 0;
2983 IUnknown *pFile = NULL;
2985 *ppTypeLib = NULL;
2987 index_str = strrchrW(pszFileName, '\\');
2988 if(index_str && *++index_str != '\0')
2990 LPWSTR end_ptr;
2991 LONG idx = strtolW(index_str, &end_ptr, 10);
2992 if(*end_ptr == '\0')
2994 int str_len = index_str - pszFileName - 1;
2995 index = idx;
2996 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2997 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2998 file[str_len] = 0;
3002 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3004 if(strchrW(file, '\\'))
3006 lstrcpyW(pszPath, file);
3008 else
3010 int len = GetSystemDirectoryW(pszPath, cchPath);
3011 pszPath[len] = '\\';
3012 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3016 if(file != pszFileName) heap_free(file);
3018 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3020 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3021 EnterCriticalSection(&cache_section);
3022 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3024 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3026 TRACE("cache hit\n");
3027 *ppTypeLib = &entry->ITypeLib2_iface;
3028 ITypeLib2_AddRef(*ppTypeLib);
3029 LeaveCriticalSection(&cache_section);
3030 return S_OK;
3033 LeaveCriticalSection(&cache_section);
3035 /* now actually load and parse the typelib */
3037 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3038 if (ret == TYPE_E_CANTLOADLIBRARY)
3039 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3040 if (ret == TYPE_E_CANTLOADLIBRARY)
3041 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3042 if (SUCCEEDED(ret))
3044 if (dwTLBLength >= 4)
3046 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3047 if (dwSignature == MSFT_SIGNATURE)
3048 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3049 else if (dwSignature == SLTG_SIGNATURE)
3050 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3051 else
3053 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3054 ret = TYPE_E_CANTLOADLIBRARY;
3057 else
3058 ret = TYPE_E_CANTLOADLIBRARY;
3059 IUnknown_Release(pFile);
3062 if(*ppTypeLib) {
3063 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3065 TRACE("adding to cache\n");
3066 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3067 lstrcpyW(impl->path, pszPath);
3068 /* We should really canonicalise the path here. */
3069 impl->index = index;
3071 /* FIXME: check if it has added already in the meantime */
3072 EnterCriticalSection(&cache_section);
3073 list_add_head(&tlb_cache, &impl->entry);
3074 LeaveCriticalSection(&cache_section);
3075 ret = S_OK;
3077 else
3079 if(ret != E_FAIL)
3080 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3082 ret = TYPE_E_CANTLOADLIBRARY;
3086 return ret;
3089 /*================== ITypeLib(2) Methods ===================================*/
3091 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3093 ITypeLibImpl* pTypeLibImpl;
3095 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3096 if (!pTypeLibImpl) return NULL;
3098 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3099 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3100 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3101 pTypeLibImpl->ref = 1;
3103 list_init(&pTypeLibImpl->implib_list);
3104 list_init(&pTypeLibImpl->custdata_list);
3105 list_init(&pTypeLibImpl->ref_list);
3106 pTypeLibImpl->dispatch_href = -1;
3108 return pTypeLibImpl;
3111 /****************************************************************************
3112 * ITypeLib2_Constructor_MSFT
3114 * loading an MSFT typelib from an in-memory image
3116 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3118 TLBContext cx;
3119 LONG lPSegDir;
3120 MSFT_Header tlbHeader;
3121 MSFT_SegDir tlbSegDir;
3122 ITypeLibImpl * pTypeLibImpl;
3124 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3126 pTypeLibImpl = TypeLibImpl_Constructor();
3127 if (!pTypeLibImpl) return NULL;
3129 /* get pointer to beginning of typelib data */
3130 cx.pos = 0;
3131 cx.oStart=0;
3132 cx.mapping = pLib;
3133 cx.pLibInfo = pTypeLibImpl;
3134 cx.length = dwTLBLength;
3136 /* read header */
3137 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3138 TRACE_(typelib)("header:\n");
3139 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3140 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3141 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3142 return NULL;
3144 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3146 /* there is a small amount of information here until the next important
3147 * part:
3148 * the segment directory . Try to calculate the amount of data */
3149 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3151 /* now read the segment directory */
3152 TRACE("read segment directory (at %d)\n",lPSegDir);
3153 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3154 cx.pTblDir = &tlbSegDir;
3156 /* just check two entries */
3157 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3159 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3160 heap_free(pTypeLibImpl);
3161 return NULL;
3164 /* now fill our internal data */
3165 /* TLIBATTR fields */
3166 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3168 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3169 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3170 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3171 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3172 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3174 pTypeLibImpl->lcid = tlbHeader.lcid;
3176 /* name, eventually add to a hash table */
3177 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3179 /* help info */
3180 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3181 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3183 if( tlbHeader.varflags & HELPDLLFLAG)
3185 int offset;
3186 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3187 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3190 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3192 /* custom data */
3193 if(tlbHeader.CustomDataOffset >= 0)
3195 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3198 /* fill in type descriptions */
3199 if(tlbSegDir.pTypdescTab.length > 0)
3201 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3202 INT16 td[4];
3203 pTypeLibImpl->ctTypeDesc = cTD;
3204 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3205 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3206 for(i=0; i<cTD; )
3208 /* FIXME: add several sanity checks here */
3209 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3210 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3212 /* FIXME: check safearray */
3213 if(td[3] < 0)
3214 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3215 else
3216 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3218 else if(td[0] == VT_CARRAY)
3220 /* array descr table here */
3221 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3223 else if(td[0] == VT_USERDEFINED)
3225 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3227 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3230 /* second time around to fill the array subscript info */
3231 for(i=0;i<cTD;i++)
3233 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3234 if(tlbSegDir.pArrayDescriptions.offset>0)
3236 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3237 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3239 if(td[1]<0)
3240 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3241 else
3242 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3244 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3246 for(j = 0; j<td[2]; j++)
3248 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3249 sizeof(INT), &cx, DO_NOT_SEEK);
3250 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3251 sizeof(INT), &cx, DO_NOT_SEEK);
3254 else
3256 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3257 ERR("didn't find array description data\n");
3262 /* imported type libs */
3263 if(tlbSegDir.pImpFiles.offset>0)
3265 TLBImpLib *pImpLib;
3266 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3267 UINT16 size;
3269 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3271 char *name;
3273 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3274 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3275 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3277 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3278 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3279 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3280 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3282 size >>= 2;
3283 name = heap_alloc_zero(size+1);
3284 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3285 pImpLib->name = TLB_MultiByteToBSTR(name);
3286 heap_free(name);
3288 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3289 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3291 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3295 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3296 if(pTypeLibImpl->dispatch_href != -1)
3297 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3299 /* type infos */
3300 if(tlbHeader.nrtypeinfos >= 0 )
3302 ITypeInfoImpl **ppTI;
3303 int i;
3305 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3307 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3309 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3311 ++ppTI;
3312 (pTypeLibImpl->TypeInfoCount)++;
3316 TRACE("(%p)\n", pTypeLibImpl);
3317 return &pTypeLibImpl->ITypeLib2_iface;
3321 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3323 char b[3];
3324 int i;
3325 short s;
3327 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3328 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3329 return FALSE;
3332 guid->Data4[0] = s >> 8;
3333 guid->Data4[1] = s & 0xff;
3335 b[2] = '\0';
3336 for(i = 0; i < 6; i++) {
3337 memcpy(b, str + 24 + 2 * i, 2);
3338 guid->Data4[i + 2] = strtol(b, NULL, 16);
3340 return TRUE;
3343 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3345 WORD bytelen;
3346 DWORD len;
3348 *pBstr = NULL;
3349 bytelen = *(const WORD*)ptr;
3350 if(bytelen == 0xffff) return 2;
3351 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3352 *pBstr = SysAllocStringLen(NULL, len);
3353 if (*pBstr)
3354 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3355 return bytelen + 2;
3358 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3360 WORD bytelen;
3362 *str = NULL;
3363 bytelen = *(const WORD*)ptr;
3364 if(bytelen == 0xffff) return 2;
3365 *str = heap_alloc(bytelen + 1);
3366 memcpy(*str, ptr + 2, bytelen);
3367 (*str)[bytelen] = '\0';
3368 return bytelen + 2;
3371 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3373 char *ptr = pLibBlk;
3374 WORD w;
3376 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3377 FIXME("libblk magic = %04x\n", w);
3378 return 0;
3381 ptr += 6;
3382 if((w = *(WORD*)ptr) != 0xffff) {
3383 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3384 ptr += w;
3386 ptr += 2;
3388 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3390 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3392 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3393 ptr += 4;
3395 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3396 ptr += 2;
3398 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3399 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3400 else
3401 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3402 ptr += 2;
3404 ptr += 4; /* skip res12 */
3406 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3407 ptr += 2;
3409 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3410 ptr += 2;
3412 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3413 ptr += 2;
3415 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3416 ptr += sizeof(GUID);
3418 return ptr - (char*)pLibBlk;
3421 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3422 typedef struct
3424 unsigned int num;
3425 HREFTYPE refs[1];
3426 } sltg_ref_lookup_t;
3428 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3429 HREFTYPE *typelib_ref)
3431 if(table && typeinfo_ref < table->num)
3433 *typelib_ref = table->refs[typeinfo_ref];
3434 return S_OK;
3437 ERR_(typelib)("Unable to find reference\n");
3438 *typelib_ref = -1;
3439 return E_FAIL;
3442 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3444 BOOL done = FALSE;
3446 while(!done) {
3447 if((*pType & 0xe00) == 0xe00) {
3448 pTD->vt = VT_PTR;
3449 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3450 pTD = pTD->u.lptdesc;
3452 switch(*pType & 0x3f) {
3453 case VT_PTR:
3454 pTD->vt = VT_PTR;
3455 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3456 pTD = pTD->u.lptdesc;
3457 break;
3459 case VT_USERDEFINED:
3460 pTD->vt = VT_USERDEFINED;
3461 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3462 done = TRUE;
3463 break;
3465 case VT_CARRAY:
3467 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3468 array */
3470 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3472 pTD->vt = VT_CARRAY;
3473 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3474 pTD->u.lpadesc->cDims = pSA->cDims;
3475 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3476 pSA->cDims * sizeof(SAFEARRAYBOUND));
3478 pTD = &pTD->u.lpadesc->tdescElem;
3479 break;
3482 case VT_SAFEARRAY:
3484 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3485 useful? */
3487 pType++;
3488 pTD->vt = VT_SAFEARRAY;
3489 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3490 pTD = pTD->u.lptdesc;
3491 break;
3493 default:
3494 pTD->vt = *pType & 0x3f;
3495 done = TRUE;
3496 break;
3498 pType++;
3500 return pType;
3503 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3504 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3506 /* Handle [in/out] first */
3507 if((*pType & 0xc000) == 0xc000)
3508 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3509 else if(*pType & 0x8000)
3510 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3511 else if(*pType & 0x4000)
3512 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3513 else
3514 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3516 if(*pType & 0x2000)
3517 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3519 if(*pType & 0x80)
3520 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3522 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3526 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3527 char *pNameTable)
3529 unsigned int ref;
3530 char *name;
3531 TLBRefType *ref_type;
3532 sltg_ref_lookup_t *table;
3533 HREFTYPE typelib_ref;
3535 if(pRef->magic != SLTG_REF_MAGIC) {
3536 FIXME("Ref magic = %x\n", pRef->magic);
3537 return NULL;
3539 name = ( (char*)pRef->names + pRef->number);
3541 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3542 table->num = pRef->number >> 3;
3544 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3546 /* We don't want the first href to be 0 */
3547 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3549 for(ref = 0; ref < pRef->number >> 3; ref++) {
3550 char *refname;
3551 unsigned int lib_offs, type_num;
3553 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3555 name += SLTG_ReadStringA(name, &refname);
3556 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3557 FIXME_(typelib)("Can't sscanf ref\n");
3558 if(lib_offs != 0xffff) {
3559 TLBImpLib *import;
3561 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3562 if(import->offset == lib_offs)
3563 break;
3565 if(&import->entry == &pTL->implib_list) {
3566 char fname[MAX_PATH+1];
3567 int len;
3569 import = heap_alloc_zero(sizeof(*import));
3570 import->offset = lib_offs;
3571 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3572 &import->guid);
3573 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3574 &import->wVersionMajor,
3575 &import->wVersionMinor,
3576 &import->lcid, fname) != 4) {
3577 FIXME_(typelib)("can't sscanf ref %s\n",
3578 pNameTable + lib_offs + 40);
3580 len = strlen(fname);
3581 if(fname[len-1] != '#')
3582 FIXME("fname = %s\n", fname);
3583 fname[len-1] = '\0';
3584 import->name = TLB_MultiByteToBSTR(fname);
3585 list_add_tail(&pTL->implib_list, &import->entry);
3587 ref_type->pImpTLInfo = import;
3589 /* Store a reference to IDispatch */
3590 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3591 pTL->dispatch_href = typelib_ref;
3593 } else { /* internal ref */
3594 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3596 ref_type->reference = typelib_ref;
3597 ref_type->index = type_num;
3599 heap_free(refname);
3600 list_add_tail(&pTL->ref_list, &ref_type->entry);
3602 table->refs[ref] = typelib_ref;
3603 typelib_ref += 4;
3605 if((BYTE)*name != SLTG_REF_MAGIC)
3606 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3607 dump_TLBRefType(pTL);
3608 return table;
3611 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3612 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3614 SLTG_ImplInfo *info;
3615 TLBImplType *pImplType;
3616 /* I don't really get this structure, usually it's 0x16 bytes
3617 long, but iuser.tlb contains some that are 0x18 bytes long.
3618 That's ok because we can use the next ptr to jump to the next
3619 one. But how do we know the length of the last one? The WORD
3620 at offs 0x8 might be the clue. For now I'm just assuming that
3621 the last one is the regular 0x16 bytes. */
3623 info = (SLTG_ImplInfo*)pBlk;
3624 while(1){
3625 pTI->TypeAttr.cImplTypes++;
3626 if(info->next == 0xffff)
3627 break;
3628 info = (SLTG_ImplInfo*)(pBlk + info->next);
3631 info = (SLTG_ImplInfo*)pBlk;
3632 pTI->impltypes = TLBImplType_Alloc(pTI->TypeAttr.cImplTypes);
3633 pImplType = pTI->impltypes;
3634 while(1) {
3635 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3636 pImplType->implflags = info->impltypeflags;
3637 ++pImplType;
3639 if(info->next == 0xffff)
3640 break;
3641 if(OneOnly)
3642 FIXME_(typelib)("Interface inheriting more than one interface\n");
3643 info = (SLTG_ImplInfo*)(pBlk + info->next);
3645 info++; /* see comment at top of function */
3646 return (char*)info;
3649 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3650 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3652 TLBVarDesc *pVarDesc;
3653 BSTR bstrPrevName = NULL;
3654 SLTG_Variable *pItem;
3655 unsigned short i;
3656 WORD *pType;
3658 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3660 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3661 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3663 pVarDesc->vardesc.memid = pItem->memid;
3665 if (pItem->magic != SLTG_VAR_MAGIC &&
3666 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3667 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3668 return;
3671 if (pItem->name == 0xfffe)
3672 pVarDesc->Name = SysAllocString(bstrPrevName);
3673 else
3674 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3676 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3677 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3678 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3680 if(pItem->flags & 0x02)
3681 pType = &pItem->type;
3682 else
3683 pType = (WORD*)(pBlk + pItem->type);
3685 if (pItem->flags & ~0xda)
3686 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3688 SLTG_DoElem(pType, pBlk,
3689 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3691 if (TRACE_ON(typelib)) {
3692 char buf[300];
3693 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3694 TRACE_(typelib)("elemdescVar: %s\n", buf);
3697 if (pItem->flags & 0x40) {
3698 TRACE_(typelib)("VAR_DISPATCH\n");
3699 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3701 else if (pItem->flags & 0x10) {
3702 TRACE_(typelib)("VAR_CONST\n");
3703 pVarDesc->vardesc.varkind = VAR_CONST;
3704 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3705 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3706 if (pItem->flags & 0x08)
3707 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3708 else {
3709 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3711 case VT_LPSTR:
3712 case VT_LPWSTR:
3713 case VT_BSTR:
3715 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3716 BSTR str;
3717 TRACE_(typelib)("len = %u\n", len);
3718 if (len == 0xffff) {
3719 str = NULL;
3720 } else {
3721 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3722 str = SysAllocStringLen(NULL, alloc_len);
3723 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3725 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3726 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3727 break;
3729 case VT_I2:
3730 case VT_UI2:
3731 case VT_I4:
3732 case VT_UI4:
3733 case VT_INT:
3734 case VT_UINT:
3735 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3736 *(INT*)(pBlk + pItem->byte_offs);
3737 break;
3738 default:
3739 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3743 else {
3744 TRACE_(typelib)("VAR_PERINSTANCE\n");
3745 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3746 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3749 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3750 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3752 if (pItem->flags & 0x80)
3753 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3755 bstrPrevName = pVarDesc->Name;
3757 pTI->TypeAttr.cVars = cVars;
3760 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3761 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3763 SLTG_Function *pFunc;
3764 unsigned short i;
3765 TLBFuncDesc *pFuncDesc;
3767 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
3769 pFuncDesc = pTI->funcdescs;
3770 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3771 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3773 int param;
3774 WORD *pType, *pArg;
3776 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3777 case SLTG_FUNCTION_MAGIC:
3778 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3779 break;
3780 case SLTG_DISPATCH_FUNCTION_MAGIC:
3781 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3782 break;
3783 case SLTG_STATIC_FUNCTION_MAGIC:
3784 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3785 break;
3786 default:
3787 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3788 continue;
3790 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3792 pFuncDesc->funcdesc.memid = pFunc->dispid;
3793 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3794 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3795 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3796 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3797 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3799 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3800 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3802 if(pFunc->retnextopt & 0x80)
3803 pType = &pFunc->rettype;
3804 else
3805 pType = (WORD*)(pBlk + pFunc->rettype);
3807 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3809 pFuncDesc->funcdesc.lprgelemdescParam =
3810 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3811 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3813 pArg = (WORD*)(pBlk + pFunc->arg_off);
3815 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3816 char *paramName = pNameTable + *pArg;
3817 BOOL HaveOffs;
3818 /* If arg type follows then paramName points to the 2nd
3819 letter of the name, else the next WORD is an offset to
3820 the arg type and paramName points to the first letter.
3821 So let's take one char off paramName and see if we're
3822 pointing at an alpha-numeric char. However if *pArg is
3823 0xffff or 0xfffe then the param has no name, the former
3824 meaning that the next WORD is the type, the latter
3825 meaning that the next WORD is an offset to the type. */
3827 HaveOffs = FALSE;
3828 if(*pArg == 0xffff)
3829 paramName = NULL;
3830 else if(*pArg == 0xfffe) {
3831 paramName = NULL;
3832 HaveOffs = TRUE;
3834 else if(paramName[-1] && !isalnum(paramName[-1]))
3835 HaveOffs = TRUE;
3837 pArg++;
3839 if(HaveOffs) { /* the next word is an offset to type */
3840 pType = (WORD*)(pBlk + *pArg);
3841 SLTG_DoElem(pType, pBlk,
3842 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3843 pArg++;
3844 } else {
3845 if(paramName)
3846 paramName--;
3847 pArg = SLTG_DoElem(pArg, pBlk,
3848 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3851 /* Are we an optional param ? */
3852 if(pFuncDesc->funcdesc.cParams - param <=
3853 pFuncDesc->funcdesc.cParamsOpt)
3854 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3856 if(paramName) {
3857 pFuncDesc->pParamDesc[param].Name =
3858 TLB_MultiByteToBSTR(paramName);
3859 } else {
3860 pFuncDesc->pParamDesc[param].Name =
3861 SysAllocString(pFuncDesc->Name);
3865 pTI->TypeAttr.cFuncs = cFuncs;
3868 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3869 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3870 SLTG_TypeInfoTail *pTITail)
3872 char *pFirstItem;
3873 sltg_ref_lookup_t *ref_lookup = NULL;
3875 if(pTIHeader->href_table != 0xffffffff) {
3876 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3877 pNameTable);
3880 pFirstItem = pBlk;
3882 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3883 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3885 heap_free(ref_lookup);
3889 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3890 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3891 const SLTG_TypeInfoTail *pTITail)
3893 char *pFirstItem;
3894 sltg_ref_lookup_t *ref_lookup = NULL;
3896 if(pTIHeader->href_table != 0xffffffff) {
3897 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3898 pNameTable);
3901 pFirstItem = pBlk;
3903 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3904 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3907 if (pTITail->funcs_off != 0xffff)
3908 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3910 heap_free(ref_lookup);
3912 if (TRACE_ON(typelib))
3913 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3916 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3917 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3918 const SLTG_TypeInfoTail *pTITail)
3920 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3923 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3924 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3925 const SLTG_TypeInfoTail *pTITail)
3927 WORD *pType;
3928 sltg_ref_lookup_t *ref_lookup = NULL;
3930 if (pTITail->simple_alias) {
3931 /* if simple alias, no more processing required */
3932 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3933 return;
3936 if(pTIHeader->href_table != 0xffffffff) {
3937 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3938 pNameTable);
3941 /* otherwise it is an offset to a type */
3942 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3944 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3946 heap_free(ref_lookup);
3949 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3950 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3951 const SLTG_TypeInfoTail *pTITail)
3953 sltg_ref_lookup_t *ref_lookup = NULL;
3954 if (pTIHeader->href_table != 0xffffffff)
3955 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3956 pNameTable);
3958 if (pTITail->vars_off != 0xffff)
3959 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3961 if (pTITail->funcs_off != 0xffff)
3962 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3964 if (pTITail->impls_off != 0xffff)
3965 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3967 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3968 * of dispinterface functions including the IDispatch ones, so
3969 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3970 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3972 heap_free(ref_lookup);
3973 if (TRACE_ON(typelib))
3974 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3977 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3978 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3979 const SLTG_TypeInfoTail *pTITail)
3981 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3984 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3985 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3986 const SLTG_TypeInfoTail *pTITail)
3988 sltg_ref_lookup_t *ref_lookup = NULL;
3989 if (pTIHeader->href_table != 0xffffffff)
3990 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3991 pNameTable);
3993 if (pTITail->vars_off != 0xffff)
3994 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3996 if (pTITail->funcs_off != 0xffff)
3997 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3998 heap_free(ref_lookup);
3999 if (TRACE_ON(typelib))
4000 dump_TypeInfo(pTI);
4003 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4004 manageable copy of it into this */
4005 typedef struct {
4006 WORD small_no;
4007 char *index_name;
4008 char *other_name;
4009 WORD res1a;
4010 WORD name_offs;
4011 WORD more_bytes;
4012 char *extra;
4013 WORD res20;
4014 DWORD helpcontext;
4015 WORD res26;
4016 GUID uuid;
4017 } SLTG_InternalOtherTypeInfo;
4019 /****************************************************************************
4020 * ITypeLib2_Constructor_SLTG
4022 * loading a SLTG typelib from an in-memory image
4024 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4026 ITypeLibImpl *pTypeLibImpl;
4027 SLTG_Header *pHeader;
4028 SLTG_BlkEntry *pBlkEntry;
4029 SLTG_Magic *pMagic;
4030 SLTG_Index *pIndex;
4031 SLTG_Pad9 *pPad9;
4032 LPVOID pBlk, pFirstBlk;
4033 SLTG_LibBlk *pLibBlk;
4034 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4035 char *pAfterOTIBlks = NULL;
4036 char *pNameTable, *ptr;
4037 int i;
4038 DWORD len, order;
4039 ITypeInfoImpl **ppTypeInfoImpl;
4041 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4044 pTypeLibImpl = TypeLibImpl_Constructor();
4045 if (!pTypeLibImpl) return NULL;
4047 pHeader = pLib;
4049 TRACE_(typelib)("header:\n");
4050 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4051 pHeader->nrOfFileBlks );
4052 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4053 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4054 pHeader->SLTG_magic);
4055 return NULL;
4058 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4059 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4061 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4062 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4064 /* Next we have a magic block */
4065 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4067 /* Let's see if we're still in sync */
4068 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4069 sizeof(SLTG_COMPOBJ_MAGIC))) {
4070 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4071 return NULL;
4073 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4074 sizeof(SLTG_DIR_MAGIC))) {
4075 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4076 return NULL;
4079 pIndex = (SLTG_Index*)(pMagic+1);
4081 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4083 pFirstBlk = pPad9 + 1;
4085 /* We'll set up a ptr to the main library block, which is the last one. */
4087 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4088 pBlkEntry[order].next != 0;
4089 order = pBlkEntry[order].next - 1, i++) {
4090 pBlk = (char*)pBlk + pBlkEntry[order].len;
4092 pLibBlk = pBlk;
4094 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4096 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4097 interspersed */
4099 len += 0x40;
4101 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4103 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4106 ptr = (char*)pLibBlk + len;
4108 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4109 WORD w, extra;
4110 len = 0;
4112 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4114 w = *(WORD*)(ptr + 2);
4115 if(w != 0xffff) {
4116 len += w;
4117 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4118 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4119 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4121 w = *(WORD*)(ptr + 4 + len);
4122 if(w != 0xffff) {
4123 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4124 len += w;
4125 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4126 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4127 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4129 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4130 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4131 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4132 if(extra) {
4133 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4134 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4135 len += extra;
4137 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4138 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4139 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4140 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4141 len += sizeof(SLTG_OtherTypeInfo);
4142 ptr += len;
4145 pAfterOTIBlks = ptr;
4147 /* Skip this WORD and get the next DWORD */
4148 len = *(DWORD*)(pAfterOTIBlks + 2);
4150 /* Now add this to pLibBLk look at what we're pointing at and
4151 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4152 dust and we should be pointing at the beginning of the name
4153 table */
4155 pNameTable = (char*)pLibBlk + len;
4157 switch(*(WORD*)pNameTable) {
4158 case 0xffff:
4159 break;
4160 case 0x0200:
4161 pNameTable += 0x20;
4162 break;
4163 default:
4164 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4165 break;
4168 pNameTable += 0x216;
4170 pNameTable += 2;
4172 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4174 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4177 /* Hopefully we now have enough ptrs set up to actually read in
4178 some TypeInfos. It's not clear which order to do them in, so
4179 I'll just follow the links along the BlkEntry chain and read
4180 them in the order in which they are in the file */
4182 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4183 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4185 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4186 pBlkEntry[order].next != 0;
4187 order = pBlkEntry[order].next - 1, i++) {
4189 SLTG_TypeInfoHeader *pTIHeader;
4190 SLTG_TypeInfoTail *pTITail;
4191 SLTG_MemberHeader *pMemHeader;
4193 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4194 FIXME_(typelib)("Index strings don't match\n");
4195 heap_free(pOtherTypeInfoBlks);
4196 return NULL;
4199 pTIHeader = pBlk;
4200 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4201 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4202 heap_free(pOtherTypeInfoBlks);
4203 return NULL;
4205 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4206 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4207 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4209 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4210 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4211 (*ppTypeInfoImpl)->index = i;
4212 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4213 pOtherTypeInfoBlks[i].name_offs +
4214 pNameTable);
4215 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4216 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4217 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4218 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4219 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4220 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4221 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4223 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4224 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4226 if((pTIHeader->typeflags1 & 7) != 2)
4227 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4228 if(pTIHeader->typeflags3 != 2)
4229 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4231 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4232 debugstr_w((*ppTypeInfoImpl)->Name),
4233 typekind_desc[pTIHeader->typekind],
4234 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4235 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4237 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4239 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4241 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4242 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4243 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4245 switch(pTIHeader->typekind) {
4246 case TKIND_ENUM:
4247 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4248 pTIHeader, pTITail);
4249 break;
4251 case TKIND_RECORD:
4252 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4253 pTIHeader, pTITail);
4254 break;
4256 case TKIND_INTERFACE:
4257 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4258 pTIHeader, pTITail);
4259 break;
4261 case TKIND_COCLASS:
4262 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4263 pTIHeader, pTITail);
4264 break;
4266 case TKIND_ALIAS:
4267 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4268 pTIHeader, pTITail);
4269 break;
4271 case TKIND_DISPATCH:
4272 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4273 pTIHeader, pTITail);
4274 break;
4276 case TKIND_MODULE:
4277 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4278 pTIHeader, pTITail);
4279 break;
4281 default:
4282 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4283 break;
4287 /* could get cFuncs, cVars and cImplTypes from here
4288 but we've already set those */
4289 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4290 X(06);
4291 X(16);
4292 X(18);
4293 X(1a);
4294 X(1e);
4295 X(24);
4296 X(26);
4297 X(2a);
4298 X(2c);
4299 X(2e);
4300 X(30);
4301 X(32);
4302 X(34);
4303 #undef X
4304 ++ppTypeInfoImpl;
4305 pBlk = (char*)pBlk + pBlkEntry[order].len;
4308 if(i != pTypeLibImpl->TypeInfoCount) {
4309 FIXME("Somehow processed %d TypeInfos\n", i);
4310 heap_free(pOtherTypeInfoBlks);
4311 return NULL;
4314 heap_free(pOtherTypeInfoBlks);
4315 return &pTypeLibImpl->ITypeLib2_iface;
4318 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4320 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4322 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4324 if(IsEqualIID(riid, &IID_IUnknown) ||
4325 IsEqualIID(riid,&IID_ITypeLib)||
4326 IsEqualIID(riid,&IID_ITypeLib2))
4328 *ppv = &This->ITypeLib2_iface;
4330 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4331 IsEqualIID(riid, &IID_ICreateTypeLib2))
4333 *ppv = &This->ICreateTypeLib2_iface;
4335 else
4337 *ppv = NULL;
4338 TRACE("-- Interface: E_NOINTERFACE\n");
4339 return E_NOINTERFACE;
4342 IUnknown_AddRef((IUnknown*)*ppv);
4343 return S_OK;
4346 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4348 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4349 ULONG ref = InterlockedIncrement(&This->ref);
4351 TRACE("(%p) ref=%u\n", This, ref);
4353 return ref;
4356 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4358 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4359 ULONG ref = InterlockedDecrement(&This->ref);
4361 TRACE("(%p) ref=%u\n",This, ref);
4363 if (!ref)
4365 TLBImpLib *pImpLib, *pImpLibNext;
4366 TLBRefType *ref_type;
4367 void *cursor2;
4368 int i;
4370 /* remove cache entry */
4371 if(This->path)
4373 TRACE("removing from cache list\n");
4374 EnterCriticalSection(&cache_section);
4375 if(This->entry.next)
4376 list_remove(&This->entry);
4377 LeaveCriticalSection(&cache_section);
4378 heap_free(This->path);
4380 TRACE(" destroying ITypeLib(%p)\n",This);
4382 SysFreeString(This->Name);
4383 This->Name = NULL;
4385 SysFreeString(This->DocString);
4386 This->DocString = NULL;
4388 SysFreeString(This->HelpFile);
4389 This->HelpFile = NULL;
4391 SysFreeString(This->HelpStringDll);
4392 This->HelpStringDll = NULL;
4394 TLB_FreeCustData(&This->custdata_list);
4396 for (i = 0; i < This->ctTypeDesc; i++)
4397 if (This->pTypeDesc[i].vt == VT_CARRAY)
4398 heap_free(This->pTypeDesc[i].u.lpadesc);
4400 heap_free(This->pTypeDesc);
4402 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4404 if (pImpLib->pImpTypeLib)
4405 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4406 SysFreeString(pImpLib->name);
4408 list_remove(&pImpLib->entry);
4409 heap_free(pImpLib);
4412 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4414 list_remove(&ref_type->entry);
4415 heap_free(ref_type);
4418 for (i = 0; i < This->TypeInfoCount; ++i)
4419 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4420 heap_free(This->typeinfos);
4421 heap_free(This);
4422 return 0;
4425 return ref;
4428 /* ITypeLib::GetTypeInfoCount
4430 * Returns the number of type descriptions in the type library
4432 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4434 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4435 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4436 return This->TypeInfoCount;
4439 /* ITypeLib::GetTypeInfo
4441 * retrieves the specified type description in the library.
4443 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4444 ITypeLib2 *iface,
4445 UINT index,
4446 ITypeInfo **ppTInfo)
4448 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4450 TRACE("%p %u %p\n", This, index, ppTInfo);
4452 if(!ppTInfo)
4453 return E_INVALIDARG;
4455 if(index >= This->TypeInfoCount)
4456 return TYPE_E_ELEMENTNOTFOUND;
4458 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4459 ITypeInfo_AddRef(*ppTInfo);
4461 return S_OK;
4465 /* ITypeLibs::GetTypeInfoType
4467 * Retrieves the type of a type description.
4469 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4470 ITypeLib2 *iface,
4471 UINT index,
4472 TYPEKIND *pTKind)
4474 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4476 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4478 if(!pTKind)
4479 return E_INVALIDARG;
4481 if(index >= This->TypeInfoCount)
4482 return TYPE_E_ELEMENTNOTFOUND;
4484 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4486 return S_OK;
4489 /* ITypeLib::GetTypeInfoOfGuid
4491 * Retrieves the type description that corresponds to the specified GUID.
4494 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4495 ITypeLib2 *iface,
4496 REFGUID guid,
4497 ITypeInfo **ppTInfo)
4499 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4500 int i;
4502 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4504 for(i = 0; i < This->TypeInfoCount; ++i){
4505 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4506 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4507 ITypeInfo_AddRef(*ppTInfo);
4508 return S_OK;
4512 return TYPE_E_ELEMENTNOTFOUND;
4515 /* ITypeLib::GetLibAttr
4517 * Retrieves the structure that contains the library's attributes.
4520 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4521 ITypeLib2 *iface,
4522 LPTLIBATTR *attr)
4524 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4526 TRACE("(%p, %p)\n", This, attr);
4528 if (!attr) return E_INVALIDARG;
4530 *attr = heap_alloc(sizeof(**attr));
4531 if (!*attr) return E_OUTOFMEMORY;
4533 **attr = This->LibAttr;
4534 return S_OK;
4537 /* ITypeLib::GetTypeComp
4539 * Enables a client compiler to bind to a library's types, variables,
4540 * constants, and global functions.
4543 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4544 ITypeLib2 *iface,
4545 ITypeComp **ppTComp)
4547 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4549 TRACE("(%p)->(%p)\n",This,ppTComp);
4550 *ppTComp = &This->ITypeComp_iface;
4551 ITypeComp_AddRef(*ppTComp);
4553 return S_OK;
4556 /* ITypeLib::GetDocumentation
4558 * Retrieves the library's documentation string, the complete Help file name
4559 * and path, and the context identifier for the library Help topic in the Help
4560 * file.
4562 * On a successful return all non-null BSTR pointers will have been set,
4563 * possibly to NULL.
4565 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4566 ITypeLib2 *iface,
4567 INT index,
4568 BSTR *pBstrName,
4569 BSTR *pBstrDocString,
4570 DWORD *pdwHelpContext,
4571 BSTR *pBstrHelpFile)
4573 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4574 HRESULT result = E_INVALIDARG;
4575 ITypeInfo *pTInfo;
4577 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4578 This, index,
4579 pBstrName, pBstrDocString,
4580 pdwHelpContext, pBstrHelpFile);
4582 if(index<0)
4584 /* documentation for the typelib */
4585 if(pBstrName)
4587 if (This->Name)
4589 if(!(*pBstrName = SysAllocString(This->Name)))
4590 goto memerr1;
4592 else
4593 *pBstrName = NULL;
4595 if(pBstrDocString)
4597 if (This->DocString)
4599 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4600 goto memerr2;
4602 else if (This->Name)
4604 if(!(*pBstrDocString = SysAllocString(This->Name)))
4605 goto memerr2;
4607 else
4608 *pBstrDocString = NULL;
4610 if(pdwHelpContext)
4612 *pdwHelpContext = This->dwHelpContext;
4614 if(pBstrHelpFile)
4616 if (This->HelpFile)
4618 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4619 goto memerr3;
4621 else
4622 *pBstrHelpFile = NULL;
4625 result = S_OK;
4627 else
4629 /* for a typeinfo */
4630 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4632 if(SUCCEEDED(result))
4634 result = ITypeInfo_GetDocumentation(pTInfo,
4635 MEMBERID_NIL,
4636 pBstrName,
4637 pBstrDocString,
4638 pdwHelpContext, pBstrHelpFile);
4640 ITypeInfo_Release(pTInfo);
4643 return result;
4644 memerr3:
4645 if (pBstrDocString) SysFreeString (*pBstrDocString);
4646 memerr2:
4647 if (pBstrName) SysFreeString (*pBstrName);
4648 memerr1:
4649 return STG_E_INSUFFICIENTMEMORY;
4652 /* ITypeLib::IsName
4654 * Indicates whether a passed-in string contains the name of a type or member
4655 * described in the library.
4658 static HRESULT WINAPI ITypeLib2_fnIsName(
4659 ITypeLib2 *iface,
4660 LPOLESTR szNameBuf,
4661 ULONG lHashVal,
4662 BOOL *pfName)
4664 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4665 int tic;
4666 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4668 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4669 pfName);
4671 *pfName=TRUE;
4672 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4673 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4674 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4675 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4676 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4677 int pc;
4679 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4680 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4681 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4682 goto ITypeLib2_fnIsName_exit;
4684 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4685 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4686 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4690 *pfName=FALSE;
4692 ITypeLib2_fnIsName_exit:
4693 TRACE("(%p)slow! search for %s: %s found!\n", This,
4694 debugstr_w(szNameBuf), *pfName?"NOT":"");
4696 return S_OK;
4699 /* ITypeLib::FindName
4701 * Finds occurrences of a type description in a type library. This may be used
4702 * to quickly verify that a name exists in a type library.
4705 static HRESULT WINAPI ITypeLib2_fnFindName(
4706 ITypeLib2 *iface,
4707 LPOLESTR name,
4708 ULONG hash,
4709 ITypeInfo **ppTInfo,
4710 MEMBERID *memid,
4711 UINT16 *found)
4713 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4714 int tic;
4715 UINT count = 0;
4716 UINT len;
4718 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4720 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4721 return E_INVALIDARG;
4723 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4724 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4725 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4726 TLBVarDesc *var;
4727 UINT fdc;
4729 if(!memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4730 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4731 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4732 int pc;
4734 if(!memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4735 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4736 if(!memcmp(name, func->pParamDesc[pc].Name, len))
4737 goto ITypeLib2_fnFindName_exit;
4741 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, name);
4742 if (var)
4743 goto ITypeLib2_fnFindName_exit;
4745 continue;
4746 ITypeLib2_fnFindName_exit:
4747 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4748 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4749 count++;
4751 TRACE("found %d typeinfos\n", count);
4753 *found = count;
4755 return S_OK;
4758 /* ITypeLib::ReleaseTLibAttr
4760 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4763 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4764 ITypeLib2 *iface,
4765 TLIBATTR *pTLibAttr)
4767 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4768 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4769 heap_free(pTLibAttr);
4772 /* ITypeLib2::GetCustData
4774 * gets the custom data
4776 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4777 ITypeLib2 * iface,
4778 REFGUID guid,
4779 VARIANT *pVarVal)
4781 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4782 TLBCustData *pCData;
4784 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
4786 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4787 if(!pCData)
4788 return TYPE_E_ELEMENTNOTFOUND;
4790 VariantInit(pVarVal);
4791 VariantCopy(pVarVal, &pCData->data);
4793 return S_OK;
4796 /* ITypeLib2::GetLibStatistics
4798 * Returns statistics about a type library that are required for efficient
4799 * sizing of hash tables.
4802 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4803 ITypeLib2 * iface,
4804 ULONG *pcUniqueNames,
4805 ULONG *pcchUniqueNames)
4807 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4809 FIXME("(%p): stub!\n", This);
4811 if(pcUniqueNames) *pcUniqueNames=1;
4812 if(pcchUniqueNames) *pcchUniqueNames=1;
4813 return S_OK;
4816 /* ITypeLib2::GetDocumentation2
4818 * Retrieves the library's documentation string, the complete Help file name
4819 * and path, the localization context to use, and the context ID for the
4820 * library Help topic in the Help file.
4823 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4824 ITypeLib2 * iface,
4825 INT index,
4826 LCID lcid,
4827 BSTR *pbstrHelpString,
4828 DWORD *pdwHelpStringContext,
4829 BSTR *pbstrHelpStringDll)
4831 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4832 HRESULT result;
4833 ITypeInfo *pTInfo;
4835 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4837 /* the help string should be obtained from the helpstringdll,
4838 * using the _DLLGetDocumentation function, based on the supplied
4839 * lcid. Nice to do sometime...
4841 if(index<0)
4843 /* documentation for the typelib */
4844 if(pbstrHelpString)
4845 *pbstrHelpString=SysAllocString(This->DocString);
4846 if(pdwHelpStringContext)
4847 *pdwHelpStringContext=This->dwHelpContext;
4848 if(pbstrHelpStringDll)
4849 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4851 result = S_OK;
4853 else
4855 /* for a typeinfo */
4856 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4858 if(SUCCEEDED(result))
4860 ITypeInfo2 * pTInfo2;
4861 result = ITypeInfo_QueryInterface(pTInfo,
4862 &IID_ITypeInfo2,
4863 (LPVOID*) &pTInfo2);
4865 if(SUCCEEDED(result))
4867 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4868 MEMBERID_NIL,
4869 lcid,
4870 pbstrHelpString,
4871 pdwHelpStringContext,
4872 pbstrHelpStringDll);
4874 ITypeInfo2_Release(pTInfo2);
4877 ITypeInfo_Release(pTInfo);
4880 return result;
4883 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4885 TLBCustData *pCData;
4886 unsigned int ct;
4887 CUSTDATAITEM *cdi;
4889 ct = list_count(custdata_list);
4891 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4892 if(!pCustData->prgCustData)
4893 return E_OUTOFMEMORY;
4895 pCustData->cCustData = ct;
4897 cdi = pCustData->prgCustData;
4898 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4899 cdi->guid = pCData->guid;
4900 VariantCopy(&cdi->varValue, &pCData->data);
4901 ++cdi;
4904 return S_OK;
4908 /* ITypeLib2::GetAllCustData
4910 * Gets all custom data items for the library.
4913 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4914 ITypeLib2 * iface,
4915 CUSTDATA *pCustData)
4917 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4918 TRACE("(%p)->(%p)\n", This, pCustData);
4919 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4922 static const ITypeLib2Vtbl tlbvt = {
4923 ITypeLib2_fnQueryInterface,
4924 ITypeLib2_fnAddRef,
4925 ITypeLib2_fnRelease,
4926 ITypeLib2_fnGetTypeInfoCount,
4927 ITypeLib2_fnGetTypeInfo,
4928 ITypeLib2_fnGetTypeInfoType,
4929 ITypeLib2_fnGetTypeInfoOfGuid,
4930 ITypeLib2_fnGetLibAttr,
4931 ITypeLib2_fnGetTypeComp,
4932 ITypeLib2_fnGetDocumentation,
4933 ITypeLib2_fnIsName,
4934 ITypeLib2_fnFindName,
4935 ITypeLib2_fnReleaseTLibAttr,
4937 ITypeLib2_fnGetCustData,
4938 ITypeLib2_fnGetLibStatistics,
4939 ITypeLib2_fnGetDocumentation2,
4940 ITypeLib2_fnGetAllCustData
4944 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4946 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4948 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
4951 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4953 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4955 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
4958 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4960 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4962 return ITypeLib2_Release(&This->ITypeLib2_iface);
4965 static HRESULT WINAPI ITypeLibComp_fnBind(
4966 ITypeComp * iface,
4967 OLECHAR * szName,
4968 ULONG lHash,
4969 WORD wFlags,
4970 ITypeInfo ** ppTInfo,
4971 DESCKIND * pDescKind,
4972 BINDPTR * pBindPtr)
4974 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4975 int typemismatch=0, i;
4977 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4979 *pDescKind = DESCKIND_NONE;
4980 pBindPtr->lptcomp = NULL;
4981 *ppTInfo = NULL;
4983 for(i = 0; i < This->TypeInfoCount; ++i){
4984 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4985 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4987 /* FIXME: check wFlags here? */
4988 /* FIXME: we should use a hash table to look this info up using lHash
4989 * instead of an O(n) search */
4990 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4991 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4993 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4995 *pDescKind = DESCKIND_TYPECOMP;
4996 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
4997 ITypeComp_AddRef(pBindPtr->lptcomp);
4998 TRACE("module or enum: %s\n", debugstr_w(szName));
4999 return S_OK;
5003 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
5004 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
5006 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5007 HRESULT hr;
5009 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5010 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5012 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5013 return S_OK;
5015 else if (hr == TYPE_E_TYPEMISMATCH)
5016 typemismatch = 1;
5019 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
5020 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5022 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5023 HRESULT hr;
5024 ITypeInfo *subtypeinfo;
5025 BINDPTR subbindptr;
5026 DESCKIND subdesckind;
5028 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5029 &subtypeinfo, &subdesckind, &subbindptr);
5030 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5032 TYPEDESC tdesc_appobject;
5033 const VARDESC vardesc_appobject =
5035 -2, /* memid */
5036 NULL, /* lpstrSchema */
5038 0 /* oInst */
5041 /* ELEMDESC */
5043 /* TYPEDESC */
5045 &tdesc_appobject
5047 VT_PTR
5050 0, /* wVarFlags */
5051 VAR_STATIC /* varkind */
5054 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5055 tdesc_appobject.vt = VT_USERDEFINED;
5057 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5059 /* cleanup things filled in by Bind call so we can put our
5060 * application object data in there instead */
5061 switch (subdesckind)
5063 case DESCKIND_FUNCDESC:
5064 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5065 break;
5066 case DESCKIND_VARDESC:
5067 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5068 break;
5069 default:
5070 break;
5072 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5074 if (pTypeInfo->hreftype == -1)
5075 FIXME("no hreftype for interface %p\n", pTypeInfo);
5077 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5078 if (FAILED(hr))
5079 return hr;
5081 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5082 *ppTInfo = (ITypeInfo *)pTypeInfo;
5083 ITypeInfo_AddRef(*ppTInfo);
5084 return S_OK;
5086 else if (hr == TYPE_E_TYPEMISMATCH)
5087 typemismatch = 1;
5091 if (typemismatch)
5093 TRACE("type mismatch %s\n", debugstr_w(szName));
5094 return TYPE_E_TYPEMISMATCH;
5096 else
5098 TRACE("name not found %s\n", debugstr_w(szName));
5099 return S_OK;
5103 static HRESULT WINAPI ITypeLibComp_fnBindType(
5104 ITypeComp * iface,
5105 OLECHAR * szName,
5106 ULONG lHash,
5107 ITypeInfo ** ppTInfo,
5108 ITypeComp ** ppTComp)
5110 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5111 ITypeInfoImpl *info;
5113 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5115 if(!szName || !ppTInfo || !ppTComp)
5116 return E_INVALIDARG;
5118 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5119 if(!info){
5120 *ppTInfo = NULL;
5121 *ppTComp = NULL;
5122 return S_OK;
5125 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5126 ITypeInfo_AddRef(*ppTInfo);
5127 *ppTComp = &info->ITypeComp_iface;
5128 ITypeComp_AddRef(*ppTComp);
5130 return S_OK;
5133 static const ITypeCompVtbl tlbtcvt =
5136 ITypeLibComp_fnQueryInterface,
5137 ITypeLibComp_fnAddRef,
5138 ITypeLibComp_fnRelease,
5140 ITypeLibComp_fnBind,
5141 ITypeLibComp_fnBindType
5144 /*================== ITypeInfo(2) Methods ===================================*/
5145 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5147 ITypeInfoImpl *pTypeInfoImpl;
5149 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5150 if (pTypeInfoImpl)
5152 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5153 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5154 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5155 pTypeInfoImpl->ref = 0;
5156 pTypeInfoImpl->hreftype = -1;
5157 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5158 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5159 list_init(&pTypeInfoImpl->custdata_list);
5161 TRACE("(%p)\n", pTypeInfoImpl);
5162 return pTypeInfoImpl;
5165 /* ITypeInfo::QueryInterface
5167 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5168 ITypeInfo2 *iface,
5169 REFIID riid,
5170 VOID **ppvObject)
5172 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5174 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5176 *ppvObject=NULL;
5177 if(IsEqualIID(riid, &IID_IUnknown) ||
5178 IsEqualIID(riid,&IID_ITypeInfo)||
5179 IsEqualIID(riid,&IID_ITypeInfo2))
5180 *ppvObject = This;
5181 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5182 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5183 *ppvObject = &This->ICreateTypeInfo2_iface;
5185 if(*ppvObject){
5186 ITypeInfo2_AddRef(iface);
5187 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5188 return S_OK;
5190 TRACE("-- Interface: E_NOINTERFACE\n");
5191 return E_NOINTERFACE;
5194 /* ITypeInfo::AddRef
5196 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5198 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5199 ULONG ref = InterlockedIncrement(&This->ref);
5201 TRACE("(%p)->ref is %u\n",This, ref);
5203 if (ref == 1 /* incremented from 0 */)
5204 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5206 return ref;
5209 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5211 UINT i;
5213 TRACE("destroying ITypeInfo(%p)\n",This);
5215 SysFreeString(This->Name);
5216 This->Name = NULL;
5218 SysFreeString(This->DocString);
5219 This->DocString = NULL;
5221 SysFreeString(This->DllName);
5222 This->DllName = NULL;
5224 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5226 int j;
5227 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5228 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5230 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5231 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5233 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5234 heap_free(elemdesc->u.paramdesc.pparamdescex);
5236 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5237 SysFreeString(pFInfo->pParamDesc[j].Name);
5239 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5240 heap_free(pFInfo->pParamDesc);
5241 TLB_FreeCustData(&pFInfo->custdata_list);
5242 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5243 SysFreeString(pFInfo->Entry);
5244 SysFreeString(pFInfo->HelpString);
5245 SysFreeString(pFInfo->Name);
5247 heap_free(This->funcdescs);
5249 for(i = 0; i < This->TypeAttr.cVars; ++i)
5251 TLBVarDesc *pVInfo = &This->vardescs[i];
5252 if (pVInfo->vardesc.varkind == VAR_CONST)
5254 VariantClear(pVInfo->vardesc.u.lpvarValue);
5255 heap_free(pVInfo->vardesc.u.lpvarValue);
5257 TLB_FreeCustData(&pVInfo->custdata_list);
5258 SysFreeString(pVInfo->Name);
5259 SysFreeString(pVInfo->HelpString);
5261 heap_free(This->vardescs);
5263 if(This->impltypes){
5264 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5265 TLBImplType *pImpl = &This->impltypes[i];
5266 TLB_FreeCustData(&pImpl->custdata_list);
5268 heap_free(This->impltypes);
5271 TLB_FreeCustData(&This->custdata_list);
5273 heap_free(This);
5276 /* ITypeInfo::Release
5278 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5280 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5281 ULONG ref = InterlockedDecrement(&This->ref);
5283 TRACE("(%p)->(%u)\n",This, ref);
5285 if (!ref)
5287 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5288 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5289 if (not_attached_to_typelib)
5290 heap_free(This);
5291 /* otherwise This will be freed when typelib is freed */
5294 return ref;
5297 /* ITypeInfo::GetTypeAttr
5299 * Retrieves a TYPEATTR structure that contains the attributes of the type
5300 * description.
5303 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5304 LPTYPEATTR *ppTypeAttr)
5306 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5307 SIZE_T size;
5309 TRACE("(%p)\n",This);
5311 size = sizeof(**ppTypeAttr);
5312 if (This->TypeAttr.typekind == TKIND_ALIAS)
5313 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5315 *ppTypeAttr = heap_alloc(size);
5316 if (!*ppTypeAttr)
5317 return E_OUTOFMEMORY;
5319 **ppTypeAttr = This->TypeAttr;
5321 if (This->TypeAttr.typekind == TKIND_ALIAS)
5322 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5323 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5325 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5326 /* This should include all the inherited funcs */
5327 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5328 /* This is always the size of IDispatch's vtbl */
5329 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5330 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5332 return S_OK;
5335 /* ITypeInfo::GetTypeComp
5337 * Retrieves the ITypeComp interface for the type description, which enables a
5338 * client compiler to bind to the type description's members.
5341 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5342 ITypeComp * *ppTComp)
5344 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5346 TRACE("(%p)->(%p)\n", This, ppTComp);
5348 *ppTComp = &This->ITypeComp_iface;
5349 ITypeComp_AddRef(*ppTComp);
5350 return S_OK;
5353 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5355 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5356 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5357 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5358 return size;
5361 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5363 *dest = *src;
5364 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5365 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5367 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5368 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5369 *buffer += sizeof(PARAMDESCEX);
5370 *pparamdescex_dest = *pparamdescex_src;
5371 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5372 VariantInit(&pparamdescex_dest->varDefaultValue);
5373 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5374 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5376 else
5377 dest->u.paramdesc.pparamdescex = NULL;
5378 return S_OK;
5381 static HRESULT TLB_SanitizeBSTR(BSTR str)
5383 UINT len = SysStringLen(str), i;
5384 for (i = 0; i < len; ++i)
5385 if (str[i] > 0x7f)
5386 str[i] = '?';
5387 return S_OK;
5390 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5392 if (V_VT(var) == VT_INT)
5393 return VariantChangeType(var, var, 0, VT_I4);
5394 else if (V_VT(var) == VT_UINT)
5395 return VariantChangeType(var, var, 0, VT_UI4);
5396 else if (V_VT(var) == VT_BSTR)
5397 return TLB_SanitizeBSTR(V_BSTR(var));
5399 return S_OK;
5402 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5404 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5405 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5408 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5410 FUNCDESC *dest;
5411 char *buffer;
5412 SIZE_T size = sizeof(*src);
5413 SHORT i;
5414 HRESULT hr;
5416 size += sizeof(*src->lprgscode) * src->cScodes;
5417 size += TLB_SizeElemDesc(&src->elemdescFunc);
5418 for (i = 0; i < src->cParams; i++)
5420 size += sizeof(ELEMDESC);
5421 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5424 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5425 if (!dest) return E_OUTOFMEMORY;
5427 *dest = *src;
5428 if (dispinterface) /* overwrite funckind */
5429 dest->funckind = FUNC_DISPATCH;
5430 buffer = (char *)(dest + 1);
5432 dest->oVft = dest->oVft & 0xFFFC;
5434 if (dest->cScodes) {
5435 dest->lprgscode = (SCODE *)buffer;
5436 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5437 buffer += sizeof(*src->lprgscode) * src->cScodes;
5438 } else
5439 dest->lprgscode = NULL;
5441 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5442 if (FAILED(hr))
5444 SysFreeString((BSTR)dest);
5445 return hr;
5448 if (dest->cParams) {
5449 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5450 buffer += sizeof(ELEMDESC) * src->cParams;
5451 for (i = 0; i < src->cParams; i++)
5453 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5454 if (FAILED(hr))
5455 break;
5457 if (FAILED(hr))
5459 /* undo the above actions */
5460 for (i = i - 1; i >= 0; i--)
5461 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5462 TLB_FreeElemDesc(&dest->elemdescFunc);
5463 SysFreeString((BSTR)dest);
5464 return hr;
5466 } else
5467 dest->lprgelemdescParam = NULL;
5469 /* special treatment for dispinterfaces: this makes functions appear
5470 * to return their [retval] value when it is really returning an
5471 * HRESULT */
5472 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5474 if (dest->cParams &&
5475 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5477 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5478 if (elemdesc->tdesc.vt != VT_PTR)
5480 ERR("elemdesc should have started with VT_PTR instead of:\n");
5481 if (ERR_ON(ole))
5482 dump_ELEMDESC(elemdesc);
5483 return E_UNEXPECTED;
5486 /* copy last parameter to the return value. we are using a flat
5487 * buffer so there is no danger of leaking memory in
5488 * elemdescFunc */
5489 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5491 /* remove the last parameter */
5492 dest->cParams--;
5494 else
5495 /* otherwise this function is made to appear to have no return
5496 * value */
5497 dest->elemdescFunc.tdesc.vt = VT_VOID;
5501 *dest_ptr = dest;
5502 return S_OK;
5505 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5507 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5509 if (index >= This->TypeAttr.cFuncs)
5510 return TYPE_E_ELEMENTNOTFOUND;
5512 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5513 return S_OK;
5516 /* internal function to make the inherited interfaces' methods appear
5517 * part of the interface */
5518 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5519 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5521 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5522 HRESULT hr;
5523 UINT implemented_funcs = 0;
5525 if (funcs)
5526 *funcs = 0;
5527 else
5528 *hrefoffset = DISPATCH_HREF_OFFSET;
5530 if(This->impltypes)
5532 ITypeInfo *pSubTypeInfo;
5533 UINT sub_funcs;
5535 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5536 if (FAILED(hr))
5537 return hr;
5539 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5540 index,
5541 ppFuncDesc,
5542 &sub_funcs, hrefoffset);
5543 implemented_funcs += sub_funcs;
5544 ITypeInfo_Release(pSubTypeInfo);
5545 if (SUCCEEDED(hr))
5546 return hr;
5547 *hrefoffset += DISPATCH_HREF_OFFSET;
5550 if (funcs)
5551 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5552 else
5553 *hrefoffset = 0;
5555 if (index < implemented_funcs)
5556 return E_INVALIDARG;
5557 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5558 ppFuncDesc);
5561 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5563 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5564 while (TRUE)
5566 switch (pTypeDesc->vt)
5568 case VT_USERDEFINED:
5569 pTypeDesc->u.hreftype += hrefoffset;
5570 return;
5571 case VT_PTR:
5572 case VT_SAFEARRAY:
5573 pTypeDesc = pTypeDesc->u.lptdesc;
5574 break;
5575 case VT_CARRAY:
5576 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5577 break;
5578 default:
5579 return;
5584 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5586 SHORT i;
5587 for (i = 0; i < pFuncDesc->cParams; i++)
5588 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5589 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5592 /* ITypeInfo::GetFuncDesc
5594 * Retrieves the FUNCDESC structure that contains information about a
5595 * specified function.
5598 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5599 LPFUNCDESC *ppFuncDesc)
5601 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5602 const FUNCDESC *internal_funcdesc;
5603 HRESULT hr;
5604 UINT hrefoffset = 0;
5606 TRACE("(%p) index %d\n", This, index);
5608 if (!ppFuncDesc)
5609 return E_INVALIDARG;
5611 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5612 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5613 &internal_funcdesc, NULL,
5614 &hrefoffset);
5615 else
5616 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5617 &internal_funcdesc);
5618 if (FAILED(hr))
5620 WARN("description for function %d not found\n", index);
5621 return hr;
5624 hr = TLB_AllocAndInitFuncDesc(
5625 internal_funcdesc,
5626 ppFuncDesc,
5627 This->TypeAttr.typekind == TKIND_DISPATCH);
5629 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5630 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5632 TRACE("-- 0x%08x\n", hr);
5633 return hr;
5636 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5638 VARDESC *dest;
5639 char *buffer;
5640 SIZE_T size = sizeof(*src);
5641 HRESULT hr;
5643 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5644 if (src->varkind == VAR_CONST)
5645 size += sizeof(VARIANT);
5646 size += TLB_SizeElemDesc(&src->elemdescVar);
5648 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5649 if (!dest) return E_OUTOFMEMORY;
5651 *dest = *src;
5652 buffer = (char *)(dest + 1);
5653 if (src->lpstrSchema)
5655 int len;
5656 dest->lpstrSchema = (LPOLESTR)buffer;
5657 len = strlenW(src->lpstrSchema);
5658 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5659 buffer += (len + 1) * sizeof(WCHAR);
5662 if (src->varkind == VAR_CONST)
5664 HRESULT hr;
5666 dest->u.lpvarValue = (VARIANT *)buffer;
5667 *dest->u.lpvarValue = *src->u.lpvarValue;
5668 buffer += sizeof(VARIANT);
5669 VariantInit(dest->u.lpvarValue);
5670 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5671 if (FAILED(hr))
5673 SysFreeString((BSTR)dest);
5674 return hr;
5677 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5678 if (FAILED(hr))
5680 if (src->varkind == VAR_CONST)
5681 VariantClear(dest->u.lpvarValue);
5682 SysFreeString((BSTR)dest);
5683 return hr;
5685 *dest_ptr = dest;
5686 return S_OK;
5689 /* ITypeInfo::GetVarDesc
5691 * Retrieves a VARDESC structure that describes the specified variable.
5694 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5695 LPVARDESC *ppVarDesc)
5697 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5698 const TLBVarDesc *pVDesc = &This->vardescs[index];
5700 TRACE("(%p) index %d\n", This, index);
5702 if(index >= This->TypeAttr.cVars)
5703 return TYPE_E_ELEMENTNOTFOUND;
5705 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5708 /* ITypeInfo_GetNames
5710 * Retrieves the variable with the specified member ID (or the name of the
5711 * property or method and its parameters) that correspond to the specified
5712 * function ID.
5714 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5715 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5717 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5718 const TLBFuncDesc *pFDesc;
5719 const TLBVarDesc *pVDesc;
5720 int i;
5721 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5722 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5723 if(pFDesc)
5725 /* function found, now return function and parameter names */
5726 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5728 if(!i)
5729 *rgBstrNames=SysAllocString(pFDesc->Name);
5730 else
5731 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5733 *pcNames=i;
5735 else
5737 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5738 if(pVDesc)
5740 *rgBstrNames=SysAllocString(pVDesc->Name);
5741 *pcNames=1;
5743 else
5745 if(This->impltypes &&
5746 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5747 /* recursive search */
5748 ITypeInfo *pTInfo;
5749 HRESULT result;
5750 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5751 if(SUCCEEDED(result))
5753 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5754 ITypeInfo_Release(pTInfo);
5755 return result;
5757 WARN("Could not search inherited interface!\n");
5759 else
5761 WARN("no names found\n");
5763 *pcNames=0;
5764 return TYPE_E_ELEMENTNOTFOUND;
5767 return S_OK;
5771 /* ITypeInfo::GetRefTypeOfImplType
5773 * If a type description describes a COM class, it retrieves the type
5774 * description of the implemented interface types. For an interface,
5775 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5776 * if any exist.
5779 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5780 ITypeInfo2 *iface,
5781 UINT index,
5782 HREFTYPE *pRefType)
5784 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5785 HRESULT hr = S_OK;
5787 TRACE("(%p) index %d\n", This, index);
5788 if (TRACE_ON(ole)) dump_TypeInfo(This);
5790 if(index==(UINT)-1)
5792 /* only valid on dual interfaces;
5793 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5796 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5798 *pRefType = -2;
5800 else
5802 hr = TYPE_E_ELEMENTNOTFOUND;
5805 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5807 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5808 *pRefType = This->pTypeLib->dispatch_href;
5810 else
5812 if(index >= This->TypeAttr.cImplTypes)
5813 hr = TYPE_E_ELEMENTNOTFOUND;
5814 else
5815 *pRefType = This->impltypes[index].hRef;
5818 if(TRACE_ON(ole))
5820 if(SUCCEEDED(hr))
5821 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5822 else
5823 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5826 return hr;
5829 /* ITypeInfo::GetImplTypeFlags
5831 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5832 * or base interface in a type description.
5834 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5835 UINT index, INT *pImplTypeFlags)
5837 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5839 TRACE("(%p) index %d\n", This, index);
5841 if(!pImplTypeFlags)
5842 return E_INVALIDARG;
5844 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5845 *pImplTypeFlags = 0;
5846 return S_OK;
5849 if(index >= This->TypeAttr.cImplTypes)
5850 return TYPE_E_ELEMENTNOTFOUND;
5852 *pImplTypeFlags = This->impltypes[index].implflags;
5854 return S_OK;
5857 /* GetIDsOfNames
5858 * Maps between member names and member IDs, and parameter names and
5859 * parameter IDs.
5861 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5862 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5864 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5865 const TLBVarDesc *pVDesc;
5866 HRESULT ret=S_OK;
5867 UINT i, fdc;
5869 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5870 cNames);
5872 /* init out parameters in case of failure */
5873 for (i = 0; i < cNames; i++)
5874 pMemId[i] = MEMBERID_NIL;
5876 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5877 int j;
5878 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5879 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5880 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5881 for(i=1; i < cNames; i++){
5882 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5883 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5884 break;
5885 if( j<pFDesc->funcdesc.cParams)
5886 pMemId[i]=j;
5887 else
5888 ret=DISP_E_UNKNOWNNAME;
5890 TRACE("-- 0x%08x\n", ret);
5891 return ret;
5894 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5895 if(pVDesc){
5896 if(cNames)
5897 *pMemId = pVDesc->vardesc.memid;
5898 return ret;
5900 /* not found, see if it can be found in an inherited interface */
5901 if(This->impltypes) {
5902 /* recursive search */
5903 ITypeInfo *pTInfo;
5904 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5905 if(SUCCEEDED(ret)){
5906 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5907 ITypeInfo_Release(pTInfo);
5908 return ret;
5910 WARN("Could not search inherited interface!\n");
5911 } else
5912 WARN("no names found\n");
5913 return DISP_E_UNKNOWNNAME;
5917 #ifdef __i386__
5919 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5920 __ASM_GLOBAL_FUNC( call_method,
5921 "pushl %ebp\n\t"
5922 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5923 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5924 "movl %esp,%ebp\n\t"
5925 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5926 "pushl %esi\n\t"
5927 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5928 "pushl %edi\n\t"
5929 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5930 "movl 12(%ebp),%edx\n\t"
5931 "movl %esp,%edi\n\t"
5932 "shll $2,%edx\n\t"
5933 "jz 1f\n\t"
5934 "subl %edx,%edi\n\t"
5935 "andl $~15,%edi\n\t"
5936 "movl %edi,%esp\n\t"
5937 "movl 12(%ebp),%ecx\n\t"
5938 "movl 16(%ebp),%esi\n\t"
5939 "cld\n\t"
5940 "rep; movsl\n"
5941 "1:\tcall *8(%ebp)\n\t"
5942 "subl %esp,%edi\n\t"
5943 "movl 20(%ebp),%ecx\n\t"
5944 "movl %edi,(%ecx)\n\t"
5945 "leal -8(%ebp),%esp\n\t"
5946 "popl %edi\n\t"
5947 __ASM_CFI(".cfi_same_value %edi\n\t")
5948 "popl %esi\n\t"
5949 __ASM_CFI(".cfi_same_value %esi\n\t")
5950 "popl %ebp\n\t"
5951 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5952 __ASM_CFI(".cfi_same_value %ebp\n\t")
5953 "ret" )
5955 /* same function but returning floating point */
5956 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5958 /* ITypeInfo::Invoke
5960 * Invokes a method, or accesses a property of an object, that implements the
5961 * interface described by the type description.
5963 DWORD
5964 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5965 DWORD res;
5966 int stack_offset;
5968 if (TRACE_ON(ole)) {
5969 int i;
5970 TRACE("Calling %p(",func);
5971 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5972 if (nrargs > 30) TRACE("...");
5973 TRACE(")\n");
5976 switch (callconv) {
5977 case CC_STDCALL:
5978 case CC_CDECL:
5979 res = call_method( func, nrargs, args, &stack_offset );
5980 break;
5981 default:
5982 FIXME("unsupported calling convention %d\n",callconv);
5983 res = -1;
5984 break;
5986 TRACE("returns %08x\n",res);
5987 return res;
5990 #elif defined(__x86_64__)
5992 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5993 __ASM_GLOBAL_FUNC( call_method,
5994 "pushq %rbp\n\t"
5995 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5996 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5997 "movq %rsp,%rbp\n\t"
5998 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5999 "pushq %rsi\n\t"
6000 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6001 "pushq %rdi\n\t"
6002 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6003 "movq %rcx,%rax\n\t"
6004 "movq $4,%rcx\n\t"
6005 "cmp %rcx,%rdx\n\t"
6006 "cmovgq %rdx,%rcx\n\t"
6007 "leaq 0(,%rcx,8),%rdx\n\t"
6008 "subq %rdx,%rsp\n\t"
6009 "andq $~15,%rsp\n\t"
6010 "movq %rsp,%rdi\n\t"
6011 "movq %r8,%rsi\n\t"
6012 "rep; movsq\n\t"
6013 "movq 0(%rsp),%rcx\n\t"
6014 "movq 8(%rsp),%rdx\n\t"
6015 "movq 16(%rsp),%r8\n\t"
6016 "movq 24(%rsp),%r9\n\t"
6017 "movq %rcx,%xmm0\n\t"
6018 "movq %rdx,%xmm1\n\t"
6019 "movq %r8,%xmm2\n\t"
6020 "movq %r9,%xmm3\n\t"
6021 "callq *%rax\n\t"
6022 "leaq -16(%rbp),%rsp\n\t"
6023 "popq %rdi\n\t"
6024 __ASM_CFI(".cfi_same_value %rdi\n\t")
6025 "popq %rsi\n\t"
6026 __ASM_CFI(".cfi_same_value %rsi\n\t")
6027 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6028 "popq %rbp\n\t"
6029 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6030 __ASM_CFI(".cfi_same_value %rbp\n\t")
6031 "ret")
6033 /* same function but returning floating point */
6034 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6036 #endif /* __x86_64__ */
6038 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6040 HRESULT hr = S_OK;
6041 ITypeInfo *tinfo2 = NULL;
6042 TYPEATTR *tattr = NULL;
6044 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6045 if (hr)
6047 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6048 "hr = 0x%08x\n",
6049 tdesc->u.hreftype, hr);
6050 return hr;
6052 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6053 if (hr)
6055 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6056 ITypeInfo_Release(tinfo2);
6057 return hr;
6060 switch (tattr->typekind)
6062 case TKIND_ENUM:
6063 *vt |= VT_I4;
6064 break;
6066 case TKIND_ALIAS:
6067 tdesc = &tattr->tdescAlias;
6068 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6069 break;
6071 case TKIND_INTERFACE:
6072 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6073 *vt |= VT_DISPATCH;
6074 else
6075 *vt |= VT_UNKNOWN;
6076 break;
6078 case TKIND_DISPATCH:
6079 *vt |= VT_DISPATCH;
6080 break;
6082 case TKIND_COCLASS:
6083 *vt |= VT_DISPATCH;
6084 break;
6086 case TKIND_RECORD:
6087 FIXME("TKIND_RECORD unhandled.\n");
6088 hr = E_NOTIMPL;
6089 break;
6091 case TKIND_UNION:
6092 FIXME("TKIND_UNION unhandled.\n");
6093 hr = E_NOTIMPL;
6094 break;
6096 default:
6097 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6098 hr = E_NOTIMPL;
6099 break;
6101 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6102 ITypeInfo_Release(tinfo2);
6103 return hr;
6106 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6108 HRESULT hr = S_OK;
6110 /* enforce only one level of pointer indirection */
6111 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6113 tdesc = tdesc->u.lptdesc;
6115 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6116 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6117 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6118 if ((tdesc->vt == VT_USERDEFINED) ||
6119 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6121 VARTYPE vt_userdefined = 0;
6122 const TYPEDESC *tdesc_userdefined = tdesc;
6123 if (tdesc->vt == VT_PTR)
6125 vt_userdefined = VT_BYREF;
6126 tdesc_userdefined = tdesc->u.lptdesc;
6128 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6129 if ((hr == S_OK) &&
6130 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6131 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6133 *vt |= vt_userdefined;
6134 return S_OK;
6137 *vt = VT_BYREF;
6140 switch (tdesc->vt)
6142 case VT_HRESULT:
6143 *vt |= VT_ERROR;
6144 break;
6145 case VT_USERDEFINED:
6146 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6147 break;
6148 case VT_VOID:
6149 case VT_CARRAY:
6150 case VT_PTR:
6151 case VT_LPSTR:
6152 case VT_LPWSTR:
6153 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6154 hr = DISP_E_BADVARTYPE;
6155 break;
6156 case VT_SAFEARRAY:
6157 *vt |= VT_ARRAY;
6158 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6159 break;
6160 case VT_INT:
6161 *vt |= VT_I4;
6162 break;
6163 case VT_UINT:
6164 *vt |= VT_UI4;
6165 break;
6166 default:
6167 *vt |= tdesc->vt;
6168 break;
6170 return hr;
6173 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6175 ITypeInfo *tinfo2;
6176 TYPEATTR *tattr;
6177 HRESULT hres;
6179 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6180 if(FAILED(hres))
6181 return hres;
6183 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6184 if(FAILED(hres)) {
6185 ITypeInfo_Release(tinfo2);
6186 return hres;
6189 switch(tattr->typekind) {
6190 case TKIND_ALIAS:
6191 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6192 break;
6194 case TKIND_INTERFACE:
6195 case TKIND_DISPATCH:
6196 *guid = tattr->guid;
6197 break;
6199 default:
6200 ERR("Unexpected typekind %d\n", tattr->typekind);
6201 hres = E_UNEXPECTED;
6204 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6205 ITypeInfo_Release(tinfo2);
6206 return hres;
6209 /***********************************************************************
6210 * DispCallFunc (OLEAUT32.@)
6212 * Invokes a function of the specified calling convention, passing the
6213 * specified arguments and returns the result.
6215 * PARAMS
6216 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6217 * oVft [I] The offset in the vtable. See notes.
6218 * cc [I] Calling convention of the function to call.
6219 * vtReturn [I] The return type of the function.
6220 * cActuals [I] Number of parameters.
6221 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6222 * prgpvarg [I] The arguments to pass.
6223 * pvargResult [O] The return value of the function. Can be NULL.
6225 * RETURNS
6226 * Success: S_OK.
6227 * Failure: HRESULT code.
6229 * NOTES
6230 * The HRESULT return value of this function is not affected by the return
6231 * value of the user supplied function, which is returned in pvargResult.
6233 * If pvInstance is NULL then a non-object function is to be called and oVft
6234 * is the address of the function to call.
6236 * The cc parameter can be one of the following values:
6237 *|CC_FASTCALL
6238 *|CC_CDECL
6239 *|CC_PASCAL
6240 *|CC_STDCALL
6241 *|CC_FPFASTCALL
6242 *|CC_SYSCALL
6243 *|CC_MPWCDECL
6244 *|CC_MPWPASCAL
6247 HRESULT WINAPI
6248 DispCallFunc(
6249 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6250 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6252 #ifdef __i386__
6253 int argspos, stack_offset;
6254 void *func;
6255 UINT i;
6256 DWORD *args;
6258 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6259 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6260 pvargResult, V_VT(pvargResult));
6262 if (cc != CC_STDCALL && cc != CC_CDECL)
6264 FIXME("unsupported calling convention %d\n",cc);
6265 return E_INVALIDARG;
6268 /* maximum size for an argument is sizeof(VARIANT) */
6269 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6271 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6272 argspos = 1;
6273 if (pvInstance)
6275 const FARPROC *vtable = *(FARPROC **)pvInstance;
6276 func = vtable[oVft/sizeof(void *)];
6277 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6279 else func = (void *)oVft;
6281 for (i = 0; i < cActuals; i++)
6283 VARIANT *arg = prgpvarg[i];
6285 switch (prgvt[i])
6287 case VT_EMPTY:
6288 break;
6289 case VT_I8:
6290 case VT_UI8:
6291 case VT_R8:
6292 case VT_DATE:
6293 case VT_CY:
6294 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6295 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6296 break;
6297 case VT_DECIMAL:
6298 case VT_VARIANT:
6299 memcpy( &args[argspos], arg, sizeof(*arg) );
6300 argspos += sizeof(*arg) / sizeof(DWORD);
6301 break;
6302 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6303 args[argspos++] = V_BOOL(arg);
6304 break;
6305 default:
6306 args[argspos++] = V_UI4(arg);
6307 break;
6309 TRACE("arg %u: type %d\n",i,prgvt[i]);
6310 dump_Variant(arg);
6313 switch (vtReturn)
6315 case VT_EMPTY:
6316 call_method( func, argspos - 1, args + 1, &stack_offset );
6317 break;
6318 case VT_R4:
6319 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6320 break;
6321 case VT_R8:
6322 case VT_DATE:
6323 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6324 break;
6325 case VT_DECIMAL:
6326 case VT_VARIANT:
6327 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6328 call_method( func, argspos, args, &stack_offset );
6329 break;
6330 case VT_I8:
6331 case VT_UI8:
6332 case VT_CY:
6333 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6334 break;
6335 case VT_HRESULT:
6336 WARN("invalid return type %u\n", vtReturn);
6337 heap_free( args );
6338 return E_INVALIDARG;
6339 default:
6340 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6341 break;
6343 heap_free( args );
6344 if (stack_offset && cc == CC_STDCALL)
6346 WARN( "stack pointer off by %d\n", stack_offset );
6347 return DISP_E_BADCALLEE;
6349 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6350 TRACE("retval: "); dump_Variant(pvargResult);
6351 return S_OK;
6353 #elif defined(__x86_64__)
6354 int argspos;
6355 UINT i;
6356 DWORD_PTR *args;
6357 void *func;
6359 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6360 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6361 pvargResult, V_VT(pvargResult));
6363 if (cc != CC_STDCALL && cc != CC_CDECL)
6365 FIXME("unsupported calling convention %d\n",cc);
6366 return E_INVALIDARG;
6369 /* maximum size for an argument is sizeof(DWORD_PTR) */
6370 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6372 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6373 argspos = 1;
6374 if (pvInstance)
6376 const FARPROC *vtable = *(FARPROC **)pvInstance;
6377 func = vtable[oVft/sizeof(void *)];
6378 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6380 else func = (void *)oVft;
6382 for (i = 0; i < cActuals; i++)
6384 VARIANT *arg = prgpvarg[i];
6386 switch (prgvt[i])
6388 case VT_DECIMAL:
6389 case VT_VARIANT:
6390 args[argspos++] = (ULONG_PTR)arg;
6391 break;
6392 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6393 args[argspos++] = V_BOOL(arg);
6394 break;
6395 default:
6396 args[argspos++] = V_UI8(arg);
6397 break;
6399 TRACE("arg %u: type %d\n",i,prgvt[i]);
6400 dump_Variant(arg);
6403 switch (vtReturn)
6405 case VT_R4:
6406 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6407 break;
6408 case VT_R8:
6409 case VT_DATE:
6410 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6411 break;
6412 case VT_DECIMAL:
6413 case VT_VARIANT:
6414 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6415 call_method( func, argspos, args );
6416 break;
6417 case VT_HRESULT:
6418 WARN("invalid return type %u\n", vtReturn);
6419 heap_free( args );
6420 return E_INVALIDARG;
6421 default:
6422 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6423 break;
6425 heap_free( args );
6426 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6427 TRACE("retval: "); dump_Variant(pvargResult);
6428 return S_OK;
6430 #else
6431 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6432 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6433 return E_NOTIMPL;
6434 #endif
6437 static inline BOOL func_restricted( const FUNCDESC *desc )
6439 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6442 #define INVBUF_ELEMENT_SIZE \
6443 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6444 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6445 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6446 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6447 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6448 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6449 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6450 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6452 static HRESULT WINAPI ITypeInfo_fnInvoke(
6453 ITypeInfo2 *iface,
6454 VOID *pIUnk,
6455 MEMBERID memid,
6456 UINT16 wFlags,
6457 DISPPARAMS *pDispParams,
6458 VARIANT *pVarResult,
6459 EXCEPINFO *pExcepInfo,
6460 UINT *pArgErr)
6462 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6463 int i;
6464 unsigned int var_index;
6465 TYPEKIND type_kind;
6466 HRESULT hres;
6467 const TLBFuncDesc *pFuncInfo;
6468 UINT fdc;
6470 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6471 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6474 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6475 return DISP_E_MEMBERNOTFOUND;
6477 if (!pDispParams)
6479 ERR("NULL pDispParams not allowed\n");
6480 return E_INVALIDARG;
6483 dump_DispParms(pDispParams);
6485 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6487 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6488 pDispParams->cNamedArgs, pDispParams->cArgs);
6489 return E_INVALIDARG;
6492 /* we do this instead of using GetFuncDesc since it will return a fake
6493 * FUNCDESC for dispinterfaces and we want the real function description */
6494 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6495 pFuncInfo = &This->funcdescs[fdc];
6496 if ((memid == pFuncInfo->funcdesc.memid) &&
6497 (wFlags & pFuncInfo->funcdesc.invkind) &&
6498 !func_restricted( &pFuncInfo->funcdesc ))
6499 break;
6502 if (fdc < This->TypeAttr.cFuncs) {
6503 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6505 if (TRACE_ON(ole))
6507 TRACE("invoking:\n");
6508 dump_TLBFuncDescOne(pFuncInfo);
6511 switch (func_desc->funckind) {
6512 case FUNC_PUREVIRTUAL:
6513 case FUNC_VIRTUAL: {
6514 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6515 VARIANT varresult;
6516 VARIANT retval; /* pointer for storing byref retvals in */
6517 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6518 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6519 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6520 UINT cNamedArgs = pDispParams->cNamedArgs;
6521 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6522 UINT vargs_converted=0;
6524 hres = S_OK;
6526 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6528 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6530 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6531 hres = DISP_E_PARAMNOTFOUND;
6532 goto func_fail;
6536 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6538 ERR("functions with the vararg attribute do not support named arguments\n");
6539 hres = DISP_E_NONAMEDARGS;
6540 goto func_fail;
6543 for (i = 0; i < func_desc->cParams; i++)
6545 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6546 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6547 if (FAILED(hres))
6548 goto func_fail;
6551 TRACE("changing args\n");
6552 for (i = 0; i < func_desc->cParams; i++)
6554 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6555 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6556 VARIANTARG *src_arg;
6558 if (wParamFlags & PARAMFLAG_FLCID)
6560 VARIANTARG *arg;
6561 arg = prgpvarg[i] = &rgvarg[i];
6562 V_VT(arg) = VT_I4;
6563 V_I4(arg) = This->pTypeLib->lcid;
6564 continue;
6567 src_arg = NULL;
6569 if (cNamedArgs)
6571 USHORT j;
6572 for (j = 0; j < cNamedArgs; j++)
6573 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6575 src_arg = &pDispParams->rgvarg[j];
6576 break;
6580 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6582 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6583 vargs_converted++;
6586 if (wParamFlags & PARAMFLAG_FRETVAL)
6588 /* under most conditions the caller is not allowed to
6589 * pass in a dispparam arg in the index of what would be
6590 * the retval parameter. however, there is an exception
6591 * where the extra parameter is used in an extra
6592 * IDispatch::Invoke below */
6593 if ((i < pDispParams->cArgs) &&
6594 ((func_desc->cParams != 1) || !pVarResult ||
6595 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6597 hres = DISP_E_BADPARAMCOUNT;
6598 break;
6601 /* note: this check is placed so that if the caller passes
6602 * in a VARIANTARG for the retval we just ignore it, like
6603 * native does */
6604 if (i == func_desc->cParams - 1)
6606 VARIANTARG *arg;
6607 arg = prgpvarg[i] = &rgvarg[i];
6608 memset(arg, 0, sizeof(*arg));
6609 V_VT(arg) = rgvt[i];
6610 memset(&retval, 0, sizeof(retval));
6611 V_BYREF(arg) = &retval;
6613 else
6615 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6616 hres = E_UNEXPECTED;
6617 break;
6620 else if (src_arg)
6622 dump_Variant(src_arg);
6624 if(rgvt[i]!=V_VT(src_arg))
6626 if (rgvt[i] == VT_VARIANT)
6627 hres = VariantCopy(&rgvarg[i], src_arg);
6628 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6630 if (rgvt[i] == V_VT(src_arg))
6631 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6632 else
6634 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6635 if (wParamFlags & PARAMFLAG_FIN)
6636 hres = VariantCopy(&missing_arg[i], src_arg);
6637 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6639 V_VT(&rgvarg[i]) = rgvt[i];
6641 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6643 SAFEARRAY *a;
6644 SAFEARRAYBOUND bound;
6645 VARIANT *v;
6646 LONG j;
6647 bound.lLbound = 0;
6648 bound.cElements = pDispParams->cArgs-i;
6649 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6651 ERR("SafeArrayCreate failed\n");
6652 break;
6654 hres = SafeArrayAccessData(a, (LPVOID)&v);
6655 if (hres != S_OK)
6657 ERR("SafeArrayAccessData failed with %x\n", hres);
6658 SafeArrayDestroy(a);
6659 break;
6661 for (j = 0; j < bound.cElements; j++)
6662 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6663 hres = SafeArrayUnaccessData(a);
6664 if (hres != S_OK)
6666 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6667 SafeArrayDestroy(a);
6668 break;
6670 V_ARRAY(&rgvarg[i]) = a;
6671 V_VT(&rgvarg[i]) = rgvt[i];
6673 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6675 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6676 if (wParamFlags & PARAMFLAG_FIN)
6677 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6678 else
6679 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6680 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6681 V_VT(&rgvarg[i]) = rgvt[i];
6683 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6685 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6686 V_VT(&rgvarg[i]) = rgvt[i];
6688 else
6690 /* FIXME: this doesn't work for VT_BYREF arguments if
6691 * they are not the same type as in the paramdesc */
6692 V_VT(&rgvarg[i]) = V_VT(src_arg);
6693 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6694 V_VT(&rgvarg[i]) = rgvt[i];
6697 if (FAILED(hres))
6699 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6700 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6701 debugstr_VT(src_arg), debugstr_VF(src_arg));
6702 break;
6704 prgpvarg[i] = &rgvarg[i];
6706 else
6708 prgpvarg[i] = src_arg;
6711 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6712 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6713 && V_UNKNOWN(prgpvarg[i])) {
6714 IUnknown *userdefined_iface;
6715 GUID guid;
6717 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6718 if(FAILED(hres))
6719 break;
6721 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6722 if(FAILED(hres)) {
6723 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6724 break;
6727 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6728 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6731 else if (wParamFlags & PARAMFLAG_FOPT)
6733 VARIANTARG *arg;
6734 arg = prgpvarg[i] = &rgvarg[i];
6735 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6737 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6738 if (FAILED(hres))
6739 break;
6741 else
6743 VARIANTARG *missing_arg;
6744 /* if the function wants a pointer to a variant then
6745 * set that up, otherwise just pass the VT_ERROR in
6746 * the argument by value */
6747 if (rgvt[i] & VT_BYREF)
6749 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6750 V_VT(arg) = VT_VARIANT | VT_BYREF;
6751 V_VARIANTREF(arg) = missing_arg;
6753 else
6754 missing_arg = arg;
6755 V_VT(missing_arg) = VT_ERROR;
6756 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6759 else
6761 hres = DISP_E_BADPARAMCOUNT;
6762 break;
6765 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6767 /* VT_VOID is a special case for return types, so it is not
6768 * handled in the general function */
6769 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6770 V_VT(&varresult) = VT_EMPTY;
6771 else
6773 V_VT(&varresult) = 0;
6774 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6775 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6778 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
6779 V_VT(&varresult), func_desc->cParams, rgvt,
6780 prgpvarg, &varresult);
6782 vargs_converted = 0;
6784 for (i = 0; i < func_desc->cParams; i++)
6786 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6787 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6789 if (wParamFlags & PARAMFLAG_FLCID)
6790 continue;
6791 else if (wParamFlags & PARAMFLAG_FRETVAL)
6793 if (TRACE_ON(ole))
6795 TRACE("[retval] value: ");
6796 dump_Variant(prgpvarg[i]);
6799 if (pVarResult)
6801 VariantInit(pVarResult);
6802 /* deref return value */
6803 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6806 VARIANT_ClearInd(prgpvarg[i]);
6808 else if (vargs_converted < pDispParams->cArgs)
6810 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6811 if (wParamFlags & PARAMFLAG_FOUT)
6813 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6815 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6817 if (FAILED(hres))
6819 ERR("failed to convert param %d to vt %d\n", i,
6820 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6821 break;
6825 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6826 func_desc->cParamsOpt < 0 &&
6827 i == func_desc->cParams-1)
6829 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6830 LONG j, ubound;
6831 VARIANT *v;
6832 hres = SafeArrayGetUBound(a, 1, &ubound);
6833 if (hres != S_OK)
6835 ERR("SafeArrayGetUBound failed with %x\n", hres);
6836 break;
6838 hres = SafeArrayAccessData(a, (LPVOID)&v);
6839 if (hres != S_OK)
6841 ERR("SafeArrayAccessData failed with %x\n", hres);
6842 break;
6844 for (j = 0; j <= ubound; j++)
6845 VariantClear(&v[j]);
6846 hres = SafeArrayUnaccessData(a);
6847 if (hres != S_OK)
6849 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6850 break;
6853 VariantClear(&rgvarg[i]);
6854 vargs_converted++;
6856 else if (wParamFlags & PARAMFLAG_FOPT)
6858 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6859 VariantClear(&rgvarg[i]);
6862 VariantClear(&missing_arg[i]);
6865 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6867 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6868 hres = DISP_E_EXCEPTION;
6869 if (pExcepInfo)
6871 IErrorInfo *pErrorInfo;
6872 pExcepInfo->scode = V_ERROR(&varresult);
6873 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6875 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6876 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6877 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6878 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6880 IErrorInfo_Release(pErrorInfo);
6884 if (V_VT(&varresult) != VT_ERROR)
6886 TRACE("varresult value: ");
6887 dump_Variant(&varresult);
6889 if (pVarResult)
6891 VariantClear(pVarResult);
6892 *pVarResult = varresult;
6894 else
6895 VariantClear(&varresult);
6898 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6899 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6900 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6901 (pDispParams->cArgs != 0))
6903 if (V_VT(pVarResult) == VT_DISPATCH)
6905 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6906 /* Note: not VariantClear; we still need the dispatch
6907 * pointer to be valid */
6908 VariantInit(pVarResult);
6909 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6910 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6911 pDispParams, pVarResult, pExcepInfo, pArgErr);
6912 IDispatch_Release(pDispatch);
6914 else
6916 VariantClear(pVarResult);
6917 hres = DISP_E_NOTACOLLECTION;
6921 func_fail:
6922 heap_free(buffer);
6923 break;
6925 case FUNC_DISPATCH: {
6926 IDispatch *disp;
6928 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6929 if (SUCCEEDED(hres)) {
6930 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6931 hres = IDispatch_Invoke(
6932 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6933 pVarResult,pExcepInfo,pArgErr
6935 if (FAILED(hres))
6936 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6937 IDispatch_Release(disp);
6938 } else
6939 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6940 break;
6942 default:
6943 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6944 hres = E_FAIL;
6945 break;
6948 TRACE("-- 0x%08x\n", hres);
6949 return hres;
6951 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6952 VARDESC *var_desc;
6954 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6955 if(FAILED(hres)) return hres;
6957 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6958 dump_VARDESC(var_desc);
6959 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6960 return E_NOTIMPL;
6963 /* not found, look for it in inherited interfaces */
6964 ITypeInfo2_GetTypeKind(iface, &type_kind);
6965 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6966 if(This->impltypes) {
6967 /* recursive search */
6968 ITypeInfo *pTInfo;
6969 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6970 if(SUCCEEDED(hres)){
6971 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6972 ITypeInfo_Release(pTInfo);
6973 return hres;
6975 WARN("Could not search inherited interface!\n");
6978 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6979 return DISP_E_MEMBERNOTFOUND;
6982 /* ITypeInfo::GetDocumentation
6984 * Retrieves the documentation string, the complete Help file name and path,
6985 * and the context ID for the Help topic for a specified type description.
6987 * (Can be tested by the Visual Basic Editor in Word for instance.)
6989 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6990 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6991 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6993 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6994 const TLBFuncDesc *pFDesc;
6995 const TLBVarDesc *pVDesc;
6996 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6997 " HelpContext(%p) HelpFile(%p)\n",
6998 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6999 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7000 if(pBstrName)
7001 *pBstrName=SysAllocString(This->Name);
7002 if(pBstrDocString)
7003 *pBstrDocString=SysAllocString(This->DocString);
7004 if(pdwHelpContext)
7005 *pdwHelpContext=This->dwHelpContext;
7006 if(pBstrHelpFile)
7007 *pBstrHelpFile=SysAllocString(This->pTypeLib->HelpFile);
7008 return S_OK;
7009 }else {/* for a member */
7010 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7011 if(pFDesc){
7012 if(pBstrName)
7013 *pBstrName = SysAllocString(pFDesc->Name);
7014 if(pBstrDocString)
7015 *pBstrDocString=SysAllocString(pFDesc->HelpString);
7016 if(pdwHelpContext)
7017 *pdwHelpContext=pFDesc->helpcontext;
7018 return S_OK;
7020 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7021 if(pVDesc){
7022 if(pBstrName)
7023 *pBstrName = SysAllocString(pVDesc->Name);
7024 if(pBstrDocString)
7025 *pBstrDocString=SysAllocString(pVDesc->HelpString);
7026 if(pdwHelpContext)
7027 *pdwHelpContext=pVDesc->HelpContext;
7028 if(pBstrHelpFile)
7029 *pBstrHelpFile = SysAllocString(This->pTypeLib->HelpFile);
7030 return S_OK;
7034 if(This->impltypes &&
7035 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
7036 /* recursive search */
7037 ITypeInfo *pTInfo;
7038 HRESULT result;
7039 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7040 if(SUCCEEDED(result)) {
7041 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7042 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7043 ITypeInfo_Release(pTInfo);
7044 return result;
7046 WARN("Could not search inherited interface!\n");
7049 WARN("member %d not found\n", memid);
7050 return TYPE_E_ELEMENTNOTFOUND;
7053 /* ITypeInfo::GetDllEntry
7055 * Retrieves a description or specification of an entry point for a function
7056 * in a DLL.
7058 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7059 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7060 WORD *pwOrdinal)
7062 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7063 const TLBFuncDesc *pFDesc;
7065 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7067 if (pBstrDllName) *pBstrDllName = NULL;
7068 if (pBstrName) *pBstrName = NULL;
7069 if (pwOrdinal) *pwOrdinal = 0;
7071 if (This->TypeAttr.typekind != TKIND_MODULE)
7072 return TYPE_E_BADMODULEKIND;
7074 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7075 if(pFDesc){
7076 dump_TypeInfo(This);
7077 if (TRACE_ON(ole))
7078 dump_TLBFuncDescOne(pFDesc);
7080 if (pBstrDllName)
7081 *pBstrDllName = SysAllocString(This->DllName);
7083 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7084 if (pBstrName)
7085 *pBstrName = SysAllocString(pFDesc->Entry);
7086 if (pwOrdinal)
7087 *pwOrdinal = -1;
7088 return S_OK;
7090 if (pBstrName)
7091 *pBstrName = NULL;
7092 if (pwOrdinal)
7093 *pwOrdinal = LOWORD(pFDesc->Entry);
7094 return S_OK;
7096 return TYPE_E_ELEMENTNOTFOUND;
7099 /* internal function to make the inherited interfaces' methods appear
7100 * part of the interface */
7101 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7102 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7104 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7105 HRESULT hr;
7107 TRACE("%p, 0x%x\n", iface, *hRefType);
7109 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7111 ITypeInfo *pSubTypeInfo;
7113 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7114 if (FAILED(hr))
7115 return hr;
7117 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7118 hRefType, ppTInfo);
7119 ITypeInfo_Release(pSubTypeInfo);
7120 if (SUCCEEDED(hr))
7121 return hr;
7123 *hRefType -= DISPATCH_HREF_OFFSET;
7125 if (!(*hRefType & DISPATCH_HREF_MASK))
7126 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7127 else
7128 return E_FAIL;
7131 /* ITypeInfo::GetRefTypeInfo
7133 * If a type description references other type descriptions, it retrieves
7134 * the referenced type descriptions.
7136 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7137 ITypeInfo2 *iface,
7138 HREFTYPE hRefType,
7139 ITypeInfo **ppTInfo)
7141 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7142 HRESULT result = E_FAIL;
7144 if(!ppTInfo)
7145 return E_INVALIDARG;
7147 if ((INT)hRefType < 0) {
7148 ITypeInfoImpl *pTypeInfoImpl;
7150 if (!(This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL) ||
7151 !(This->TypeAttr.typekind == TKIND_INTERFACE ||
7152 This->TypeAttr.typekind == TKIND_DISPATCH))
7153 return TYPE_E_ELEMENTNOTFOUND;
7155 /* when we meet a DUAL typeinfo, we must create the alternate
7156 * version of it.
7158 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7160 *pTypeInfoImpl = *This;
7161 pTypeInfoImpl->ref = 0;
7163 if (This->TypeAttr.typekind == TKIND_INTERFACE)
7164 pTypeInfoImpl->TypeAttr.typekind = TKIND_DISPATCH;
7165 else
7166 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
7168 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7169 /* the AddRef implicitly adds a reference to the parent typelib, which
7170 * stops the copied data from being destroyed until the new typeinfo's
7171 * refcount goes to zero, but we need to signal to the new instance to
7172 * not free its data structures when it is destroyed */
7173 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7175 ITypeInfo_AddRef(*ppTInfo);
7177 result = S_OK;
7179 else if (This->hreftype == hRefType)
7181 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
7182 ITypeInfo_AddRef(*ppTInfo);
7183 result = S_OK;
7184 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7185 (This->TypeAttr.typekind == TKIND_DISPATCH))
7187 HREFTYPE href_dispatch = hRefType;
7188 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7189 } else {
7190 TLBRefType *ref_type;
7191 ITypeLib *pTLib = NULL;
7192 UINT i;
7194 if(!(hRefType & 0x1)){
7195 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7197 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7199 result = S_OK;
7200 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7201 ITypeInfo_AddRef(*ppTInfo);
7202 goto end;
7205 result = TYPE_E_ELEMENTNOTFOUND;
7206 goto end;
7209 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7211 if(ref_type->reference == (hRefType & (~0x3)))
7212 break;
7214 if(&ref_type->entry == &This->pTypeLib->ref_list)
7216 FIXME("Can't find pRefType for ref %x\n", hRefType);
7217 goto end;
7220 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7221 UINT Index;
7222 TRACE("internal reference\n");
7223 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7224 } else {
7225 if(ref_type->pImpTLInfo->pImpTypeLib) {
7226 TRACE("typeinfo in imported typelib that is already loaded\n");
7227 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7228 ITypeLib_AddRef(pTLib);
7229 result = S_OK;
7230 } else {
7231 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7232 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
7233 ref_type->pImpTLInfo->wVersionMajor,
7234 ref_type->pImpTLInfo->wVersionMinor,
7235 ref_type->pImpTLInfo->lcid,
7236 &pTLib);
7238 if(FAILED(result)) {
7239 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7240 result=LoadTypeLib(libnam, &pTLib);
7241 SysFreeString(libnam);
7243 if(SUCCEEDED(result)) {
7244 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7245 ITypeLib_AddRef(pTLib);
7249 if(SUCCEEDED(result)) {
7250 if(ref_type->index == TLB_REF_USE_GUID)
7251 result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
7252 else
7253 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7255 if (pTLib != NULL)
7256 ITypeLib_Release(pTLib);
7259 end:
7260 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7261 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7262 return result;
7265 /* ITypeInfo::AddressOfMember
7267 * Retrieves the addresses of static functions or variables, such as those
7268 * defined in a DLL.
7270 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7271 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7273 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7274 HRESULT hr;
7275 BSTR dll, entry;
7276 WORD ordinal;
7277 HMODULE module;
7279 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7281 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7282 if (FAILED(hr))
7283 return hr;
7285 module = LoadLibraryW(dll);
7286 if (!module)
7288 ERR("couldn't load %s\n", debugstr_w(dll));
7289 SysFreeString(dll);
7290 SysFreeString(entry);
7291 return STG_E_FILENOTFOUND;
7293 /* FIXME: store library somewhere where we can free it */
7295 if (entry)
7297 LPSTR entryA;
7298 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7299 entryA = heap_alloc(len);
7300 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7302 *ppv = GetProcAddress(module, entryA);
7303 if (!*ppv)
7304 ERR("function not found %s\n", debugstr_a(entryA));
7306 heap_free(entryA);
7308 else
7310 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7311 if (!*ppv)
7312 ERR("function not found %d\n", ordinal);
7315 SysFreeString(dll);
7316 SysFreeString(entry);
7318 if (!*ppv)
7319 return TYPE_E_DLLFUNCTIONNOTFOUND;
7321 return S_OK;
7324 /* ITypeInfo::CreateInstance
7326 * Creates a new instance of a type that describes a component object class
7327 * (coclass).
7329 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7330 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7332 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7333 HRESULT hr;
7334 TYPEATTR *pTA;
7336 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7338 *ppvObj = NULL;
7340 if(pOuterUnk)
7342 WARN("Not able to aggregate\n");
7343 return CLASS_E_NOAGGREGATION;
7346 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7347 if(FAILED(hr)) return hr;
7349 if(pTA->typekind != TKIND_COCLASS)
7351 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7352 hr = E_INVALIDARG;
7353 goto end;
7356 hr = S_FALSE;
7357 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7359 IUnknown *pUnk;
7360 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7361 TRACE("GetActiveObject rets %08x\n", hr);
7362 if(hr == S_OK)
7364 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7365 IUnknown_Release(pUnk);
7369 if(hr != S_OK)
7370 hr = CoCreateInstance(&pTA->guid, NULL,
7371 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7372 riid, ppvObj);
7374 end:
7375 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7376 return hr;
7379 /* ITypeInfo::GetMops
7381 * Retrieves marshalling information.
7383 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7384 BSTR *pBstrMops)
7386 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7387 FIXME("(%p %d) stub!\n", This, memid);
7388 *pBstrMops = NULL;
7389 return S_OK;
7392 /* ITypeInfo::GetContainingTypeLib
7394 * Retrieves the containing type library and the index of the type description
7395 * within that type library.
7397 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7398 ITypeLib * *ppTLib, UINT *pIndex)
7400 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7402 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7403 if (pIndex) {
7404 *pIndex=This->index;
7405 TRACE("returning pIndex=%d\n", *pIndex);
7408 if (ppTLib) {
7409 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7410 ITypeLib_AddRef(*ppTLib);
7411 TRACE("returning ppTLib=%p\n", *ppTLib);
7414 return S_OK;
7417 /* ITypeInfo::ReleaseTypeAttr
7419 * Releases a TYPEATTR previously returned by GetTypeAttr.
7422 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7423 TYPEATTR* pTypeAttr)
7425 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7426 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7427 heap_free(pTypeAttr);
7430 /* ITypeInfo::ReleaseFuncDesc
7432 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7434 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7435 ITypeInfo2 *iface,
7436 FUNCDESC *pFuncDesc)
7438 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7439 SHORT i;
7441 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7443 for (i = 0; i < pFuncDesc->cParams; i++)
7444 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7445 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7447 SysFreeString((BSTR)pFuncDesc);
7450 /* ITypeInfo::ReleaseVarDesc
7452 * Releases a VARDESC previously returned by GetVarDesc.
7454 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7455 VARDESC *pVarDesc)
7457 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7458 TRACE("(%p)->(%p)\n", This, pVarDesc);
7460 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7461 if (pVarDesc->varkind == VAR_CONST)
7462 VariantClear(pVarDesc->u.lpvarValue);
7463 SysFreeString((BSTR)pVarDesc);
7466 /* ITypeInfo2::GetTypeKind
7468 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7471 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7472 TYPEKIND *pTypeKind)
7474 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7475 *pTypeKind=This->TypeAttr.typekind;
7476 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7477 return S_OK;
7480 /* ITypeInfo2::GetTypeFlags
7482 * Returns the type flags without any allocations. This returns a DWORD type
7483 * flag, which expands the type flags without growing the TYPEATTR (type
7484 * attribute).
7487 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7489 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7490 *pTypeFlags=This->TypeAttr.wTypeFlags;
7491 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7492 return S_OK;
7495 /* ITypeInfo2::GetFuncIndexOfMemId
7496 * Binds to a specific member based on a known DISPID, where the member name
7497 * is not known (for example, when binding to a default member).
7500 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7501 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7503 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7504 UINT fdc;
7505 HRESULT result;
7507 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7508 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7509 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7510 break;
7512 if(fdc < This->TypeAttr.cFuncs) {
7513 *pFuncIndex = fdc;
7514 result = S_OK;
7515 } else
7516 result = TYPE_E_ELEMENTNOTFOUND;
7518 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7519 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7520 return result;
7523 /* TypeInfo2::GetVarIndexOfMemId
7525 * Binds to a specific member based on a known DISPID, where the member name
7526 * is not known (for example, when binding to a default member).
7529 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7530 MEMBERID memid, UINT *pVarIndex)
7532 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7533 TLBVarDesc *pVarInfo;
7535 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7537 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7538 if(!pVarInfo)
7539 return TYPE_E_ELEMENTNOTFOUND;
7541 *pVarIndex = (pVarInfo - This->vardescs);
7543 return S_OK;
7546 /* ITypeInfo2::GetCustData
7548 * Gets the custom data
7550 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7551 ITypeInfo2 * iface,
7552 REFGUID guid,
7553 VARIANT *pVarVal)
7555 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7556 TLBCustData *pCData;
7558 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7560 if(!guid || !pVarVal)
7561 return E_INVALIDARG;
7563 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7565 VariantInit( pVarVal);
7566 if (pCData)
7567 VariantCopy( pVarVal, &pCData->data);
7568 else
7569 VariantClear( pVarVal );
7570 return S_OK;
7573 /* ITypeInfo2::GetFuncCustData
7575 * Gets the custom data
7577 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7578 ITypeInfo2 * iface,
7579 UINT index,
7580 REFGUID guid,
7581 VARIANT *pVarVal)
7583 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7584 TLBCustData *pCData;
7585 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7587 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7589 if(index >= This->TypeAttr.cFuncs)
7590 return TYPE_E_ELEMENTNOTFOUND;
7592 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7593 if(!pCData)
7594 return TYPE_E_ELEMENTNOTFOUND;
7596 VariantInit(pVarVal);
7597 VariantCopy(pVarVal, &pCData->data);
7599 return S_OK;
7602 /* ITypeInfo2::GetParamCustData
7604 * Gets the custom data
7606 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7607 ITypeInfo2 * iface,
7608 UINT indexFunc,
7609 UINT indexParam,
7610 REFGUID guid,
7611 VARIANT *pVarVal)
7613 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7614 TLBCustData *pCData;
7615 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7617 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7618 debugstr_guid(guid), pVarVal);
7620 if(indexFunc >= This->TypeAttr.cFuncs)
7621 return TYPE_E_ELEMENTNOTFOUND;
7623 if(indexParam >= pFDesc->funcdesc.cParams)
7624 return TYPE_E_ELEMENTNOTFOUND;
7626 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7627 if(!pCData)
7628 return TYPE_E_ELEMENTNOTFOUND;
7630 VariantInit(pVarVal);
7631 VariantCopy(pVarVal, &pCData->data);
7633 return S_OK;
7636 /* ITypeInfo2::GetVarCustData
7638 * Gets the custom data
7640 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7641 ITypeInfo2 * iface,
7642 UINT index,
7643 REFGUID guid,
7644 VARIANT *pVarVal)
7646 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7647 TLBCustData *pCData;
7648 TLBVarDesc *pVDesc = &This->vardescs[index];
7650 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7652 if(index >= This->TypeAttr.cVars)
7653 return TYPE_E_ELEMENTNOTFOUND;
7655 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7656 if(!pCData)
7657 return TYPE_E_ELEMENTNOTFOUND;
7659 VariantInit(pVarVal);
7660 VariantCopy(pVarVal, &pCData->data);
7662 return S_OK;
7665 /* ITypeInfo2::GetImplCustData
7667 * Gets the custom data
7669 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7670 ITypeInfo2 * iface,
7671 UINT index,
7672 REFGUID guid,
7673 VARIANT *pVarVal)
7675 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7676 TLBCustData *pCData;
7677 TLBImplType *pRDesc = &This->impltypes[index];
7679 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7681 if(index >= This->TypeAttr.cImplTypes)
7682 return TYPE_E_ELEMENTNOTFOUND;
7684 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7685 if(!pCData)
7686 return TYPE_E_ELEMENTNOTFOUND;
7688 VariantInit(pVarVal);
7689 VariantCopy(pVarVal, &pCData->data);
7691 return S_OK;
7694 /* ITypeInfo2::GetDocumentation2
7696 * Retrieves the documentation string, the complete Help file name and path,
7697 * the localization context to use, and the context ID for the library Help
7698 * topic in the Help file.
7701 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7702 ITypeInfo2 * iface,
7703 MEMBERID memid,
7704 LCID lcid,
7705 BSTR *pbstrHelpString,
7706 DWORD *pdwHelpStringContext,
7707 BSTR *pbstrHelpStringDll)
7709 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7710 const TLBFuncDesc *pFDesc;
7711 const TLBVarDesc *pVDesc;
7712 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7713 "HelpStringContext(%p) HelpStringDll(%p)\n",
7714 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7715 pbstrHelpStringDll );
7716 /* the help string should be obtained from the helpstringdll,
7717 * using the _DLLGetDocumentation function, based on the supplied
7718 * lcid. Nice to do sometime...
7720 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7721 if(pbstrHelpString)
7722 *pbstrHelpString=SysAllocString(This->Name);
7723 if(pdwHelpStringContext)
7724 *pdwHelpStringContext=This->dwHelpStringContext;
7725 if(pbstrHelpStringDll)
7726 *pbstrHelpStringDll=
7727 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7728 return S_OK;
7729 }else {/* for a member */
7730 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7731 if(pFDesc){
7732 if(pbstrHelpString)
7733 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7734 if(pdwHelpStringContext)
7735 *pdwHelpStringContext=pFDesc->HelpStringContext;
7736 if(pbstrHelpStringDll)
7737 *pbstrHelpStringDll=
7738 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7739 return S_OK;
7741 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7742 if(pVDesc){
7743 if(pbstrHelpString)
7744 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7745 if(pdwHelpStringContext)
7746 *pdwHelpStringContext=pVDesc->HelpStringContext;
7747 if(pbstrHelpStringDll)
7748 *pbstrHelpStringDll=
7749 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7750 return S_OK;
7753 return TYPE_E_ELEMENTNOTFOUND;
7756 /* ITypeInfo2::GetAllCustData
7758 * Gets all custom data items for the Type info.
7761 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7762 ITypeInfo2 * iface,
7763 CUSTDATA *pCustData)
7765 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7767 TRACE("%p %p\n", This, pCustData);
7769 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7772 /* ITypeInfo2::GetAllFuncCustData
7774 * Gets all custom data items for the specified Function
7777 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7778 ITypeInfo2 * iface,
7779 UINT index,
7780 CUSTDATA *pCustData)
7782 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7783 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7785 TRACE("%p %u %p\n", This, index, pCustData);
7787 if(index >= This->TypeAttr.cFuncs)
7788 return TYPE_E_ELEMENTNOTFOUND;
7790 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7793 /* ITypeInfo2::GetAllParamCustData
7795 * Gets all custom data items for the Functions
7798 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7799 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7801 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7802 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7804 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7806 if(indexFunc >= This->TypeAttr.cFuncs)
7807 return TYPE_E_ELEMENTNOTFOUND;
7809 if(indexParam >= pFDesc->funcdesc.cParams)
7810 return TYPE_E_ELEMENTNOTFOUND;
7812 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7815 /* ITypeInfo2::GetAllVarCustData
7817 * Gets all custom data items for the specified Variable
7820 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7821 UINT index, CUSTDATA *pCustData)
7823 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7824 TLBVarDesc * pVDesc = &This->vardescs[index];
7826 TRACE("%p %u %p\n", This, index, pCustData);
7828 if(index >= This->TypeAttr.cVars)
7829 return TYPE_E_ELEMENTNOTFOUND;
7831 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7834 /* ITypeInfo2::GetAllImplCustData
7836 * Gets all custom data items for the specified implementation type
7839 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7840 ITypeInfo2 * iface,
7841 UINT index,
7842 CUSTDATA *pCustData)
7844 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7845 TLBImplType *pRDesc = &This->impltypes[index];
7847 TRACE("%p %u %p\n", This, index, pCustData);
7849 if(index >= This->TypeAttr.cImplTypes)
7850 return TYPE_E_ELEMENTNOTFOUND;
7852 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7855 static const ITypeInfo2Vtbl tinfvt =
7858 ITypeInfo_fnQueryInterface,
7859 ITypeInfo_fnAddRef,
7860 ITypeInfo_fnRelease,
7862 ITypeInfo_fnGetTypeAttr,
7863 ITypeInfo_fnGetTypeComp,
7864 ITypeInfo_fnGetFuncDesc,
7865 ITypeInfo_fnGetVarDesc,
7866 ITypeInfo_fnGetNames,
7867 ITypeInfo_fnGetRefTypeOfImplType,
7868 ITypeInfo_fnGetImplTypeFlags,
7869 ITypeInfo_fnGetIDsOfNames,
7870 ITypeInfo_fnInvoke,
7871 ITypeInfo_fnGetDocumentation,
7872 ITypeInfo_fnGetDllEntry,
7873 ITypeInfo_fnGetRefTypeInfo,
7874 ITypeInfo_fnAddressOfMember,
7875 ITypeInfo_fnCreateInstance,
7876 ITypeInfo_fnGetMops,
7877 ITypeInfo_fnGetContainingTypeLib,
7878 ITypeInfo_fnReleaseTypeAttr,
7879 ITypeInfo_fnReleaseFuncDesc,
7880 ITypeInfo_fnReleaseVarDesc,
7882 ITypeInfo2_fnGetTypeKind,
7883 ITypeInfo2_fnGetTypeFlags,
7884 ITypeInfo2_fnGetFuncIndexOfMemId,
7885 ITypeInfo2_fnGetVarIndexOfMemId,
7886 ITypeInfo2_fnGetCustData,
7887 ITypeInfo2_fnGetFuncCustData,
7888 ITypeInfo2_fnGetParamCustData,
7889 ITypeInfo2_fnGetVarCustData,
7890 ITypeInfo2_fnGetImplTypeCustData,
7891 ITypeInfo2_fnGetDocumentation2,
7892 ITypeInfo2_fnGetAllCustData,
7893 ITypeInfo2_fnGetAllFuncCustData,
7894 ITypeInfo2_fnGetAllParamCustData,
7895 ITypeInfo2_fnGetAllVarCustData,
7896 ITypeInfo2_fnGetAllImplTypeCustData,
7899 /******************************************************************************
7900 * CreateDispTypeInfo [OLEAUT32.31]
7902 * Build type information for an object so it can be called through an
7903 * IDispatch interface.
7905 * RETURNS
7906 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7907 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7909 * NOTES
7910 * This call allows an objects methods to be accessed through IDispatch, by
7911 * building an ITypeInfo object that IDispatch can use to call through.
7913 HRESULT WINAPI CreateDispTypeInfo(
7914 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7915 LCID lcid, /* [I] Locale Id */
7916 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7918 ITypeInfoImpl *pTIClass, *pTIIface;
7919 ITypeLibImpl *pTypeLibImpl;
7920 unsigned int param, func;
7921 TLBFuncDesc *pFuncDesc;
7922 TLBRefType *ref;
7924 TRACE("\n");
7925 pTypeLibImpl = TypeLibImpl_Constructor();
7926 if (!pTypeLibImpl) return E_FAIL;
7928 pTypeLibImpl->TypeInfoCount = 2;
7929 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7931 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7932 pTIIface->pTypeLib = pTypeLibImpl;
7933 pTIIface->index = 0;
7934 pTIIface->Name = NULL;
7935 pTIIface->dwHelpContext = -1;
7936 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7937 pTIIface->TypeAttr.lcid = lcid;
7938 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7939 pTIIface->TypeAttr.wMajorVerNum = 0;
7940 pTIIface->TypeAttr.wMinorVerNum = 0;
7941 pTIIface->TypeAttr.cbAlignment = 2;
7942 pTIIface->TypeAttr.cbSizeInstance = -1;
7943 pTIIface->TypeAttr.cbSizeVft = -1;
7944 pTIIface->TypeAttr.cFuncs = 0;
7945 pTIIface->TypeAttr.cImplTypes = 0;
7946 pTIIface->TypeAttr.cVars = 0;
7947 pTIIface->TypeAttr.wTypeFlags = 0;
7948 pTIIface->hreftype = 0;
7950 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
7951 pFuncDesc = pTIIface->funcdescs;
7952 for(func = 0; func < pidata->cMembers; func++) {
7953 METHODDATA *md = pidata->pmethdata + func;
7954 pFuncDesc->Name = SysAllocString(md->szName);
7955 pFuncDesc->funcdesc.memid = md->dispid;
7956 pFuncDesc->funcdesc.lprgscode = NULL;
7957 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7958 pFuncDesc->funcdesc.invkind = md->wFlags;
7959 pFuncDesc->funcdesc.callconv = md->cc;
7960 pFuncDesc->funcdesc.cParams = md->cArgs;
7961 pFuncDesc->funcdesc.cParamsOpt = 0;
7962 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7963 pFuncDesc->funcdesc.cScodes = 0;
7964 pFuncDesc->funcdesc.wFuncFlags = 0;
7965 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7966 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7967 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7968 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7969 md->cArgs * sizeof(ELEMDESC));
7970 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7971 for(param = 0; param < md->cArgs; param++) {
7972 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7973 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7975 pFuncDesc->helpcontext = 0;
7976 pFuncDesc->HelpStringContext = 0;
7977 pFuncDesc->HelpString = NULL;
7978 pFuncDesc->Entry = NULL;
7979 list_init(&pFuncDesc->custdata_list);
7980 pTIIface->TypeAttr.cFuncs++;
7981 ++pFuncDesc;
7984 dump_TypeInfo(pTIIface);
7986 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7987 pTIClass->pTypeLib = pTypeLibImpl;
7988 pTIClass->index = 1;
7989 pTIClass->Name = NULL;
7990 pTIClass->dwHelpContext = -1;
7991 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7992 pTIClass->TypeAttr.lcid = lcid;
7993 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7994 pTIClass->TypeAttr.wMajorVerNum = 0;
7995 pTIClass->TypeAttr.wMinorVerNum = 0;
7996 pTIClass->TypeAttr.cbAlignment = 2;
7997 pTIClass->TypeAttr.cbSizeInstance = -1;
7998 pTIClass->TypeAttr.cbSizeVft = -1;
7999 pTIClass->TypeAttr.cFuncs = 0;
8000 pTIClass->TypeAttr.cImplTypes = 1;
8001 pTIClass->TypeAttr.cVars = 0;
8002 pTIClass->TypeAttr.wTypeFlags = 0;
8003 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8005 pTIClass->impltypes = TLBImplType_Alloc(1);
8007 ref = heap_alloc_zero(sizeof(*ref));
8008 ref->pImpTLInfo = TLB_REF_INTERNAL;
8009 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8011 dump_TypeInfo(pTIClass);
8013 *pptinfo = (ITypeInfo*)pTIClass;
8015 ITypeInfo_AddRef(*pptinfo);
8016 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8018 return S_OK;
8022 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8024 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8026 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
8029 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8031 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8033 return ITypeInfo_AddRef((ITypeInfo *)This);
8036 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8038 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8040 return ITypeInfo_Release((ITypeInfo *)This);
8043 static HRESULT WINAPI ITypeComp_fnBind(
8044 ITypeComp * iface,
8045 OLECHAR * szName,
8046 ULONG lHash,
8047 WORD wFlags,
8048 ITypeInfo ** ppTInfo,
8049 DESCKIND * pDescKind,
8050 BINDPTR * pBindPtr)
8052 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8053 const TLBFuncDesc *pFDesc;
8054 const TLBVarDesc *pVDesc;
8055 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8056 UINT fdc;
8058 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8060 *pDescKind = DESCKIND_NONE;
8061 pBindPtr->lpfuncdesc = NULL;
8062 *ppTInfo = NULL;
8064 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
8065 pFDesc = &This->funcdescs[fdc];
8066 if (!strcmpiW(pFDesc->Name, szName)) {
8067 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8068 break;
8069 else
8070 /* name found, but wrong flags */
8071 hr = TYPE_E_TYPEMISMATCH;
8075 if (fdc < This->TypeAttr.cFuncs)
8077 HRESULT hr = TLB_AllocAndInitFuncDesc(
8078 &pFDesc->funcdesc,
8079 &pBindPtr->lpfuncdesc,
8080 This->TypeAttr.typekind == TKIND_DISPATCH);
8081 if (FAILED(hr))
8082 return hr;
8083 *pDescKind = DESCKIND_FUNCDESC;
8084 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8085 ITypeInfo_AddRef(*ppTInfo);
8086 return S_OK;
8087 } else {
8088 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
8089 if(pVDesc){
8090 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8091 if (FAILED(hr))
8092 return hr;
8093 *pDescKind = DESCKIND_VARDESC;
8094 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8095 ITypeInfo_AddRef(*ppTInfo);
8096 return S_OK;
8099 /* FIXME: search each inherited interface, not just the first */
8100 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8101 /* recursive search */
8102 ITypeInfo *pTInfo;
8103 ITypeComp *pTComp;
8104 HRESULT hr;
8105 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8106 if (SUCCEEDED(hr))
8108 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8109 ITypeInfo_Release(pTInfo);
8111 if (SUCCEEDED(hr))
8113 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8114 ITypeComp_Release(pTComp);
8115 return hr;
8117 WARN("Could not search inherited interface!\n");
8119 if (hr == DISP_E_MEMBERNOTFOUND)
8120 hr = S_OK;
8121 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8122 return hr;
8125 static HRESULT WINAPI ITypeComp_fnBindType(
8126 ITypeComp * iface,
8127 OLECHAR * szName,
8128 ULONG lHash,
8129 ITypeInfo ** ppTInfo,
8130 ITypeComp ** ppTComp)
8132 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8134 /* strange behaviour (does nothing) but like the
8135 * original */
8137 if (!ppTInfo || !ppTComp)
8138 return E_POINTER;
8140 *ppTInfo = NULL;
8141 *ppTComp = NULL;
8143 return S_OK;
8146 static const ITypeCompVtbl tcompvt =
8149 ITypeComp_fnQueryInterface,
8150 ITypeComp_fnAddRef,
8151 ITypeComp_fnRelease,
8153 ITypeComp_fnBind,
8154 ITypeComp_fnBindType
8157 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8158 REFIID riid, void **object)
8160 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8162 return ITypeLib2_QueryInterface((ITypeLib2*)This, riid, object);
8165 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8167 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8169 return ITypeLib2_AddRef((ITypeLib2*)This);
8172 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8174 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8176 return ITypeLib2_Release((ITypeLib2*)This);
8179 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8180 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8182 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8183 ITypeInfoImpl *info;
8184 HRESULT hres;
8186 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8188 if (!ctinfo || !name)
8189 return E_INVALIDARG;
8191 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8192 if (info)
8193 return TYPE_E_NAMECONFLICT;
8195 if (This->typeinfos)
8196 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8197 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8198 else
8199 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8201 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8203 info->pTypeLib = This;
8204 info->Name = SysAllocString(name);
8205 info->index = This->TypeInfoCount;
8206 info->TypeAttr.typekind = kind;
8207 info->TypeAttr.cbAlignment = 4;
8209 switch(info->TypeAttr.typekind) {
8210 case TKIND_ENUM:
8211 case TKIND_INTERFACE:
8212 case TKIND_DISPATCH:
8213 case TKIND_COCLASS:
8214 info->TypeAttr.cbSizeInstance = 4;
8215 break;
8216 case TKIND_RECORD:
8217 case TKIND_UNION:
8218 info->TypeAttr.cbSizeInstance = 0;
8219 break;
8220 case TKIND_MODULE:
8221 info->TypeAttr.cbSizeInstance = 2;
8222 break;
8223 case TKIND_ALIAS:
8224 info->TypeAttr.cbSizeInstance = -0x75;
8225 break;
8226 default:
8227 FIXME("unrecognized typekind %d\n", info->TypeAttr.typekind);
8228 info->TypeAttr.cbSizeInstance = 0xdeadbeef;
8229 break;
8232 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8233 &IID_ICreateTypeInfo, (void **)ctinfo);
8234 if (FAILED(hres)) {
8235 SysFreeString(info->Name);
8236 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8237 return hres;
8240 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8242 ++This->TypeInfoCount;
8244 return S_OK;
8247 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8248 LPOLESTR name)
8250 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8252 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8254 if (!name)
8255 return E_INVALIDARG;
8257 SysFreeString(This->Name);
8258 This->Name = SysAllocString(name);
8260 return S_OK;
8263 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8264 WORD majorVerNum, WORD minorVerNum)
8266 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8268 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8270 This->LibAttr.wMajorVerNum = majorVerNum;
8271 This->LibAttr.wMinorVerNum = minorVerNum;
8273 return S_OK;
8276 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8277 REFGUID guid)
8279 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8281 TRACE("%p %s\n", This, debugstr_guid(guid));
8283 memcpy(&This->LibAttr.guid, guid, sizeof(GUID));
8285 return S_OK;
8288 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8289 LPOLESTR doc)
8291 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8293 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8295 if (!doc)
8296 return E_INVALIDARG;
8298 SysFreeString(This->DocString);
8299 This->DocString = SysAllocString(doc);
8301 return S_OK;
8304 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8305 LPOLESTR helpFileName)
8307 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8309 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8311 if (!helpFileName)
8312 return E_INVALIDARG;
8314 SysFreeString(This->HelpFile);
8315 This->HelpFile = SysAllocString(helpFileName);
8317 return S_OK;
8320 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8321 DWORD helpContext)
8323 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8325 TRACE("%p %d\n", This, helpContext);
8327 This->dwHelpContext = helpContext;
8329 return S_OK;
8332 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8333 LCID lcid)
8335 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8337 TRACE("%p %x\n", This, lcid);
8339 This->LibAttr.lcid = lcid;
8341 return S_OK;
8344 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8345 UINT libFlags)
8347 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8349 TRACE("%p %x\n", This, libFlags);
8351 This->LibAttr.wLibFlags = libFlags;
8353 return S_OK;
8356 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
8358 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8359 FIXME("%p - stub\n", This);
8360 return E_NOTIMPL;
8363 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
8364 LPOLESTR name)
8366 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8367 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
8368 return E_NOTIMPL;
8371 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
8372 REFGUID guid, VARIANT *varVal)
8374 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8375 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
8376 return E_NOTIMPL;
8379 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
8380 ULONG helpStringContext)
8382 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8383 FIXME("%p %u - stub\n", This, helpStringContext);
8384 return E_NOTIMPL;
8387 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
8388 LPOLESTR filename)
8390 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8391 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
8393 if (!filename)
8394 return E_INVALIDARG;
8396 SysFreeString(This->HelpStringDll);
8397 This->HelpStringDll = SysAllocString(filename);
8399 return S_OK;
8402 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
8403 ICreateTypeLib2_fnQueryInterface,
8404 ICreateTypeLib2_fnAddRef,
8405 ICreateTypeLib2_fnRelease,
8406 ICreateTypeLib2_fnCreateTypeInfo,
8407 ICreateTypeLib2_fnSetName,
8408 ICreateTypeLib2_fnSetVersion,
8409 ICreateTypeLib2_fnSetGuid,
8410 ICreateTypeLib2_fnSetDocString,
8411 ICreateTypeLib2_fnSetHelpFileName,
8412 ICreateTypeLib2_fnSetHelpContext,
8413 ICreateTypeLib2_fnSetLcid,
8414 ICreateTypeLib2_fnSetLibFlags,
8415 ICreateTypeLib2_fnSaveAllChanges,
8416 ICreateTypeLib2_fnDeleteTypeInfo,
8417 ICreateTypeLib2_fnSetCustData,
8418 ICreateTypeLib2_fnSetHelpStringContext,
8419 ICreateTypeLib2_fnSetHelpStringDll
8422 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
8423 REFIID riid, void **object)
8425 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8427 return ITypeInfo2_QueryInterface((ITypeInfo2*)This, riid, object);
8430 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
8432 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8434 return ITypeInfo2_AddRef((ITypeInfo2*)This);
8437 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
8439 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8441 return ITypeInfo2_Release((ITypeInfo2*)This);
8444 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
8445 REFGUID guid)
8447 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8449 TRACE("%p %s\n", This, debugstr_guid(guid));
8451 memcpy(&This->TypeAttr.guid, guid, sizeof(GUID));
8453 return S_OK;
8456 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
8457 UINT typeFlags)
8459 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8461 TRACE("%p %x\n", This, typeFlags);
8463 if (typeFlags & TYPEFLAG_FDUAL) {
8464 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
8465 ITypeLib *stdole;
8466 ITypeInfo *dispatch;
8467 HREFTYPE hreftype;
8468 HRESULT hres;
8470 hres = LoadTypeLib(stdole2tlb, &stdole);
8471 if(FAILED(hres))
8472 return hres;
8474 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
8475 ITypeLib_Release(stdole);
8476 if(FAILED(hres))
8477 return hres;
8479 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
8480 ITypeInfo_Release(dispatch);
8481 if(FAILED(hres))
8482 return hres;
8485 This->TypeAttr.wTypeFlags = typeFlags;
8487 return S_OK;
8490 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
8491 LPOLESTR doc)
8493 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8495 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8497 if (!doc)
8498 return E_INVALIDARG;
8500 SysFreeString(This->DocString);
8501 This->DocString = SysAllocString(doc);
8503 return S_OK;
8506 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
8507 DWORD helpContext)
8509 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8511 TRACE("%p %d\n", This, helpContext);
8513 This->dwHelpContext = helpContext;
8515 return S_OK;
8518 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
8519 WORD majorVerNum, WORD minorVerNum)
8521 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8523 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8525 This->TypeAttr.wMajorVerNum = majorVerNum;
8526 This->TypeAttr.wMinorVerNum = minorVerNum;
8528 return S_OK;
8531 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
8532 ITypeInfo *typeInfo, HREFTYPE *refType)
8534 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8535 UINT index;
8536 ITypeLib *container;
8537 TLBRefType *ref_type;
8538 TLBImpLib *implib;
8539 TYPEATTR *typeattr;
8540 TLIBATTR *libattr;
8541 HRESULT hres;
8543 TRACE("%p %p %p\n", This, typeInfo, refType);
8545 if (!typeInfo || !refType)
8546 return E_INVALIDARG;
8548 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
8549 if (FAILED(hres))
8550 return hres;
8552 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
8553 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
8555 ITypeLib_Release(container);
8557 *refType = target->hreftype;
8559 return S_OK;
8562 hres = ITypeLib_GetLibAttr(container, &libattr);
8563 if (FAILED(hres)) {
8564 ITypeLib_Release(container);
8565 return hres;
8568 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
8569 if(IsEqualGUID(&implib->guid, &libattr->guid) &&
8570 implib->lcid == libattr->lcid &&
8571 implib->wVersionMajor == libattr->wMajorVerNum &&
8572 implib->wVersionMinor == libattr->wMinorVerNum)
8573 break;
8576 if(&implib->entry == &This->pTypeLib->implib_list){
8577 implib = heap_alloc_zero(sizeof(TLBImpLib));
8579 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
8580 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
8581 implib->name = SysAllocString(our_container->path);
8582 }else{
8583 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
8584 libattr->wMinorVerNum, libattr->lcid, &implib->name);
8585 if(FAILED(hres)){
8586 implib->name = NULL;
8587 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
8591 implib->guid = libattr->guid;
8592 implib->lcid = libattr->lcid;
8593 implib->wVersionMajor = libattr->wMajorVerNum;
8594 implib->wVersionMinor = libattr->wMinorVerNum;
8596 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
8599 ITypeLib_ReleaseTLibAttr(container, libattr);
8600 ITypeLib_Release(container);
8602 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
8603 if (FAILED(hres))
8604 return hres;
8606 index = 0;
8607 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
8608 if(ref_type->index == TLB_REF_USE_GUID &&
8609 IsEqualGUID(&ref_type->guid, &typeattr->guid) &&
8610 ref_type->tkind == typeattr->typekind)
8611 break;
8612 ++index;
8615 if(&ref_type->entry == &This->pTypeLib->ref_list){
8616 ref_type = heap_alloc_zero(sizeof(TLBRefType));
8618 ref_type->tkind = typeattr->typekind;
8619 ref_type->pImpTLInfo = implib;
8620 ref_type->reference = index * sizeof(MSFT_ImpInfo);
8622 ref_type->index = TLB_REF_USE_GUID;
8624 ref_type->guid = typeattr->guid;
8626 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
8629 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
8631 *refType = ref_type->reference | 0x1;
8633 if(IsEqualGUID(&ref_type->guid, &IID_IDispatch))
8634 This->pTypeLib->dispatch_href = *refType;
8636 return S_OK;
8639 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
8640 UINT index, FUNCDESC *funcDesc)
8642 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8643 TLBFuncDesc tmp_func_desc, *func_desc;
8644 int buf_size, i;
8645 char *buffer;
8646 HRESULT hres;
8648 TRACE("%p %u %p\n", This, index, funcDesc);
8650 if (!funcDesc || funcDesc->oVft & 3)
8651 return E_INVALIDARG;
8653 switch (This->TypeAttr.typekind) {
8654 case TKIND_MODULE:
8655 if (funcDesc->funckind != FUNC_STATIC)
8656 return TYPE_E_BADMODULEKIND;
8657 break;
8658 case TKIND_DISPATCH:
8659 if (funcDesc->funckind != FUNC_DISPATCH)
8660 return TYPE_E_BADMODULEKIND;
8661 break;
8662 default:
8663 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
8664 return TYPE_E_BADMODULEKIND;
8667 if (index > This->TypeAttr.cFuncs)
8668 return TYPE_E_ELEMENTNOTFOUND;
8670 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
8671 !funcDesc->cParams)
8672 return TYPE_E_INCONSISTENTPROPFUNCS;
8674 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
8675 TLBFuncDesc_Constructor(&tmp_func_desc);
8677 tmp_func_desc.funcdesc = *funcDesc;
8679 if (tmp_func_desc.funcdesc.oVft != 0)
8680 tmp_func_desc.funcdesc.oVft |= 1;
8682 if (funcDesc->cScodes) {
8683 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
8684 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
8685 } else
8686 tmp_func_desc.funcdesc.lprgscode = NULL;
8688 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
8689 for (i = 0; i < funcDesc->cParams; ++i) {
8690 buf_size += sizeof(ELEMDESC);
8691 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
8693 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
8694 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
8696 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
8697 if (FAILED(hres)) {
8698 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8699 heap_free(tmp_func_desc.funcdesc.lprgscode);
8700 return hres;
8703 for (i = 0; i < funcDesc->cParams; ++i) {
8704 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
8705 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
8706 if (FAILED(hres)) {
8707 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8708 heap_free(tmp_func_desc.funcdesc.lprgscode);
8709 return hres;
8711 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
8712 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
8713 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
8714 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
8715 if (FAILED(hres)) {
8716 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
8717 heap_free(tmp_func_desc.funcdesc.lprgscode);
8718 return hres;
8723 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
8725 if (This->funcdescs) {
8726 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
8727 sizeof(TLBFuncDesc) * (This->TypeAttr.cFuncs + 1));
8729 if (index < This->TypeAttr.cFuncs) {
8730 memmove(This->funcdescs + index + 1, This->funcdescs + index,
8731 (This->TypeAttr.cFuncs - index) * sizeof(TLBFuncDesc));
8732 func_desc = This->funcdescs + index;
8733 } else
8734 func_desc = This->funcdescs + This->TypeAttr.cFuncs;
8736 /* move custdata lists to the new memory location */
8737 for(i = 0; i < This->TypeAttr.cFuncs + 1; ++i){
8738 if(index != i){
8739 TLBFuncDesc *fd = &This->funcdescs[i];
8740 if(fd->custdata_list.prev == fd->custdata_list.next)
8741 list_init(&fd->custdata_list);
8742 else{
8743 fd->custdata_list.prev->next = &fd->custdata_list;
8744 fd->custdata_list.next->prev = &fd->custdata_list;
8748 } else
8749 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
8751 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
8752 list_init(&func_desc->custdata_list);
8754 ++This->TypeAttr.cFuncs;
8756 return S_OK;
8759 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
8760 UINT index, HREFTYPE refType)
8762 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8763 TLBImplType *impl_type;
8765 TRACE("%p %u %d\n", This, index, refType);
8767 switch(This->TypeAttr.typekind){
8768 case TKIND_COCLASS: {
8769 if (index == -1) {
8770 FIXME("Unhandled index: -1\n");
8771 return E_NOTIMPL;
8774 if(index != This->TypeAttr.cImplTypes)
8775 return TYPE_E_ELEMENTNOTFOUND;
8777 break;
8779 case TKIND_INTERFACE:
8780 case TKIND_DISPATCH:
8781 if (index != 0 || This->TypeAttr.cImplTypes)
8782 return TYPE_E_ELEMENTNOTFOUND;
8783 break;
8784 default:
8785 FIXME("Unimplemented typekind: %d\n", This->TypeAttr.typekind);
8786 return E_NOTIMPL;
8789 if (This->impltypes){
8790 UINT i;
8792 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
8793 sizeof(TLBImplType) * (This->TypeAttr.cImplTypes + 1));
8795 if (index < This->TypeAttr.cImplTypes) {
8796 memmove(This->impltypes + index + 1, This->impltypes + index,
8797 (This->TypeAttr.cImplTypes - index) * sizeof(TLBImplType));
8798 impl_type = This->impltypes + index;
8799 } else
8800 impl_type = This->impltypes + This->TypeAttr.cImplTypes;
8802 /* move custdata lists to the new memory location */
8803 for(i = 0; i < This->TypeAttr.cImplTypes + 1; ++i){
8804 if(index != i){
8805 TLBImplType *it = &This->impltypes[i];
8806 if(it->custdata_list.prev == it->custdata_list.next)
8807 list_init(&it->custdata_list);
8808 else{
8809 it->custdata_list.prev->next = &it->custdata_list;
8810 it->custdata_list.next->prev = &it->custdata_list;
8814 } else
8815 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
8817 memset(impl_type, 0, sizeof(TLBImplType));
8818 TLBImplType_Constructor(impl_type);
8819 impl_type->hRef = refType;
8821 ++This->TypeAttr.cImplTypes;
8823 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
8824 This->TypeAttr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
8826 return S_OK;
8829 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
8830 UINT index, INT implTypeFlags)
8832 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8833 TLBImplType *impl_type = &This->impltypes[index];
8835 TRACE("%p %u %x\n", This, index, implTypeFlags);
8837 if (This->TypeAttr.typekind != TKIND_COCLASS)
8838 return TYPE_E_BADMODULEKIND;
8840 if (index >= This->TypeAttr.cImplTypes)
8841 return TYPE_E_ELEMENTNOTFOUND;
8843 impl_type->implflags = implTypeFlags;
8845 return S_OK;
8848 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
8849 WORD alignment)
8851 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8853 TRACE("%p %d\n", This, alignment);
8855 This->TypeAttr.cbAlignment = alignment;
8857 return S_OK;
8860 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
8861 LPOLESTR schema)
8863 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8865 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
8867 if (!schema)
8868 return E_INVALIDARG;
8870 SysFreeString(This->TypeAttr.lpstrSchema);
8871 This->TypeAttr.lpstrSchema = SysAllocString(schema);
8873 return S_OK;
8876 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
8877 UINT index, VARDESC *varDesc)
8879 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8880 FIXME("%p %u %p - stub\n", This, index, varDesc);
8881 return E_NOTIMPL;
8884 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
8885 UINT index, LPOLESTR *names, UINT numNames)
8887 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8888 TLBFuncDesc *func_desc = &This->funcdescs[index];
8889 int i;
8891 TRACE("%p %u %p %u\n", This, index, names, numNames);
8893 if (!names)
8894 return E_INVALIDARG;
8896 if (index >= This->TypeAttr.cFuncs || numNames == 0)
8897 return TYPE_E_ELEMENTNOTFOUND;
8899 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
8900 if(numNames > func_desc->funcdesc.cParams)
8901 return TYPE_E_ELEMENTNOTFOUND;
8902 } else
8903 if(numNames > func_desc->funcdesc.cParams + 1)
8904 return TYPE_E_ELEMENTNOTFOUND;
8906 for(i = 0; i < This->TypeAttr.cFuncs; ++i) {
8907 TLBFuncDesc *iter = &This->funcdescs[i];
8908 if (iter->Name && !strcmpW(iter->Name, *names)) {
8909 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
8910 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
8911 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
8912 continue;
8913 return TYPE_E_AMBIGUOUSNAME;
8917 SysFreeString(func_desc->Name);
8918 func_desc->Name = SysAllocString(*names);
8920 for (i = 1; i < numNames; ++i) {
8921 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
8922 SysFreeString(par_desc->Name);
8923 par_desc->Name = SysAllocString(*(names + i));
8926 return S_OK;
8929 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
8930 UINT index, LPOLESTR name)
8932 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8933 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
8934 return E_NOTIMPL;
8937 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
8938 TYPEDESC *tdescAlias)
8940 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8941 FIXME("%p %p - stub\n", This, tdescAlias);
8942 return E_NOTIMPL;
8945 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
8946 UINT index, LPOLESTR dllName, LPOLESTR procName)
8948 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8949 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
8950 return E_NOTIMPL;
8953 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
8954 UINT index, LPOLESTR docString)
8956 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8957 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
8958 return E_NOTIMPL;
8961 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
8962 UINT index, LPOLESTR docString)
8964 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8965 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
8966 return E_NOTIMPL;
8969 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
8970 UINT index, DWORD helpContext)
8972 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8973 TLBFuncDesc *func_desc = &This->funcdescs[index];
8975 TRACE("%p %u %d\n", This, index, helpContext);
8977 if(index >= This->TypeAttr.cFuncs)
8978 return TYPE_E_ELEMENTNOTFOUND;
8980 func_desc->helpcontext = helpContext;
8982 return S_OK;
8985 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
8986 UINT index, DWORD helpContext)
8988 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8989 FIXME("%p %u %d - stub\n", This, index, helpContext);
8990 return E_NOTIMPL;
8993 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
8994 UINT index, BSTR bstrMops)
8996 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
8997 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
8998 return E_NOTIMPL;
9001 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
9002 IDLDESC *idlDesc)
9004 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9006 TRACE("%p %p\n", This, idlDesc);
9008 if (!idlDesc)
9009 return E_INVALIDARG;
9011 This->TypeAttr.idldescType.dwReserved = idlDesc->dwReserved;
9012 This->TypeAttr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
9014 return S_OK;
9017 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
9019 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9020 FIXME("%p - stub\n", This);
9021 return E_NOTIMPL;
9024 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
9025 UINT index)
9027 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9028 FIXME("%p %u - stub\n", This, index);
9029 return E_NOTIMPL;
9032 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
9033 MEMBERID memid, INVOKEKIND invKind)
9035 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9036 FIXME("%p %x %d - stub\n", This, memid, invKind);
9037 return E_NOTIMPL;
9040 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
9041 UINT index)
9043 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9044 FIXME("%p %u - stub\n", This, index);
9045 return E_NOTIMPL;
9048 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
9049 MEMBERID memid)
9051 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9052 FIXME("%p %x - stub\n", This, memid);
9053 return E_NOTIMPL;
9056 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
9057 UINT index)
9059 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9060 FIXME("%p %u - stub\n", This, index);
9061 return E_NOTIMPL;
9064 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
9065 REFGUID guid, VARIANT *varVal)
9067 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9069 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
9071 if (!guid || !varVal)
9072 return E_INVALIDARG;
9074 return TLB_set_custdata(&This->custdata_list, guid, varVal);
9077 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
9078 UINT index, REFGUID guid, VARIANT *varVal)
9080 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9081 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9082 return E_NOTIMPL;
9085 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
9086 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
9088 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9089 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
9090 return E_NOTIMPL;
9093 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
9094 UINT index, REFGUID guid, VARIANT *varVal)
9096 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9097 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9098 return E_NOTIMPL;
9101 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
9102 UINT index, REFGUID guid, VARIANT *varVal)
9104 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9105 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
9106 return E_NOTIMPL;
9109 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
9110 ULONG helpStringContext)
9112 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9114 TRACE("%p %u\n", This, helpStringContext);
9116 This->dwHelpStringContext = helpStringContext;
9118 return S_OK;
9121 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
9122 UINT index, ULONG helpStringContext)
9124 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9125 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
9126 return E_NOTIMPL;
9129 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
9130 UINT index, ULONG helpStringContext)
9132 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9133 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
9134 return E_NOTIMPL;
9137 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
9139 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9140 FIXME("%p - stub\n", This);
9141 return E_NOTIMPL;
9144 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
9145 LPOLESTR name)
9147 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9149 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9151 if (!name)
9152 return E_INVALIDARG;
9154 SysFreeString(This->Name);
9155 This->Name = SysAllocString(name);
9157 return S_OK;
9160 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
9161 ICreateTypeInfo2_fnQueryInterface,
9162 ICreateTypeInfo2_fnAddRef,
9163 ICreateTypeInfo2_fnRelease,
9164 ICreateTypeInfo2_fnSetGuid,
9165 ICreateTypeInfo2_fnSetTypeFlags,
9166 ICreateTypeInfo2_fnSetDocString,
9167 ICreateTypeInfo2_fnSetHelpContext,
9168 ICreateTypeInfo2_fnSetVersion,
9169 ICreateTypeInfo2_fnAddRefTypeInfo,
9170 ICreateTypeInfo2_fnAddFuncDesc,
9171 ICreateTypeInfo2_fnAddImplType,
9172 ICreateTypeInfo2_fnSetImplTypeFlags,
9173 ICreateTypeInfo2_fnSetAlignment,
9174 ICreateTypeInfo2_fnSetSchema,
9175 ICreateTypeInfo2_fnAddVarDesc,
9176 ICreateTypeInfo2_fnSetFuncAndParamNames,
9177 ICreateTypeInfo2_fnSetVarName,
9178 ICreateTypeInfo2_fnSetTypeDescAlias,
9179 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
9180 ICreateTypeInfo2_fnSetFuncDocString,
9181 ICreateTypeInfo2_fnSetVarDocString,
9182 ICreateTypeInfo2_fnSetFuncHelpContext,
9183 ICreateTypeInfo2_fnSetVarHelpContext,
9184 ICreateTypeInfo2_fnSetMops,
9185 ICreateTypeInfo2_fnSetTypeIdldesc,
9186 ICreateTypeInfo2_fnLayOut,
9187 ICreateTypeInfo2_fnDeleteFuncDesc,
9188 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
9189 ICreateTypeInfo2_fnDeleteVarDesc,
9190 ICreateTypeInfo2_fnDeleteVarDescByMemId,
9191 ICreateTypeInfo2_fnDeleteImplType,
9192 ICreateTypeInfo2_fnSetCustData,
9193 ICreateTypeInfo2_fnSetFuncCustData,
9194 ICreateTypeInfo2_fnSetParamCustData,
9195 ICreateTypeInfo2_fnSetVarCustData,
9196 ICreateTypeInfo2_fnSetImplTypeCustData,
9197 ICreateTypeInfo2_fnSetHelpStringContext,
9198 ICreateTypeInfo2_fnSetFuncHelpStringContext,
9199 ICreateTypeInfo2_fnSetVarHelpStringContext,
9200 ICreateTypeInfo2_fnInvalidate,
9201 ICreateTypeInfo2_fnSetName