push 556f62bab943c37bb6cbad95a6ecb3d73e04a93f
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blob75a30d212fffc82d205230874fc9a84c0c6c1c42
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 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_min = -1;
178 HKEY hkey;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (wMaj == v_maj)
198 if (*wMin == v_min)
200 best_min = v_min;
201 break; /* exact match */
203 if (v_min > best_min) best_min = v_min;
206 len = sizeof(key_name);
208 RegCloseKey( hkey );
209 if (best_min >= 0)
211 *wMin = best_min;
212 return TRUE;
214 return FALSE;
217 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
218 /* buffer must be at least 60 characters long */
219 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
221 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
222 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
224 memcpy( buffer, TypelibW, sizeof(TypelibW) );
225 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
226 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
227 return buffer;
230 /* get the path of an interface key, in the form "Interface\\<guid>" */
231 /* buffer must be at least 50 characters long */
232 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
234 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
236 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
237 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
238 return buffer;
241 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
242 /* buffer must be at least 16 characters long */
243 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
245 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
246 static const WCHAR win16W[] = {'w','i','n','1','6',0};
247 static const WCHAR win32W[] = {'w','i','n','3','2',0};
249 sprintfW( buffer, LcidFormatW, lcid );
250 switch(syskind)
252 case SYS_WIN16: strcatW( buffer, win16W ); break;
253 case SYS_WIN32: strcatW( buffer, win32W ); break;
254 default:
255 TRACE("Typelib is for unsupported syskind %i\n", syskind);
256 return NULL;
258 return buffer;
261 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
264 /****************************************************************************
265 * QueryPathOfRegTypeLib [OLEAUT32.164]
267 * Gets the path to a registered type library.
269 * PARAMS
270 * guid [I] referenced guid
271 * wMaj [I] major version
272 * wMin [I] minor version
273 * lcid [I] locale id
274 * path [O] path of typelib
276 * RETURNS
277 * Success: S_OK.
278 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
279 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
280 * opened.
282 HRESULT WINAPI QueryPathOfRegTypeLib(
283 REFGUID guid,
284 WORD wMaj,
285 WORD wMin,
286 LCID lcid,
287 LPBSTR path )
289 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
290 LCID myLCID = lcid;
291 HKEY hkey;
292 WCHAR buffer[60];
293 WCHAR Path[MAX_PATH];
294 LONG res;
296 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
298 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
299 get_typelib_key( guid, wMaj, wMin, buffer );
301 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
302 if (res == ERROR_FILE_NOT_FOUND)
304 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
305 return TYPE_E_LIBNOTREGISTERED;
307 else if (res != ERROR_SUCCESS)
309 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
310 return TYPE_E_REGISTRYACCESS;
313 while (hr != S_OK)
315 LONG dwPathLen = sizeof(Path);
317 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
319 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
321 if (!lcid)
322 break;
323 else if (myLCID == lcid)
325 /* try with sub-langid */
326 myLCID = SUBLANGID(lcid);
328 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
330 /* try with system langid */
331 myLCID = 0;
333 else
335 break;
338 else
340 *path = SysAllocString( Path );
341 hr = S_OK;
344 RegCloseKey( hkey );
345 TRACE_(typelib)("-- 0x%08x\n", hr);
346 return hr;
349 /******************************************************************************
350 * CreateTypeLib [OLEAUT32.160] creates a typelib
352 * RETURNS
353 * Success: S_OK
354 * Failure: Status
356 HRESULT WINAPI CreateTypeLib(
357 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
359 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
360 return E_FAIL;
363 /******************************************************************************
364 * LoadTypeLib [OLEAUT32.161]
366 * Loads a type library
368 * PARAMS
369 * szFile [I] Name of file to load from.
370 * pptLib [O] Pointer that receives ITypeLib object on success.
372 * RETURNS
373 * Success: S_OK
374 * Failure: Status
376 * SEE
377 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
379 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
381 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
382 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
385 /******************************************************************************
386 * LoadTypeLibEx [OLEAUT32.183]
388 * Loads and optionally registers a type library
390 * RETURNS
391 * Success: S_OK
392 * Failure: Status
394 HRESULT WINAPI LoadTypeLibEx(
395 LPCOLESTR szFile, /* [in] Name of file to load from */
396 REGKIND regkind, /* [in] Specify kind of registration */
397 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
399 WCHAR szPath[MAX_PATH+1];
400 HRESULT res;
402 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
404 *pptLib = NULL;
406 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
408 if (SUCCEEDED(res))
409 switch(regkind)
411 case REGKIND_DEFAULT:
412 /* don't register typelibs supplied with full path. Experimentation confirms the following */
413 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
414 (szFile[0] && (szFile[1] == ':'))) break;
415 /* else fall-through */
417 case REGKIND_REGISTER:
418 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
420 IUnknown_Release(*pptLib);
421 *pptLib = 0;
423 break;
424 case REGKIND_NONE:
425 break;
428 TRACE(" returns %08x\n",res);
429 return res;
432 /******************************************************************************
433 * LoadRegTypeLib [OLEAUT32.162]
435 * Loads a registered type library.
437 * PARAMS
438 * rguid [I] GUID of the registered type library.
439 * wVerMajor [I] major version.
440 * wVerMinor [I] minor version.
441 * lcid [I] locale ID.
442 * ppTLib [O] pointer that receives an ITypeLib object on success.
444 * RETURNS
445 * Success: S_OK.
446 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
447 * LoadTypeLib.
449 HRESULT WINAPI LoadRegTypeLib(
450 REFGUID rguid,
451 WORD wVerMajor,
452 WORD wVerMinor,
453 LCID lcid,
454 ITypeLib **ppTLib)
456 BSTR bstr=NULL;
457 HRESULT res;
459 *ppTLib = NULL;
461 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
463 if(SUCCEEDED(res))
465 res= LoadTypeLib(bstr, ppTLib);
466 SysFreeString(bstr);
469 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
471 return res;
475 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
476 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
477 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
478 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
479 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
480 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
482 /******************************************************************************
483 * RegisterTypeLib [OLEAUT32.163]
484 * Adds information about a type library to the System Registry
485 * NOTES
486 * Docs: ITypeLib FAR * ptlib
487 * Docs: OLECHAR FAR* szFullPath
488 * Docs: OLECHAR FAR* szHelpDir
490 * RETURNS
491 * Success: S_OK
492 * Failure: Status
494 HRESULT WINAPI RegisterTypeLib(
495 ITypeLib * ptlib, /* [in] Pointer to the library*/
496 OLECHAR * szFullPath, /* [in] full Path of the library*/
497 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
498 may be NULL*/
500 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
501 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
502 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
503 HRESULT res;
504 TLIBATTR *attr;
505 WCHAR keyName[60];
506 WCHAR tmp[16];
507 HKEY key, subKey;
508 UINT types, tidx;
509 TYPEKIND kind;
510 DWORD disposition;
512 if (ptlib == NULL || szFullPath == NULL)
513 return E_INVALIDARG;
515 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
516 return E_FAIL;
518 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
520 res = S_OK;
521 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
522 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
524 LPOLESTR doc;
526 /* Set the human-readable name of the typelib */
527 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
529 if (RegSetValueExW(key, NULL, 0, REG_SZ,
530 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
531 res = E_FAIL;
533 SysFreeString(doc);
535 else
536 res = E_FAIL;
538 /* Make up the name of the typelib path subkey */
539 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
541 /* Create the typelib path subkey */
542 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
543 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
545 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
546 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
547 res = E_FAIL;
549 RegCloseKey(subKey);
551 else
552 res = E_FAIL;
554 /* Create the flags subkey */
555 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
556 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
558 /* FIXME: is %u correct? */
559 static const WCHAR formatW[] = {'%','u',0};
560 WCHAR buf[20];
561 sprintfW(buf, formatW, attr->wLibFlags);
562 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
563 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
564 res = E_FAIL;
566 RegCloseKey(subKey);
568 else
569 res = E_FAIL;
571 /* create the helpdir subkey */
572 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
573 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
575 BOOL freeHelpDir = FALSE;
576 OLECHAR* pIndexStr;
578 /* if we created a new key, and helpDir was null, set the helpdir
579 to the directory which contains the typelib. However,
580 if we just opened an existing key, we leave the helpdir alone */
581 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
582 szHelpDir = SysAllocString(szFullPath);
583 pIndexStr = strrchrW(szHelpDir, '\\');
584 if (pIndexStr) {
585 *pIndexStr = 0;
587 freeHelpDir = TRUE;
590 /* if we have an szHelpDir, set it! */
591 if (szHelpDir != NULL) {
592 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
594 res = E_FAIL;
598 /* tidy up */
599 if (freeHelpDir) SysFreeString(szHelpDir);
600 RegCloseKey(subKey);
602 } else {
603 res = E_FAIL;
606 RegCloseKey(key);
608 else
609 res = E_FAIL;
611 /* register OLE Automation-compatible interfaces for this typelib */
612 types = ITypeLib_GetTypeInfoCount(ptlib);
613 for (tidx=0; tidx<types; tidx++) {
614 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
615 LPOLESTR name = NULL;
616 ITypeInfo *tinfo = NULL;
618 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
620 switch (kind) {
621 case TKIND_INTERFACE:
622 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
623 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
624 break;
626 case TKIND_DISPATCH:
627 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
628 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
629 break;
631 default:
632 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
633 break;
636 if (tinfo) {
637 TYPEATTR *tattr = NULL;
638 ITypeInfo_GetTypeAttr(tinfo, &tattr);
640 if (tattr) {
641 TRACE_(typelib)("guid=%s, flags=%04x (",
642 debugstr_guid(&tattr->guid),
643 tattr->wTypeFlags);
645 if (TRACE_ON(typelib)) {
646 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
647 XX(FAPPOBJECT);
648 XX(FCANCREATE);
649 XX(FLICENSED);
650 XX(FPREDECLID);
651 XX(FHIDDEN);
652 XX(FCONTROL);
653 XX(FDUAL);
654 XX(FNONEXTENSIBLE);
655 XX(FOLEAUTOMATION);
656 XX(FRESTRICTED);
657 XX(FAGGREGATABLE);
658 XX(FREPLACEABLE);
659 XX(FDISPATCHABLE);
660 XX(FREVERSEBIND);
661 XX(FPROXY);
662 #undef XX
663 MESSAGE("\n");
666 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
668 /* register interface<->typelib coupling */
669 get_interface_key( &tattr->guid, keyName );
670 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
671 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
673 if (name)
674 RegSetValueExW(key, NULL, 0, REG_SZ,
675 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
677 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
678 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
679 RegSetValueExW(subKey, NULL, 0, REG_SZ,
680 (const BYTE *)PSOA, sizeof PSOA);
681 RegCloseKey(subKey);
684 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
685 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
686 RegSetValueExW(subKey, NULL, 0, REG_SZ,
687 (const BYTE *)PSOA, sizeof PSOA);
688 RegCloseKey(subKey);
691 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
692 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
694 WCHAR buffer[40];
695 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
696 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
698 StringFromGUID2(&attr->guid, buffer, 40);
699 RegSetValueExW(subKey, NULL, 0, REG_SZ,
700 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
701 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
702 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
703 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
704 RegCloseKey(subKey);
707 RegCloseKey(key);
711 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
714 ITypeInfo_Release(tinfo);
717 SysFreeString(name);
721 ITypeLib_ReleaseTLibAttr(ptlib, attr);
723 return res;
727 /******************************************************************************
728 * UnRegisterTypeLib [OLEAUT32.186]
729 * Removes information about a type library from the System Registry
730 * NOTES
732 * RETURNS
733 * Success: S_OK
734 * Failure: Status
736 HRESULT WINAPI UnRegisterTypeLib(
737 REFGUID libid, /* [in] Guid of the library */
738 WORD wVerMajor, /* [in] major version */
739 WORD wVerMinor, /* [in] minor version */
740 LCID lcid, /* [in] locale id */
741 SYSKIND syskind)
743 BSTR tlibPath = NULL;
744 DWORD tmpLength;
745 WCHAR keyName[60];
746 WCHAR subKeyName[50];
747 int result = S_OK;
748 DWORD i = 0;
749 BOOL deleteOtherStuff;
750 HKEY key = NULL;
751 HKEY subKey = NULL;
752 TYPEATTR* typeAttr = NULL;
753 TYPEKIND kind;
754 ITypeInfo* typeInfo = NULL;
755 ITypeLib* typeLib = NULL;
756 int numTypes;
758 TRACE("(IID: %s)\n",debugstr_guid(libid));
760 /* Create the path to the key */
761 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
763 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
765 TRACE("Unsupported syskind %i\n", syskind);
766 result = E_INVALIDARG;
767 goto end;
770 /* get the path to the typelib on disk */
771 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
772 result = E_INVALIDARG;
773 goto end;
776 /* Try and open the key to the type library. */
777 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
778 result = E_INVALIDARG;
779 goto end;
782 /* Try and load the type library */
783 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
784 result = TYPE_E_INVALIDSTATE;
785 goto end;
788 /* remove any types registered with this typelib */
789 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
790 for (i=0; i<numTypes; i++) {
791 /* get the kind of type */
792 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
793 goto enddeleteloop;
796 /* skip non-interfaces, and get type info for the type */
797 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
798 goto enddeleteloop;
800 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
801 goto enddeleteloop;
803 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
804 goto enddeleteloop;
807 /* the path to the type */
808 get_interface_key( &typeAttr->guid, subKeyName );
810 /* Delete its bits */
811 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
812 goto enddeleteloop;
814 RegDeleteKeyW(subKey, ProxyStubClsidW);
815 RegDeleteKeyW(subKey, ProxyStubClsid32W);
816 RegDeleteKeyW(subKey, TypeLibW);
817 RegCloseKey(subKey);
818 subKey = NULL;
819 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
821 enddeleteloop:
822 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
823 typeAttr = NULL;
824 if (typeInfo) ITypeInfo_Release(typeInfo);
825 typeInfo = NULL;
828 /* Now, delete the type library path subkey */
829 get_lcid_subkey( lcid, syskind, subKeyName );
830 RegDeleteKeyW(key, subKeyName);
831 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
832 RegDeleteKeyW(key, subKeyName);
834 /* check if there is anything besides the FLAGS/HELPDIR keys.
835 If there is, we don't delete them */
836 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
837 deleteOtherStuff = TRUE;
838 i = 0;
839 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
840 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
842 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
843 if (!strcmpW(subKeyName, FLAGSW)) continue;
844 if (!strcmpW(subKeyName, HELPDIRW)) continue;
845 deleteOtherStuff = FALSE;
846 break;
849 /* only delete the other parts of the key if we're absolutely sure */
850 if (deleteOtherStuff) {
851 RegDeleteKeyW(key, FLAGSW);
852 RegDeleteKeyW(key, HELPDIRW);
853 RegCloseKey(key);
854 key = NULL;
856 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
857 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
858 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
861 end:
862 SysFreeString(tlibPath);
863 if (typeLib) ITypeLib_Release(typeLib);
864 if (subKey) RegCloseKey(subKey);
865 if (key) RegCloseKey(key);
866 return result;
869 /*======================= ITypeLib implementation =======================*/
871 typedef struct tagTLBCustData
873 GUID guid;
874 VARIANT data;
875 struct tagTLBCustData* next;
876 } TLBCustData;
878 /* data structure for import typelibs */
879 typedef struct tagTLBImpLib
881 int offset; /* offset in the file (MSFT)
882 offset in nametable (SLTG)
883 just used to identify library while reading
884 data from file */
885 GUID guid; /* libid */
886 BSTR name; /* name */
888 LCID lcid; /* lcid of imported typelib */
890 WORD wVersionMajor; /* major version number */
891 WORD wVersionMinor; /* minor version number */
893 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
894 NULL if not yet loaded */
895 struct tagTLBImpLib * next;
896 } TLBImpLib;
898 /* internal ITypeLib data */
899 typedef struct tagITypeLibImpl
901 const ITypeLib2Vtbl *lpVtbl;
902 const ITypeCompVtbl *lpVtblTypeComp;
903 LONG ref;
904 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
906 /* strings can be stored in tlb as multibyte strings BUT they are *always*
907 * exported to the application as a UNICODE string.
909 BSTR Name;
910 BSTR DocString;
911 BSTR HelpFile;
912 BSTR HelpStringDll;
913 unsigned long dwHelpContext;
914 int TypeInfoCount; /* nr of typeinfo's in librarry */
915 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
916 int ctCustData; /* number of items in cust data list */
917 TLBCustData * pCustData; /* linked list to cust data */
918 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
919 int ctTypeDesc; /* number of items in type desc array */
920 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
921 library. Only used while reading MSFT
922 typelibs */
923 struct list ref_list; /* list of ref types in this typelib */
924 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
927 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
928 struct tagITypeLibImpl *next, *prev;
929 WCHAR *path;
930 INT index;
931 } ITypeLibImpl;
933 static const ITypeLib2Vtbl tlbvt;
934 static const ITypeCompVtbl tlbtcvt;
936 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
938 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
941 /* ITypeLib methods */
942 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
943 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
945 /*======================= ITypeInfo implementation =======================*/
947 /* data for referenced types */
948 typedef struct tagTLBRefType
950 INT index; /* Type index for internal ref or for external ref
951 it the format is SLTG. -2 indicates to
952 use guid */
954 GUID guid; /* guid of the referenced type */
955 /* if index == TLB_REF_USE_GUID */
957 HREFTYPE reference; /* The href of this ref */
958 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
959 TLB_REF_INTERNAL for internal refs
960 TLB_REF_NOT_FOUND for broken refs */
962 struct list entry;
963 } TLBRefType;
965 #define TLB_REF_USE_GUID -2
967 #define TLB_REF_INTERNAL (void*)-2
968 #define TLB_REF_NOT_FOUND (void*)-1
970 /* internal Parameter data */
971 typedef struct tagTLBParDesc
973 BSTR Name;
974 int ctCustData;
975 TLBCustData * pCustData; /* linked list to cust data */
976 } TLBParDesc;
978 /* internal Function data */
979 typedef struct tagTLBFuncDesc
981 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
982 BSTR Name; /* the name of this function */
983 TLBParDesc *pParamDesc; /* array with param names and custom data */
984 int helpcontext;
985 int HelpStringContext;
986 BSTR HelpString;
987 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
988 int ctCustData;
989 TLBCustData * pCustData; /* linked list to cust data; */
990 struct tagTLBFuncDesc * next;
991 } TLBFuncDesc;
993 /* internal Variable data */
994 typedef struct tagTLBVarDesc
996 VARDESC vardesc; /* lots of info on the variable and its attributes. */
997 BSTR Name; /* the name of this variable */
998 int HelpContext;
999 int HelpStringContext; /* FIXME: where? */
1000 BSTR HelpString;
1001 int ctCustData;
1002 TLBCustData * pCustData;/* linked list to cust data; */
1003 struct tagTLBVarDesc * next;
1004 } TLBVarDesc;
1006 /* internal implemented interface data */
1007 typedef struct tagTLBImplType
1009 HREFTYPE hRef; /* hRef of interface */
1010 int implflags; /* IMPLFLAG_*s */
1011 int ctCustData;
1012 TLBCustData * pCustData;/* linked list to custom data; */
1013 struct tagTLBImplType *next;
1014 } TLBImplType;
1016 /* internal TypeInfo data */
1017 typedef struct tagITypeInfoImpl
1019 const ITypeInfo2Vtbl *lpVtbl;
1020 const ITypeCompVtbl *lpVtblTypeComp;
1021 LONG ref;
1022 BOOL no_free_data; /* don't free data structures */
1023 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1024 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1025 int index; /* index in this typelib; */
1026 HREFTYPE hreftype; /* hreftype for app object binding */
1027 /* type libs seem to store the doc strings in ascii
1028 * so why should we do it in unicode?
1030 BSTR Name;
1031 BSTR DocString;
1032 BSTR DllName;
1033 unsigned long dwHelpContext;
1034 unsigned long dwHelpStringContext;
1036 /* functions */
1037 TLBFuncDesc * funclist; /* linked list with function descriptions */
1039 /* variables */
1040 TLBVarDesc * varlist; /* linked list with variable descriptions */
1042 /* Implemented Interfaces */
1043 TLBImplType * impltypelist;
1045 int ctCustData;
1046 TLBCustData * pCustData; /* linked list to cust data; */
1047 struct tagITypeInfoImpl * next;
1048 } ITypeInfoImpl;
1050 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1052 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1055 static const ITypeInfo2Vtbl tinfvt;
1056 static const ITypeCompVtbl tcompvt;
1058 static ITypeInfo2 * ITypeInfo_Constructor(void);
1060 typedef struct tagTLBContext
1062 unsigned int oStart; /* start of TLB in file */
1063 unsigned int pos; /* current pos */
1064 unsigned int length; /* total length */
1065 void *mapping; /* memory mapping */
1066 MSFT_SegDir * pTblDir;
1067 ITypeLibImpl* pLibInfo;
1068 } TLBContext;
1071 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1074 debug
1076 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1077 if (pTD->vt & VT_RESERVED)
1078 szVarType += strlen(strcpy(szVarType, "reserved | "));
1079 if (pTD->vt & VT_BYREF)
1080 szVarType += strlen(strcpy(szVarType, "ref to "));
1081 if (pTD->vt & VT_ARRAY)
1082 szVarType += strlen(strcpy(szVarType, "array of "));
1083 if (pTD->vt & VT_VECTOR)
1084 szVarType += strlen(strcpy(szVarType, "vector of "));
1085 switch(pTD->vt & VT_TYPEMASK) {
1086 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1087 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1088 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1089 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1090 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1091 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1092 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1093 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1094 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1095 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1096 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1097 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1098 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1099 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1100 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1101 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1102 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1103 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1104 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1105 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1106 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1107 pTD->u.hreftype); break;
1108 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1109 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1110 case VT_PTR: sprintf(szVarType, "ptr to ");
1111 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1112 break;
1113 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1114 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1115 break;
1116 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1117 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1118 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1119 break;
1121 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1125 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1126 char buf[200];
1127 USHORT flags = edesc->u.paramdesc.wParamFlags;
1128 dump_TypeDesc(&edesc->tdesc,buf);
1129 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1130 MESSAGE("\t\tu.paramdesc.wParamFlags");
1131 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1132 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1133 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1134 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1135 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1136 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1137 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1138 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1139 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1141 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1142 int i;
1143 MESSAGE("memid is %08x\n",funcdesc->memid);
1144 for (i=0;i<funcdesc->cParams;i++) {
1145 MESSAGE("Param %d:\n",i);
1146 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1148 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1149 switch (funcdesc->funckind) {
1150 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1151 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1152 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1153 case FUNC_STATIC: MESSAGE("static");break;
1154 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1155 default: MESSAGE("unknown");break;
1157 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1158 switch (funcdesc->invkind) {
1159 case INVOKE_FUNC: MESSAGE("func");break;
1160 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1161 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1162 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1164 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1165 switch (funcdesc->callconv) {
1166 case CC_CDECL: MESSAGE("cdecl");break;
1167 case CC_PASCAL: MESSAGE("pascal");break;
1168 case CC_STDCALL: MESSAGE("stdcall");break;
1169 case CC_SYSCALL: MESSAGE("syscall");break;
1170 default:break;
1172 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1173 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1174 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1176 MESSAGE("\telemdescFunc (return value type):\n");
1177 dump_ELEMDESC(&funcdesc->elemdescFunc);
1180 static const char * const typekind_desc[] =
1182 "TKIND_ENUM",
1183 "TKIND_RECORD",
1184 "TKIND_MODULE",
1185 "TKIND_INTERFACE",
1186 "TKIND_DISPATCH",
1187 "TKIND_COCLASS",
1188 "TKIND_ALIAS",
1189 "TKIND_UNION",
1190 "TKIND_MAX"
1193 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1195 int i;
1196 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1197 for (i=0;i<pfd->funcdesc.cParams;i++)
1198 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1201 dump_FUNCDESC(&(pfd->funcdesc));
1203 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1204 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1206 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1208 while (pfd)
1210 dump_TLBFuncDescOne(pfd);
1211 pfd = pfd->next;
1214 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1216 while (pvd)
1218 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1219 pvd = pvd->next;
1223 static void dump_TLBImpLib(const TLBImpLib *import)
1225 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1226 debugstr_w(import->name));
1227 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1228 import->wVersionMinor, import->lcid, import->offset);
1231 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1233 TLBRefType *ref;
1235 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1237 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1238 if(ref->index == -1)
1239 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1240 else
1241 TRACE_(typelib)("type no: %d\n", ref->index);
1243 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1245 TRACE_(typelib)("in lib\n");
1246 dump_TLBImpLib(ref->pImpTLInfo);
1251 static void dump_TLBImplType(const TLBImplType * impl)
1253 while (impl) {
1254 TRACE_(typelib)(
1255 "implementing/inheriting interface hRef = %x implflags %x\n",
1256 impl->hRef, impl->implflags);
1257 impl = impl->next;
1261 static void dump_Variant(const VARIANT * pvar)
1263 SYSTEMTIME st;
1265 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1267 if (pvar)
1269 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1270 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1272 TRACE(",%p", V_BYREF(pvar));
1274 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1276 TRACE(",%p", V_ARRAY(pvar));
1278 else switch (V_TYPE(pvar))
1280 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1281 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1282 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1283 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1284 case VT_INT:
1285 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1286 case VT_UINT:
1287 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1288 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1289 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1290 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1291 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1292 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1293 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1294 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1295 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1296 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1297 V_CY(pvar).s.Lo); break;
1298 case VT_DATE:
1299 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1300 TRACE(",<invalid>");
1301 else
1302 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1303 st.wHour, st.wMinute, st.wSecond);
1304 break;
1305 case VT_ERROR:
1306 case VT_VOID:
1307 case VT_USERDEFINED:
1308 case VT_EMPTY:
1309 case VT_NULL: break;
1310 default: TRACE(",?"); break;
1313 TRACE("}\n");
1316 static void dump_DispParms(const DISPPARAMS * pdp)
1318 unsigned int index;
1320 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1322 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1324 TRACE("named args:\n");
1325 for (index = 0; index < pdp->cNamedArgs; index++)
1326 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1329 if (pdp->cArgs && pdp->rgvarg)
1331 TRACE("args:\n");
1332 for (index = 0; index < pdp->cArgs; index++)
1333 dump_Variant( &pdp->rgvarg[index] );
1337 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1339 TRACE("%p ref=%u\n", pty, pty->ref);
1340 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1341 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1342 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1343 TRACE("fct:%u var:%u impl:%u\n",
1344 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1345 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1346 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1347 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1348 if (TRACE_ON(ole))
1349 dump_TLBFuncDesc(pty->funclist);
1350 dump_TLBVarDesc(pty->varlist);
1351 dump_TLBImplType(pty->impltypelist);
1354 static void dump_VARDESC(const VARDESC *v)
1356 MESSAGE("memid %d\n",v->memid);
1357 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1358 MESSAGE("oInst %d\n",v->u.oInst);
1359 dump_ELEMDESC(&(v->elemdescVar));
1360 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1361 MESSAGE("varkind %d\n",v->varkind);
1364 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1366 /* VT_LPWSTR is largest type that */
1367 /* may appear in type description*/
1368 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1369 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1370 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1371 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1372 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1373 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1374 {{0},30},{{0},31}
1377 static void TLB_abort(void)
1379 DebugBreak();
1382 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1383 static void * TLB_Alloc(unsigned size)
1385 void * ret;
1386 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1387 /* FIXME */
1388 ERR("cannot allocate memory\n");
1390 return ret;
1393 static void TLB_Free(void * ptr)
1395 HeapFree(GetProcessHeap(), 0, ptr);
1398 /* returns the size required for a deep copy of a typedesc into a
1399 * flat buffer */
1400 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1402 SIZE_T size = 0;
1404 if (alloc_initial_space)
1405 size += sizeof(TYPEDESC);
1407 switch (tdesc->vt)
1409 case VT_PTR:
1410 case VT_SAFEARRAY:
1411 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1412 break;
1413 case VT_CARRAY:
1414 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1415 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1416 break;
1418 return size;
1421 /* deep copy a typedesc into a flat buffer */
1422 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1424 if (!dest)
1426 dest = buffer;
1427 buffer = (char *)buffer + sizeof(TYPEDESC);
1430 *dest = *src;
1432 switch (src->vt)
1434 case VT_PTR:
1435 case VT_SAFEARRAY:
1436 dest->u.lptdesc = buffer;
1437 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1438 break;
1439 case VT_CARRAY:
1440 dest->u.lpadesc = buffer;
1441 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1442 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1443 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1444 break;
1446 return buffer;
1449 /* free custom data allocated by MSFT_CustData */
1450 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1452 TLBCustData *pCustDataNext;
1453 for (; pCustData; pCustData = pCustDataNext)
1455 VariantClear(&pCustData->data);
1457 pCustDataNext = pCustData->next;
1458 TLB_Free(pCustData);
1462 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1464 DWORD len;
1465 BSTR ret;
1467 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1468 ret = SysAllocStringLen(NULL, len - 1);
1469 if (!ret) return ret;
1470 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1471 return ret;
1474 /**********************************************************************
1476 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1478 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1480 return pcx->pos;
1483 static inline void MSFT_Seek(TLBContext *pcx, long where)
1485 if (where != DO_NOT_SEEK)
1487 where += pcx->oStart;
1488 if (where > pcx->length)
1490 /* FIXME */
1491 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1492 TLB_abort();
1494 pcx->pos = where;
1498 /* read function */
1499 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1501 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1502 pcx->pos, count, pcx->oStart, pcx->length, where);
1504 MSFT_Seek(pcx, where);
1505 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1506 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1507 pcx->pos += count;
1508 return count;
1511 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1512 long where )
1514 DWORD ret;
1516 ret = MSFT_Read(buffer, count, pcx, where);
1517 FromLEDWords(buffer, ret);
1519 return ret;
1522 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1523 long where )
1525 DWORD ret;
1527 ret = MSFT_Read(buffer, count, pcx, where);
1528 FromLEWords(buffer, ret);
1530 return ret;
1533 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1535 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1536 memset(pGuid,0, sizeof(GUID));
1537 return;
1539 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1540 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1541 pGuid->Data2 = FromLEWord(pGuid->Data2);
1542 pGuid->Data3 = FromLEWord(pGuid->Data3);
1543 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1546 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1548 MSFT_NameIntro niName;
1550 if (offset < 0)
1552 ERR_(typelib)("bad offset %d\n", offset);
1553 return -1;
1556 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1557 pcx->pTblDir->pNametab.offset+offset);
1559 return niName.hreftype;
1562 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1564 char * name;
1565 MSFT_NameIntro niName;
1566 int lengthInChars;
1567 BSTR bstrName = NULL;
1569 if (offset < 0)
1571 ERR_(typelib)("bad offset %d\n", offset);
1572 return NULL;
1574 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1575 pcx->pTblDir->pNametab.offset+offset);
1576 niName.namelen &= 0xFF; /* FIXME: correct ? */
1577 name=TLB_Alloc((niName.namelen & 0xff) +1);
1578 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1579 name[niName.namelen & 0xff]='\0';
1581 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1582 name, -1, NULL, 0);
1584 /* no invalid characters in string */
1585 if (lengthInChars)
1587 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1589 /* don't check for invalid character since this has been done previously */
1590 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1592 TLB_Free(name);
1594 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1595 return bstrName;
1598 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1600 char * string;
1601 INT16 length;
1602 int lengthInChars;
1603 BSTR bstr = NULL;
1605 if(offset<0) return NULL;
1606 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1607 if(length <= 0) return 0;
1608 string=TLB_Alloc(length +1);
1609 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1610 string[length]='\0';
1612 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1613 string, -1, NULL, 0);
1615 /* no invalid characters in string */
1616 if (lengthInChars)
1618 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1620 /* don't check for invalid character since this has been done previously */
1621 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1623 TLB_Free(string);
1625 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1626 return bstr;
1629 * read a value and fill a VARIANT structure
1631 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1633 int size;
1635 TRACE_(typelib)("\n");
1637 if(offset <0) { /* data are packed in here */
1638 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1639 V_I4(pVar) = offset & 0x3ffffff;
1640 return;
1642 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1643 pcx->pTblDir->pCustData.offset + offset );
1644 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1645 switch (V_VT(pVar)){
1646 case VT_EMPTY: /* FIXME: is this right? */
1647 case VT_NULL: /* FIXME: is this right? */
1648 case VT_I2 : /* this should not happen */
1649 case VT_I4 :
1650 case VT_R4 :
1651 case VT_ERROR :
1652 case VT_BOOL :
1653 case VT_I1 :
1654 case VT_UI1 :
1655 case VT_UI2 :
1656 case VT_UI4 :
1657 case VT_INT :
1658 case VT_UINT :
1659 case VT_VOID : /* FIXME: is this right? */
1660 case VT_HRESULT :
1661 size=4; break;
1662 case VT_R8 :
1663 case VT_CY :
1664 case VT_DATE :
1665 case VT_I8 :
1666 case VT_UI8 :
1667 case VT_DECIMAL : /* FIXME: is this right? */
1668 case VT_FILETIME :
1669 size=8;break;
1670 /* pointer types with known behaviour */
1671 case VT_BSTR :{
1672 char * ptr;
1673 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1674 if(size < 0) {
1675 char next;
1676 DWORD origPos = MSFT_Tell(pcx), nullPos;
1678 do {
1679 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1680 } while (next);
1681 nullPos = MSFT_Tell(pcx);
1682 size = nullPos - origPos;
1683 MSFT_Seek(pcx, origPos);
1685 ptr=TLB_Alloc(size);/* allocate temp buffer */
1686 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1687 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1688 /* FIXME: do we need a AtoW conversion here? */
1689 V_UNION(pVar, bstrVal[size])='\0';
1690 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1691 TLB_Free(ptr);
1693 size=-4; break;
1694 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1695 case VT_DISPATCH :
1696 case VT_VARIANT :
1697 case VT_UNKNOWN :
1698 case VT_PTR :
1699 case VT_SAFEARRAY :
1700 case VT_CARRAY :
1701 case VT_USERDEFINED :
1702 case VT_LPSTR :
1703 case VT_LPWSTR :
1704 case VT_BLOB :
1705 case VT_STREAM :
1706 case VT_STORAGE :
1707 case VT_STREAMED_OBJECT :
1708 case VT_STORED_OBJECT :
1709 case VT_BLOB_OBJECT :
1710 case VT_CF :
1711 case VT_CLSID :
1712 default:
1713 size=0;
1714 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1715 V_VT(pVar));
1718 if(size>0) /* (big|small) endian correct? */
1719 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1720 return;
1723 * create a linked list with custom data
1725 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1727 MSFT_CDGuid entry;
1728 TLBCustData* pNew;
1729 int count=0;
1731 TRACE_(typelib)("\n");
1733 while(offset >=0){
1734 count++;
1735 pNew=TLB_Alloc(sizeof(TLBCustData));
1736 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1737 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1738 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1739 /* add new custom data at head of the list */
1740 pNew->next=*ppCustData;
1741 *ppCustData=pNew;
1742 offset = entry.next;
1744 return count;
1747 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1748 ITypeInfoImpl *pTI)
1750 if(type <0)
1751 pTd->vt=type & VT_TYPEMASK;
1752 else
1753 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1755 if(pTd->vt == VT_USERDEFINED)
1756 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1758 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1761 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1763 /* resolve referenced type if any */
1764 while (lpTypeDesc)
1766 switch (lpTypeDesc->vt)
1768 case VT_PTR:
1769 lpTypeDesc = lpTypeDesc->u.lptdesc;
1770 break;
1772 case VT_CARRAY:
1773 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1774 break;
1776 case VT_USERDEFINED:
1777 MSFT_DoRefType(pcx, pTI->pTypeLib,
1778 lpTypeDesc->u.hreftype);
1780 lpTypeDesc = NULL;
1781 break;
1783 default:
1784 lpTypeDesc = NULL;
1789 static void
1790 MSFT_DoFuncs(TLBContext* pcx,
1791 ITypeInfoImpl* pTI,
1792 int cFuncs,
1793 int cVars,
1794 int offset,
1795 TLBFuncDesc** pptfd)
1798 * member information is stored in a data structure at offset
1799 * indicated by the memoffset field of the typeinfo structure
1800 * There are several distinctive parts.
1801 * The first part starts with a field that holds the total length
1802 * of this (first) part excluding this field. Then follow the records,
1803 * for each member there is one record.
1805 * The first entry is always the length of the record (including this
1806 * length word).
1807 * The rest of the record depends on the type of the member. If there is
1808 * a field indicating the member type (function, variable, interface, etc)
1809 * I have not found it yet. At this time we depend on the information
1810 * in the type info and the usual order how things are stored.
1812 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1813 * for each member;
1815 * Third is an equal sized array with file offsets to the name entry
1816 * of each member.
1818 * The fourth and last (?) part is an array with offsets to the records
1819 * in the first part of this file segment.
1822 int infolen, nameoffset, reclength, nrattributes, i;
1823 int recoffset = offset + sizeof(INT);
1825 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1826 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1827 TLBFuncDesc *ptfd_prev = NULL;
1829 TRACE_(typelib)("\n");
1831 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1833 for ( i = 0; i < cFuncs ; i++ )
1835 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1837 /* name, eventually add to a hash table */
1838 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1839 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1841 /* nameoffset is sometimes -1 on the second half of a propget/propput
1842 * pair of functions */
1843 if ((nameoffset == -1) && (i > 0))
1844 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1845 else
1846 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1848 /* read the function information record */
1849 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1851 reclength &= 0xffff;
1853 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1855 /* do the attributes */
1856 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1857 / sizeof(int);
1859 if ( nrattributes > 0 )
1861 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1863 if ( nrattributes > 1 )
1865 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1866 pFuncRec->OptAttr[1]) ;
1868 if ( nrattributes > 2 )
1870 if ( pFuncRec->FKCCIC & 0x2000 )
1872 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1873 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1874 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1876 else
1878 (*pptfd)->Entry = MSFT_ReadString(pcx,
1879 pFuncRec->OptAttr[2]);
1881 if( nrattributes > 5 )
1883 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1885 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1887 MSFT_CustData(pcx,
1888 pFuncRec->OptAttr[6],
1889 &(*pptfd)->pCustData);
1893 else
1895 (*pptfd)->Entry = (BSTR)-1;
1900 /* fill the FuncDesc Structure */
1901 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1902 offset + infolen + ( i + 1) * sizeof(INT));
1904 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1905 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1906 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1907 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1908 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1909 (*pptfd)->funcdesc.oVft = (pFuncRec->VtableOffset * sizeof(void *))/4;
1910 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1912 MSFT_GetTdesc(pcx,
1913 pFuncRec->DataType,
1914 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1915 pTI);
1916 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1918 /* do the parameters/arguments */
1919 if(pFuncRec->nrargs)
1921 int j = 0;
1922 MSFT_ParameterInfo paraminfo;
1924 (*pptfd)->funcdesc.lprgelemdescParam =
1925 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1927 (*pptfd)->pParamDesc =
1928 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1930 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1931 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1933 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1935 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1937 MSFT_GetTdesc(pcx,
1938 paraminfo.DataType,
1939 &elemdesc->tdesc,
1940 pTI);
1942 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1944 /* name */
1945 if (paraminfo.oName == -1)
1946 /* this occurs for [propput] or [propget] methods, so
1947 * we should just set the name of the parameter to the
1948 * name of the method. */
1949 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1950 else
1951 (*pptfd)->pParamDesc[j].Name =
1952 MSFT_ReadName( pcx, paraminfo.oName );
1953 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1955 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1957 /* default value */
1958 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1959 (pFuncRec->FKCCIC & 0x1000) )
1961 INT* pInt = (INT *)((char *)pFuncRec +
1962 reclength -
1963 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1965 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1967 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1968 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1970 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1971 pInt[j], pcx);
1973 else
1974 elemdesc->u.paramdesc.pparamdescex = NULL;
1975 /* custom info */
1976 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1978 MSFT_CustData(pcx,
1979 pFuncRec->OptAttr[7+j],
1980 &(*pptfd)->pParamDesc[j].pCustData);
1983 /* SEEK value = jump to offset,
1984 * from there jump to the end of record,
1985 * go back by (j-1) arguments
1987 MSFT_ReadLEDWords( &paraminfo ,
1988 sizeof(MSFT_ParameterInfo), pcx,
1989 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1990 * sizeof(MSFT_ParameterInfo)));
1994 /* scode is not used: archaic win16 stuff FIXME: right? */
1995 (*pptfd)->funcdesc.cScodes = 0 ;
1996 (*pptfd)->funcdesc.lprgscode = NULL ;
1998 ptfd_prev = *pptfd;
1999 pptfd = & ((*pptfd)->next);
2000 recoffset += reclength;
2002 HeapFree(GetProcessHeap(), 0, recbuf);
2005 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2006 int cVars, int offset, TLBVarDesc ** pptvd)
2008 int infolen, nameoffset, reclength;
2009 char recbuf[256];
2010 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2011 int i;
2012 int recoffset;
2014 TRACE_(typelib)("\n");
2016 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2017 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2018 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2019 recoffset += offset+sizeof(INT);
2020 for(i=0;i<cVars;i++){
2021 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2022 /* name, eventually add to a hash table */
2023 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2024 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2025 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2026 /* read the variable information record */
2027 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2028 reclength &=0xff;
2029 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2030 /* Optional data */
2031 if(reclength >(6*sizeof(INT)) )
2032 (*pptvd)->HelpContext=pVarRec->HelpContext;
2033 if(reclength >(7*sizeof(INT)) )
2034 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2035 if(reclength >(8*sizeof(INT)) )
2036 if(reclength >(9*sizeof(INT)) )
2037 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2038 /* fill the VarDesc Structure */
2039 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2040 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2041 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2042 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2043 MSFT_GetTdesc(pcx, pVarRec->DataType,
2044 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2045 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2046 if(pVarRec->VarKind == VAR_CONST ){
2047 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2048 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2049 pVarRec->OffsValue, pcx);
2050 } else
2051 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2052 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2053 pptvd=&((*pptvd)->next);
2054 recoffset += reclength;
2057 /* fill in data for a hreftype (offset). When the referenced type is contained
2058 * in the typelib, it's just an (file) offset in the type info base dir.
2059 * If comes from import, it's an offset+1 in the ImpInfo table
2060 * */
2061 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2062 int offset)
2064 TLBRefType *ref;
2066 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2068 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2070 if(ref->reference == offset) return;
2073 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2074 list_add_tail(&pTL->ref_list, &ref->entry);
2076 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2077 /* external typelib */
2078 MSFT_ImpInfo impinfo;
2079 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2081 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2083 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2084 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2085 while (pImpLib){ /* search the known offsets of all import libraries */
2086 if(pImpLib->offset==impinfo.oImpFile) break;
2087 pImpLib=pImpLib->next;
2089 if(pImpLib){
2090 ref->reference = offset;
2091 ref->pImpTLInfo = pImpLib;
2092 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2093 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2094 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2095 ref->index = TLB_REF_USE_GUID;
2096 } else
2097 ref->index = impinfo.oGuid;
2098 }else{
2099 ERR("Cannot find a reference\n");
2100 ref->reference = -1;
2101 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2103 }else{
2104 /* in this typelib */
2105 ref->index = MSFT_HREFTYPE_INDEX(offset);
2106 ref->reference = offset;
2107 ref->pImpTLInfo = TLB_REF_INTERNAL;
2111 /* process Implemented Interfaces of a com class */
2112 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2113 int offset)
2115 int i;
2116 MSFT_RefRecord refrec;
2117 TLBImplType **ppImpl = &pTI->impltypelist;
2119 TRACE_(typelib)("\n");
2121 for(i=0;i<count;i++){
2122 if(offset<0) break; /* paranoia */
2123 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2124 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2125 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2126 (*ppImpl)->hRef = refrec.reftype;
2127 (*ppImpl)->implflags=refrec.flags;
2128 (*ppImpl)->ctCustData=
2129 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2130 offset=refrec.onext;
2131 ppImpl=&((*ppImpl)->next);
2135 * process a typeinfo record
2137 static ITypeInfoImpl * MSFT_DoTypeInfo(
2138 TLBContext *pcx,
2139 int count,
2140 ITypeLibImpl * pLibInfo)
2142 MSFT_TypeInfoBase tiBase;
2143 ITypeInfoImpl *ptiRet;
2145 TRACE_(typelib)("count=%u\n", count);
2147 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2148 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2149 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2151 /* this is where we are coming from */
2152 ptiRet->pTypeLib = pLibInfo;
2153 ptiRet->index=count;
2154 /* fill in the typeattr fields */
2156 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2157 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2158 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2159 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2160 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2161 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2162 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2163 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2164 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2165 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2166 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2167 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2168 ptiRet->TypeAttr.cbSizeVft=(tiBase.cbSizeVft * sizeof(void *))/4; /* FIXME: this is only the non inherited part */
2169 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2170 MSFT_GetTdesc(pcx, tiBase.datatype1,
2171 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2173 /* FIXME: */
2174 /* IDLDESC idldescType; *//* never saw this one != zero */
2176 /* name, eventually add to a hash table */
2177 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2178 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2179 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2180 /* help info */
2181 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2182 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2183 ptiRet->dwHelpContext=tiBase.helpcontext;
2185 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2186 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2188 /* note: InfoType's Help file and HelpStringDll come from the containing
2189 * library. Further HelpString and Docstring appear to be the same thing :(
2191 /* functions */
2192 if(ptiRet->TypeAttr.cFuncs >0 )
2193 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2194 ptiRet->TypeAttr.cVars,
2195 tiBase.memoffset, & ptiRet->funclist);
2196 /* variables */
2197 if(ptiRet->TypeAttr.cVars >0 )
2198 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2199 ptiRet->TypeAttr.cVars,
2200 tiBase.memoffset, & ptiRet->varlist);
2201 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2202 switch(ptiRet->TypeAttr.typekind)
2204 case TKIND_COCLASS:
2205 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2206 tiBase.datatype1);
2207 break;
2208 case TKIND_DISPATCH:
2209 /* This is not -1 when the interface is a non-base dual interface or
2210 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2211 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2212 not this interface.
2215 if (tiBase.datatype1 != -1)
2217 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2218 ptiRet->impltypelist->hRef = tiBase.datatype1;
2219 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2221 break;
2222 default:
2223 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2224 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2225 ptiRet->impltypelist->hRef = tiBase.datatype1;
2226 break;
2229 ptiRet->ctCustData=
2230 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2232 TRACE_(typelib)("%s guid: %s kind:%s\n",
2233 debugstr_w(ptiRet->Name),
2234 debugstr_guid(&ptiRet->TypeAttr.guid),
2235 typekind_desc[ptiRet->TypeAttr.typekind]);
2236 if (TRACE_ON(typelib))
2237 dump_TypeInfo(ptiRet);
2239 return ptiRet;
2242 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2243 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2244 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2245 * tradeoff here.
2247 static ITypeLibImpl *tlb_cache_first;
2248 static CRITICAL_SECTION cache_section;
2249 static CRITICAL_SECTION_DEBUG cache_section_debug =
2251 0, 0, &cache_section,
2252 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2253 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2255 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2258 typedef struct TLB_PEFile
2260 const IUnknownVtbl *lpvtbl;
2261 LONG refs;
2262 HMODULE dll;
2263 HRSRC typelib_resource;
2264 HGLOBAL typelib_global;
2265 LPVOID typelib_base;
2266 } TLB_PEFile;
2268 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2270 if (IsEqualIID(riid, &IID_IUnknown))
2272 *ppv = iface;
2273 IUnknown_AddRef(iface);
2274 return S_OK;
2276 *ppv = NULL;
2277 return E_NOINTERFACE;
2280 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2282 TLB_PEFile *This = (TLB_PEFile *)iface;
2283 return InterlockedIncrement(&This->refs);
2286 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2288 TLB_PEFile *This = (TLB_PEFile *)iface;
2289 ULONG refs = InterlockedDecrement(&This->refs);
2290 if (!refs)
2292 if (This->typelib_global)
2293 FreeResource(This->typelib_global);
2294 if (This->dll)
2295 FreeLibrary(This->dll);
2296 HeapFree(GetProcessHeap(), 0, This);
2298 return refs;
2301 static const IUnknownVtbl TLB_PEFile_Vtable =
2303 TLB_PEFile_QueryInterface,
2304 TLB_PEFile_AddRef,
2305 TLB_PEFile_Release
2308 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2310 TLB_PEFile *This;
2312 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2313 if (!This)
2314 return E_OUTOFMEMORY;
2316 This->lpvtbl = &TLB_PEFile_Vtable;
2317 This->refs = 1;
2318 This->dll = NULL;
2319 This->typelib_resource = NULL;
2320 This->typelib_global = NULL;
2321 This->typelib_base = NULL;
2323 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2324 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2326 if (This->dll)
2328 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2329 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2330 if (This->typelib_resource)
2332 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2333 if (This->typelib_global)
2335 This->typelib_base = LockResource(This->typelib_global);
2337 if (This->typelib_base)
2339 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2340 *ppBase = This->typelib_base;
2341 *ppFile = (IUnknown *)&This->lpvtbl;
2342 return S_OK;
2348 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2349 return TYPE_E_CANTLOADLIBRARY;
2352 typedef struct TLB_NEFile
2354 const IUnknownVtbl *lpvtbl;
2355 LONG refs;
2356 LPVOID typelib_base;
2357 } TLB_NEFile;
2359 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2361 if (IsEqualIID(riid, &IID_IUnknown))
2363 *ppv = iface;
2364 IUnknown_AddRef(iface);
2365 return S_OK;
2367 *ppv = NULL;
2368 return E_NOINTERFACE;
2371 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2373 TLB_NEFile *This = (TLB_NEFile *)iface;
2374 return InterlockedIncrement(&This->refs);
2377 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2379 TLB_NEFile *This = (TLB_NEFile *)iface;
2380 ULONG refs = InterlockedDecrement(&This->refs);
2381 if (!refs)
2383 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2384 HeapFree(GetProcessHeap(), 0, This);
2386 return refs;
2389 static const IUnknownVtbl TLB_NEFile_Vtable =
2391 TLB_NEFile_QueryInterface,
2392 TLB_NEFile_AddRef,
2393 TLB_NEFile_Release
2396 /***********************************************************************
2397 * read_xx_header [internal]
2399 static int read_xx_header( HFILE lzfd )
2401 IMAGE_DOS_HEADER mzh;
2402 char magic[3];
2404 LZSeek( lzfd, 0, SEEK_SET );
2405 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2406 return 0;
2407 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2408 return 0;
2410 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2411 if ( 2 != LZRead( lzfd, magic, 2 ) )
2412 return 0;
2414 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2416 if ( magic[0] == 'N' && magic[1] == 'E' )
2417 return IMAGE_OS2_SIGNATURE;
2418 if ( magic[0] == 'P' && magic[1] == 'E' )
2419 return IMAGE_NT_SIGNATURE;
2421 magic[2] = '\0';
2422 WARN("Can't handle %s files.\n", magic );
2423 return 0;
2427 /***********************************************************************
2428 * find_ne_resource [internal]
2430 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2431 DWORD *resLen, DWORD *resOff )
2433 IMAGE_OS2_HEADER nehd;
2434 NE_TYPEINFO *typeInfo;
2435 NE_NAMEINFO *nameInfo;
2436 DWORD nehdoffset;
2437 LPBYTE resTab;
2438 DWORD resTabSize;
2439 int count;
2441 /* Read in NE header */
2442 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2443 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2445 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2446 if ( !resTabSize )
2448 TRACE("No resources in NE dll\n" );
2449 return FALSE;
2452 /* Read in resource table */
2453 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2454 if ( !resTab ) return FALSE;
2456 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2457 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2459 HeapFree( GetProcessHeap(), 0, resTab );
2460 return FALSE;
2463 /* Find resource */
2464 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2466 if (HIWORD(typeid) != 0) /* named type */
2468 BYTE len = strlen( typeid );
2469 while (typeInfo->type_id)
2471 if (!(typeInfo->type_id & 0x8000))
2473 BYTE *p = resTab + typeInfo->type_id;
2474 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2476 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2477 typeInfo->count * sizeof(NE_NAMEINFO));
2480 else /* numeric type id */
2482 WORD id = LOWORD(typeid) | 0x8000;
2483 while (typeInfo->type_id)
2485 if (typeInfo->type_id == id) goto found_type;
2486 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2487 typeInfo->count * sizeof(NE_NAMEINFO));
2490 TRACE("No typeid entry found for %p\n", typeid );
2491 HeapFree( GetProcessHeap(), 0, resTab );
2492 return FALSE;
2494 found_type:
2495 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2497 if (HIWORD(resid) != 0) /* named resource */
2499 BYTE len = strlen( resid );
2500 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2502 BYTE *p = resTab + nameInfo->id;
2503 if (nameInfo->id & 0x8000) continue;
2504 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2507 else /* numeric resource id */
2509 WORD id = LOWORD(resid) | 0x8000;
2510 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2511 if (nameInfo->id == id) goto found_name;
2513 TRACE("No resid entry found for %p\n", typeid );
2514 HeapFree( GetProcessHeap(), 0, resTab );
2515 return FALSE;
2517 found_name:
2518 /* Return resource data */
2519 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2520 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2522 HeapFree( GetProcessHeap(), 0, resTab );
2523 return TRUE;
2526 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2528 HFILE lzfd = -1;
2529 OFSTRUCT ofs;
2530 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2531 TLB_NEFile *This = NULL;
2533 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2534 if (!This) return E_OUTOFMEMORY;
2536 This->lpvtbl = &TLB_NEFile_Vtable;
2537 This->refs = 1;
2538 This->typelib_base = NULL;
2540 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2541 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2543 DWORD reslen, offset;
2544 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2546 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2547 if( !This->typelib_base )
2548 hr = E_OUTOFMEMORY;
2549 else
2551 LZSeek( lzfd, offset, SEEK_SET );
2552 reslen = LZRead( lzfd, This->typelib_base, reslen );
2553 LZClose( lzfd );
2554 *ppBase = This->typelib_base;
2555 *pdwTLBLength = reslen;
2556 *ppFile = (IUnknown *)&This->lpvtbl;
2557 return S_OK;
2562 if( lzfd >= 0) LZClose( lzfd );
2563 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2564 return hr;
2567 typedef struct TLB_Mapping
2569 const IUnknownVtbl *lpvtbl;
2570 LONG refs;
2571 HANDLE file;
2572 HANDLE mapping;
2573 LPVOID typelib_base;
2574 } TLB_Mapping;
2576 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2578 if (IsEqualIID(riid, &IID_IUnknown))
2580 *ppv = iface;
2581 IUnknown_AddRef(iface);
2582 return S_OK;
2584 *ppv = NULL;
2585 return E_NOINTERFACE;
2588 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2590 TLB_Mapping *This = (TLB_Mapping *)iface;
2591 return InterlockedIncrement(&This->refs);
2594 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2596 TLB_Mapping *This = (TLB_Mapping *)iface;
2597 ULONG refs = InterlockedDecrement(&This->refs);
2598 if (!refs)
2600 if (This->typelib_base)
2601 UnmapViewOfFile(This->typelib_base);
2602 if (This->mapping)
2603 CloseHandle(This->mapping);
2604 if (This->file != INVALID_HANDLE_VALUE)
2605 CloseHandle(This->file);
2606 HeapFree(GetProcessHeap(), 0, This);
2608 return refs;
2611 static const IUnknownVtbl TLB_Mapping_Vtable =
2613 TLB_Mapping_QueryInterface,
2614 TLB_Mapping_AddRef,
2615 TLB_Mapping_Release
2618 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2620 TLB_Mapping *This;
2622 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2623 if (!This)
2624 return E_OUTOFMEMORY;
2626 This->lpvtbl = &TLB_Mapping_Vtable;
2627 This->refs = 1;
2628 This->file = INVALID_HANDLE_VALUE;
2629 This->mapping = NULL;
2630 This->typelib_base = NULL;
2632 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2633 if (INVALID_HANDLE_VALUE != This->file)
2635 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2636 if (This->mapping)
2638 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2639 if(This->typelib_base)
2641 /* retrieve file size */
2642 *pdwTLBLength = GetFileSize(This->file, NULL);
2643 *ppBase = This->typelib_base;
2644 *ppFile = (IUnknown *)&This->lpvtbl;
2645 return S_OK;
2650 IUnknown_Release((IUnknown *)&This->lpvtbl);
2651 return TYPE_E_CANTLOADLIBRARY;
2654 /****************************************************************************
2655 * TLB_ReadTypeLib
2657 * find the type of the typelib file and map the typelib resource into
2658 * the memory
2660 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2661 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2662 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2664 ITypeLibImpl *entry;
2665 HRESULT ret;
2666 INT index = 1;
2667 LPWSTR index_str, file = (LPWSTR)pszFileName;
2668 LPVOID pBase = NULL;
2669 DWORD dwTLBLength = 0;
2670 IUnknown *pFile = NULL;
2672 *ppTypeLib = NULL;
2674 index_str = strrchrW(pszFileName, '\\');
2675 if(index_str && *++index_str != '\0')
2677 LPWSTR end_ptr;
2678 long idx = strtolW(index_str, &end_ptr, 10);
2679 if(*end_ptr == '\0')
2681 int str_len = index_str - pszFileName - 1;
2682 index = idx;
2683 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2684 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2685 file[str_len] = 0;
2689 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2691 if(strchrW(file, '\\'))
2693 lstrcpyW(pszPath, file);
2695 else
2697 int len = GetSystemDirectoryW(pszPath, cchPath);
2698 pszPath[len] = '\\';
2699 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2703 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2705 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2707 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2708 EnterCriticalSection(&cache_section);
2709 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2711 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2713 TRACE("cache hit\n");
2714 *ppTypeLib = (ITypeLib2*)entry;
2715 ITypeLib_AddRef(*ppTypeLib);
2716 LeaveCriticalSection(&cache_section);
2717 return S_OK;
2720 LeaveCriticalSection(&cache_section);
2722 /* now actually load and parse the typelib */
2724 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2725 if (ret == TYPE_E_CANTLOADLIBRARY)
2726 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2727 if (ret == TYPE_E_CANTLOADLIBRARY)
2728 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2729 if (SUCCEEDED(ret))
2731 if (dwTLBLength >= 4)
2733 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2734 if (dwSignature == MSFT_SIGNATURE)
2735 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2736 else if (dwSignature == SLTG_SIGNATURE)
2737 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2738 else
2740 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2741 ret = TYPE_E_CANTLOADLIBRARY;
2744 else
2745 ret = TYPE_E_CANTLOADLIBRARY;
2746 IUnknown_Release(pFile);
2749 if(*ppTypeLib) {
2750 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2752 TRACE("adding to cache\n");
2753 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2754 lstrcpyW(impl->path, pszPath);
2755 /* We should really canonicalise the path here. */
2756 impl->index = index;
2758 /* FIXME: check if it has added already in the meantime */
2759 EnterCriticalSection(&cache_section);
2760 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2761 impl->prev = NULL;
2762 tlb_cache_first = impl;
2763 LeaveCriticalSection(&cache_section);
2764 ret = S_OK;
2765 } else
2766 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2768 return ret;
2771 /*================== ITypeLib(2) Methods ===================================*/
2773 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2775 ITypeLibImpl* pTypeLibImpl;
2777 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2778 if (!pTypeLibImpl) return NULL;
2780 pTypeLibImpl->lpVtbl = &tlbvt;
2781 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2782 pTypeLibImpl->ref = 1;
2784 list_init(&pTypeLibImpl->ref_list);
2785 pTypeLibImpl->dispatch_href = -1;
2787 return pTypeLibImpl;
2790 /****************************************************************************
2791 * ITypeLib2_Constructor_MSFT
2793 * loading an MSFT typelib from an in-memory image
2795 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2797 TLBContext cx;
2798 long lPSegDir;
2799 MSFT_Header tlbHeader;
2800 MSFT_SegDir tlbSegDir;
2801 ITypeLibImpl * pTypeLibImpl;
2803 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2805 pTypeLibImpl = TypeLibImpl_Constructor();
2806 if (!pTypeLibImpl) return NULL;
2808 /* get pointer to beginning of typelib data */
2809 cx.pos = 0;
2810 cx.oStart=0;
2811 cx.mapping = pLib;
2812 cx.pLibInfo = pTypeLibImpl;
2813 cx.length = dwTLBLength;
2815 /* read header */
2816 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2817 TRACE_(typelib)("header:\n");
2818 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2819 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2820 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2821 return NULL;
2823 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2825 /* there is a small amount of information here until the next important
2826 * part:
2827 * the segment directory . Try to calculate the amount of data */
2828 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2830 /* now read the segment directory */
2831 TRACE("read segment directory (at %ld)\n",lPSegDir);
2832 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2833 cx.pTblDir = &tlbSegDir;
2835 /* just check two entries */
2836 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2838 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2839 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2840 return NULL;
2843 /* now fill our internal data */
2844 /* TLIBATTR fields */
2845 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2847 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2848 /* Windows seems to have zero here, is this correct? */
2849 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2850 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2851 else
2852 pTypeLibImpl->LibAttr.lcid = 0;
2854 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2855 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2856 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2857 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2859 /* name, eventually add to a hash table */
2860 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2862 /* help info */
2863 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2864 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2866 if( tlbHeader.varflags & HELPDLLFLAG)
2868 int offset;
2869 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2870 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2873 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2875 /* custom data */
2876 if(tlbHeader.CustomDataOffset >= 0)
2878 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2881 /* fill in type descriptions */
2882 if(tlbSegDir.pTypdescTab.length > 0)
2884 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2885 INT16 td[4];
2886 pTypeLibImpl->ctTypeDesc = cTD;
2887 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2888 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2889 for(i=0; i<cTD; )
2891 /* FIXME: add several sanity checks here */
2892 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2893 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2895 /* FIXME: check safearray */
2896 if(td[3] < 0)
2897 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2898 else
2899 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2901 else if(td[0] == VT_CARRAY)
2903 /* array descr table here */
2904 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2906 else if(td[0] == VT_USERDEFINED)
2908 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2910 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2913 /* second time around to fill the array subscript info */
2914 for(i=0;i<cTD;i++)
2916 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2917 if(tlbSegDir.pArrayDescriptions.offset>0)
2919 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2920 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2922 if(td[1]<0)
2923 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2924 else
2925 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2927 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2929 for(j = 0; j<td[2]; j++)
2931 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2932 sizeof(INT), &cx, DO_NOT_SEEK);
2933 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2934 sizeof(INT), &cx, DO_NOT_SEEK);
2937 else
2939 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2940 ERR("didn't find array description data\n");
2945 /* imported type libs */
2946 if(tlbSegDir.pImpFiles.offset>0)
2948 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2949 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2950 UINT16 size;
2952 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2954 char *name;
2956 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2957 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2958 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2960 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2961 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2962 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2963 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2965 size >>= 2;
2966 name = TLB_Alloc(size+1);
2967 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2968 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2970 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2971 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2973 ppImpLib = &(*ppImpLib)->next;
2977 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2978 if(pTypeLibImpl->dispatch_href != -1)
2979 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2981 /* type info's */
2982 if(tlbHeader.nrtypeinfos >= 0 )
2984 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2985 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2986 int i;
2988 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2990 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2992 ppTI = &((*ppTI)->next);
2993 (pTypeLibImpl->TypeInfoCount)++;
2997 TRACE("(%p)\n", pTypeLibImpl);
2998 return (ITypeLib2*) pTypeLibImpl;
3002 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3004 char b[3];
3005 int i;
3006 short s;
3008 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3009 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3010 return FALSE;
3013 guid->Data4[0] = s >> 8;
3014 guid->Data4[1] = s & 0xff;
3016 b[2] = '\0';
3017 for(i = 0; i < 6; i++) {
3018 memcpy(b, str + 24 + 2 * i, 2);
3019 guid->Data4[i + 2] = strtol(b, NULL, 16);
3021 return TRUE;
3024 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3026 WORD bytelen;
3027 DWORD len;
3029 *pBstr = NULL;
3030 bytelen = *(const WORD*)ptr;
3031 if(bytelen == 0xffff) return 2;
3032 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3033 *pBstr = SysAllocStringLen(NULL, len - 1);
3034 if (*pBstr)
3035 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3036 return bytelen + 2;
3039 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3041 WORD bytelen;
3043 *str = NULL;
3044 bytelen = *(const WORD*)ptr;
3045 if(bytelen == 0xffff) return 2;
3046 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3047 memcpy(*str, ptr + 2, bytelen);
3048 (*str)[bytelen] = '\0';
3049 return bytelen + 2;
3052 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3054 char *ptr = pLibBlk;
3055 WORD w;
3057 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3058 FIXME("libblk magic = %04x\n", w);
3059 return 0;
3062 ptr += 6;
3063 if((w = *(WORD*)ptr) != 0xffff) {
3064 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3065 ptr += w;
3067 ptr += 2;
3069 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3071 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3073 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3074 ptr += 4;
3076 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3077 ptr += 2;
3079 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3080 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3081 else
3082 pTypeLibImpl->LibAttr.lcid = 0;
3083 ptr += 2;
3085 ptr += 4; /* skip res12 */
3087 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3088 ptr += 2;
3090 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3091 ptr += 2;
3093 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3094 ptr += 2;
3096 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3097 ptr += sizeof(GUID);
3099 return ptr - (char*)pLibBlk;
3102 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3103 typedef struct
3105 unsigned int num;
3106 HREFTYPE refs[1];
3107 } sltg_ref_lookup_t;
3109 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3110 HREFTYPE *typelib_ref)
3112 if(typeinfo_ref < table->num)
3114 *typelib_ref = table->refs[typeinfo_ref];
3115 return S_OK;
3118 ERR_(typelib)("Unable to find reference\n");
3119 *typelib_ref = -1;
3120 return E_FAIL;
3123 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3125 BOOL done = FALSE;
3127 while(!done) {
3128 if((*pType & 0xe00) == 0xe00) {
3129 pTD->vt = VT_PTR;
3130 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3131 sizeof(TYPEDESC));
3132 pTD = pTD->u.lptdesc;
3134 switch(*pType & 0x3f) {
3135 case VT_PTR:
3136 pTD->vt = VT_PTR;
3137 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3138 sizeof(TYPEDESC));
3139 pTD = pTD->u.lptdesc;
3140 break;
3142 case VT_USERDEFINED:
3143 pTD->vt = VT_USERDEFINED;
3144 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3145 done = TRUE;
3146 break;
3148 case VT_CARRAY:
3150 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3151 array */
3153 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3155 pTD->vt = VT_CARRAY;
3156 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3157 sizeof(ARRAYDESC) +
3158 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3159 pTD->u.lpadesc->cDims = pSA->cDims;
3160 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3161 pSA->cDims * sizeof(SAFEARRAYBOUND));
3163 pTD = &pTD->u.lpadesc->tdescElem;
3164 break;
3167 case VT_SAFEARRAY:
3169 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3170 useful? */
3172 pType++;
3173 pTD->vt = VT_SAFEARRAY;
3174 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3175 sizeof(TYPEDESC));
3176 pTD = pTD->u.lptdesc;
3177 break;
3179 default:
3180 pTD->vt = *pType & 0x3f;
3181 done = TRUE;
3182 break;
3184 pType++;
3186 return pType;
3189 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3190 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3192 /* Handle [in/out] first */
3193 if((*pType & 0xc000) == 0xc000)
3194 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3195 else if(*pType & 0x8000)
3196 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3197 else if(*pType & 0x4000)
3198 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3199 else
3200 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3202 if(*pType & 0x2000)
3203 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3205 if(*pType & 0x80)
3206 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3208 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3212 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3213 char *pNameTable)
3215 unsigned int ref;
3216 char *name;
3217 TLBRefType *ref_type;
3218 sltg_ref_lookup_t *table;
3219 HREFTYPE typelib_ref;
3221 if(pRef->magic != SLTG_REF_MAGIC) {
3222 FIXME("Ref magic = %x\n", pRef->magic);
3223 return NULL;
3225 name = ( (char*)pRef->names + pRef->number);
3227 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3228 table->num = pRef->number >> 3;
3230 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3232 /* We don't want the first href to be 0 */
3233 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3235 for(ref = 0; ref < pRef->number >> 3; ref++) {
3236 char *refname;
3237 unsigned int lib_offs, type_num;
3239 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3241 name += SLTG_ReadStringA(name, &refname);
3242 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3243 FIXME_(typelib)("Can't sscanf ref\n");
3244 if(lib_offs != 0xffff) {
3245 TLBImpLib **import = &pTL->pImpLibs;
3247 while(*import) {
3248 if((*import)->offset == lib_offs)
3249 break;
3250 import = &(*import)->next;
3252 if(!*import) {
3253 char fname[MAX_PATH+1];
3254 int len;
3256 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3257 sizeof(**import));
3258 (*import)->offset = lib_offs;
3259 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3260 &(*import)->guid);
3261 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3262 &(*import)->wVersionMajor,
3263 &(*import)->wVersionMinor,
3264 &(*import)->lcid, fname) != 4) {
3265 FIXME_(typelib)("can't sscanf ref %s\n",
3266 pNameTable + lib_offs + 40);
3268 len = strlen(fname);
3269 if(fname[len-1] != '#')
3270 FIXME("fname = %s\n", fname);
3271 fname[len-1] = '\0';
3272 (*import)->name = TLB_MultiByteToBSTR(fname);
3274 ref_type->pImpTLInfo = *import;
3276 /* Store a reference to IDispatch */
3277 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3278 pTL->dispatch_href = typelib_ref;
3280 } else { /* internal ref */
3281 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3283 ref_type->reference = typelib_ref;
3284 ref_type->index = type_num;
3286 HeapFree(GetProcessHeap(), 0, refname);
3287 list_add_tail(&pTL->ref_list, &ref_type->entry);
3289 table->refs[ref] = typelib_ref;
3290 typelib_ref += 4;
3292 if((BYTE)*name != SLTG_REF_MAGIC)
3293 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3294 dump_TLBRefType(pTL);
3295 return table;
3298 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3299 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3301 SLTG_ImplInfo *info;
3302 TLBImplType **ppImplType = &pTI->impltypelist;
3303 /* I don't really get this structure, usually it's 0x16 bytes
3304 long, but iuser.tlb contains some that are 0x18 bytes long.
3305 That's ok because we can use the next ptr to jump to the next
3306 one. But how do we know the length of the last one? The WORD
3307 at offs 0x8 might be the clue. For now I'm just assuming that
3308 the last one is the regular 0x16 bytes. */
3310 info = (SLTG_ImplInfo*)pBlk;
3311 while(1) {
3312 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3313 sizeof(**ppImplType));
3314 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3315 (*ppImplType)->implflags = info->impltypeflags;
3316 pTI->TypeAttr.cImplTypes++;
3317 ppImplType = &(*ppImplType)->next;
3319 if(info->next == 0xffff)
3320 break;
3321 if(OneOnly)
3322 FIXME_(typelib)("Interface inheriting more than one interface\n");
3323 info = (SLTG_ImplInfo*)(pBlk + info->next);
3325 info++; /* see comment at top of function */
3326 return (char*)info;
3329 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3330 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3332 TLBVarDesc **ppVarDesc = &pTI->varlist;
3333 BSTR bstrPrevName = NULL;
3334 SLTG_Variable *pItem;
3335 unsigned short i;
3336 WORD *pType;
3338 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3339 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3341 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3342 sizeof(**ppVarDesc));
3343 (*ppVarDesc)->vardesc.memid = pItem->memid;
3345 if (pItem->magic != SLTG_VAR_MAGIC &&
3346 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3347 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3348 return;
3351 if (pItem->name == 0xfffe)
3352 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3353 else
3354 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3356 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3357 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3358 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3360 if(pItem->flags & 0x02)
3361 pType = &pItem->type;
3362 else
3363 pType = (WORD*)(pBlk + pItem->type);
3365 if (pItem->flags & ~0xda)
3366 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3368 SLTG_DoElem(pType, pBlk,
3369 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3371 if (TRACE_ON(typelib)) {
3372 char buf[300];
3373 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3374 TRACE_(typelib)("elemdescVar: %s\n", buf);
3377 if (pItem->flags & 0x40) {
3378 TRACE_(typelib)("VAR_DISPATCH\n");
3379 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3381 else if (pItem->flags & 0x10) {
3382 TRACE_(typelib)("VAR_CONST\n");
3383 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3384 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3385 sizeof(VARIANT));
3386 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3387 if (pItem->flags & 0x08)
3388 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3389 else {
3390 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3392 case VT_LPSTR:
3393 case VT_LPWSTR:
3394 case VT_BSTR:
3396 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3397 BSTR str;
3398 TRACE_(typelib)("len = %u\n", len);
3399 if (len == 0xffff) {
3400 str = NULL;
3401 } else {
3402 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3403 str = SysAllocStringLen(NULL, alloc_len);
3404 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3406 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3407 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3408 break;
3410 case VT_I2:
3411 case VT_UI2:
3412 case VT_I4:
3413 case VT_UI4:
3414 case VT_INT:
3415 case VT_UINT:
3416 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3417 *(INT*)(pBlk + pItem->byte_offs);
3418 break;
3419 default:
3420 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3424 else {
3425 TRACE_(typelib)("VAR_PERINSTANCE\n");
3426 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3427 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3430 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3431 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3433 if (pItem->flags & 0x80)
3434 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3436 bstrPrevName = (*ppVarDesc)->Name;
3437 ppVarDesc = &((*ppVarDesc)->next);
3439 pTI->TypeAttr.cVars = cVars;
3442 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3443 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3445 SLTG_Function *pFunc;
3446 unsigned short i;
3447 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3449 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3450 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3452 int param;
3453 WORD *pType, *pArg;
3455 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3456 sizeof(**ppFuncDesc));
3458 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3459 case SLTG_FUNCTION_MAGIC:
3460 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3461 break;
3462 case SLTG_DISPATCH_FUNCTION_MAGIC:
3463 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3464 break;
3465 case SLTG_STATIC_FUNCTION_MAGIC:
3466 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3467 break;
3468 default:
3469 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3470 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3471 *ppFuncDesc = NULL;
3472 return;
3474 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3476 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3477 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3478 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3479 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3480 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3481 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3483 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3484 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3486 if(pFunc->retnextopt & 0x80)
3487 pType = &pFunc->rettype;
3488 else
3489 pType = (WORD*)(pBlk + pFunc->rettype);
3491 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3493 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3494 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3495 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3496 (*ppFuncDesc)->pParamDesc =
3497 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3498 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3500 pArg = (WORD*)(pBlk + pFunc->arg_off);
3502 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3503 char *paramName = pNameTable + *pArg;
3504 BOOL HaveOffs;
3505 /* If arg type follows then paramName points to the 2nd
3506 letter of the name, else the next WORD is an offset to
3507 the arg type and paramName points to the first letter.
3508 So let's take one char off paramName and see if we're
3509 pointing at an alpha-numeric char. However if *pArg is
3510 0xffff or 0xfffe then the param has no name, the former
3511 meaning that the next WORD is the type, the latter
3512 meaning that the next WORD is an offset to the type. */
3514 HaveOffs = FALSE;
3515 if(*pArg == 0xffff)
3516 paramName = NULL;
3517 else if(*pArg == 0xfffe) {
3518 paramName = NULL;
3519 HaveOffs = TRUE;
3521 else if(paramName[-1] && !isalnum(paramName[-1]))
3522 HaveOffs = TRUE;
3524 pArg++;
3526 if(HaveOffs) { /* the next word is an offset to type */
3527 pType = (WORD*)(pBlk + *pArg);
3528 SLTG_DoElem(pType, pBlk,
3529 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3530 pArg++;
3531 } else {
3532 if(paramName)
3533 paramName--;
3534 pArg = SLTG_DoElem(pArg, pBlk,
3535 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3538 /* Are we an optional param ? */
3539 if((*ppFuncDesc)->funcdesc.cParams - param <=
3540 (*ppFuncDesc)->funcdesc.cParamsOpt)
3541 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3543 if(paramName) {
3544 (*ppFuncDesc)->pParamDesc[param].Name =
3545 TLB_MultiByteToBSTR(paramName);
3546 } else {
3547 (*ppFuncDesc)->pParamDesc[param].Name =
3548 SysAllocString((*ppFuncDesc)->Name);
3552 ppFuncDesc = &((*ppFuncDesc)->next);
3553 if(pFunc->next == 0xffff) break;
3555 pTI->TypeAttr.cFuncs = cFuncs;
3558 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3559 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3560 SLTG_TypeInfoTail *pTITail)
3562 char *pFirstItem;
3563 sltg_ref_lookup_t *ref_lookup = NULL;
3565 if(pTIHeader->href_table != 0xffffffff) {
3566 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3567 pNameTable);
3570 pFirstItem = pBlk;
3572 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3573 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3575 HeapFree(GetProcessHeap(), 0, ref_lookup);
3579 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3580 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3581 const SLTG_TypeInfoTail *pTITail)
3583 char *pFirstItem;
3584 sltg_ref_lookup_t *ref_lookup = NULL;
3586 if(pTIHeader->href_table != 0xffffffff) {
3587 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3588 pNameTable);
3591 pFirstItem = pBlk;
3593 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3594 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3597 if (pTITail->funcs_off != 0xffff)
3598 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3600 HeapFree(GetProcessHeap(), 0, ref_lookup);
3602 if (TRACE_ON(typelib))
3603 dump_TLBFuncDesc(pTI->funclist);
3606 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3607 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3608 const SLTG_TypeInfoTail *pTITail)
3610 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3613 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3614 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3615 const SLTG_TypeInfoTail *pTITail)
3617 WORD *pType;
3618 sltg_ref_lookup_t *ref_lookup = NULL;
3620 if (pTITail->simple_alias) {
3621 /* if simple alias, no more processing required */
3622 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3623 return;
3626 if(pTIHeader->href_table != 0xffffffff) {
3627 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3628 pNameTable);
3631 /* otherwise it is an offset to a type */
3632 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3634 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3636 HeapFree(GetProcessHeap(), 0, ref_lookup);
3639 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3640 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3641 const SLTG_TypeInfoTail *pTITail)
3643 sltg_ref_lookup_t *ref_lookup = NULL;
3644 if (pTIHeader->href_table != 0xffffffff)
3645 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3646 pNameTable);
3648 if (pTITail->vars_off != 0xffff)
3649 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3651 if (pTITail->funcs_off != 0xffff)
3652 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3654 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3655 * of dispinterface functions including the IDispatch ones, so
3656 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3657 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3659 HeapFree(GetProcessHeap(), 0, ref_lookup);
3660 if (TRACE_ON(typelib))
3661 dump_TLBFuncDesc(pTI->funclist);
3664 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3665 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3666 const SLTG_TypeInfoTail *pTITail)
3668 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3671 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3672 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3673 const SLTG_TypeInfoTail *pTITail)
3675 sltg_ref_lookup_t *ref_lookup = NULL;
3676 if (pTIHeader->href_table != 0xffffffff)
3677 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3678 pNameTable);
3680 if (pTITail->vars_off != 0xffff)
3681 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3683 if (pTITail->funcs_off != 0xffff)
3684 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3685 HeapFree(GetProcessHeap(), 0, ref_lookup);
3686 if (TRACE_ON(typelib))
3687 dump_TypeInfo(pTI);
3690 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3691 managable copy of it into this */
3692 typedef struct {
3693 WORD small_no;
3694 char *index_name;
3695 char *other_name;
3696 WORD res1a;
3697 WORD name_offs;
3698 WORD more_bytes;
3699 char *extra;
3700 WORD res20;
3701 DWORD helpcontext;
3702 WORD res26;
3703 GUID uuid;
3704 } SLTG_InternalOtherTypeInfo;
3706 /****************************************************************************
3707 * ITypeLib2_Constructor_SLTG
3709 * loading a SLTG typelib from an in-memory image
3711 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3713 ITypeLibImpl *pTypeLibImpl;
3714 SLTG_Header *pHeader;
3715 SLTG_BlkEntry *pBlkEntry;
3716 SLTG_Magic *pMagic;
3717 SLTG_Index *pIndex;
3718 SLTG_Pad9 *pPad9;
3719 LPVOID pBlk, pFirstBlk;
3720 SLTG_LibBlk *pLibBlk;
3721 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3722 char *pAfterOTIBlks = NULL;
3723 char *pNameTable, *ptr;
3724 int i;
3725 DWORD len, order;
3726 ITypeInfoImpl **ppTypeInfoImpl;
3728 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3731 pTypeLibImpl = TypeLibImpl_Constructor();
3732 if (!pTypeLibImpl) return NULL;
3734 pHeader = pLib;
3736 TRACE_(typelib)("header:\n");
3737 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3738 pHeader->nrOfFileBlks );
3739 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3740 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3741 pHeader->SLTG_magic);
3742 return NULL;
3745 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3746 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3748 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3749 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3751 /* Next we have a magic block */
3752 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3754 /* Let's see if we're still in sync */
3755 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3756 sizeof(SLTG_COMPOBJ_MAGIC))) {
3757 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3758 return NULL;
3760 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3761 sizeof(SLTG_DIR_MAGIC))) {
3762 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3763 return NULL;
3766 pIndex = (SLTG_Index*)(pMagic+1);
3768 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3770 pFirstBlk = pPad9 + 1;
3772 /* We'll set up a ptr to the main library block, which is the last one. */
3774 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3775 pBlkEntry[order].next != 0;
3776 order = pBlkEntry[order].next - 1, i++) {
3777 pBlk = (char*)pBlk + pBlkEntry[order].len;
3779 pLibBlk = pBlk;
3781 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3783 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3784 interspersed */
3786 len += 0x40;
3788 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3790 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3791 sizeof(*pOtherTypeInfoBlks) *
3792 pTypeLibImpl->TypeInfoCount);
3795 ptr = (char*)pLibBlk + len;
3797 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3798 WORD w, extra;
3799 len = 0;
3801 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3803 w = *(WORD*)(ptr + 2);
3804 if(w != 0xffff) {
3805 len += w;
3806 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3807 w+1);
3808 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3809 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3811 w = *(WORD*)(ptr + 4 + len);
3812 if(w != 0xffff) {
3813 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3814 len += w;
3815 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3816 w+1);
3817 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3818 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3820 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3821 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3822 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3823 if(extra) {
3824 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3825 extra);
3826 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3827 len += extra;
3829 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3830 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3831 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3832 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3833 len += sizeof(SLTG_OtherTypeInfo);
3834 ptr += len;
3837 pAfterOTIBlks = ptr;
3839 /* Skip this WORD and get the next DWORD */
3840 len = *(DWORD*)(pAfterOTIBlks + 2);
3842 /* Now add this to pLibBLk look at what we're pointing at and
3843 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3844 dust and we should be pointing at the beginning of the name
3845 table */
3847 pNameTable = (char*)pLibBlk + len;
3849 switch(*(WORD*)pNameTable) {
3850 case 0xffff:
3851 break;
3852 case 0x0200:
3853 pNameTable += 0x20;
3854 break;
3855 default:
3856 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3857 break;
3860 pNameTable += 0x216;
3862 pNameTable += 2;
3864 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3866 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3869 /* Hopefully we now have enough ptrs set up to actually read in
3870 some TypeInfos. It's not clear which order to do them in, so
3871 I'll just follow the links along the BlkEntry chain and read
3872 them in the order in which they are in the file */
3874 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3876 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3877 pBlkEntry[order].next != 0;
3878 order = pBlkEntry[order].next - 1, i++) {
3880 SLTG_TypeInfoHeader *pTIHeader;
3881 SLTG_TypeInfoTail *pTITail;
3882 SLTG_MemberHeader *pMemHeader;
3884 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3885 pOtherTypeInfoBlks[i].index_name)) {
3886 FIXME_(typelib)("Index strings don't match\n");
3887 return NULL;
3890 pTIHeader = pBlk;
3891 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3892 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3893 return NULL;
3895 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3896 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3897 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3899 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3900 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3901 (*ppTypeInfoImpl)->index = i;
3902 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3903 pOtherTypeInfoBlks[i].name_offs +
3904 pNameTable);
3905 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3906 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3907 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3908 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3909 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3910 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3911 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3913 if((pTIHeader->typeflags1 & 7) != 2)
3914 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3915 if(pTIHeader->typeflags3 != 2)
3916 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3918 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3919 debugstr_w((*ppTypeInfoImpl)->Name),
3920 typekind_desc[pTIHeader->typekind],
3921 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3922 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3924 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3926 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3928 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3929 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3930 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = (pTITail->cbSizeVft * sizeof(void *))/4;
3932 switch(pTIHeader->typekind) {
3933 case TKIND_ENUM:
3934 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3935 pTIHeader, pTITail);
3936 break;
3938 case TKIND_RECORD:
3939 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3940 pTIHeader, pTITail);
3941 break;
3943 case TKIND_INTERFACE:
3944 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3945 pTIHeader, pTITail);
3946 break;
3948 case TKIND_COCLASS:
3949 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3950 pTIHeader, pTITail);
3951 break;
3953 case TKIND_ALIAS:
3954 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3955 pTIHeader, pTITail);
3956 break;
3958 case TKIND_DISPATCH:
3959 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3960 pTIHeader, pTITail);
3961 break;
3963 case TKIND_MODULE:
3964 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3965 pTIHeader, pTITail);
3966 break;
3968 default:
3969 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3970 break;
3974 /* could get cFuncs, cVars and cImplTypes from here
3975 but we've already set those */
3976 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3977 X(06);
3978 X(16);
3979 X(18);
3980 X(1a);
3981 X(1e);
3982 X(24);
3983 X(26);
3984 X(2a);
3985 X(2c);
3986 X(2e);
3987 X(30);
3988 X(32);
3989 X(34);
3990 #undef X
3991 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3992 pBlk = (char*)pBlk + pBlkEntry[order].len;
3995 if(i != pTypeLibImpl->TypeInfoCount) {
3996 FIXME("Somehow processed %d TypeInfos\n", i);
3997 return NULL;
4000 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4001 return (ITypeLib2*)pTypeLibImpl;
4004 /* ITypeLib::QueryInterface
4006 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4007 ITypeLib2 * iface,
4008 REFIID riid,
4009 VOID **ppvObject)
4011 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4013 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4015 *ppvObject=NULL;
4016 if(IsEqualIID(riid, &IID_IUnknown) ||
4017 IsEqualIID(riid,&IID_ITypeLib)||
4018 IsEqualIID(riid,&IID_ITypeLib2))
4020 *ppvObject = This;
4023 if(*ppvObject)
4025 ITypeLib2_AddRef(iface);
4026 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4027 return S_OK;
4029 TRACE("-- Interface: E_NOINTERFACE\n");
4030 return E_NOINTERFACE;
4033 /* ITypeLib::AddRef
4035 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4037 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4038 ULONG ref = InterlockedIncrement(&This->ref);
4040 TRACE("(%p)->ref was %u\n",This, ref - 1);
4042 return ref;
4045 /* ITypeLib::Release
4047 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4049 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4050 ULONG ref = InterlockedDecrement(&This->ref);
4052 TRACE("(%p)->(%u)\n",This, ref);
4054 if (!ref)
4056 TLBImpLib *pImpLib, *pImpLibNext;
4057 TLBCustData *pCustData, *pCustDataNext;
4058 TLBRefType *ref_type;
4059 void *cursor2;
4060 int i;
4062 /* remove cache entry */
4063 if(This->path)
4065 TRACE("removing from cache list\n");
4066 EnterCriticalSection(&cache_section);
4067 if (This->next) This->next->prev = This->prev;
4068 if (This->prev) This->prev->next = This->next;
4069 else tlb_cache_first = This->next;
4070 LeaveCriticalSection(&cache_section);
4071 HeapFree(GetProcessHeap(), 0, This->path);
4073 TRACE(" destroying ITypeLib(%p)\n",This);
4075 SysFreeString(This->Name);
4076 This->Name = NULL;
4078 SysFreeString(This->DocString);
4079 This->DocString = NULL;
4081 SysFreeString(This->HelpFile);
4082 This->HelpFile = NULL;
4084 SysFreeString(This->HelpStringDll);
4085 This->HelpStringDll = NULL;
4087 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4089 VariantClear(&pCustData->data);
4091 pCustDataNext = pCustData->next;
4092 TLB_Free(pCustData);
4095 for (i = 0; i < This->ctTypeDesc; i++)
4096 if (This->pTypeDesc[i].vt == VT_CARRAY)
4097 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4099 TLB_Free(This->pTypeDesc);
4101 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4103 if (pImpLib->pImpTypeLib)
4104 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4105 SysFreeString(pImpLib->name);
4107 pImpLibNext = pImpLib->next;
4108 TLB_Free(pImpLib);
4111 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4113 list_remove(&ref_type->entry);
4114 TLB_Free(ref_type);
4117 if (This->pTypeInfo) /* can be NULL */
4118 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4119 HeapFree(GetProcessHeap(),0,This);
4120 return 0;
4123 return ref;
4126 /* ITypeLib::GetTypeInfoCount
4128 * Returns the number of type descriptions in the type library
4130 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4132 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4133 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4134 return This->TypeInfoCount;
4137 /* ITypeLib::GetTypeInfo
4139 * retrieves the specified type description in the library.
4141 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4142 ITypeLib2 *iface,
4143 UINT index,
4144 ITypeInfo **ppTInfo)
4146 UINT i;
4148 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4149 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4151 TRACE("(%p)->(index=%d)\n", This, index);
4153 if (!ppTInfo) return E_INVALIDARG;
4155 /* search element n in list */
4156 for(i=0; i < index; i++)
4158 pTypeInfo = pTypeInfo->next;
4159 if (!pTypeInfo)
4161 TRACE("-- element not found\n");
4162 return TYPE_E_ELEMENTNOTFOUND;
4166 *ppTInfo = (ITypeInfo *) pTypeInfo;
4168 ITypeInfo_AddRef(*ppTInfo);
4169 TRACE("-- found (%p)\n",*ppTInfo);
4170 return S_OK;
4174 /* ITypeLibs::GetTypeInfoType
4176 * Retrieves the type of a type description.
4178 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4179 ITypeLib2 *iface,
4180 UINT index,
4181 TYPEKIND *pTKind)
4183 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4184 UINT i;
4185 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4187 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4188 return TYPE_E_ELEMENTNOTFOUND;
4190 TRACE("(%p) index %d\n", This, index);
4192 if(!pTKind) return E_INVALIDARG;
4194 /* search element n in list */
4195 for(i=0; i < index; i++)
4197 if(!pTInfo)
4199 TRACE("-- element not found\n");
4200 return TYPE_E_ELEMENTNOTFOUND;
4202 pTInfo = pTInfo->next;
4205 *pTKind = pTInfo->TypeAttr.typekind;
4206 TRACE("-- found Type (%d)\n", *pTKind);
4207 return S_OK;
4210 /* ITypeLib::GetTypeInfoOfGuid
4212 * Retrieves the type description that corresponds to the specified GUID.
4215 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4216 ITypeLib2 *iface,
4217 REFGUID guid,
4218 ITypeInfo **ppTInfo)
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4221 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4223 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4225 if (!pTypeInfo)
4227 WARN("-- element not found\n");
4228 return TYPE_E_ELEMENTNOTFOUND;
4231 /* search linked list for guid */
4232 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4234 pTypeInfo = pTypeInfo->next;
4236 if (!pTypeInfo)
4238 /* end of list reached */
4239 WARN("-- element not found\n");
4240 return TYPE_E_ELEMENTNOTFOUND;
4244 TRACE("-- found (%p, %s)\n",
4245 pTypeInfo,
4246 debugstr_w(pTypeInfo->Name));
4248 *ppTInfo = (ITypeInfo*)pTypeInfo;
4249 ITypeInfo_AddRef(*ppTInfo);
4250 return S_OK;
4253 /* ITypeLib::GetLibAttr
4255 * Retrieves the structure that contains the library's attributes.
4258 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4259 ITypeLib2 *iface,
4260 LPTLIBATTR *ppTLibAttr)
4262 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4263 TRACE("(%p)\n",This);
4264 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4265 **ppTLibAttr = This->LibAttr;
4266 return S_OK;
4269 /* ITypeLib::GetTypeComp
4271 * Enables a client compiler to bind to a library's types, variables,
4272 * constants, and global functions.
4275 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4276 ITypeLib2 *iface,
4277 ITypeComp **ppTComp)
4279 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4281 TRACE("(%p)->(%p)\n",This,ppTComp);
4282 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4283 ITypeComp_AddRef(*ppTComp);
4285 return S_OK;
4288 /* ITypeLib::GetDocumentation
4290 * Retrieves the library's documentation string, the complete Help file name
4291 * and path, and the context identifier for the library Help topic in the Help
4292 * file.
4294 * On a successful return all non-null BSTR pointers will have been set,
4295 * possibly to NULL.
4297 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4298 ITypeLib2 *iface,
4299 INT index,
4300 BSTR *pBstrName,
4301 BSTR *pBstrDocString,
4302 DWORD *pdwHelpContext,
4303 BSTR *pBstrHelpFile)
4305 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4307 HRESULT result = E_INVALIDARG;
4309 ITypeInfo *pTInfo;
4312 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4313 This, index,
4314 pBstrName, pBstrDocString,
4315 pdwHelpContext, pBstrHelpFile);
4317 if(index<0)
4319 /* documentation for the typelib */
4320 if(pBstrName)
4322 if (This->Name)
4324 if(!(*pBstrName = SysAllocString(This->Name)))
4325 goto memerr1;
4327 else
4328 *pBstrName = NULL;
4330 if(pBstrDocString)
4332 if (This->DocString)
4334 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4335 goto memerr2;
4337 else if (This->Name)
4339 if(!(*pBstrDocString = SysAllocString(This->Name)))
4340 goto memerr2;
4342 else
4343 *pBstrDocString = NULL;
4345 if(pdwHelpContext)
4347 *pdwHelpContext = This->dwHelpContext;
4349 if(pBstrHelpFile)
4351 if (This->HelpFile)
4353 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4354 goto memerr3;
4356 else
4357 *pBstrHelpFile = NULL;
4360 result = S_OK;
4362 else
4364 /* for a typeinfo */
4365 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4367 if(SUCCEEDED(result))
4369 result = ITypeInfo_GetDocumentation(pTInfo,
4370 MEMBERID_NIL,
4371 pBstrName,
4372 pBstrDocString,
4373 pdwHelpContext, pBstrHelpFile);
4375 ITypeInfo_Release(pTInfo);
4378 return result;
4379 memerr3:
4380 if (pBstrDocString) SysFreeString (*pBstrDocString);
4381 memerr2:
4382 if (pBstrName) SysFreeString (*pBstrName);
4383 memerr1:
4384 return STG_E_INSUFFICIENTMEMORY;
4387 /* ITypeLib::IsName
4389 * Indicates whether a passed-in string contains the name of a type or member
4390 * described in the library.
4393 static HRESULT WINAPI ITypeLib2_fnIsName(
4394 ITypeLib2 *iface,
4395 LPOLESTR szNameBuf,
4396 ULONG lHashVal,
4397 BOOL *pfName)
4399 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4400 ITypeInfoImpl *pTInfo;
4401 TLBFuncDesc *pFInfo;
4402 TLBVarDesc *pVInfo;
4403 int i;
4404 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4406 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4407 pfName);
4409 *pfName=TRUE;
4410 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4411 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4412 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4413 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4414 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4415 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4416 goto ITypeLib2_fnIsName_exit;
4418 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4419 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4422 *pfName=FALSE;
4424 ITypeLib2_fnIsName_exit:
4425 TRACE("(%p)slow! search for %s: %s found!\n", This,
4426 debugstr_w(szNameBuf), *pfName?"NOT":"");
4428 return S_OK;
4431 /* ITypeLib::FindName
4433 * Finds occurrences of a type description in a type library. This may be used
4434 * to quickly verify that a name exists in a type library.
4437 static HRESULT WINAPI ITypeLib2_fnFindName(
4438 ITypeLib2 *iface,
4439 LPOLESTR szNameBuf,
4440 ULONG lHashVal,
4441 ITypeInfo **ppTInfo,
4442 MEMBERID *rgMemId,
4443 UINT16 *pcFound)
4445 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4446 ITypeInfoImpl *pTInfo;
4447 TLBFuncDesc *pFInfo;
4448 TLBVarDesc *pVInfo;
4449 int i,j = 0;
4450 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4452 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4453 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4454 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4455 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4456 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4457 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4458 goto ITypeLib2_fnFindName_exit;
4461 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4462 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4463 continue;
4464 ITypeLib2_fnFindName_exit:
4465 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4466 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4467 j++;
4469 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4470 This, *pcFound, debugstr_w(szNameBuf), j);
4472 *pcFound=j;
4474 return S_OK;
4477 /* ITypeLib::ReleaseTLibAttr
4479 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4482 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4483 ITypeLib2 *iface,
4484 TLIBATTR *pTLibAttr)
4486 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4487 TRACE("freeing (%p)\n",This);
4488 HeapFree(GetProcessHeap(),0,pTLibAttr);
4492 /* ITypeLib2::GetCustData
4494 * gets the custom data
4496 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4497 ITypeLib2 * iface,
4498 REFGUID guid,
4499 VARIANT *pVarVal)
4501 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4502 TLBCustData *pCData;
4504 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4506 if( IsEqualIID(guid, &pCData->guid)) break;
4509 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4511 if(pCData)
4513 VariantInit( pVarVal);
4514 VariantCopy( pVarVal, &pCData->data);
4515 return S_OK;
4517 return E_INVALIDARG; /* FIXME: correct? */
4520 /* ITypeLib2::GetLibStatistics
4522 * Returns statistics about a type library that are required for efficient
4523 * sizing of hash tables.
4526 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4527 ITypeLib2 * iface,
4528 ULONG *pcUniqueNames,
4529 ULONG *pcchUniqueNames)
4531 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4533 FIXME("(%p): stub!\n", This);
4535 if(pcUniqueNames) *pcUniqueNames=1;
4536 if(pcchUniqueNames) *pcchUniqueNames=1;
4537 return S_OK;
4540 /* ITypeLib2::GetDocumentation2
4542 * Retrieves the library's documentation string, the complete Help file name
4543 * and path, the localization context to use, and the context ID for the
4544 * library Help topic in the Help file.
4547 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4548 ITypeLib2 * iface,
4549 INT index,
4550 LCID lcid,
4551 BSTR *pbstrHelpString,
4552 DWORD *pdwHelpStringContext,
4553 BSTR *pbstrHelpStringDll)
4555 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4556 HRESULT result;
4557 ITypeInfo *pTInfo;
4559 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4561 /* the help string should be obtained from the helpstringdll,
4562 * using the _DLLGetDocumentation function, based on the supplied
4563 * lcid. Nice to do sometime...
4565 if(index<0)
4567 /* documentation for the typelib */
4568 if(pbstrHelpString)
4569 *pbstrHelpString=SysAllocString(This->DocString);
4570 if(pdwHelpStringContext)
4571 *pdwHelpStringContext=This->dwHelpContext;
4572 if(pbstrHelpStringDll)
4573 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4575 result = S_OK;
4577 else
4579 /* for a typeinfo */
4580 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4582 if(SUCCEEDED(result))
4584 ITypeInfo2 * pTInfo2;
4585 result = ITypeInfo_QueryInterface(pTInfo,
4586 &IID_ITypeInfo2,
4587 (LPVOID*) &pTInfo2);
4589 if(SUCCEEDED(result))
4591 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4592 MEMBERID_NIL,
4593 lcid,
4594 pbstrHelpString,
4595 pdwHelpStringContext,
4596 pbstrHelpStringDll);
4598 ITypeInfo2_Release(pTInfo2);
4601 ITypeInfo_Release(pTInfo);
4604 return result;
4607 /* ITypeLib2::GetAllCustData
4609 * Gets all custom data items for the library.
4612 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4613 ITypeLib2 * iface,
4614 CUSTDATA *pCustData)
4616 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4617 TLBCustData *pCData;
4618 int i;
4619 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4620 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4621 if(pCustData->prgCustData ){
4622 pCustData->cCustData=This->ctCustData;
4623 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4624 pCustData->prgCustData[i].guid=pCData->guid;
4625 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4627 }else{
4628 ERR(" OUT OF MEMORY!\n");
4629 return E_OUTOFMEMORY;
4631 return S_OK;
4634 static const ITypeLib2Vtbl tlbvt = {
4635 ITypeLib2_fnQueryInterface,
4636 ITypeLib2_fnAddRef,
4637 ITypeLib2_fnRelease,
4638 ITypeLib2_fnGetTypeInfoCount,
4639 ITypeLib2_fnGetTypeInfo,
4640 ITypeLib2_fnGetTypeInfoType,
4641 ITypeLib2_fnGetTypeInfoOfGuid,
4642 ITypeLib2_fnGetLibAttr,
4643 ITypeLib2_fnGetTypeComp,
4644 ITypeLib2_fnGetDocumentation,
4645 ITypeLib2_fnIsName,
4646 ITypeLib2_fnFindName,
4647 ITypeLib2_fnReleaseTLibAttr,
4649 ITypeLib2_fnGetCustData,
4650 ITypeLib2_fnGetLibStatistics,
4651 ITypeLib2_fnGetDocumentation2,
4652 ITypeLib2_fnGetAllCustData
4656 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4658 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4660 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4663 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4665 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4667 return ITypeLib2_AddRef((ITypeLib2 *)This);
4670 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4672 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4674 return ITypeLib2_Release((ITypeLib2 *)This);
4677 static HRESULT WINAPI ITypeLibComp_fnBind(
4678 ITypeComp * iface,
4679 OLECHAR * szName,
4680 ULONG lHash,
4681 WORD wFlags,
4682 ITypeInfo ** ppTInfo,
4683 DESCKIND * pDescKind,
4684 BINDPTR * pBindPtr)
4686 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4687 ITypeInfoImpl *pTypeInfo;
4689 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4691 *pDescKind = DESCKIND_NONE;
4692 pBindPtr->lptcomp = NULL;
4693 *ppTInfo = NULL;
4695 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4697 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4699 /* FIXME: check wFlags here? */
4700 /* FIXME: we should use a hash table to look this info up using lHash
4701 * instead of an O(n) search */
4702 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4703 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4705 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4707 *pDescKind = DESCKIND_TYPECOMP;
4708 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4709 ITypeComp_AddRef(pBindPtr->lptcomp);
4710 TRACE("module or enum: %s\n", debugstr_w(szName));
4711 return S_OK;
4715 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4716 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4718 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4719 HRESULT hr;
4721 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4722 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4724 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4725 return S_OK;
4729 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4730 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4732 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4733 HRESULT hr;
4734 ITypeInfo *subtypeinfo;
4735 BINDPTR subbindptr;
4736 DESCKIND subdesckind;
4738 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4739 &subtypeinfo, &subdesckind, &subbindptr);
4740 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4742 TYPEDESC tdesc_appobject =
4745 (TYPEDESC *)pTypeInfo->hreftype
4747 VT_USERDEFINED
4749 const VARDESC vardesc_appobject =
4751 -2, /* memid */
4752 NULL, /* lpstrSchema */
4754 0 /* oInst */
4757 /* ELEMDESC */
4759 /* TYPEDESC */
4761 &tdesc_appobject
4763 VT_PTR
4766 0, /* wVarFlags */
4767 VAR_STATIC /* varkind */
4770 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4772 /* cleanup things filled in by Bind call so we can put our
4773 * application object data in there instead */
4774 switch (subdesckind)
4776 case DESCKIND_FUNCDESC:
4777 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4778 break;
4779 case DESCKIND_VARDESC:
4780 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4781 break;
4782 default:
4783 break;
4785 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4787 if (pTypeInfo->hreftype == -1)
4788 FIXME("no hreftype for interface %p\n", pTypeInfo);
4790 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4791 if (FAILED(hr))
4792 return hr;
4794 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4795 *ppTInfo = (ITypeInfo *)pTypeInfo;
4796 ITypeInfo_AddRef(*ppTInfo);
4797 return S_OK;
4802 TRACE("name not found %s\n", debugstr_w(szName));
4803 return S_OK;
4806 static HRESULT WINAPI ITypeLibComp_fnBindType(
4807 ITypeComp * iface,
4808 OLECHAR * szName,
4809 ULONG lHash,
4810 ITypeInfo ** ppTInfo,
4811 ITypeComp ** ppTComp)
4813 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4814 return E_NOTIMPL;
4817 static const ITypeCompVtbl tlbtcvt =
4820 ITypeLibComp_fnQueryInterface,
4821 ITypeLibComp_fnAddRef,
4822 ITypeLibComp_fnRelease,
4824 ITypeLibComp_fnBind,
4825 ITypeLibComp_fnBindType
4828 /*================== ITypeInfo(2) Methods ===================================*/
4829 static ITypeInfo2 * ITypeInfo_Constructor(void)
4831 ITypeInfoImpl * pTypeInfoImpl;
4833 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4834 if (pTypeInfoImpl)
4836 pTypeInfoImpl->lpVtbl = &tinfvt;
4837 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4838 pTypeInfoImpl->ref=1;
4839 pTypeInfoImpl->hreftype = -1;
4840 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4841 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4843 TRACE("(%p)\n", pTypeInfoImpl);
4844 return (ITypeInfo2*) pTypeInfoImpl;
4847 /* ITypeInfo::QueryInterface
4849 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4850 ITypeInfo2 *iface,
4851 REFIID riid,
4852 VOID **ppvObject)
4854 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4856 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4858 *ppvObject=NULL;
4859 if(IsEqualIID(riid, &IID_IUnknown) ||
4860 IsEqualIID(riid,&IID_ITypeInfo)||
4861 IsEqualIID(riid,&IID_ITypeInfo2))
4862 *ppvObject = This;
4864 if(*ppvObject){
4865 ITypeInfo_AddRef(iface);
4866 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4867 return S_OK;
4869 TRACE("-- Interface: E_NOINTERFACE\n");
4870 return E_NOINTERFACE;
4873 /* ITypeInfo::AddRef
4875 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4877 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4878 ULONG ref = InterlockedIncrement(&This->ref);
4880 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4882 TRACE("(%p)->ref is %u\n",This, ref);
4883 return ref;
4886 /* ITypeInfo::Release
4888 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4890 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4891 ULONG ref = InterlockedDecrement(&This->ref);
4893 TRACE("(%p)->(%u)\n",This, ref);
4895 if (ref) {
4896 /* We don't release ITypeLib when ref=0 because
4897 it means that function is called by ITypeLib2_Release */
4898 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4899 } else {
4900 TLBFuncDesc *pFInfo, *pFInfoNext;
4901 TLBVarDesc *pVInfo, *pVInfoNext;
4902 TLBImplType *pImpl, *pImplNext;
4904 TRACE("destroying ITypeInfo(%p)\n",This);
4906 if (This->no_free_data)
4907 goto finish_free;
4909 SysFreeString(This->Name);
4910 This->Name = NULL;
4912 SysFreeString(This->DocString);
4913 This->DocString = NULL;
4915 SysFreeString(This->DllName);
4916 This->DllName = NULL;
4918 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4920 INT i;
4921 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4923 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4924 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4926 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4927 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4929 SysFreeString(pFInfo->pParamDesc[i].Name);
4931 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4932 TLB_Free(pFInfo->pParamDesc);
4933 TLB_FreeCustData(pFInfo->pCustData);
4934 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4935 SysFreeString(pFInfo->Entry);
4936 SysFreeString(pFInfo->HelpString);
4937 SysFreeString(pFInfo->Name);
4939 pFInfoNext = pFInfo->next;
4940 TLB_Free(pFInfo);
4942 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4944 if (pVInfo->vardesc.varkind == VAR_CONST)
4946 VariantClear(pVInfo->vardesc.u.lpvarValue);
4947 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4949 TLB_FreeCustData(pVInfo->pCustData);
4950 SysFreeString(pVInfo->Name);
4951 pVInfoNext = pVInfo->next;
4952 TLB_Free(pVInfo);
4954 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4956 TLB_FreeCustData(pImpl->pCustData);
4957 pImplNext = pImpl->next;
4958 TLB_Free(pImpl);
4960 TLB_FreeCustData(This->pCustData);
4962 finish_free:
4963 if (This->next)
4965 ITypeInfo_Release((ITypeInfo*)This->next);
4968 HeapFree(GetProcessHeap(),0,This);
4969 return 0;
4971 return ref;
4974 /* ITypeInfo::GetTypeAttr
4976 * Retrieves a TYPEATTR structure that contains the attributes of the type
4977 * description.
4980 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4981 LPTYPEATTR *ppTypeAttr)
4983 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4984 SIZE_T size;
4986 TRACE("(%p)\n",This);
4988 size = sizeof(**ppTypeAttr);
4989 if (This->TypeAttr.typekind == TKIND_ALIAS)
4990 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4992 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4993 if (!*ppTypeAttr)
4994 return E_OUTOFMEMORY;
4996 **ppTypeAttr = This->TypeAttr;
4998 if (This->TypeAttr.typekind == TKIND_ALIAS)
4999 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5000 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5002 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5003 /* This should include all the inherited funcs */
5004 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5005 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5006 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5008 return S_OK;
5011 /* ITypeInfo::GetTypeComp
5013 * Retrieves the ITypeComp interface for the type description, which enables a
5014 * client compiler to bind to the type description's members.
5017 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5018 ITypeComp * *ppTComp)
5020 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5022 TRACE("(%p)->(%p)\n", This, ppTComp);
5024 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5025 ITypeComp_AddRef(*ppTComp);
5026 return S_OK;
5029 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5031 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5032 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5033 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5034 return size;
5037 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5039 *dest = *src;
5040 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5041 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5043 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5044 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5045 *buffer += sizeof(PARAMDESCEX);
5046 *pparamdescex_dest = *pparamdescex_src;
5047 VariantInit(&pparamdescex_dest->varDefaultValue);
5048 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5049 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5051 else
5052 dest->u.paramdesc.pparamdescex = NULL;
5053 return S_OK;
5056 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5058 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5059 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5062 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5064 FUNCDESC *dest;
5065 char *buffer;
5066 SIZE_T size = sizeof(*src);
5067 SHORT i;
5068 HRESULT hr;
5070 size += sizeof(*src->lprgscode) * src->cScodes;
5071 size += TLB_SizeElemDesc(&src->elemdescFunc);
5072 for (i = 0; i < src->cParams; i++)
5074 size += sizeof(ELEMDESC);
5075 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5078 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5079 if (!dest) return E_OUTOFMEMORY;
5081 *dest = *src;
5082 if (dispinterface) /* overwrite funckind */
5083 dest->funckind = FUNC_DISPATCH;
5084 buffer = (char *)(dest + 1);
5086 dest->lprgscode = (SCODE *)buffer;
5087 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5088 buffer += sizeof(*src->lprgscode) * src->cScodes;
5090 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5091 if (FAILED(hr))
5093 SysFreeString((BSTR)dest);
5094 return hr;
5097 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5098 buffer += sizeof(ELEMDESC) * src->cParams;
5099 for (i = 0; i < src->cParams; i++)
5101 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5102 if (FAILED(hr))
5103 break;
5105 if (FAILED(hr))
5107 /* undo the above actions */
5108 for (i = i - 1; i >= 0; i--)
5109 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5110 TLB_FreeElemDesc(&dest->elemdescFunc);
5111 SysFreeString((BSTR)dest);
5112 return hr;
5115 /* special treatment for dispinterfaces: this makes functions appear
5116 * to return their [retval] value when it is really returning an
5117 * HRESULT */
5118 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5120 if (dest->cParams &&
5121 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5123 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5124 if (elemdesc->tdesc.vt != VT_PTR)
5126 ERR("elemdesc should have started with VT_PTR instead of:\n");
5127 if (ERR_ON(ole))
5128 dump_ELEMDESC(elemdesc);
5129 return E_UNEXPECTED;
5132 /* copy last parameter to the return value. we are using a flat
5133 * buffer so there is no danger of leaking memory in
5134 * elemdescFunc */
5135 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5137 /* remove the last parameter */
5138 dest->cParams--;
5140 else
5141 /* otherwise this function is made to appear to have no return
5142 * value */
5143 dest->elemdescFunc.tdesc.vt = VT_VOID;
5147 *dest_ptr = dest;
5148 return S_OK;
5151 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5153 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5154 const TLBFuncDesc *pFDesc;
5155 UINT i;
5157 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5160 if (pFDesc)
5162 *ppFuncDesc = &pFDesc->funcdesc;
5163 return S_OK;
5166 return TYPE_E_ELEMENTNOTFOUND;
5169 /* internal function to make the inherited interfaces' methods appear
5170 * part of the interface */
5171 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5172 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5174 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5175 HRESULT hr;
5176 UINT implemented_funcs = 0;
5178 if (funcs)
5179 *funcs = 0;
5180 else
5181 *hrefoffset = DISPATCH_HREF_OFFSET;
5183 if(This->impltypelist)
5185 ITypeInfo *pSubTypeInfo;
5186 UINT sub_funcs;
5188 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5189 if (FAILED(hr))
5190 return hr;
5192 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5193 index,
5194 ppFuncDesc,
5195 &sub_funcs, hrefoffset);
5196 implemented_funcs += sub_funcs;
5197 ITypeInfo_Release(pSubTypeInfo);
5198 if (SUCCEEDED(hr))
5199 return hr;
5200 *hrefoffset += DISPATCH_HREF_OFFSET;
5203 if (funcs)
5204 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5205 else
5206 *hrefoffset = 0;
5208 if (index < implemented_funcs)
5209 return E_INVALIDARG;
5210 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5211 ppFuncDesc);
5214 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5216 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5217 while (TRUE)
5219 switch (pTypeDesc->vt)
5221 case VT_USERDEFINED:
5222 pTypeDesc->u.hreftype += hrefoffset;
5223 return;
5224 case VT_PTR:
5225 case VT_SAFEARRAY:
5226 pTypeDesc = pTypeDesc->u.lptdesc;
5227 break;
5228 case VT_CARRAY:
5229 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5230 break;
5231 default:
5232 return;
5237 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5239 SHORT i;
5240 for (i = 0; i < pFuncDesc->cParams; i++)
5241 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5242 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5245 /* ITypeInfo::GetFuncDesc
5247 * Retrieves the FUNCDESC structure that contains information about a
5248 * specified function.
5251 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5252 LPFUNCDESC *ppFuncDesc)
5254 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5255 const FUNCDESC *internal_funcdesc;
5256 HRESULT hr;
5257 UINT hrefoffset = 0;
5259 TRACE("(%p) index %d\n", This, index);
5261 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5262 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5263 &internal_funcdesc, NULL,
5264 &hrefoffset);
5265 else
5266 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5267 &internal_funcdesc);
5268 if (FAILED(hr))
5270 WARN("description for function %d not found\n", index);
5271 return hr;
5274 hr = TLB_AllocAndInitFuncDesc(
5275 internal_funcdesc,
5276 ppFuncDesc,
5277 This->TypeAttr.typekind == TKIND_DISPATCH);
5279 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5280 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5282 TRACE("-- 0x%08x\n", hr);
5283 return hr;
5286 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5288 VARDESC *dest;
5289 char *buffer;
5290 SIZE_T size = sizeof(*src);
5291 HRESULT hr;
5293 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5294 if (src->varkind == VAR_CONST)
5295 size += sizeof(VARIANT);
5296 size += TLB_SizeElemDesc(&src->elemdescVar);
5298 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5299 if (!dest) return E_OUTOFMEMORY;
5301 *dest = *src;
5302 buffer = (char *)(dest + 1);
5303 if (src->lpstrSchema)
5305 int len;
5306 dest->lpstrSchema = (LPOLESTR)buffer;
5307 len = strlenW(src->lpstrSchema);
5308 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5309 buffer += (len + 1) * sizeof(WCHAR);
5312 if (src->varkind == VAR_CONST)
5314 HRESULT hr;
5316 dest->u.lpvarValue = (VARIANT *)buffer;
5317 *dest->u.lpvarValue = *src->u.lpvarValue;
5318 buffer += sizeof(VARIANT);
5319 VariantInit(dest->u.lpvarValue);
5320 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5321 if (FAILED(hr))
5323 SysFreeString((BSTR)dest_ptr);
5324 return hr;
5327 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5328 if (FAILED(hr))
5330 if (src->varkind == VAR_CONST)
5331 VariantClear(dest->u.lpvarValue);
5332 SysFreeString((BSTR)dest);
5333 return hr;
5335 *dest_ptr = dest;
5336 return S_OK;
5339 /* ITypeInfo::GetVarDesc
5341 * Retrieves a VARDESC structure that describes the specified variable.
5344 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5345 LPVARDESC *ppVarDesc)
5347 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5348 UINT i;
5349 const TLBVarDesc *pVDesc;
5351 TRACE("(%p) index %d\n", This, index);
5353 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5356 if (pVDesc)
5357 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5359 return E_INVALIDARG;
5362 /* ITypeInfo_GetNames
5364 * Retrieves the variable with the specified member ID (or the name of the
5365 * property or method and its parameters) that correspond to the specified
5366 * function ID.
5368 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5369 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5371 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5372 const TLBFuncDesc *pFDesc;
5373 const TLBVarDesc *pVDesc;
5374 int i;
5375 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5376 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5377 if(pFDesc)
5379 /* function found, now return function and parameter names */
5380 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5382 if(!i)
5383 *rgBstrNames=SysAllocString(pFDesc->Name);
5384 else
5385 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5387 *pcNames=i;
5389 else
5391 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5392 if(pVDesc)
5394 *rgBstrNames=SysAllocString(pVDesc->Name);
5395 *pcNames=1;
5397 else
5399 if(This->impltypelist &&
5400 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5401 /* recursive search */
5402 ITypeInfo *pTInfo;
5403 HRESULT result;
5404 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5405 &pTInfo);
5406 if(SUCCEEDED(result))
5408 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5409 ITypeInfo_Release(pTInfo);
5410 return result;
5412 WARN("Could not search inherited interface!\n");
5414 else
5416 WARN("no names found\n");
5418 *pcNames=0;
5419 return TYPE_E_ELEMENTNOTFOUND;
5422 return S_OK;
5426 /* ITypeInfo::GetRefTypeOfImplType
5428 * If a type description describes a COM class, it retrieves the type
5429 * description of the implemented interface types. For an interface,
5430 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5431 * if any exist.
5434 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5435 ITypeInfo2 *iface,
5436 UINT index,
5437 HREFTYPE *pRefType)
5439 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5440 UINT i;
5441 HRESULT hr = S_OK;
5442 const TLBImplType *pImpl = This->impltypelist;
5444 TRACE("(%p) index %d\n", This, index);
5445 if (TRACE_ON(ole)) dump_TypeInfo(This);
5447 if(index==(UINT)-1)
5449 /* only valid on dual interfaces;
5450 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5452 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5454 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5455 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5457 *pRefType = -1;
5459 else
5461 hr = TYPE_E_ELEMENTNOTFOUND;
5464 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5466 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5467 *pRefType = This->pTypeLib->dispatch_href;
5469 else
5471 /* get element n from linked list */
5472 for(i=0; pImpl && i<index; i++)
5474 pImpl = pImpl->next;
5477 if (pImpl)
5478 *pRefType = pImpl->hRef;
5479 else
5480 hr = TYPE_E_ELEMENTNOTFOUND;
5483 if(TRACE_ON(ole))
5485 if(SUCCEEDED(hr))
5486 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5487 else
5488 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5491 return hr;
5494 /* ITypeInfo::GetImplTypeFlags
5496 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5497 * or base interface in a type description.
5499 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5500 UINT index, INT *pImplTypeFlags)
5502 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5503 UINT i;
5504 TLBImplType *pImpl;
5506 TRACE("(%p) index %d\n", This, index);
5507 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5508 i++, pImpl=pImpl->next)
5510 if(i==index && pImpl){
5511 *pImplTypeFlags=pImpl->implflags;
5512 return S_OK;
5514 *pImplTypeFlags=0;
5515 return TYPE_E_ELEMENTNOTFOUND;
5518 /* GetIDsOfNames
5519 * Maps between member names and member IDs, and parameter names and
5520 * parameter IDs.
5522 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5523 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5525 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5526 const TLBFuncDesc *pFDesc;
5527 const TLBVarDesc *pVDesc;
5528 HRESULT ret=S_OK;
5529 UINT i;
5531 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5532 cNames);
5534 /* init out parameters in case of failure */
5535 for (i = 0; i < cNames; i++)
5536 pMemId[i] = MEMBERID_NIL;
5538 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5539 int j;
5540 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5541 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5542 for(i=1; i < cNames; i++){
5543 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5544 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5545 break;
5546 if( j<pFDesc->funcdesc.cParams)
5547 pMemId[i]=j;
5548 else
5549 ret=DISP_E_UNKNOWNNAME;
5551 TRACE("-- 0x%08x\n", ret);
5552 return ret;
5555 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5556 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5557 if(cNames) *pMemId=pVDesc->vardesc.memid;
5558 return ret;
5561 /* not found, see if it can be found in an inherited interface */
5562 if(This->impltypelist) {
5563 /* recursive search */
5564 ITypeInfo *pTInfo;
5565 ret=ITypeInfo_GetRefTypeInfo(iface,
5566 This->impltypelist->hRef, &pTInfo);
5567 if(SUCCEEDED(ret)){
5568 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5569 ITypeInfo_Release(pTInfo);
5570 return ret;
5572 WARN("Could not search inherited interface!\n");
5573 } else
5574 WARN("no names found\n");
5575 return DISP_E_UNKNOWNNAME;
5578 /* ITypeInfo::Invoke
5580 * Invokes a method, or accesses a property of an object, that implements the
5581 * interface described by the type description.
5583 DWORD
5584 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5585 DWORD res;
5587 if (TRACE_ON(ole)) {
5588 int i;
5589 TRACE("Calling %p(",func);
5590 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5591 TRACE(")\n");
5594 switch (callconv) {
5595 case CC_STDCALL:
5597 switch (nrargs) {
5598 case 0:
5599 res = func();
5600 break;
5601 case 1:
5602 res = func(args[0]);
5603 break;
5604 case 2:
5605 res = func(args[0],args[1]);
5606 break;
5607 case 3:
5608 res = func(args[0],args[1],args[2]);
5609 break;
5610 case 4:
5611 res = func(args[0],args[1],args[2],args[3]);
5612 break;
5613 case 5:
5614 res = func(args[0],args[1],args[2],args[3],args[4]);
5615 break;
5616 case 6:
5617 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5618 break;
5619 case 7:
5620 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5621 break;
5622 case 8:
5623 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5624 break;
5625 case 9:
5626 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5627 break;
5628 case 10:
5629 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5630 break;
5631 case 11:
5632 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5633 break;
5634 case 12:
5635 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5636 break;
5637 case 13:
5638 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5639 break;
5640 case 14:
5641 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5642 break;
5643 case 15:
5644 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5645 break;
5646 case 16:
5647 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5648 break;
5649 case 17:
5650 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5651 break;
5652 case 18:
5653 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5654 break;
5655 case 19:
5656 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5657 break;
5658 case 20:
5659 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5660 break;
5661 case 21:
5662 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5663 break;
5664 case 22:
5665 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5666 break;
5667 case 23:
5668 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5669 break;
5670 case 24:
5671 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5672 break;
5673 case 25:
5674 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5675 break;
5676 case 26:
5677 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5678 break;
5679 case 27:
5680 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5681 break;
5682 case 28:
5683 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5684 break;
5685 case 29:
5686 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5687 break;
5688 case 30:
5689 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5690 break;
5691 default:
5692 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5693 res = -1;
5694 break;
5696 break;
5697 default:
5698 FIXME("unsupported calling convention %d\n",callconv);
5699 res = -1;
5700 break;
5702 TRACE("returns %08x\n",res);
5703 return res;
5706 /* The size of the argument on the stack in DWORD units (in all x86 call
5707 * convetions the arguments on the stack are DWORD-aligned)
5709 static int _dispargsize(VARTYPE vt)
5711 switch (vt) {
5712 case VT_I8:
5713 case VT_UI8:
5714 return 8/sizeof(DWORD);
5715 case VT_R8:
5716 return sizeof(double)/sizeof(DWORD);
5717 case VT_DECIMAL:
5718 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5719 case VT_CY:
5720 return sizeof(CY)/sizeof(DWORD);
5721 case VT_DATE:
5722 return sizeof(DATE)/sizeof(DWORD);
5723 case VT_VARIANT:
5724 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5725 case VT_RECORD:
5726 FIXME("VT_RECORD not implemented\n");
5727 return 1;
5728 default:
5729 return 1;
5733 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5735 HRESULT hr = S_OK;
5736 ITypeInfo *tinfo2 = NULL;
5737 TYPEATTR *tattr = NULL;
5739 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5740 if (hr)
5742 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5743 "hr = 0x%08x\n",
5744 tdesc->u.hreftype, hr);
5745 return hr;
5747 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5748 if (hr)
5750 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5751 ITypeInfo_Release(tinfo2);
5752 return hr;
5755 switch (tattr->typekind)
5757 case TKIND_ENUM:
5758 *vt |= VT_I4;
5759 break;
5761 case TKIND_ALIAS:
5762 tdesc = &tattr->tdescAlias;
5763 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5764 break;
5766 case TKIND_INTERFACE:
5767 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5768 *vt |= VT_DISPATCH;
5769 else
5770 *vt |= VT_UNKNOWN;
5771 break;
5773 case TKIND_DISPATCH:
5774 *vt |= VT_DISPATCH;
5775 break;
5777 case TKIND_COCLASS:
5778 *vt |= VT_DISPATCH;
5779 break;
5781 case TKIND_RECORD:
5782 FIXME("TKIND_RECORD unhandled.\n");
5783 hr = E_NOTIMPL;
5784 break;
5786 case TKIND_UNION:
5787 FIXME("TKIND_UNION unhandled.\n");
5788 hr = E_NOTIMPL;
5789 break;
5791 default:
5792 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5793 hr = E_NOTIMPL;
5794 break;
5796 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5797 ITypeInfo_Release(tinfo2);
5798 return hr;
5801 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5803 HRESULT hr = S_OK;
5805 /* enforce only one level of pointer indirection */
5806 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5808 tdesc = tdesc->u.lptdesc;
5810 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5811 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5812 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5813 if ((tdesc->vt == VT_USERDEFINED) ||
5814 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5816 VARTYPE vt_userdefined = 0;
5817 const TYPEDESC *tdesc_userdefined = tdesc;
5818 if (tdesc->vt == VT_PTR)
5820 vt_userdefined = VT_BYREF;
5821 tdesc_userdefined = tdesc->u.lptdesc;
5823 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5824 if ((hr == S_OK) &&
5825 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5826 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5828 *vt |= vt_userdefined;
5829 return S_OK;
5832 *vt = VT_BYREF;
5835 switch (tdesc->vt)
5837 case VT_HRESULT:
5838 *vt |= VT_ERROR;
5839 break;
5840 case VT_USERDEFINED:
5841 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5842 break;
5843 case VT_VOID:
5844 case VT_CARRAY:
5845 case VT_PTR:
5846 case VT_LPSTR:
5847 case VT_LPWSTR:
5848 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5849 hr = DISP_E_BADVARTYPE;
5850 break;
5851 case VT_SAFEARRAY:
5852 *vt |= VT_ARRAY;
5853 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5854 break;
5855 default:
5856 *vt |= tdesc->vt;
5857 break;
5859 return hr;
5862 /***********************************************************************
5863 * DispCallFunc (OLEAUT32.@)
5865 * Invokes a function of the specified calling convention, passing the
5866 * specified arguments and returns the result.
5868 * PARAMS
5869 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5870 * oVft [I] The offset in the vtable. See notes.
5871 * cc [I] Calling convention of the function to call.
5872 * vtReturn [I] The return type of the function.
5873 * cActuals [I] Number of parameters.
5874 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5875 * prgpvarg [I] The arguments to pass.
5876 * pvargResult [O] The return value of the function. Can be NULL.
5878 * RETURNS
5879 * Success: S_OK.
5880 * Failure: HRESULT code.
5882 * NOTES
5883 * The HRESULT return value of this function is not affected by the return
5884 * value of the user supplied function, which is returned in pvargResult.
5886 * If pvInstance is NULL then a non-object function is to be called and oVft
5887 * is the address of the function to call.
5889 * The cc parameter can be one of the following values:
5890 *|CC_FASTCALL
5891 *|CC_CDECL
5892 *|CC_PASCAL
5893 *|CC_STDCALL
5894 *|CC_FPFASTCALL
5895 *|CC_SYSCALL
5896 *|CC_MPWCDECL
5897 *|CC_MPWPASCAL
5900 HRESULT WINAPI
5901 DispCallFunc(
5902 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5903 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5905 int argsize, argspos;
5906 UINT i;
5907 DWORD *args;
5908 HRESULT hres;
5910 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5911 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5912 pvargResult, V_VT(pvargResult));
5914 argsize = 0;
5915 if (pvInstance)
5916 argsize++; /* for This pointer */
5918 for (i=0;i<cActuals;i++)
5920 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5921 dump_Variant(prgpvarg[i]);
5922 argsize += _dispargsize(prgvt[i]);
5924 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5926 argspos = 0;
5927 if (pvInstance)
5929 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5930 argspos++;
5933 for (i=0;i<cActuals;i++)
5935 VARIANT *arg = prgpvarg[i];
5936 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5937 if (prgvt[i] == VT_VARIANT)
5938 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5939 else
5940 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5941 argspos += _dispargsize(prgvt[i]);
5944 if (pvInstance)
5946 FARPROC *vtable = *(FARPROC**)pvInstance;
5947 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5949 else
5950 /* if we aren't invoking an object then the function pointer is stored
5951 * in oVft */
5952 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5954 if (pvargResult && (vtReturn != VT_EMPTY))
5956 TRACE("Method returned 0x%08x\n",hres);
5957 V_VT(pvargResult) = vtReturn;
5958 V_UI4(pvargResult) = hres;
5961 HeapFree(GetProcessHeap(),0,args);
5962 return S_OK;
5965 #define INVBUF_ELEMENT_SIZE \
5966 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5967 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5968 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5969 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5970 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5971 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5972 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5973 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5975 static HRESULT WINAPI ITypeInfo_fnInvoke(
5976 ITypeInfo2 *iface,
5977 VOID *pIUnk,
5978 MEMBERID memid,
5979 UINT16 wFlags,
5980 DISPPARAMS *pDispParams,
5981 VARIANT *pVarResult,
5982 EXCEPINFO *pExcepInfo,
5983 UINT *pArgErr)
5985 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5986 int i;
5987 unsigned int var_index;
5988 TYPEKIND type_kind;
5989 HRESULT hres;
5990 const TLBFuncDesc *pFuncInfo;
5992 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5993 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5996 if (!pDispParams)
5998 ERR("NULL pDispParams not allowed\n");
5999 return E_INVALIDARG;
6002 dump_DispParms(pDispParams);
6004 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6006 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6007 pDispParams->cNamedArgs, pDispParams->cArgs);
6008 return E_INVALIDARG;
6011 /* we do this instead of using GetFuncDesc since it will return a fake
6012 * FUNCDESC for dispinterfaces and we want the real function description */
6013 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6014 if ((memid == pFuncInfo->funcdesc.memid) &&
6015 (wFlags & pFuncInfo->funcdesc.invkind))
6016 break;
6018 if (pFuncInfo) {
6019 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6021 if (TRACE_ON(ole))
6023 TRACE("invoking:\n");
6024 dump_TLBFuncDescOne(pFuncInfo);
6027 switch (func_desc->funckind) {
6028 case FUNC_PUREVIRTUAL:
6029 case FUNC_VIRTUAL: {
6030 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6031 VARIANT varresult;
6032 VARIANT retval; /* pointer for storing byref retvals in */
6033 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6034 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6035 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6036 UINT cNamedArgs = pDispParams->cNamedArgs;
6037 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6039 hres = S_OK;
6041 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6043 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6045 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6046 hres = DISP_E_PARAMNOTFOUND;
6047 goto func_fail;
6049 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6050 cNamedArgs--;
6051 rgdispidNamedArgs++;
6054 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6056 ERR("functions with the vararg attribute do not support named arguments\n");
6057 hres = DISP_E_NONAMEDARGS;
6058 goto func_fail;
6061 for (i = 0; i < func_desc->cParams; i++)
6063 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6064 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6065 if (FAILED(hres))
6066 goto func_fail;
6069 TRACE("changing args\n");
6070 for (i = 0; i < func_desc->cParams; i++)
6072 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6073 VARIANTARG *src_arg;
6075 if (cNamedArgs)
6077 USHORT j;
6078 src_arg = NULL;
6079 for (j = 0; j < cNamedArgs; j++)
6080 if (rgdispidNamedArgs[j] == i)
6082 src_arg = &pDispParams->rgvarg[j];
6083 break;
6086 else
6087 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6089 if (wParamFlags & PARAMFLAG_FRETVAL)
6091 /* under most conditions the caller is not allowed to
6092 * pass in a dispparam arg in the index of what would be
6093 * the retval parameter. however, there is an exception
6094 * where the extra parameter is used in an extra
6095 * IDispatch::Invoke below */
6096 if ((i < pDispParams->cArgs) &&
6097 ((func_desc->cParams != 1) || !pVarResult ||
6098 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6100 hres = DISP_E_BADPARAMCOUNT;
6101 break;
6104 /* note: this check is placed so that if the caller passes
6105 * in a VARIANTARG for the retval we just ignore it, like
6106 * native does */
6107 if (i == func_desc->cParams - 1)
6109 VARIANTARG *arg;
6110 arg = prgpvarg[i] = &rgvarg[i];
6111 memset(arg, 0, sizeof(*arg));
6112 V_VT(arg) = rgvt[i];
6113 memset(&retval, 0, sizeof(retval));
6114 V_BYREF(arg) = &retval;
6116 else
6118 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6119 hres = E_UNEXPECTED;
6120 break;
6123 else if (src_arg)
6125 dump_Variant(src_arg);
6127 if (rgvt[i] == VT_VARIANT)
6128 hres = VariantCopy(&rgvarg[i], src_arg);
6129 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6131 if (rgvt[i] == V_VT(src_arg))
6132 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6133 else
6135 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6136 hres = VariantCopy(&missing_arg[i], src_arg);
6137 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6139 V_VT(&rgvarg[i]) = rgvt[i];
6141 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6143 SAFEARRAY *a;
6144 SAFEARRAYBOUND bound;
6145 VARIANT *v;
6146 LONG j;
6147 bound.lLbound = 0;
6148 bound.cElements = pDispParams->cArgs-i;
6149 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6151 ERR("SafeArrayCreate failed\n");
6152 break;
6154 hres = SafeArrayAccessData(a, (LPVOID)&v);
6155 if (hres != S_OK)
6157 ERR("SafeArrayAccessData failed with %x\n", hres);
6158 break;
6160 for (j = 0; j < bound.cElements; j++)
6161 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6162 hres = SafeArrayUnaccessData(a);
6163 if (hres != S_OK)
6165 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6166 break;
6168 V_ARRAY(&rgvarg[i]) = a;
6169 V_VT(&rgvarg[i]) = rgvt[i];
6171 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6173 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6174 V_VT(&missing_arg[i]) = V_VT(src_arg);
6175 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6176 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6177 V_VT(&rgvarg[i]) = rgvt[i];
6179 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6181 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6182 V_VT(&rgvarg[i]) = rgvt[i];
6184 else
6186 /* FIXME: this doesn't work for VT_BYREF arguments if
6187 * they are not the same type as in the paramdesc */
6188 V_VT(&rgvarg[i]) = V_VT(src_arg);
6189 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6190 V_VT(&rgvarg[i]) = rgvt[i];
6193 if (FAILED(hres))
6195 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6196 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6197 debugstr_VT(src_arg), debugstr_VF(src_arg));
6198 break;
6200 prgpvarg[i] = &rgvarg[i];
6202 else if (wParamFlags & PARAMFLAG_FOPT)
6204 VARIANTARG *arg;
6205 arg = prgpvarg[i] = &rgvarg[i];
6206 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6208 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6209 if (FAILED(hres))
6210 break;
6212 else
6214 VARIANTARG *missing_arg;
6215 /* if the function wants a pointer to a variant then
6216 * set that up, otherwise just pass the VT_ERROR in
6217 * the argument by value */
6218 if (rgvt[i] & VT_BYREF)
6220 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6221 V_VT(arg) = VT_VARIANT | VT_BYREF;
6222 V_VARIANTREF(arg) = missing_arg;
6224 else
6225 missing_arg = arg;
6226 V_VT(missing_arg) = VT_ERROR;
6227 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6230 else
6232 hres = DISP_E_BADPARAMCOUNT;
6233 break;
6236 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6238 /* VT_VOID is a special case for return types, so it is not
6239 * handled in the general function */
6240 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6241 V_VT(&varresult) = VT_EMPTY;
6242 else
6244 V_VT(&varresult) = 0;
6245 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6246 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6249 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6250 V_VT(&varresult), func_desc->cParams, rgvt,
6251 prgpvarg, &varresult);
6253 for (i = 0; i < func_desc->cParams; i++)
6255 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6256 if (wParamFlags & PARAMFLAG_FRETVAL)
6258 if (TRACE_ON(ole))
6260 TRACE("[retval] value: ");
6261 dump_Variant(prgpvarg[i]);
6264 if (pVarResult)
6266 VariantInit(pVarResult);
6267 /* deref return value */
6268 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6271 /* free data stored in varresult. Note that
6272 * VariantClear doesn't do what we want because we are
6273 * working with byref types. */
6274 /* FIXME: clear safearrays, bstrs, records and
6275 * variants here too */
6276 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6277 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6279 if(*V_UNKNOWNREF(prgpvarg[i]))
6280 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6282 break;
6284 else if (i < pDispParams->cArgs)
6286 if (wParamFlags & PARAMFLAG_FOUT)
6288 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6290 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6291 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6293 if (FAILED(hres))
6295 ERR("failed to convert param %d to vt %d\n", i,
6296 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6297 break;
6300 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6301 func_desc->cParamsOpt < 0 &&
6302 i == func_desc->cParams-1)
6304 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6305 LONG j, ubound;
6306 VARIANT *v;
6307 hres = SafeArrayGetUBound(a, 1, &ubound);
6308 if (hres != S_OK)
6310 ERR("SafeArrayGetUBound failed with %x\n", hres);
6311 break;
6313 hres = SafeArrayAccessData(a, (LPVOID)&v);
6314 if (hres != S_OK)
6316 ERR("SafeArrayAccessData failed with %x\n", hres);
6317 break;
6319 for (j = 0; j <= ubound; j++)
6320 VariantClear(&v[j]);
6321 hres = SafeArrayUnaccessData(a);
6322 if (hres != S_OK)
6324 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6325 break;
6328 VariantClear(&rgvarg[i]);
6330 else if (wParamFlags & PARAMFLAG_FOPT)
6332 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6333 VariantClear(&rgvarg[i]);
6337 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6339 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6340 hres = DISP_E_EXCEPTION;
6341 if (pExcepInfo)
6343 IErrorInfo *pErrorInfo;
6344 pExcepInfo->scode = V_ERROR(&varresult);
6345 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6347 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6348 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6349 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6350 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6352 IErrorInfo_Release(pErrorInfo);
6356 if (V_VT(&varresult) != VT_ERROR)
6358 TRACE("varresult value: ");
6359 dump_Variant(&varresult);
6361 if (pVarResult)
6363 VariantClear(pVarResult);
6364 *pVarResult = varresult;
6366 else
6367 VariantClear(&varresult);
6370 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6371 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6372 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6373 (pDispParams->cArgs != 0))
6375 if (V_VT(pVarResult) == VT_DISPATCH)
6377 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6378 /* Note: not VariantClear; we still need the dispatch
6379 * pointer to be valid */
6380 VariantInit(pVarResult);
6381 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6382 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6383 pDispParams, pVarResult, pExcepInfo, pArgErr);
6384 IDispatch_Release(pDispatch);
6386 else
6388 VariantClear(pVarResult);
6389 hres = DISP_E_NOTACOLLECTION;
6393 func_fail:
6394 HeapFree(GetProcessHeap(), 0, buffer);
6395 break;
6397 case FUNC_DISPATCH: {
6398 IDispatch *disp;
6400 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6401 if (SUCCEEDED(hres)) {
6402 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6403 hres = IDispatch_Invoke(
6404 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6405 pVarResult,pExcepInfo,pArgErr
6407 if (FAILED(hres))
6408 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6409 IDispatch_Release(disp);
6410 } else
6411 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6412 break;
6414 default:
6415 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6416 hres = E_FAIL;
6417 break;
6420 TRACE("-- 0x%08x\n", hres);
6421 return hres;
6423 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6424 VARDESC *var_desc;
6426 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6427 if(FAILED(hres)) return hres;
6429 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6430 dump_VARDESC(var_desc);
6431 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6432 return E_NOTIMPL;
6435 /* not found, look for it in inherited interfaces */
6436 ITypeInfo2_GetTypeKind(iface, &type_kind);
6437 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6438 if(This->impltypelist) {
6439 /* recursive search */
6440 ITypeInfo *pTInfo;
6441 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6442 if(SUCCEEDED(hres)){
6443 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6444 ITypeInfo_Release(pTInfo);
6445 return hres;
6447 WARN("Could not search inherited interface!\n");
6450 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6451 return DISP_E_MEMBERNOTFOUND;
6454 /* ITypeInfo::GetDocumentation
6456 * Retrieves the documentation string, the complete Help file name and path,
6457 * and the context ID for the Help topic for a specified type description.
6459 * (Can be tested by the Visual Basic Editor in Word for instance.)
6461 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6462 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6463 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6465 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6466 const TLBFuncDesc *pFDesc;
6467 const TLBVarDesc *pVDesc;
6468 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6469 " HelpContext(%p) HelpFile(%p)\n",
6470 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6471 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6472 if(pBstrName)
6473 *pBstrName=SysAllocString(This->Name);
6474 if(pBstrDocString)
6475 *pBstrDocString=SysAllocString(This->DocString);
6476 if(pdwHelpContext)
6477 *pdwHelpContext=This->dwHelpContext;
6478 if(pBstrHelpFile)
6479 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6480 return S_OK;
6481 }else {/* for a member */
6482 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6483 if(pFDesc->funcdesc.memid==memid){
6484 if(pBstrName)
6485 *pBstrName = SysAllocString(pFDesc->Name);
6486 if(pBstrDocString)
6487 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6488 if(pdwHelpContext)
6489 *pdwHelpContext=pFDesc->helpcontext;
6490 return S_OK;
6492 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6493 if(pVDesc->vardesc.memid==memid){
6494 if(pBstrName)
6495 *pBstrName = SysAllocString(pVDesc->Name);
6496 if(pBstrDocString)
6497 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6498 if(pdwHelpContext)
6499 *pdwHelpContext=pVDesc->HelpContext;
6500 return S_OK;
6504 if(This->impltypelist &&
6505 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6506 /* recursive search */
6507 ITypeInfo *pTInfo;
6508 HRESULT result;
6509 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6510 &pTInfo);
6511 if(SUCCEEDED(result)) {
6512 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6513 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6514 ITypeInfo_Release(pTInfo);
6515 return result;
6517 WARN("Could not search inherited interface!\n");
6520 WARN("member %d not found\n", memid);
6521 return TYPE_E_ELEMENTNOTFOUND;
6524 /* ITypeInfo::GetDllEntry
6526 * Retrieves a description or specification of an entry point for a function
6527 * in a DLL.
6529 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6530 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6531 WORD *pwOrdinal)
6533 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6534 const TLBFuncDesc *pFDesc;
6536 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6538 if (pBstrDllName) *pBstrDllName = NULL;
6539 if (pBstrName) *pBstrName = NULL;
6540 if (pwOrdinal) *pwOrdinal = 0;
6542 if (This->TypeAttr.typekind != TKIND_MODULE)
6543 return TYPE_E_BADMODULEKIND;
6545 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6546 if(pFDesc->funcdesc.memid==memid){
6547 dump_TypeInfo(This);
6548 if (TRACE_ON(ole))
6549 dump_TLBFuncDescOne(pFDesc);
6551 if (pBstrDllName)
6552 *pBstrDllName = SysAllocString(This->DllName);
6554 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6555 if (pBstrName)
6556 *pBstrName = SysAllocString(pFDesc->Entry);
6557 if (pwOrdinal)
6558 *pwOrdinal = -1;
6559 return S_OK;
6561 if (pBstrName)
6562 *pBstrName = NULL;
6563 if (pwOrdinal)
6564 *pwOrdinal = (DWORD)pFDesc->Entry;
6565 return S_OK;
6567 return TYPE_E_ELEMENTNOTFOUND;
6570 /* internal function to make the inherited interfaces' methods appear
6571 * part of the interface */
6572 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6573 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6575 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6576 HRESULT hr;
6578 TRACE("%p, 0x%x\n", iface, *hRefType);
6580 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6582 ITypeInfo *pSubTypeInfo;
6584 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6585 if (FAILED(hr))
6586 return hr;
6588 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6589 hRefType, ppTInfo);
6590 ITypeInfo_Release(pSubTypeInfo);
6591 if (SUCCEEDED(hr))
6592 return hr;
6594 *hRefType -= DISPATCH_HREF_OFFSET;
6596 if (!(*hRefType & DISPATCH_HREF_MASK))
6597 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6598 else
6599 return E_FAIL;
6602 /* ITypeInfo::GetRefTypeInfo
6604 * If a type description references other type descriptions, it retrieves
6605 * the referenced type descriptions.
6607 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6608 ITypeInfo2 *iface,
6609 HREFTYPE hRefType,
6610 ITypeInfo **ppTInfo)
6612 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6613 HRESULT result = E_FAIL;
6615 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6617 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6618 ITypeInfo_AddRef(*ppTInfo);
6619 result = S_OK;
6621 else if (hRefType == -1 &&
6622 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6623 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6625 /* when we meet a DUAL dispinterface, we must create the interface
6626 * version of it.
6628 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6631 /* the interface version contains the same information as the dispinterface
6632 * copy the contents of the structs.
6634 *pTypeInfoImpl = *This;
6635 pTypeInfoImpl->ref = 0;
6637 /* change the type to interface */
6638 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6640 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6642 /* we use data structures from This, so we need to keep a reference
6643 * to it to stop it being destroyed and signal to the new instance to
6644 * not free its data structures when it is destroyed */
6645 pTypeInfoImpl->no_free_data = TRUE;
6646 pTypeInfoImpl->next = This;
6647 ITypeInfo_AddRef((ITypeInfo*) This);
6649 ITypeInfo_AddRef(*ppTInfo);
6651 result = S_OK;
6653 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6654 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6655 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6657 HREFTYPE href_dispatch = hRefType;
6658 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6659 } else {
6660 TLBRefType *ref_type;
6661 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6663 if(ref_type->reference == hRefType)
6664 break;
6666 if(&ref_type->entry == &This->pTypeLib->ref_list)
6668 FIXME("Can't find pRefType for ref %x\n", hRefType);
6669 goto end;
6671 if(hRefType != -1) {
6672 ITypeLib *pTLib = NULL;
6674 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6675 UINT Index;
6676 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6677 } else {
6678 if(ref_type->pImpTLInfo->pImpTypeLib) {
6679 TRACE("typeinfo in imported typelib that is already loaded\n");
6680 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6681 ITypeLib2_AddRef(pTLib);
6682 result = S_OK;
6683 } else {
6684 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6685 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6686 ref_type->pImpTLInfo->wVersionMajor,
6687 ref_type->pImpTLInfo->wVersionMinor,
6688 ref_type->pImpTLInfo->lcid,
6689 &pTLib);
6691 if(FAILED(result)) {
6692 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6693 result=LoadTypeLib(libnam, &pTLib);
6694 SysFreeString(libnam);
6696 if(SUCCEEDED(result)) {
6697 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6698 ITypeLib2_AddRef(pTLib);
6702 if(SUCCEEDED(result)) {
6703 if(ref_type->index == TLB_REF_USE_GUID)
6704 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6705 &ref_type->guid,
6706 ppTInfo);
6707 else
6708 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6709 ppTInfo);
6711 if (pTLib != NULL)
6712 ITypeLib2_Release(pTLib);
6716 end:
6717 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6718 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6719 return result;
6722 /* ITypeInfo::AddressOfMember
6724 * Retrieves the addresses of static functions or variables, such as those
6725 * defined in a DLL.
6727 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6728 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6730 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6731 HRESULT hr;
6732 BSTR dll, entry;
6733 WORD ordinal;
6734 HMODULE module;
6736 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6738 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6739 if (FAILED(hr))
6740 return hr;
6742 module = LoadLibraryW(dll);
6743 if (!module)
6745 ERR("couldn't load %s\n", debugstr_w(dll));
6746 SysFreeString(dll);
6747 SysFreeString(entry);
6748 return STG_E_FILENOTFOUND;
6750 /* FIXME: store library somewhere where we can free it */
6752 if (entry)
6754 LPSTR entryA;
6755 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6756 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6757 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6759 *ppv = GetProcAddress(module, entryA);
6760 if (!*ppv)
6761 ERR("function not found %s\n", debugstr_a(entryA));
6763 HeapFree(GetProcessHeap(), 0, entryA);
6765 else
6767 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6768 if (!*ppv)
6769 ERR("function not found %d\n", ordinal);
6772 SysFreeString(dll);
6773 SysFreeString(entry);
6775 if (!*ppv)
6776 return TYPE_E_DLLFUNCTIONNOTFOUND;
6778 return S_OK;
6781 /* ITypeInfo::CreateInstance
6783 * Creates a new instance of a type that describes a component object class
6784 * (coclass).
6786 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6787 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6789 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6790 HRESULT hr;
6791 TYPEATTR *pTA;
6793 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6795 *ppvObj = NULL;
6797 if(pOuterUnk)
6799 WARN("Not able to aggregate\n");
6800 return CLASS_E_NOAGGREGATION;
6803 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6804 if(FAILED(hr)) return hr;
6806 if(pTA->typekind != TKIND_COCLASS)
6808 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6809 hr = E_INVALIDARG;
6810 goto end;
6813 hr = S_FALSE;
6814 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6816 IUnknown *pUnk;
6817 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6818 TRACE("GetActiveObject rets %08x\n", hr);
6819 if(hr == S_OK)
6821 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6822 IUnknown_Release(pUnk);
6826 if(hr != S_OK)
6827 hr = CoCreateInstance(&pTA->guid, NULL,
6828 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6829 riid, ppvObj);
6831 end:
6832 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6833 return hr;
6836 /* ITypeInfo::GetMops
6838 * Retrieves marshalling information.
6840 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6841 BSTR *pBstrMops)
6843 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6844 FIXME("(%p) stub!\n", This);
6845 return S_OK;
6848 /* ITypeInfo::GetContainingTypeLib
6850 * Retrieves the containing type library and the index of the type description
6851 * within that type library.
6853 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6854 ITypeLib * *ppTLib, UINT *pIndex)
6856 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6858 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6859 if (pIndex) {
6860 *pIndex=This->index;
6861 TRACE("returning pIndex=%d\n", *pIndex);
6864 if (ppTLib) {
6865 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6866 ITypeLib2_AddRef(*ppTLib);
6867 TRACE("returning ppTLib=%p\n", *ppTLib);
6870 return S_OK;
6873 /* ITypeInfo::ReleaseTypeAttr
6875 * Releases a TYPEATTR previously returned by GetTypeAttr.
6878 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6879 TYPEATTR* pTypeAttr)
6881 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6882 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6883 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6886 /* ITypeInfo::ReleaseFuncDesc
6888 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6890 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6891 ITypeInfo2 *iface,
6892 FUNCDESC *pFuncDesc)
6894 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6895 SHORT i;
6897 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6899 for (i = 0; i < pFuncDesc->cParams; i++)
6900 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6901 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6903 SysFreeString((BSTR)pFuncDesc);
6906 /* ITypeInfo::ReleaseVarDesc
6908 * Releases a VARDESC previously returned by GetVarDesc.
6910 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6911 VARDESC *pVarDesc)
6913 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6914 TRACE("(%p)->(%p)\n", This, pVarDesc);
6916 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6917 if (pVarDesc->varkind == VAR_CONST)
6918 VariantClear(pVarDesc->u.lpvarValue);
6919 SysFreeString((BSTR)pVarDesc);
6922 /* ITypeInfo2::GetTypeKind
6924 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6927 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6928 TYPEKIND *pTypeKind)
6930 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6931 *pTypeKind=This->TypeAttr.typekind;
6932 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6933 return S_OK;
6936 /* ITypeInfo2::GetTypeFlags
6938 * Returns the type flags without any allocations. This returns a DWORD type
6939 * flag, which expands the type flags without growing the TYPEATTR (type
6940 * attribute).
6943 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6945 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6946 *pTypeFlags=This->TypeAttr.wTypeFlags;
6947 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6948 return S_OK;
6951 /* ITypeInfo2::GetFuncIndexOfMemId
6952 * Binds to a specific member based on a known DISPID, where the member name
6953 * is not known (for example, when binding to a default member).
6956 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6957 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6959 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6960 const TLBFuncDesc *pFuncInfo;
6961 int i;
6962 HRESULT result;
6964 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6965 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6966 break;
6967 if(pFuncInfo) {
6968 *pFuncIndex = i;
6969 result = S_OK;
6970 } else
6971 result = TYPE_E_ELEMENTNOTFOUND;
6973 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6974 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6975 return result;
6978 /* TypeInfo2::GetVarIndexOfMemId
6980 * Binds to a specific member based on a known DISPID, where the member name
6981 * is not known (for example, when binding to a default member).
6984 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6985 MEMBERID memid, UINT *pVarIndex)
6987 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6988 TLBVarDesc *pVarInfo;
6989 int i;
6990 HRESULT result;
6991 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6992 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6994 if(pVarInfo) {
6995 *pVarIndex = i;
6996 result = S_OK;
6997 } else
6998 result = TYPE_E_ELEMENTNOTFOUND;
7000 TRACE("(%p) memid 0x%08x -> %s\n", This,
7001 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7002 return result;
7005 /* ITypeInfo2::GetCustData
7007 * Gets the custom data
7009 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7010 ITypeInfo2 * iface,
7011 REFGUID guid,
7012 VARIANT *pVarVal)
7014 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7015 TLBCustData *pCData;
7017 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7018 if( IsEqualIID(guid, &pCData->guid)) break;
7020 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7022 if(pCData)
7024 VariantInit( pVarVal);
7025 VariantCopy( pVarVal, &pCData->data);
7026 return S_OK;
7028 return E_INVALIDARG; /* FIXME: correct? */
7031 /* ITypeInfo2::GetFuncCustData
7033 * Gets the custom data
7035 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7036 ITypeInfo2 * iface,
7037 UINT index,
7038 REFGUID guid,
7039 VARIANT *pVarVal)
7041 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7042 TLBCustData *pCData=NULL;
7043 TLBFuncDesc * pFDesc;
7044 UINT i;
7045 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7046 pFDesc=pFDesc->next);
7048 if(pFDesc)
7049 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7050 if( IsEqualIID(guid, &pCData->guid)) break;
7052 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7054 if(pCData){
7055 VariantInit( pVarVal);
7056 VariantCopy( pVarVal, &pCData->data);
7057 return S_OK;
7059 return E_INVALIDARG; /* FIXME: correct? */
7062 /* ITypeInfo2::GetParamCustData
7064 * Gets the custom data
7066 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7067 ITypeInfo2 * iface,
7068 UINT indexFunc,
7069 UINT indexParam,
7070 REFGUID guid,
7071 VARIANT *pVarVal)
7073 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7074 TLBCustData *pCData=NULL;
7075 TLBFuncDesc * pFDesc;
7076 UINT i;
7078 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7080 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7081 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7082 pCData = pCData->next)
7083 if( IsEqualIID(guid, &pCData->guid)) break;
7085 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7087 if(pCData)
7089 VariantInit( pVarVal);
7090 VariantCopy( pVarVal, &pCData->data);
7091 return S_OK;
7093 return E_INVALIDARG; /* FIXME: correct? */
7096 /* ITypeInfo2::GetVarCustData
7098 * Gets the custom data
7100 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7101 ITypeInfo2 * iface,
7102 UINT index,
7103 REFGUID guid,
7104 VARIANT *pVarVal)
7106 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7107 TLBCustData *pCData=NULL;
7108 TLBVarDesc * pVDesc;
7109 UINT i;
7111 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7113 if(pVDesc)
7115 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7117 if( IsEqualIID(guid, &pCData->guid)) break;
7121 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7123 if(pCData)
7125 VariantInit( pVarVal);
7126 VariantCopy( pVarVal, &pCData->data);
7127 return S_OK;
7129 return E_INVALIDARG; /* FIXME: correct? */
7132 /* ITypeInfo2::GetImplCustData
7134 * Gets the custom data
7136 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7137 ITypeInfo2 * iface,
7138 UINT index,
7139 REFGUID guid,
7140 VARIANT *pVarVal)
7142 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7143 TLBCustData *pCData=NULL;
7144 TLBImplType * pRDesc;
7145 UINT i;
7147 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7149 if(pRDesc)
7151 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7153 if( IsEqualIID(guid, &pCData->guid)) break;
7157 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7159 if(pCData)
7161 VariantInit( pVarVal);
7162 VariantCopy( pVarVal, &pCData->data);
7163 return S_OK;
7165 return E_INVALIDARG; /* FIXME: correct? */
7168 /* ITypeInfo2::GetDocumentation2
7170 * Retrieves the documentation string, the complete Help file name and path,
7171 * the localization context to use, and the context ID for the library Help
7172 * topic in the Help file.
7175 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7176 ITypeInfo2 * iface,
7177 MEMBERID memid,
7178 LCID lcid,
7179 BSTR *pbstrHelpString,
7180 DWORD *pdwHelpStringContext,
7181 BSTR *pbstrHelpStringDll)
7183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7184 const TLBFuncDesc *pFDesc;
7185 const TLBVarDesc *pVDesc;
7186 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7187 "HelpStringContext(%p) HelpStringDll(%p)\n",
7188 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7189 pbstrHelpStringDll );
7190 /* the help string should be obtained from the helpstringdll,
7191 * using the _DLLGetDocumentation function, based on the supplied
7192 * lcid. Nice to do sometime...
7194 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7195 if(pbstrHelpString)
7196 *pbstrHelpString=SysAllocString(This->Name);
7197 if(pdwHelpStringContext)
7198 *pdwHelpStringContext=This->dwHelpStringContext;
7199 if(pbstrHelpStringDll)
7200 *pbstrHelpStringDll=
7201 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7202 return S_OK;
7203 }else {/* for a member */
7204 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7205 if(pFDesc->funcdesc.memid==memid){
7206 if(pbstrHelpString)
7207 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7208 if(pdwHelpStringContext)
7209 *pdwHelpStringContext=pFDesc->HelpStringContext;
7210 if(pbstrHelpStringDll)
7211 *pbstrHelpStringDll=
7212 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7213 return S_OK;
7215 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7216 if(pVDesc->vardesc.memid==memid){
7217 if(pbstrHelpString)
7218 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7219 if(pdwHelpStringContext)
7220 *pdwHelpStringContext=pVDesc->HelpStringContext;
7221 if(pbstrHelpStringDll)
7222 *pbstrHelpStringDll=
7223 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7224 return S_OK;
7227 return TYPE_E_ELEMENTNOTFOUND;
7230 /* ITypeInfo2::GetAllCustData
7232 * Gets all custom data items for the Type info.
7235 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7236 ITypeInfo2 * iface,
7237 CUSTDATA *pCustData)
7239 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7240 TLBCustData *pCData;
7241 int i;
7243 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7245 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7246 if(pCustData->prgCustData ){
7247 pCustData->cCustData=This->ctCustData;
7248 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7249 pCustData->prgCustData[i].guid=pCData->guid;
7250 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7252 }else{
7253 ERR(" OUT OF MEMORY!\n");
7254 return E_OUTOFMEMORY;
7256 return S_OK;
7259 /* ITypeInfo2::GetAllFuncCustData
7261 * Gets all custom data items for the specified Function
7264 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7265 ITypeInfo2 * iface,
7266 UINT index,
7267 CUSTDATA *pCustData)
7269 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7270 TLBCustData *pCData;
7271 TLBFuncDesc * pFDesc;
7272 UINT i;
7273 TRACE("(%p) index %d\n", This, index);
7274 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7275 pFDesc=pFDesc->next)
7277 if(pFDesc){
7278 pCustData->prgCustData =
7279 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7280 if(pCustData->prgCustData ){
7281 pCustData->cCustData=pFDesc->ctCustData;
7282 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7283 pCData = pCData->next){
7284 pCustData->prgCustData[i].guid=pCData->guid;
7285 VariantCopy(& pCustData->prgCustData[i].varValue,
7286 & pCData->data);
7288 }else{
7289 ERR(" OUT OF MEMORY!\n");
7290 return E_OUTOFMEMORY;
7292 return S_OK;
7294 return TYPE_E_ELEMENTNOTFOUND;
7297 /* ITypeInfo2::GetAllParamCustData
7299 * Gets all custom data items for the Functions
7302 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7303 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7305 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7306 TLBCustData *pCData=NULL;
7307 TLBFuncDesc * pFDesc;
7308 UINT i;
7309 TRACE("(%p) index %d\n", This, indexFunc);
7310 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7311 pFDesc=pFDesc->next)
7313 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7314 pCustData->prgCustData =
7315 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7316 sizeof(CUSTDATAITEM));
7317 if(pCustData->prgCustData ){
7318 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7319 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7320 pCData; i++, pCData = pCData->next){
7321 pCustData->prgCustData[i].guid=pCData->guid;
7322 VariantCopy(& pCustData->prgCustData[i].varValue,
7323 & pCData->data);
7325 }else{
7326 ERR(" OUT OF MEMORY!\n");
7327 return E_OUTOFMEMORY;
7329 return S_OK;
7331 return TYPE_E_ELEMENTNOTFOUND;
7334 /* ITypeInfo2::GetAllVarCustData
7336 * Gets all custom data items for the specified Variable
7339 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7340 UINT index, CUSTDATA *pCustData)
7342 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7343 TLBCustData *pCData;
7344 TLBVarDesc * pVDesc;
7345 UINT i;
7346 TRACE("(%p) index %d\n", This, index);
7347 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7348 pVDesc=pVDesc->next)
7350 if(pVDesc){
7351 pCustData->prgCustData =
7352 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7353 if(pCustData->prgCustData ){
7354 pCustData->cCustData=pVDesc->ctCustData;
7355 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7356 pCData = pCData->next){
7357 pCustData->prgCustData[i].guid=pCData->guid;
7358 VariantCopy(& pCustData->prgCustData[i].varValue,
7359 & pCData->data);
7361 }else{
7362 ERR(" OUT OF MEMORY!\n");
7363 return E_OUTOFMEMORY;
7365 return S_OK;
7367 return TYPE_E_ELEMENTNOTFOUND;
7370 /* ITypeInfo2::GetAllImplCustData
7372 * Gets all custom data items for the specified implementation type
7375 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7376 ITypeInfo2 * iface,
7377 UINT index,
7378 CUSTDATA *pCustData)
7380 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7381 TLBCustData *pCData;
7382 TLBImplType * pRDesc;
7383 UINT i;
7384 TRACE("(%p) index %d\n", This, index);
7385 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7386 pRDesc=pRDesc->next)
7388 if(pRDesc){
7389 pCustData->prgCustData =
7390 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7391 if(pCustData->prgCustData ){
7392 pCustData->cCustData=pRDesc->ctCustData;
7393 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7394 pCData = pCData->next){
7395 pCustData->prgCustData[i].guid=pCData->guid;
7396 VariantCopy(& pCustData->prgCustData[i].varValue,
7397 & pCData->data);
7399 }else{
7400 ERR(" OUT OF MEMORY!\n");
7401 return E_OUTOFMEMORY;
7403 return S_OK;
7405 return TYPE_E_ELEMENTNOTFOUND;
7408 static const ITypeInfo2Vtbl tinfvt =
7411 ITypeInfo_fnQueryInterface,
7412 ITypeInfo_fnAddRef,
7413 ITypeInfo_fnRelease,
7415 ITypeInfo_fnGetTypeAttr,
7416 ITypeInfo_fnGetTypeComp,
7417 ITypeInfo_fnGetFuncDesc,
7418 ITypeInfo_fnGetVarDesc,
7419 ITypeInfo_fnGetNames,
7420 ITypeInfo_fnGetRefTypeOfImplType,
7421 ITypeInfo_fnGetImplTypeFlags,
7422 ITypeInfo_fnGetIDsOfNames,
7423 ITypeInfo_fnInvoke,
7424 ITypeInfo_fnGetDocumentation,
7425 ITypeInfo_fnGetDllEntry,
7426 ITypeInfo_fnGetRefTypeInfo,
7427 ITypeInfo_fnAddressOfMember,
7428 ITypeInfo_fnCreateInstance,
7429 ITypeInfo_fnGetMops,
7430 ITypeInfo_fnGetContainingTypeLib,
7431 ITypeInfo_fnReleaseTypeAttr,
7432 ITypeInfo_fnReleaseFuncDesc,
7433 ITypeInfo_fnReleaseVarDesc,
7435 ITypeInfo2_fnGetTypeKind,
7436 ITypeInfo2_fnGetTypeFlags,
7437 ITypeInfo2_fnGetFuncIndexOfMemId,
7438 ITypeInfo2_fnGetVarIndexOfMemId,
7439 ITypeInfo2_fnGetCustData,
7440 ITypeInfo2_fnGetFuncCustData,
7441 ITypeInfo2_fnGetParamCustData,
7442 ITypeInfo2_fnGetVarCustData,
7443 ITypeInfo2_fnGetImplTypeCustData,
7444 ITypeInfo2_fnGetDocumentation2,
7445 ITypeInfo2_fnGetAllCustData,
7446 ITypeInfo2_fnGetAllFuncCustData,
7447 ITypeInfo2_fnGetAllParamCustData,
7448 ITypeInfo2_fnGetAllVarCustData,
7449 ITypeInfo2_fnGetAllImplTypeCustData,
7452 /******************************************************************************
7453 * CreateDispTypeInfo [OLEAUT32.31]
7455 * Build type information for an object so it can be called through an
7456 * IDispatch interface.
7458 * RETURNS
7459 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7460 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7462 * NOTES
7463 * This call allows an objects methods to be accessed through IDispatch, by
7464 * building an ITypeInfo object that IDispatch can use to call through.
7466 HRESULT WINAPI CreateDispTypeInfo(
7467 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7468 LCID lcid, /* [I] Locale Id */
7469 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7471 ITypeInfoImpl *pTIClass, *pTIIface;
7472 ITypeLibImpl *pTypeLibImpl;
7473 unsigned int param, func;
7474 TLBFuncDesc **ppFuncDesc;
7475 TLBRefType *ref;
7477 TRACE("\n");
7478 pTypeLibImpl = TypeLibImpl_Constructor();
7479 if (!pTypeLibImpl) return E_FAIL;
7481 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7482 pTIIface->pTypeLib = pTypeLibImpl;
7483 pTIIface->index = 0;
7484 pTIIface->Name = NULL;
7485 pTIIface->dwHelpContext = -1;
7486 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7487 pTIIface->TypeAttr.lcid = lcid;
7488 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7489 pTIIface->TypeAttr.wMajorVerNum = 0;
7490 pTIIface->TypeAttr.wMinorVerNum = 0;
7491 pTIIface->TypeAttr.cbAlignment = 2;
7492 pTIIface->TypeAttr.cbSizeInstance = -1;
7493 pTIIface->TypeAttr.cbSizeVft = -1;
7494 pTIIface->TypeAttr.cFuncs = 0;
7495 pTIIface->TypeAttr.cImplTypes = 0;
7496 pTIIface->TypeAttr.cVars = 0;
7497 pTIIface->TypeAttr.wTypeFlags = 0;
7499 ppFuncDesc = &pTIIface->funclist;
7500 for(func = 0; func < pidata->cMembers; func++) {
7501 METHODDATA *md = pidata->pmethdata + func;
7502 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7503 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7504 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7505 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7506 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7507 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7508 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7509 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7510 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7511 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7512 (*ppFuncDesc)->funcdesc.cScodes = 0;
7513 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7514 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7515 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7516 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7517 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7518 md->cArgs * sizeof(ELEMDESC));
7519 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7520 md->cArgs * sizeof(TLBParDesc));
7521 for(param = 0; param < md->cArgs; param++) {
7522 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7523 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7525 (*ppFuncDesc)->helpcontext = 0;
7526 (*ppFuncDesc)->HelpStringContext = 0;
7527 (*ppFuncDesc)->HelpString = NULL;
7528 (*ppFuncDesc)->Entry = NULL;
7529 (*ppFuncDesc)->ctCustData = 0;
7530 (*ppFuncDesc)->pCustData = NULL;
7531 (*ppFuncDesc)->next = NULL;
7532 pTIIface->TypeAttr.cFuncs++;
7533 ppFuncDesc = &(*ppFuncDesc)->next;
7536 dump_TypeInfo(pTIIface);
7538 pTypeLibImpl->pTypeInfo = pTIIface;
7539 pTypeLibImpl->TypeInfoCount++;
7541 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7542 pTIClass->pTypeLib = pTypeLibImpl;
7543 pTIClass->index = 1;
7544 pTIClass->Name = NULL;
7545 pTIClass->dwHelpContext = -1;
7546 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7547 pTIClass->TypeAttr.lcid = lcid;
7548 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7549 pTIClass->TypeAttr.wMajorVerNum = 0;
7550 pTIClass->TypeAttr.wMinorVerNum = 0;
7551 pTIClass->TypeAttr.cbAlignment = 2;
7552 pTIClass->TypeAttr.cbSizeInstance = -1;
7553 pTIClass->TypeAttr.cbSizeVft = -1;
7554 pTIClass->TypeAttr.cFuncs = 0;
7555 pTIClass->TypeAttr.cImplTypes = 1;
7556 pTIClass->TypeAttr.cVars = 0;
7557 pTIClass->TypeAttr.wTypeFlags = 0;
7559 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7560 pTIClass->impltypelist->hRef = 0;
7562 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7563 ref->index = 0;
7564 ref->reference = 0;
7565 ref->pImpTLInfo = TLB_REF_INTERNAL;
7566 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7568 dump_TypeInfo(pTIClass);
7570 pTIIface->next = pTIClass;
7571 pTypeLibImpl->TypeInfoCount++;
7573 *pptinfo = (ITypeInfo*)pTIClass;
7575 ITypeInfo_AddRef(*pptinfo);
7576 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7578 return S_OK;
7582 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7584 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7586 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7589 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7591 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7593 return ITypeInfo_AddRef((ITypeInfo *)This);
7596 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7598 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7600 return ITypeInfo_Release((ITypeInfo *)This);
7603 static HRESULT WINAPI ITypeComp_fnBind(
7604 ITypeComp * iface,
7605 OLECHAR * szName,
7606 ULONG lHash,
7607 WORD wFlags,
7608 ITypeInfo ** ppTInfo,
7609 DESCKIND * pDescKind,
7610 BINDPTR * pBindPtr)
7612 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7613 const TLBFuncDesc *pFDesc;
7614 const TLBVarDesc *pVDesc;
7615 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7617 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7619 *pDescKind = DESCKIND_NONE;
7620 pBindPtr->lpfuncdesc = NULL;
7621 *ppTInfo = NULL;
7623 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7624 if (!strcmpiW(pFDesc->Name, szName)) {
7625 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7626 break;
7627 else
7628 /* name found, but wrong flags */
7629 hr = TYPE_E_TYPEMISMATCH;
7632 if (pFDesc)
7634 HRESULT hr = TLB_AllocAndInitFuncDesc(
7635 &pFDesc->funcdesc,
7636 &pBindPtr->lpfuncdesc,
7637 This->TypeAttr.typekind == TKIND_DISPATCH);
7638 if (FAILED(hr))
7639 return hr;
7640 *pDescKind = DESCKIND_FUNCDESC;
7641 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7642 ITypeInfo_AddRef(*ppTInfo);
7643 return S_OK;
7644 } else {
7645 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7646 if (!strcmpiW(pVDesc->Name, szName)) {
7647 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7648 if (FAILED(hr))
7649 return hr;
7650 *pDescKind = DESCKIND_VARDESC;
7651 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7652 ITypeInfo_AddRef(*ppTInfo);
7653 return S_OK;
7657 /* FIXME: search each inherited interface, not just the first */
7658 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7659 /* recursive search */
7660 ITypeInfo *pTInfo;
7661 ITypeComp *pTComp;
7662 HRESULT hr;
7663 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7664 if (SUCCEEDED(hr))
7666 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7667 ITypeInfo_Release(pTInfo);
7669 if (SUCCEEDED(hr))
7671 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7672 ITypeComp_Release(pTComp);
7673 return hr;
7675 WARN("Could not search inherited interface!\n");
7677 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7678 return hr;
7681 static HRESULT WINAPI ITypeComp_fnBindType(
7682 ITypeComp * iface,
7683 OLECHAR * szName,
7684 ULONG lHash,
7685 ITypeInfo ** ppTInfo,
7686 ITypeComp ** ppTComp)
7688 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7690 /* strange behaviour (does nothing) but like the
7691 * original */
7693 if (!ppTInfo || !ppTComp)
7694 return E_POINTER;
7696 *ppTInfo = NULL;
7697 *ppTComp = NULL;
7699 return S_OK;
7702 static const ITypeCompVtbl tcompvt =
7705 ITypeComp_fnQueryInterface,
7706 ITypeComp_fnAddRef,
7707 ITypeComp_fnRelease,
7709 ITypeComp_fnBind,
7710 ITypeComp_fnBindType