push 915ca0aa9d2991375796d4b573b1be50b5f1fb2c
[wine/hacks.git] / dlls / oleaut32 / typelib.c
blob9bc601ec42f01166f58e93b6050aa2700f1ed724
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/winbase16.h"
70 #include "wine/unicode.h"
71 #include "objbase.h"
72 #include "typelib.h"
73 #include "wine/debug.h"
74 #include "variant.h"
75 #include "wine/list.h"
77 WINE_DEFAULT_DEBUG_CHANNEL(ole);
78 WINE_DECLARE_DEBUG_CHANNEL(typelib);
80 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
81 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
83 /****************************************************************************
84 * FromLExxx
86 * Takes p_iVal (which is in little endian) and returns it
87 * in the host machine's byte order.
89 #ifdef WORDS_BIGENDIAN
90 static WORD FromLEWord(WORD p_iVal)
92 return (((p_iVal & 0x00FF) << 8) |
93 ((p_iVal & 0xFF00) >> 8));
97 static DWORD FromLEDWord(DWORD p_iVal)
99 return (((p_iVal & 0x000000FF) << 24) |
100 ((p_iVal & 0x0000FF00) << 8) |
101 ((p_iVal & 0x00FF0000) >> 8) |
102 ((p_iVal & 0xFF000000) >> 24));
104 #else
105 #define FromLEWord(X) (X)
106 #define FromLEDWord(X) (X)
107 #endif
109 #define DISPATCH_HREF_OFFSET 0x01000000
110 #define DISPATCH_HREF_MASK 0xff000000
112 /****************************************************************************
113 * FromLExxx
115 * Fix byte order in any structure if necessary
117 #ifdef WORDS_BIGENDIAN
118 static void FromLEWords(void *p_Val, int p_iSize)
120 WORD *Val = p_Val;
122 p_iSize /= sizeof(WORD);
124 while (p_iSize) {
125 *Val = FromLEWord(*Val);
126 Val++;
127 p_iSize--;
132 static void FromLEDWords(void *p_Val, int p_iSize)
134 DWORD *Val = p_Val;
136 p_iSize /= sizeof(DWORD);
138 while (p_iSize) {
139 *Val = FromLEDWord(*Val);
140 Val++;
141 p_iSize--;
144 #else
145 #define FromLEWords(X,Y) /*nothing*/
146 #define FromLEDWords(X,Y) /*nothing*/
147 #endif
150 * Find a typelib key which matches a requested maj.min version.
152 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
154 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
155 WCHAR buffer[60];
156 char key_name[16];
157 DWORD len, i;
158 INT best_min = -1;
159 HKEY hkey;
161 memcpy( buffer, typelibW, sizeof(typelibW) );
162 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
165 return FALSE;
167 len = sizeof(key_name);
168 i = 0;
169 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
171 INT v_maj, v_min;
173 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
175 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
177 if (wMaj == v_maj)
179 if (*wMin == v_min)
181 best_min = v_min;
182 break; /* exact match */
184 if (v_min > best_min) best_min = v_min;
187 len = sizeof(key_name);
189 RegCloseKey( hkey );
190 if (best_min >= 0)
192 *wMin = best_min;
193 return TRUE;
195 return FALSE;
198 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
199 /* buffer must be at least 60 characters long */
200 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
202 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
203 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
205 memcpy( buffer, TypelibW, sizeof(TypelibW) );
206 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
207 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
208 return buffer;
211 /* get the path of an interface key, in the form "Interface\\<guid>" */
212 /* buffer must be at least 50 characters long */
213 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
215 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
217 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
218 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
219 return buffer;
222 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
223 /* buffer must be at least 16 characters long */
224 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
226 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
227 static const WCHAR win16W[] = {'w','i','n','1','6',0};
228 static const WCHAR win32W[] = {'w','i','n','3','2',0};
230 sprintfW( buffer, LcidFormatW, lcid );
231 switch(syskind)
233 case SYS_WIN16: strcatW( buffer, win16W ); break;
234 case SYS_WIN32: strcatW( buffer, win32W ); break;
235 default:
236 TRACE("Typelib is for unsupported syskind %i\n", syskind);
237 return NULL;
239 return buffer;
242 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
245 /****************************************************************************
246 * QueryPathOfRegTypeLib [OLEAUT32.164]
248 * Gets the path to a registered type library.
250 * PARAMS
251 * guid [I] referenced guid
252 * wMaj [I] major version
253 * wMin [I] minor version
254 * lcid [I] locale id
255 * path [O] path of typelib
257 * RETURNS
258 * Success: S_OK.
259 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
260 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
261 * opened.
263 HRESULT WINAPI QueryPathOfRegTypeLib(
264 REFGUID guid,
265 WORD wMaj,
266 WORD wMin,
267 LCID lcid,
268 LPBSTR path )
270 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
271 LCID myLCID = lcid;
272 HKEY hkey;
273 WCHAR buffer[60];
274 WCHAR Path[MAX_PATH];
275 LONG res;
277 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
279 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
280 get_typelib_key( guid, wMaj, wMin, buffer );
282 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
283 if (res == ERROR_FILE_NOT_FOUND)
285 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
286 return TYPE_E_LIBNOTREGISTERED;
288 else if (res != ERROR_SUCCESS)
290 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
291 return TYPE_E_REGISTRYACCESS;
294 while (hr != S_OK)
296 LONG dwPathLen = sizeof(Path);
298 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
300 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
302 if (!lcid)
303 break;
304 else if (myLCID == lcid)
306 /* try with sub-langid */
307 myLCID = SUBLANGID(lcid);
309 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
311 /* try with system langid */
312 myLCID = 0;
314 else
316 break;
319 else
321 *path = SysAllocString( Path );
322 hr = S_OK;
325 RegCloseKey( hkey );
326 TRACE_(typelib)("-- 0x%08x\n", hr);
327 return hr;
330 /******************************************************************************
331 * CreateTypeLib [OLEAUT32.160] creates a typelib
333 * RETURNS
334 * Success: S_OK
335 * Failure: Status
337 HRESULT WINAPI CreateTypeLib(
338 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
340 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
341 return E_FAIL;
344 /******************************************************************************
345 * LoadTypeLib [OLEAUT32.161]
347 * Loads a type library
349 * PARAMS
350 * szFile [I] Name of file to load from.
351 * pptLib [O] Pointer that receives ITypeLib object on success.
353 * RETURNS
354 * Success: S_OK
355 * Failure: Status
357 * SEE
358 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
360 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
362 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
363 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
366 /******************************************************************************
367 * LoadTypeLibEx [OLEAUT32.183]
369 * Loads and optionally registers a type library
371 * RETURNS
372 * Success: S_OK
373 * Failure: Status
375 HRESULT WINAPI LoadTypeLibEx(
376 LPCOLESTR szFile, /* [in] Name of file to load from */
377 REGKIND regkind, /* [in] Specify kind of registration */
378 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
380 WCHAR szPath[MAX_PATH+1];
381 HRESULT res;
383 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
385 *pptLib = NULL;
387 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
389 if (SUCCEEDED(res))
390 switch(regkind)
392 case REGKIND_DEFAULT:
393 /* don't register typelibs supplied with full path. Experimentation confirms the following */
394 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
395 (szFile[0] && (szFile[1] == ':'))) break;
396 /* else fall-through */
398 case REGKIND_REGISTER:
399 if (FAILED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
401 IUnknown_Release(*pptLib);
402 *pptLib = 0;
404 break;
405 case REGKIND_NONE:
406 break;
409 TRACE(" returns %08x\n",res);
410 return res;
413 /******************************************************************************
414 * LoadRegTypeLib [OLEAUT32.162]
416 * Loads a registered type library.
418 * PARAMS
419 * rguid [I] GUID of the registered type library.
420 * wVerMajor [I] major version.
421 * wVerMinor [I] minor version.
422 * lcid [I] locale ID.
423 * ppTLib [O] pointer that receives an ITypeLib object on success.
425 * RETURNS
426 * Success: S_OK.
427 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
428 * LoadTypeLib.
430 HRESULT WINAPI LoadRegTypeLib(
431 REFGUID rguid,
432 WORD wVerMajor,
433 WORD wVerMinor,
434 LCID lcid,
435 ITypeLib **ppTLib)
437 BSTR bstr=NULL;
438 HRESULT res;
440 *ppTLib = NULL;
442 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
444 if(SUCCEEDED(res))
446 res= LoadTypeLib(bstr, ppTLib);
447 SysFreeString(bstr);
450 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
452 return res;
456 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
457 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
458 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
459 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
460 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
461 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
463 /******************************************************************************
464 * RegisterTypeLib [OLEAUT32.163]
465 * Adds information about a type library to the System Registry
466 * NOTES
467 * Docs: ITypeLib FAR * ptlib
468 * Docs: OLECHAR FAR* szFullPath
469 * Docs: OLECHAR FAR* szHelpDir
471 * RETURNS
472 * Success: S_OK
473 * Failure: Status
475 HRESULT WINAPI RegisterTypeLib(
476 ITypeLib * ptlib, /* [in] Pointer to the library*/
477 OLECHAR * szFullPath, /* [in] full Path of the library*/
478 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
479 may be NULL*/
481 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
482 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
483 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
484 HRESULT res;
485 TLIBATTR *attr;
486 WCHAR keyName[60];
487 WCHAR tmp[16];
488 HKEY key, subKey;
489 UINT types, tidx;
490 TYPEKIND kind;
491 DWORD disposition;
493 if (ptlib == NULL || szFullPath == NULL)
494 return E_INVALIDARG;
496 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
497 return E_FAIL;
499 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
501 res = S_OK;
502 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
503 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
505 LPOLESTR doc;
507 /* Set the human-readable name of the typelib */
508 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
510 if (RegSetValueExW(key, NULL, 0, REG_SZ,
511 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
512 res = E_FAIL;
514 SysFreeString(doc);
516 else
517 res = E_FAIL;
519 /* Make up the name of the typelib path subkey */
520 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
522 /* Create the typelib path subkey */
523 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
524 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
526 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
527 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
528 res = E_FAIL;
530 RegCloseKey(subKey);
532 else
533 res = E_FAIL;
535 /* Create the flags subkey */
536 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
537 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
539 /* FIXME: is %u correct? */
540 static const WCHAR formatW[] = {'%','u',0};
541 WCHAR buf[20];
542 sprintfW(buf, formatW, attr->wLibFlags);
543 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
544 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
545 res = E_FAIL;
547 RegCloseKey(subKey);
549 else
550 res = E_FAIL;
552 /* create the helpdir subkey */
553 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
554 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
556 BOOL freeHelpDir = FALSE;
557 OLECHAR* pIndexStr;
559 /* if we created a new key, and helpDir was null, set the helpdir
560 to the directory which contains the typelib. However,
561 if we just opened an existing key, we leave the helpdir alone */
562 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
563 szHelpDir = SysAllocString(szFullPath);
564 pIndexStr = strrchrW(szHelpDir, '\\');
565 if (pIndexStr) {
566 *pIndexStr = 0;
568 freeHelpDir = TRUE;
571 /* if we have an szHelpDir, set it! */
572 if (szHelpDir != NULL) {
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
575 res = E_FAIL;
579 /* tidy up */
580 if (freeHelpDir) SysFreeString(szHelpDir);
581 RegCloseKey(subKey);
583 } else {
584 res = E_FAIL;
587 RegCloseKey(key);
589 else
590 res = E_FAIL;
592 /* register OLE Automation-compatible interfaces for this typelib */
593 types = ITypeLib_GetTypeInfoCount(ptlib);
594 for (tidx=0; tidx<types; tidx++) {
595 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
596 LPOLESTR name = NULL;
597 ITypeInfo *tinfo = NULL;
599 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
601 switch (kind) {
602 case TKIND_INTERFACE:
603 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
604 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
605 break;
607 case TKIND_DISPATCH:
608 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
609 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
610 break;
612 default:
613 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
614 break;
617 if (tinfo) {
618 TYPEATTR *tattr = NULL;
619 ITypeInfo_GetTypeAttr(tinfo, &tattr);
621 if (tattr) {
622 TRACE_(typelib)("guid=%s, flags=%04x (",
623 debugstr_guid(&tattr->guid),
624 tattr->wTypeFlags);
626 if (TRACE_ON(typelib)) {
627 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
628 XX(FAPPOBJECT);
629 XX(FCANCREATE);
630 XX(FLICENSED);
631 XX(FPREDECLID);
632 XX(FHIDDEN);
633 XX(FCONTROL);
634 XX(FDUAL);
635 XX(FNONEXTENSIBLE);
636 XX(FOLEAUTOMATION);
637 XX(FRESTRICTED);
638 XX(FAGGREGATABLE);
639 XX(FREPLACEABLE);
640 XX(FDISPATCHABLE);
641 XX(FREVERSEBIND);
642 XX(FPROXY);
643 #undef XX
644 MESSAGE("\n");
647 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
649 /* register interface<->typelib coupling */
650 get_interface_key( &tattr->guid, keyName );
651 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
652 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
654 if (name)
655 RegSetValueExW(key, NULL, 0, REG_SZ,
656 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
658 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
659 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
660 RegSetValueExW(subKey, NULL, 0, REG_SZ,
661 (const BYTE *)PSOA, sizeof PSOA);
662 RegCloseKey(subKey);
665 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
666 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
667 RegSetValueExW(subKey, NULL, 0, REG_SZ,
668 (const BYTE *)PSOA, sizeof PSOA);
669 RegCloseKey(subKey);
672 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
673 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
675 WCHAR buffer[40];
676 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
677 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
679 StringFromGUID2(&attr->guid, buffer, 40);
680 RegSetValueExW(subKey, NULL, 0, REG_SZ,
681 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
682 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
683 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
684 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
685 RegCloseKey(subKey);
688 RegCloseKey(key);
692 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
695 ITypeInfo_Release(tinfo);
698 SysFreeString(name);
702 ITypeLib_ReleaseTLibAttr(ptlib, attr);
704 return res;
708 /******************************************************************************
709 * UnRegisterTypeLib [OLEAUT32.186]
710 * Removes information about a type library from the System Registry
711 * NOTES
713 * RETURNS
714 * Success: S_OK
715 * Failure: Status
717 HRESULT WINAPI UnRegisterTypeLib(
718 REFGUID libid, /* [in] Guid of the library */
719 WORD wVerMajor, /* [in] major version */
720 WORD wVerMinor, /* [in] minor version */
721 LCID lcid, /* [in] locale id */
722 SYSKIND syskind)
724 BSTR tlibPath = NULL;
725 DWORD tmpLength;
726 WCHAR keyName[60];
727 WCHAR subKeyName[50];
728 int result = S_OK;
729 DWORD i = 0;
730 BOOL deleteOtherStuff;
731 HKEY key = NULL;
732 HKEY subKey = NULL;
733 TYPEATTR* typeAttr = NULL;
734 TYPEKIND kind;
735 ITypeInfo* typeInfo = NULL;
736 ITypeLib* typeLib = NULL;
737 int numTypes;
739 TRACE("(IID: %s)\n",debugstr_guid(libid));
741 /* Create the path to the key */
742 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
744 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
746 TRACE("Unsupported syskind %i\n", syskind);
747 result = E_INVALIDARG;
748 goto end;
751 /* get the path to the typelib on disk */
752 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
753 result = E_INVALIDARG;
754 goto end;
757 /* Try and open the key to the type library. */
758 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
759 result = E_INVALIDARG;
760 goto end;
763 /* Try and load the type library */
764 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
765 result = TYPE_E_INVALIDSTATE;
766 goto end;
769 /* remove any types registered with this typelib */
770 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
771 for (i=0; i<numTypes; i++) {
772 /* get the kind of type */
773 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
774 goto enddeleteloop;
777 /* skip non-interfaces, and get type info for the type */
778 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
779 goto enddeleteloop;
781 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
782 goto enddeleteloop;
784 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
785 goto enddeleteloop;
788 /* the path to the type */
789 get_interface_key( &typeAttr->guid, subKeyName );
791 /* Delete its bits */
792 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
793 goto enddeleteloop;
795 RegDeleteKeyW(subKey, ProxyStubClsidW);
796 RegDeleteKeyW(subKey, ProxyStubClsid32W);
797 RegDeleteKeyW(subKey, TypeLibW);
798 RegCloseKey(subKey);
799 subKey = NULL;
800 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
802 enddeleteloop:
803 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
804 typeAttr = NULL;
805 if (typeInfo) ITypeInfo_Release(typeInfo);
806 typeInfo = NULL;
809 /* Now, delete the type library path subkey */
810 get_lcid_subkey( lcid, syskind, subKeyName );
811 RegDeleteKeyW(key, subKeyName);
812 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
813 RegDeleteKeyW(key, subKeyName);
815 /* check if there is anything besides the FLAGS/HELPDIR keys.
816 If there is, we don't delete them */
817 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
818 deleteOtherStuff = TRUE;
819 i = 0;
820 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
821 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
823 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
824 if (!strcmpW(subKeyName, FLAGSW)) continue;
825 if (!strcmpW(subKeyName, HELPDIRW)) continue;
826 deleteOtherStuff = FALSE;
827 break;
830 /* only delete the other parts of the key if we're absolutely sure */
831 if (deleteOtherStuff) {
832 RegDeleteKeyW(key, FLAGSW);
833 RegDeleteKeyW(key, HELPDIRW);
834 RegCloseKey(key);
835 key = NULL;
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
838 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
839 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
842 end:
843 SysFreeString(tlibPath);
844 if (typeLib) ITypeLib_Release(typeLib);
845 if (subKey) RegCloseKey(subKey);
846 if (key) RegCloseKey(key);
847 return result;
850 /*======================= ITypeLib implementation =======================*/
852 typedef struct tagTLBCustData
854 GUID guid;
855 VARIANT data;
856 struct tagTLBCustData* next;
857 } TLBCustData;
859 /* data structure for import typelibs */
860 typedef struct tagTLBImpLib
862 int offset; /* offset in the file (MSFT)
863 offset in nametable (SLTG)
864 just used to identify library while reading
865 data from file */
866 GUID guid; /* libid */
867 BSTR name; /* name */
869 LCID lcid; /* lcid of imported typelib */
871 WORD wVersionMajor; /* major version number */
872 WORD wVersionMinor; /* minor version number */
874 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
875 NULL if not yet loaded */
876 struct tagTLBImpLib * next;
877 } TLBImpLib;
879 /* internal ITypeLib data */
880 typedef struct tagITypeLibImpl
882 const ITypeLib2Vtbl *lpVtbl;
883 const ITypeCompVtbl *lpVtblTypeComp;
884 LONG ref;
885 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
887 /* strings can be stored in tlb as multibyte strings BUT they are *always*
888 * exported to the application as a UNICODE string.
890 BSTR Name;
891 BSTR DocString;
892 BSTR HelpFile;
893 BSTR HelpStringDll;
894 unsigned long dwHelpContext;
895 int TypeInfoCount; /* nr of typeinfo's in librarry */
896 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
897 int ctCustData; /* number of items in cust data list */
898 TLBCustData * pCustData; /* linked list to cust data */
899 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
900 int ctTypeDesc; /* number of items in type desc array */
901 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
902 library. Only used while reading MSFT
903 typelibs */
904 struct list ref_list; /* list of ref types in this typelib */
905 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
908 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
909 struct tagITypeLibImpl *next, *prev;
910 WCHAR *path;
911 INT index;
912 } ITypeLibImpl;
914 static const ITypeLib2Vtbl tlbvt;
915 static const ITypeCompVtbl tlbtcvt;
917 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
919 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
922 /* ITypeLib methods */
923 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
924 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
926 /*======================= ITypeInfo implementation =======================*/
928 /* data for referenced types */
929 typedef struct tagTLBRefType
931 INT index; /* Type index for internal ref or for external ref
932 it the format is SLTG. -2 indicates to
933 use guid */
935 GUID guid; /* guid of the referenced type */
936 /* if index == TLB_REF_USE_GUID */
938 HREFTYPE reference; /* The href of this ref */
939 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
940 TLB_REF_INTERNAL for internal refs
941 TLB_REF_NOT_FOUND for broken refs */
943 struct list entry;
944 } TLBRefType;
946 #define TLB_REF_USE_GUID -2
948 #define TLB_REF_INTERNAL (void*)-2
949 #define TLB_REF_NOT_FOUND (void*)-1
951 /* internal Parameter data */
952 typedef struct tagTLBParDesc
954 BSTR Name;
955 int ctCustData;
956 TLBCustData * pCustData; /* linked list to cust data */
957 } TLBParDesc;
959 /* internal Function data */
960 typedef struct tagTLBFuncDesc
962 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
963 BSTR Name; /* the name of this function */
964 TLBParDesc *pParamDesc; /* array with param names and custom data */
965 int helpcontext;
966 int HelpStringContext;
967 BSTR HelpString;
968 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
969 int ctCustData;
970 TLBCustData * pCustData; /* linked list to cust data; */
971 struct tagTLBFuncDesc * next;
972 } TLBFuncDesc;
974 /* internal Variable data */
975 typedef struct tagTLBVarDesc
977 VARDESC vardesc; /* lots of info on the variable and its attributes. */
978 BSTR Name; /* the name of this variable */
979 int HelpContext;
980 int HelpStringContext; /* FIXME: where? */
981 BSTR HelpString;
982 int ctCustData;
983 TLBCustData * pCustData;/* linked list to cust data; */
984 struct tagTLBVarDesc * next;
985 } TLBVarDesc;
987 /* internal implemented interface data */
988 typedef struct tagTLBImplType
990 HREFTYPE hRef; /* hRef of interface */
991 int implflags; /* IMPLFLAG_*s */
992 int ctCustData;
993 TLBCustData * pCustData;/* linked list to custom data; */
994 struct tagTLBImplType *next;
995 } TLBImplType;
997 /* internal TypeInfo data */
998 typedef struct tagITypeInfoImpl
1000 const ITypeInfo2Vtbl *lpVtbl;
1001 const ITypeCompVtbl *lpVtblTypeComp;
1002 LONG ref;
1003 BOOL no_free_data; /* don't free data structures */
1004 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1005 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1006 int index; /* index in this typelib; */
1007 HREFTYPE hreftype; /* hreftype for app object binding */
1008 /* type libs seem to store the doc strings in ascii
1009 * so why should we do it in unicode?
1011 BSTR Name;
1012 BSTR DocString;
1013 BSTR DllName;
1014 unsigned long dwHelpContext;
1015 unsigned long dwHelpStringContext;
1017 /* functions */
1018 TLBFuncDesc * funclist; /* linked list with function descriptions */
1020 /* variables */
1021 TLBVarDesc * varlist; /* linked list with variable descriptions */
1023 /* Implemented Interfaces */
1024 TLBImplType * impltypelist;
1026 int ctCustData;
1027 TLBCustData * pCustData; /* linked list to cust data; */
1028 struct tagITypeInfoImpl * next;
1029 } ITypeInfoImpl;
1031 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1033 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1036 static const ITypeInfo2Vtbl tinfvt;
1037 static const ITypeCompVtbl tcompvt;
1039 static ITypeInfo2 * ITypeInfo_Constructor(void);
1041 typedef struct tagTLBContext
1043 unsigned int oStart; /* start of TLB in file */
1044 unsigned int pos; /* current pos */
1045 unsigned int length; /* total length */
1046 void *mapping; /* memory mapping */
1047 MSFT_SegDir * pTblDir;
1048 ITypeLibImpl* pLibInfo;
1049 } TLBContext;
1052 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1055 debug
1057 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1058 if (pTD->vt & VT_RESERVED)
1059 szVarType += strlen(strcpy(szVarType, "reserved | "));
1060 if (pTD->vt & VT_BYREF)
1061 szVarType += strlen(strcpy(szVarType, "ref to "));
1062 if (pTD->vt & VT_ARRAY)
1063 szVarType += strlen(strcpy(szVarType, "array of "));
1064 if (pTD->vt & VT_VECTOR)
1065 szVarType += strlen(strcpy(szVarType, "vector of "));
1066 switch(pTD->vt & VT_TYPEMASK) {
1067 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1068 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1069 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1070 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1071 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1072 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1073 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1074 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1075 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1076 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1077 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1078 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1079 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1080 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1081 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1082 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1083 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1084 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1085 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1086 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1087 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1088 pTD->u.hreftype); break;
1089 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1090 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1091 case VT_PTR: sprintf(szVarType, "ptr to ");
1092 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1093 break;
1094 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1095 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1096 break;
1097 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1098 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1099 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1100 break;
1102 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1106 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1107 char buf[200];
1108 USHORT flags = edesc->u.paramdesc.wParamFlags;
1109 dump_TypeDesc(&edesc->tdesc,buf);
1110 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1111 MESSAGE("\t\tu.paramdesc.wParamFlags");
1112 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1113 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1114 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1115 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1116 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1117 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1118 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1119 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1120 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1122 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1123 int i;
1124 MESSAGE("memid is %08x\n",funcdesc->memid);
1125 for (i=0;i<funcdesc->cParams;i++) {
1126 MESSAGE("Param %d:\n",i);
1127 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1129 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1130 switch (funcdesc->funckind) {
1131 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1132 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1133 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1134 case FUNC_STATIC: MESSAGE("static");break;
1135 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1136 default: MESSAGE("unknown");break;
1138 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1139 switch (funcdesc->invkind) {
1140 case INVOKE_FUNC: MESSAGE("func");break;
1141 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1142 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1143 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1145 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1146 switch (funcdesc->callconv) {
1147 case CC_CDECL: MESSAGE("cdecl");break;
1148 case CC_PASCAL: MESSAGE("pascal");break;
1149 case CC_STDCALL: MESSAGE("stdcall");break;
1150 case CC_SYSCALL: MESSAGE("syscall");break;
1151 default:break;
1153 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1154 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1155 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1157 MESSAGE("\telemdescFunc (return value type):\n");
1158 dump_ELEMDESC(&funcdesc->elemdescFunc);
1161 static const char * const typekind_desc[] =
1163 "TKIND_ENUM",
1164 "TKIND_RECORD",
1165 "TKIND_MODULE",
1166 "TKIND_INTERFACE",
1167 "TKIND_DISPATCH",
1168 "TKIND_COCLASS",
1169 "TKIND_ALIAS",
1170 "TKIND_UNION",
1171 "TKIND_MAX"
1174 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1176 int i;
1177 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1178 for (i=0;i<pfd->funcdesc.cParams;i++)
1179 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1182 dump_FUNCDESC(&(pfd->funcdesc));
1184 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1185 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1187 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1189 while (pfd)
1191 dump_TLBFuncDescOne(pfd);
1192 pfd = pfd->next;
1195 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1197 while (pvd)
1199 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1200 pvd = pvd->next;
1204 static void dump_TLBImpLib(const TLBImpLib *import)
1206 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1207 debugstr_w(import->name));
1208 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1209 import->wVersionMinor, import->lcid, import->offset);
1212 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1214 TLBRefType *ref;
1216 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1218 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1219 if(ref->index == -1)
1220 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1221 else
1222 TRACE_(typelib)("type no: %d\n", ref->index);
1224 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1226 TRACE_(typelib)("in lib\n");
1227 dump_TLBImpLib(ref->pImpTLInfo);
1232 static void dump_TLBImplType(const TLBImplType * impl)
1234 while (impl) {
1235 TRACE_(typelib)(
1236 "implementing/inheriting interface hRef = %x implflags %x\n",
1237 impl->hRef, impl->implflags);
1238 impl = impl->next;
1242 static void dump_Variant(const VARIANT * pvar)
1244 SYSTEMTIME st;
1246 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1248 if (pvar)
1250 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1251 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1253 TRACE(",%p", V_BYREF(pvar));
1255 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1257 TRACE(",%p", V_ARRAY(pvar));
1259 else switch (V_TYPE(pvar))
1261 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1262 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1263 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1264 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1265 case VT_INT:
1266 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1267 case VT_UINT:
1268 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1269 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1270 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1271 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1272 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1273 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1274 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1275 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1276 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1277 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1278 V_CY(pvar).s.Lo); break;
1279 case VT_DATE:
1280 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1281 TRACE(",<invalid>");
1282 else
1283 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1284 st.wHour, st.wMinute, st.wSecond);
1285 break;
1286 case VT_ERROR:
1287 case VT_VOID:
1288 case VT_USERDEFINED:
1289 case VT_EMPTY:
1290 case VT_NULL: break;
1291 default: TRACE(",?"); break;
1294 TRACE("}\n");
1297 static void dump_DispParms(const DISPPARAMS * pdp)
1299 unsigned int index;
1301 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1303 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1305 TRACE("named args:\n");
1306 for (index = 0; index < pdp->cNamedArgs; index++)
1307 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1310 if (pdp->cArgs && pdp->rgvarg)
1312 TRACE("args:\n");
1313 for (index = 0; index < pdp->cArgs; index++)
1314 dump_Variant( &pdp->rgvarg[index] );
1318 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1320 TRACE("%p ref=%u\n", pty, pty->ref);
1321 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1322 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1323 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1324 TRACE("fct:%u var:%u impl:%u\n",
1325 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1326 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1327 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1328 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1329 if (TRACE_ON(ole))
1330 dump_TLBFuncDesc(pty->funclist);
1331 dump_TLBVarDesc(pty->varlist);
1332 dump_TLBImplType(pty->impltypelist);
1335 static void dump_VARDESC(const VARDESC *v)
1337 MESSAGE("memid %d\n",v->memid);
1338 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1339 MESSAGE("oInst %d\n",v->u.oInst);
1340 dump_ELEMDESC(&(v->elemdescVar));
1341 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1342 MESSAGE("varkind %d\n",v->varkind);
1345 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1347 /* VT_LPWSTR is largest type that */
1348 /* may appear in type description*/
1349 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1350 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1351 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1352 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1353 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1354 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1355 {{0},30},{{0},31}
1358 static void TLB_abort(void)
1360 DebugBreak();
1363 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1364 static void * TLB_Alloc(unsigned size)
1366 void * ret;
1367 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1368 /* FIXME */
1369 ERR("cannot allocate memory\n");
1371 return ret;
1374 static void TLB_Free(void * ptr)
1376 HeapFree(GetProcessHeap(), 0, ptr);
1379 /* returns the size required for a deep copy of a typedesc into a
1380 * flat buffer */
1381 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1383 SIZE_T size = 0;
1385 if (alloc_initial_space)
1386 size += sizeof(TYPEDESC);
1388 switch (tdesc->vt)
1390 case VT_PTR:
1391 case VT_SAFEARRAY:
1392 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1393 break;
1394 case VT_CARRAY:
1395 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1396 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1397 break;
1399 return size;
1402 /* deep copy a typedesc into a flat buffer */
1403 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1405 if (!dest)
1407 dest = buffer;
1408 buffer = (char *)buffer + sizeof(TYPEDESC);
1411 *dest = *src;
1413 switch (src->vt)
1415 case VT_PTR:
1416 case VT_SAFEARRAY:
1417 dest->u.lptdesc = buffer;
1418 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1419 break;
1420 case VT_CARRAY:
1421 dest->u.lpadesc = buffer;
1422 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1423 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1424 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1425 break;
1427 return buffer;
1430 /* free custom data allocated by MSFT_CustData */
1431 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1433 TLBCustData *pCustDataNext;
1434 for (; pCustData; pCustData = pCustDataNext)
1436 VariantClear(&pCustData->data);
1438 pCustDataNext = pCustData->next;
1439 TLB_Free(pCustData);
1443 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1445 DWORD len;
1446 BSTR ret;
1448 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1449 ret = SysAllocStringLen(NULL, len - 1);
1450 if (!ret) return ret;
1451 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1452 return ret;
1455 /**********************************************************************
1457 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1459 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1461 return pcx->pos;
1464 static inline void MSFT_Seek(TLBContext *pcx, long where)
1466 if (where != DO_NOT_SEEK)
1468 where += pcx->oStart;
1469 if (where > pcx->length)
1471 /* FIXME */
1472 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1473 TLB_abort();
1475 pcx->pos = where;
1479 /* read function */
1480 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1482 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1483 pcx->pos, count, pcx->oStart, pcx->length, where);
1485 MSFT_Seek(pcx, where);
1486 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1487 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1488 pcx->pos += count;
1489 return count;
1492 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1493 long where )
1495 DWORD ret;
1497 ret = MSFT_Read(buffer, count, pcx, where);
1498 FromLEDWords(buffer, ret);
1500 return ret;
1503 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1504 long where )
1506 DWORD ret;
1508 ret = MSFT_Read(buffer, count, pcx, where);
1509 FromLEWords(buffer, ret);
1511 return ret;
1514 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1516 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1517 memset(pGuid,0, sizeof(GUID));
1518 return;
1520 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1521 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1522 pGuid->Data2 = FromLEWord(pGuid->Data2);
1523 pGuid->Data3 = FromLEWord(pGuid->Data3);
1524 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1527 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1529 MSFT_NameIntro niName;
1531 if (offset < 0)
1533 ERR_(typelib)("bad offset %d\n", offset);
1534 return -1;
1537 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1538 pcx->pTblDir->pNametab.offset+offset);
1540 return niName.hreftype;
1543 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1545 char * name;
1546 MSFT_NameIntro niName;
1547 int lengthInChars;
1548 BSTR bstrName = NULL;
1550 if (offset < 0)
1552 ERR_(typelib)("bad offset %d\n", offset);
1553 return NULL;
1555 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1556 pcx->pTblDir->pNametab.offset+offset);
1557 niName.namelen &= 0xFF; /* FIXME: correct ? */
1558 name=TLB_Alloc((niName.namelen & 0xff) +1);
1559 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1560 name[niName.namelen & 0xff]='\0';
1562 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1563 name, -1, NULL, 0);
1565 /* no invalid characters in string */
1566 if (lengthInChars)
1568 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1570 /* don't check for invalid character since this has been done previously */
1571 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1573 TLB_Free(name);
1575 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1576 return bstrName;
1579 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1581 char * string;
1582 INT16 length;
1583 int lengthInChars;
1584 BSTR bstr = NULL;
1586 if(offset<0) return NULL;
1587 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1588 if(length <= 0) return 0;
1589 string=TLB_Alloc(length +1);
1590 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1591 string[length]='\0';
1593 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1594 string, -1, NULL, 0);
1596 /* no invalid characters in string */
1597 if (lengthInChars)
1599 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1601 /* don't check for invalid character since this has been done previously */
1602 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1604 TLB_Free(string);
1606 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1607 return bstr;
1610 * read a value and fill a VARIANT structure
1612 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1614 int size;
1616 TRACE_(typelib)("\n");
1618 if(offset <0) { /* data are packed in here */
1619 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1620 V_I4(pVar) = offset & 0x3ffffff;
1621 return;
1623 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1624 pcx->pTblDir->pCustData.offset + offset );
1625 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1626 switch (V_VT(pVar)){
1627 case VT_EMPTY: /* FIXME: is this right? */
1628 case VT_NULL: /* FIXME: is this right? */
1629 case VT_I2 : /* this should not happen */
1630 case VT_I4 :
1631 case VT_R4 :
1632 case VT_ERROR :
1633 case VT_BOOL :
1634 case VT_I1 :
1635 case VT_UI1 :
1636 case VT_UI2 :
1637 case VT_UI4 :
1638 case VT_INT :
1639 case VT_UINT :
1640 case VT_VOID : /* FIXME: is this right? */
1641 case VT_HRESULT :
1642 size=4; break;
1643 case VT_R8 :
1644 case VT_CY :
1645 case VT_DATE :
1646 case VT_I8 :
1647 case VT_UI8 :
1648 case VT_DECIMAL : /* FIXME: is this right? */
1649 case VT_FILETIME :
1650 size=8;break;
1651 /* pointer types with known behaviour */
1652 case VT_BSTR :{
1653 char * ptr;
1654 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1655 if(size < 0) {
1656 char next;
1657 DWORD origPos = MSFT_Tell(pcx), nullPos;
1659 do {
1660 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1661 } while (next);
1662 nullPos = MSFT_Tell(pcx);
1663 size = nullPos - origPos;
1664 MSFT_Seek(pcx, origPos);
1666 ptr=TLB_Alloc(size);/* allocate temp buffer */
1667 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1668 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1669 /* FIXME: do we need a AtoW conversion here? */
1670 V_UNION(pVar, bstrVal[size])='\0';
1671 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1672 TLB_Free(ptr);
1674 size=-4; break;
1675 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1676 case VT_DISPATCH :
1677 case VT_VARIANT :
1678 case VT_UNKNOWN :
1679 case VT_PTR :
1680 case VT_SAFEARRAY :
1681 case VT_CARRAY :
1682 case VT_USERDEFINED :
1683 case VT_LPSTR :
1684 case VT_LPWSTR :
1685 case VT_BLOB :
1686 case VT_STREAM :
1687 case VT_STORAGE :
1688 case VT_STREAMED_OBJECT :
1689 case VT_STORED_OBJECT :
1690 case VT_BLOB_OBJECT :
1691 case VT_CF :
1692 case VT_CLSID :
1693 default:
1694 size=0;
1695 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1696 V_VT(pVar));
1699 if(size>0) /* (big|small) endian correct? */
1700 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1701 return;
1704 * create a linked list with custom data
1706 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1708 MSFT_CDGuid entry;
1709 TLBCustData* pNew;
1710 int count=0;
1712 TRACE_(typelib)("\n");
1714 while(offset >=0){
1715 count++;
1716 pNew=TLB_Alloc(sizeof(TLBCustData));
1717 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1718 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1719 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1720 /* add new custom data at head of the list */
1721 pNew->next=*ppCustData;
1722 *ppCustData=pNew;
1723 offset = entry.next;
1725 return count;
1728 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1729 ITypeInfoImpl *pTI)
1731 if(type <0)
1732 pTd->vt=type & VT_TYPEMASK;
1733 else
1734 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1736 if(pTd->vt == VT_USERDEFINED)
1737 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1739 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1742 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1744 /* resolve referenced type if any */
1745 while (lpTypeDesc)
1747 switch (lpTypeDesc->vt)
1749 case VT_PTR:
1750 lpTypeDesc = lpTypeDesc->u.lptdesc;
1751 break;
1753 case VT_CARRAY:
1754 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1755 break;
1757 case VT_USERDEFINED:
1758 MSFT_DoRefType(pcx, pTI->pTypeLib,
1759 lpTypeDesc->u.hreftype);
1761 lpTypeDesc = NULL;
1762 break;
1764 default:
1765 lpTypeDesc = NULL;
1770 static void
1771 MSFT_DoFuncs(TLBContext* pcx,
1772 ITypeInfoImpl* pTI,
1773 int cFuncs,
1774 int cVars,
1775 int offset,
1776 TLBFuncDesc** pptfd)
1779 * member information is stored in a data structure at offset
1780 * indicated by the memoffset field of the typeinfo structure
1781 * There are several distinctive parts.
1782 * The first part starts with a field that holds the total length
1783 * of this (first) part excluding this field. Then follow the records,
1784 * for each member there is one record.
1786 * The first entry is always the length of the record (including this
1787 * length word).
1788 * The rest of the record depends on the type of the member. If there is
1789 * a field indicating the member type (function, variable, interface, etc)
1790 * I have not found it yet. At this time we depend on the information
1791 * in the type info and the usual order how things are stored.
1793 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1794 * for each member;
1796 * Third is an equal sized array with file offsets to the name entry
1797 * of each member.
1799 * The fourth and last (?) part is an array with offsets to the records
1800 * in the first part of this file segment.
1803 int infolen, nameoffset, reclength, nrattributes, i;
1804 int recoffset = offset + sizeof(INT);
1806 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1807 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1808 TLBFuncDesc *ptfd_prev = NULL;
1810 TRACE_(typelib)("\n");
1812 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1814 for ( i = 0; i < cFuncs ; i++ )
1816 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1818 /* name, eventually add to a hash table */
1819 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1820 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1822 /* nameoffset is sometimes -1 on the second half of a propget/propput
1823 * pair of functions */
1824 if ((nameoffset == -1) && (i > 0))
1825 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1826 else
1827 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1829 /* read the function information record */
1830 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1832 reclength &= 0xffff;
1834 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1836 /* do the attributes */
1837 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1838 / sizeof(int);
1840 if ( nrattributes > 0 )
1842 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1844 if ( nrattributes > 1 )
1846 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1847 pFuncRec->OptAttr[1]) ;
1849 if ( nrattributes > 2 )
1851 if ( pFuncRec->FKCCIC & 0x2000 )
1853 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1854 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1855 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1857 else
1859 (*pptfd)->Entry = MSFT_ReadString(pcx,
1860 pFuncRec->OptAttr[2]);
1862 if( nrattributes > 5 )
1864 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1866 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1868 MSFT_CustData(pcx,
1869 pFuncRec->OptAttr[6],
1870 &(*pptfd)->pCustData);
1874 else
1876 (*pptfd)->Entry = (BSTR)-1;
1881 /* fill the FuncDesc Structure */
1882 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1883 offset + infolen + ( i + 1) * sizeof(INT));
1885 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1886 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1887 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1888 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1889 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1890 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1891 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1893 MSFT_GetTdesc(pcx,
1894 pFuncRec->DataType,
1895 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1896 pTI);
1897 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1899 /* do the parameters/arguments */
1900 if(pFuncRec->nrargs)
1902 int j = 0;
1903 MSFT_ParameterInfo paraminfo;
1905 (*pptfd)->funcdesc.lprgelemdescParam =
1906 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1908 (*pptfd)->pParamDesc =
1909 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1911 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1912 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1914 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1916 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1918 MSFT_GetTdesc(pcx,
1919 paraminfo.DataType,
1920 &elemdesc->tdesc,
1921 pTI);
1923 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1925 /* name */
1926 if (paraminfo.oName == -1)
1927 /* this occurs for [propput] or [propget] methods, so
1928 * we should just set the name of the parameter to the
1929 * name of the method. */
1930 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1931 else
1932 (*pptfd)->pParamDesc[j].Name =
1933 MSFT_ReadName( pcx, paraminfo.oName );
1934 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1936 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1938 /* default value */
1939 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1940 (pFuncRec->FKCCIC & 0x1000) )
1942 INT* pInt = (INT *)((char *)pFuncRec +
1943 reclength -
1944 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1946 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1948 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1949 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1951 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1952 pInt[j], pcx);
1954 else
1955 elemdesc->u.paramdesc.pparamdescex = NULL;
1956 /* custom info */
1957 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1959 MSFT_CustData(pcx,
1960 pFuncRec->OptAttr[7+j],
1961 &(*pptfd)->pParamDesc[j].pCustData);
1964 /* SEEK value = jump to offset,
1965 * from there jump to the end of record,
1966 * go back by (j-1) arguments
1968 MSFT_ReadLEDWords( &paraminfo ,
1969 sizeof(MSFT_ParameterInfo), pcx,
1970 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1971 * sizeof(MSFT_ParameterInfo)));
1975 /* scode is not used: archaic win16 stuff FIXME: right? */
1976 (*pptfd)->funcdesc.cScodes = 0 ;
1977 (*pptfd)->funcdesc.lprgscode = NULL ;
1979 ptfd_prev = *pptfd;
1980 pptfd = & ((*pptfd)->next);
1981 recoffset += reclength;
1983 HeapFree(GetProcessHeap(), 0, recbuf);
1986 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1987 int cVars, int offset, TLBVarDesc ** pptvd)
1989 int infolen, nameoffset, reclength;
1990 char recbuf[256];
1991 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1992 int i;
1993 int recoffset;
1995 TRACE_(typelib)("\n");
1997 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1998 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1999 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2000 recoffset += offset+sizeof(INT);
2001 for(i=0;i<cVars;i++){
2002 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2003 /* name, eventually add to a hash table */
2004 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2005 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2006 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2007 /* read the variable information record */
2008 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2009 reclength &=0xff;
2010 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2011 /* Optional data */
2012 if(reclength >(6*sizeof(INT)) )
2013 (*pptvd)->HelpContext=pVarRec->HelpContext;
2014 if(reclength >(7*sizeof(INT)) )
2015 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2016 if(reclength >(8*sizeof(INT)) )
2017 if(reclength >(9*sizeof(INT)) )
2018 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2019 /* fill the VarDesc Structure */
2020 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2021 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2022 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2023 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2024 MSFT_GetTdesc(pcx, pVarRec->DataType,
2025 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2026 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2027 if(pVarRec->VarKind == VAR_CONST ){
2028 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2029 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2030 pVarRec->OffsValue, pcx);
2031 } else
2032 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2033 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2034 pptvd=&((*pptvd)->next);
2035 recoffset += reclength;
2038 /* fill in data for a hreftype (offset). When the referenced type is contained
2039 * in the typelib, it's just an (file) offset in the type info base dir.
2040 * If comes from import, it's an offset+1 in the ImpInfo table
2041 * */
2042 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2043 int offset)
2045 TLBRefType *ref;
2047 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2049 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2051 if(ref->reference == offset) return;
2054 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2055 list_add_tail(&pTL->ref_list, &ref->entry);
2057 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2058 /* external typelib */
2059 MSFT_ImpInfo impinfo;
2060 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2062 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2064 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2065 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2066 while (pImpLib){ /* search the known offsets of all import libraries */
2067 if(pImpLib->offset==impinfo.oImpFile) break;
2068 pImpLib=pImpLib->next;
2070 if(pImpLib){
2071 ref->reference = offset;
2072 ref->pImpTLInfo = pImpLib;
2073 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2074 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2075 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2076 ref->index = TLB_REF_USE_GUID;
2077 } else
2078 ref->index = impinfo.oGuid;
2079 }else{
2080 ERR("Cannot find a reference\n");
2081 ref->reference = -1;
2082 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2084 }else{
2085 /* in this typelib */
2086 ref->index = MSFT_HREFTYPE_INDEX(offset);
2087 ref->reference = offset;
2088 ref->pImpTLInfo = TLB_REF_INTERNAL;
2092 /* process Implemented Interfaces of a com class */
2093 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2094 int offset)
2096 int i;
2097 MSFT_RefRecord refrec;
2098 TLBImplType **ppImpl = &pTI->impltypelist;
2100 TRACE_(typelib)("\n");
2102 for(i=0;i<count;i++){
2103 if(offset<0) break; /* paranoia */
2104 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2105 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2106 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2107 (*ppImpl)->hRef = refrec.reftype;
2108 (*ppImpl)->implflags=refrec.flags;
2109 (*ppImpl)->ctCustData=
2110 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2111 offset=refrec.onext;
2112 ppImpl=&((*ppImpl)->next);
2116 * process a typeinfo record
2118 static ITypeInfoImpl * MSFT_DoTypeInfo(
2119 TLBContext *pcx,
2120 int count,
2121 ITypeLibImpl * pLibInfo)
2123 MSFT_TypeInfoBase tiBase;
2124 ITypeInfoImpl *ptiRet;
2126 TRACE_(typelib)("count=%u\n", count);
2128 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2129 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2130 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2132 /* this is where we are coming from */
2133 ptiRet->pTypeLib = pLibInfo;
2134 ptiRet->index=count;
2135 /* fill in the typeattr fields */
2137 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2138 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2139 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2140 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2141 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2142 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2143 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2144 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2145 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2146 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2147 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2148 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2149 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2150 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2151 MSFT_GetTdesc(pcx, tiBase.datatype1,
2152 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2154 /* FIXME: */
2155 /* IDLDESC idldescType; *//* never saw this one != zero */
2157 /* name, eventually add to a hash table */
2158 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2159 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2160 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2161 /* help info */
2162 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2163 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2164 ptiRet->dwHelpContext=tiBase.helpcontext;
2166 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2167 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2169 /* note: InfoType's Help file and HelpStringDll come from the containing
2170 * library. Further HelpString and Docstring appear to be the same thing :(
2172 /* functions */
2173 if(ptiRet->TypeAttr.cFuncs >0 )
2174 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2175 ptiRet->TypeAttr.cVars,
2176 tiBase.memoffset, & ptiRet->funclist);
2177 /* variables */
2178 if(ptiRet->TypeAttr.cVars >0 )
2179 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2180 ptiRet->TypeAttr.cVars,
2181 tiBase.memoffset, & ptiRet->varlist);
2182 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2183 switch(ptiRet->TypeAttr.typekind)
2185 case TKIND_COCLASS:
2186 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2187 tiBase.datatype1);
2188 break;
2189 case TKIND_DISPATCH:
2190 /* This is not -1 when the interface is a non-base dual interface or
2191 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2192 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2193 not this interface.
2196 if (tiBase.datatype1 != -1)
2198 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2199 ptiRet->impltypelist->hRef = tiBase.datatype1;
2200 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2202 break;
2203 default:
2204 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2205 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2206 ptiRet->impltypelist->hRef = tiBase.datatype1;
2207 break;
2210 ptiRet->ctCustData=
2211 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2213 TRACE_(typelib)("%s guid: %s kind:%s\n",
2214 debugstr_w(ptiRet->Name),
2215 debugstr_guid(&ptiRet->TypeAttr.guid),
2216 typekind_desc[ptiRet->TypeAttr.typekind]);
2218 return ptiRet;
2221 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2222 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2223 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2224 * tradeoff here.
2226 static ITypeLibImpl *tlb_cache_first;
2227 static CRITICAL_SECTION cache_section;
2228 static CRITICAL_SECTION_DEBUG cache_section_debug =
2230 0, 0, &cache_section,
2231 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2232 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2234 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2237 typedef struct TLB_PEFile
2239 const IUnknownVtbl *lpvtbl;
2240 LONG refs;
2241 HMODULE dll;
2242 HRSRC typelib_resource;
2243 HGLOBAL typelib_global;
2244 LPVOID typelib_base;
2245 } TLB_PEFile;
2247 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2249 if (IsEqualIID(riid, &IID_IUnknown))
2251 *ppv = iface;
2252 IUnknown_AddRef(iface);
2253 return S_OK;
2255 *ppv = NULL;
2256 return E_NOINTERFACE;
2259 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2261 TLB_PEFile *This = (TLB_PEFile *)iface;
2262 return InterlockedIncrement(&This->refs);
2265 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2267 TLB_PEFile *This = (TLB_PEFile *)iface;
2268 ULONG refs = InterlockedDecrement(&This->refs);
2269 if (!refs)
2271 if (This->typelib_global)
2272 FreeResource(This->typelib_global);
2273 if (This->dll)
2274 FreeLibrary(This->dll);
2275 HeapFree(GetProcessHeap(), 0, This);
2277 return refs;
2280 static const IUnknownVtbl TLB_PEFile_Vtable =
2282 TLB_PEFile_QueryInterface,
2283 TLB_PEFile_AddRef,
2284 TLB_PEFile_Release
2287 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2289 TLB_PEFile *This;
2291 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2292 if (!This)
2293 return E_OUTOFMEMORY;
2295 This->lpvtbl = &TLB_PEFile_Vtable;
2296 This->refs = 1;
2297 This->dll = NULL;
2298 This->typelib_resource = NULL;
2299 This->typelib_global = NULL;
2300 This->typelib_base = NULL;
2302 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2303 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2305 if (This->dll)
2307 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2308 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2309 if (This->typelib_resource)
2311 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2312 if (This->typelib_global)
2314 This->typelib_base = LockResource(This->typelib_global);
2316 if (This->typelib_base)
2318 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2319 *ppBase = This->typelib_base;
2320 *ppFile = (IUnknown *)&This->lpvtbl;
2321 return S_OK;
2327 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2328 return TYPE_E_CANTLOADLIBRARY;
2331 typedef struct TLB_NEFile
2333 const IUnknownVtbl *lpvtbl;
2334 LONG refs;
2335 LPVOID typelib_base;
2336 } TLB_NEFile;
2338 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2340 if (IsEqualIID(riid, &IID_IUnknown))
2342 *ppv = iface;
2343 IUnknown_AddRef(iface);
2344 return S_OK;
2346 *ppv = NULL;
2347 return E_NOINTERFACE;
2350 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2352 TLB_NEFile *This = (TLB_NEFile *)iface;
2353 return InterlockedIncrement(&This->refs);
2356 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2358 TLB_NEFile *This = (TLB_NEFile *)iface;
2359 ULONG refs = InterlockedDecrement(&This->refs);
2360 if (!refs)
2362 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2363 HeapFree(GetProcessHeap(), 0, This);
2365 return refs;
2368 static const IUnknownVtbl TLB_NEFile_Vtable =
2370 TLB_NEFile_QueryInterface,
2371 TLB_NEFile_AddRef,
2372 TLB_NEFile_Release
2375 /***********************************************************************
2376 * read_xx_header [internal]
2378 static int read_xx_header( HFILE lzfd )
2380 IMAGE_DOS_HEADER mzh;
2381 char magic[3];
2383 LZSeek( lzfd, 0, SEEK_SET );
2384 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2385 return 0;
2386 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2387 return 0;
2389 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2390 if ( 2 != LZRead( lzfd, magic, 2 ) )
2391 return 0;
2393 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2395 if ( magic[0] == 'N' && magic[1] == 'E' )
2396 return IMAGE_OS2_SIGNATURE;
2397 if ( magic[0] == 'P' && magic[1] == 'E' )
2398 return IMAGE_NT_SIGNATURE;
2400 magic[2] = '\0';
2401 WARN("Can't handle %s files.\n", magic );
2402 return 0;
2406 /***********************************************************************
2407 * find_ne_resource [internal]
2409 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2410 DWORD *resLen, DWORD *resOff )
2412 IMAGE_OS2_HEADER nehd;
2413 NE_TYPEINFO *typeInfo;
2414 NE_NAMEINFO *nameInfo;
2415 DWORD nehdoffset;
2416 LPBYTE resTab;
2417 DWORD resTabSize;
2418 int count;
2420 /* Read in NE header */
2421 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2422 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2424 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2425 if ( !resTabSize )
2427 TRACE("No resources in NE dll\n" );
2428 return FALSE;
2431 /* Read in resource table */
2432 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2433 if ( !resTab ) return FALSE;
2435 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2436 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2438 HeapFree( GetProcessHeap(), 0, resTab );
2439 return FALSE;
2442 /* Find resource */
2443 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2445 if (HIWORD(typeid) != 0) /* named type */
2447 BYTE len = strlen( typeid );
2448 while (typeInfo->type_id)
2450 if (!(typeInfo->type_id & 0x8000))
2452 BYTE *p = resTab + typeInfo->type_id;
2453 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2455 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2456 typeInfo->count * sizeof(NE_NAMEINFO));
2459 else /* numeric type id */
2461 WORD id = LOWORD(typeid) | 0x8000;
2462 while (typeInfo->type_id)
2464 if (typeInfo->type_id == id) goto found_type;
2465 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2466 typeInfo->count * sizeof(NE_NAMEINFO));
2469 TRACE("No typeid entry found for %p\n", typeid );
2470 HeapFree( GetProcessHeap(), 0, resTab );
2471 return FALSE;
2473 found_type:
2474 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2476 if (HIWORD(resid) != 0) /* named resource */
2478 BYTE len = strlen( resid );
2479 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2481 BYTE *p = resTab + nameInfo->id;
2482 if (nameInfo->id & 0x8000) continue;
2483 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2486 else /* numeric resource id */
2488 WORD id = LOWORD(resid) | 0x8000;
2489 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2490 if (nameInfo->id == id) goto found_name;
2492 TRACE("No resid entry found for %p\n", typeid );
2493 HeapFree( GetProcessHeap(), 0, resTab );
2494 return FALSE;
2496 found_name:
2497 /* Return resource data */
2498 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2499 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2501 HeapFree( GetProcessHeap(), 0, resTab );
2502 return TRUE;
2505 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2507 HFILE lzfd = -1;
2508 OFSTRUCT ofs;
2509 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2510 TLB_NEFile *This = NULL;
2512 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2513 if (!This) return E_OUTOFMEMORY;
2515 This->lpvtbl = &TLB_NEFile_Vtable;
2516 This->refs = 1;
2517 This->typelib_base = NULL;
2519 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2520 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2522 DWORD reslen, offset;
2523 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2525 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2526 if( !This->typelib_base )
2527 hr = E_OUTOFMEMORY;
2528 else
2530 LZSeek( lzfd, offset, SEEK_SET );
2531 reslen = LZRead( lzfd, This->typelib_base, reslen );
2532 LZClose( lzfd );
2533 *ppBase = This->typelib_base;
2534 *pdwTLBLength = reslen;
2535 *ppFile = (IUnknown *)&This->lpvtbl;
2536 return S_OK;
2541 if( lzfd >= 0) LZClose( lzfd );
2542 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2543 return hr;
2546 typedef struct TLB_Mapping
2548 const IUnknownVtbl *lpvtbl;
2549 LONG refs;
2550 HANDLE file;
2551 HANDLE mapping;
2552 LPVOID typelib_base;
2553 } TLB_Mapping;
2555 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2557 if (IsEqualIID(riid, &IID_IUnknown))
2559 *ppv = iface;
2560 IUnknown_AddRef(iface);
2561 return S_OK;
2563 *ppv = NULL;
2564 return E_NOINTERFACE;
2567 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2569 TLB_Mapping *This = (TLB_Mapping *)iface;
2570 return InterlockedIncrement(&This->refs);
2573 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2575 TLB_Mapping *This = (TLB_Mapping *)iface;
2576 ULONG refs = InterlockedDecrement(&This->refs);
2577 if (!refs)
2579 if (This->typelib_base)
2580 UnmapViewOfFile(This->typelib_base);
2581 if (This->mapping)
2582 CloseHandle(This->mapping);
2583 if (This->file != INVALID_HANDLE_VALUE)
2584 CloseHandle(This->file);
2585 HeapFree(GetProcessHeap(), 0, This);
2587 return refs;
2590 static const IUnknownVtbl TLB_Mapping_Vtable =
2592 TLB_Mapping_QueryInterface,
2593 TLB_Mapping_AddRef,
2594 TLB_Mapping_Release
2597 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2599 TLB_Mapping *This;
2601 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2602 if (!This)
2603 return E_OUTOFMEMORY;
2605 This->lpvtbl = &TLB_Mapping_Vtable;
2606 This->refs = 1;
2607 This->file = INVALID_HANDLE_VALUE;
2608 This->mapping = NULL;
2609 This->typelib_base = NULL;
2611 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2612 if (INVALID_HANDLE_VALUE != This->file)
2614 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2615 if (This->mapping)
2617 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2618 if(This->typelib_base)
2620 /* retrieve file size */
2621 *pdwTLBLength = GetFileSize(This->file, NULL);
2622 *ppBase = This->typelib_base;
2623 *ppFile = (IUnknown *)&This->lpvtbl;
2624 return S_OK;
2629 IUnknown_Release((IUnknown *)&This->lpvtbl);
2630 return TYPE_E_CANTLOADLIBRARY;
2633 /****************************************************************************
2634 * TLB_ReadTypeLib
2636 * find the type of the typelib file and map the typelib resource into
2637 * the memory
2639 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2640 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2641 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2643 ITypeLibImpl *entry;
2644 HRESULT ret;
2645 INT index = 1;
2646 LPWSTR index_str, file = (LPWSTR)pszFileName;
2647 LPVOID pBase = NULL;
2648 DWORD dwTLBLength = 0;
2649 IUnknown *pFile = NULL;
2651 *ppTypeLib = NULL;
2653 index_str = strrchrW(pszFileName, '\\');
2654 if(index_str && *++index_str != '\0')
2656 LPWSTR end_ptr;
2657 long idx = strtolW(index_str, &end_ptr, 10);
2658 if(*end_ptr == '\0')
2660 int str_len = index_str - pszFileName - 1;
2661 index = idx;
2662 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2663 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2664 file[str_len] = 0;
2668 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2670 if(strchrW(file, '\\'))
2672 lstrcpyW(pszPath, file);
2674 else
2676 int len = GetSystemDirectoryW(pszPath, cchPath);
2677 pszPath[len] = '\\';
2678 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2682 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2684 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2686 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2687 EnterCriticalSection(&cache_section);
2688 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2690 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2692 TRACE("cache hit\n");
2693 *ppTypeLib = (ITypeLib2*)entry;
2694 ITypeLib_AddRef(*ppTypeLib);
2695 LeaveCriticalSection(&cache_section);
2696 return S_OK;
2699 LeaveCriticalSection(&cache_section);
2701 /* now actually load and parse the typelib */
2703 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2704 if (ret == TYPE_E_CANTLOADLIBRARY)
2705 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2706 if (ret == TYPE_E_CANTLOADLIBRARY)
2707 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2708 if (SUCCEEDED(ret))
2710 if (dwTLBLength >= 4)
2712 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2713 if (dwSignature == MSFT_SIGNATURE)
2714 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2715 else if (dwSignature == SLTG_SIGNATURE)
2716 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2717 else
2719 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2720 ret = TYPE_E_CANTLOADLIBRARY;
2723 else
2724 ret = TYPE_E_CANTLOADLIBRARY;
2725 IUnknown_Release(pFile);
2728 if(*ppTypeLib) {
2729 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2731 TRACE("adding to cache\n");
2732 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2733 lstrcpyW(impl->path, pszPath);
2734 /* We should really canonicalise the path here. */
2735 impl->index = index;
2737 /* FIXME: check if it has added already in the meantime */
2738 EnterCriticalSection(&cache_section);
2739 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2740 impl->prev = NULL;
2741 tlb_cache_first = impl;
2742 LeaveCriticalSection(&cache_section);
2743 ret = S_OK;
2744 } else
2745 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2747 return ret;
2750 /*================== ITypeLib(2) Methods ===================================*/
2752 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2754 ITypeLibImpl* pTypeLibImpl;
2756 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2757 if (!pTypeLibImpl) return NULL;
2759 pTypeLibImpl->lpVtbl = &tlbvt;
2760 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2761 pTypeLibImpl->ref = 1;
2763 list_init(&pTypeLibImpl->ref_list);
2764 pTypeLibImpl->dispatch_href = -1;
2766 return pTypeLibImpl;
2769 /****************************************************************************
2770 * ITypeLib2_Constructor_MSFT
2772 * loading an MSFT typelib from an in-memory image
2774 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2776 TLBContext cx;
2777 long lPSegDir;
2778 MSFT_Header tlbHeader;
2779 MSFT_SegDir tlbSegDir;
2780 ITypeLibImpl * pTypeLibImpl;
2782 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2784 pTypeLibImpl = TypeLibImpl_Constructor();
2785 if (!pTypeLibImpl) return NULL;
2787 /* get pointer to beginning of typelib data */
2788 cx.pos = 0;
2789 cx.oStart=0;
2790 cx.mapping = pLib;
2791 cx.pLibInfo = pTypeLibImpl;
2792 cx.length = dwTLBLength;
2794 /* read header */
2795 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2796 TRACE_(typelib)("header:\n");
2797 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2798 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2799 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2800 return NULL;
2802 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2804 /* there is a small amount of information here until the next important
2805 * part:
2806 * the segment directory . Try to calculate the amount of data */
2807 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2809 /* now read the segment directory */
2810 TRACE("read segment directory (at %ld)\n",lPSegDir);
2811 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2812 cx.pTblDir = &tlbSegDir;
2814 /* just check two entries */
2815 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2817 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2818 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2819 return NULL;
2822 /* now fill our internal data */
2823 /* TLIBATTR fields */
2824 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2826 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2827 /* Windows seems to have zero here, is this correct? */
2828 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2829 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2830 else
2831 pTypeLibImpl->LibAttr.lcid = 0;
2833 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2834 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2835 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2836 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2838 /* name, eventually add to a hash table */
2839 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2841 /* help info */
2842 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2843 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2845 if( tlbHeader.varflags & HELPDLLFLAG)
2847 int offset;
2848 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2849 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2852 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2854 /* custom data */
2855 if(tlbHeader.CustomDataOffset >= 0)
2857 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2860 /* fill in type descriptions */
2861 if(tlbSegDir.pTypdescTab.length > 0)
2863 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2864 INT16 td[4];
2865 pTypeLibImpl->ctTypeDesc = cTD;
2866 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2867 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2868 for(i=0; i<cTD; )
2870 /* FIXME: add several sanity checks here */
2871 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2872 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2874 /* FIXME: check safearray */
2875 if(td[3] < 0)
2876 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2877 else
2878 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2880 else if(td[0] == VT_CARRAY)
2882 /* array descr table here */
2883 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2885 else if(td[0] == VT_USERDEFINED)
2887 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2889 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2892 /* second time around to fill the array subscript info */
2893 for(i=0;i<cTD;i++)
2895 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2896 if(tlbSegDir.pArrayDescriptions.offset>0)
2898 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2899 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2901 if(td[1]<0)
2902 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2903 else
2904 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2906 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2908 for(j = 0; j<td[2]; j++)
2910 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2911 sizeof(INT), &cx, DO_NOT_SEEK);
2912 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2913 sizeof(INT), &cx, DO_NOT_SEEK);
2916 else
2918 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2919 ERR("didn't find array description data\n");
2924 /* imported type libs */
2925 if(tlbSegDir.pImpFiles.offset>0)
2927 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2928 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2929 UINT16 size;
2931 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2933 char *name;
2935 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2936 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2937 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2939 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2940 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2941 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2942 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2944 size >>= 2;
2945 name = TLB_Alloc(size+1);
2946 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2947 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2949 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2950 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2952 ppImpLib = &(*ppImpLib)->next;
2956 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2957 if(pTypeLibImpl->dispatch_href != -1)
2958 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2960 /* type info's */
2961 if(tlbHeader.nrtypeinfos >= 0 )
2963 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2964 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2965 int i;
2967 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2969 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2971 ppTI = &((*ppTI)->next);
2972 (pTypeLibImpl->TypeInfoCount)++;
2976 TRACE("(%p)\n", pTypeLibImpl);
2977 return (ITypeLib2*) pTypeLibImpl;
2981 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2983 char b[3];
2984 int i;
2985 short s;
2987 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2988 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2989 return FALSE;
2992 guid->Data4[0] = s >> 8;
2993 guid->Data4[1] = s & 0xff;
2995 b[2] = '\0';
2996 for(i = 0; i < 6; i++) {
2997 memcpy(b, str + 24 + 2 * i, 2);
2998 guid->Data4[i + 2] = strtol(b, NULL, 16);
3000 return TRUE;
3003 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3005 WORD bytelen;
3006 DWORD len;
3008 *pBstr = NULL;
3009 bytelen = *(const WORD*)ptr;
3010 if(bytelen == 0xffff) return 2;
3011 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3012 *pBstr = SysAllocStringLen(NULL, len - 1);
3013 if (*pBstr)
3014 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3015 return bytelen + 2;
3018 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3020 WORD bytelen;
3022 *str = NULL;
3023 bytelen = *(const WORD*)ptr;
3024 if(bytelen == 0xffff) return 2;
3025 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3026 memcpy(*str, ptr + 2, bytelen);
3027 (*str)[bytelen] = '\0';
3028 return bytelen + 2;
3031 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3033 char *ptr = pLibBlk;
3034 WORD w;
3036 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3037 FIXME("libblk magic = %04x\n", w);
3038 return 0;
3041 ptr += 6;
3042 if((w = *(WORD*)ptr) != 0xffff) {
3043 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3044 ptr += w;
3046 ptr += 2;
3048 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3050 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3052 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3053 ptr += 4;
3055 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3056 ptr += 2;
3058 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3059 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3060 else
3061 pTypeLibImpl->LibAttr.lcid = 0;
3062 ptr += 2;
3064 ptr += 4; /* skip res12 */
3066 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3067 ptr += 2;
3069 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3070 ptr += 2;
3072 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3073 ptr += 2;
3075 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3076 ptr += sizeof(GUID);
3078 return ptr - (char*)pLibBlk;
3081 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3082 typedef struct
3084 unsigned int num;
3085 HREFTYPE refs[1];
3086 } sltg_ref_lookup_t;
3088 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3089 HREFTYPE *typelib_ref)
3091 if(typeinfo_ref < table->num)
3093 *typelib_ref = table->refs[typeinfo_ref];
3094 return S_OK;
3097 ERR_(typelib)("Unable to find reference\n");
3098 *typelib_ref = -1;
3099 return E_FAIL;
3102 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3104 BOOL done = FALSE;
3106 while(!done) {
3107 if((*pType & 0xe00) == 0xe00) {
3108 pTD->vt = VT_PTR;
3109 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3110 sizeof(TYPEDESC));
3111 pTD = pTD->u.lptdesc;
3113 switch(*pType & 0x3f) {
3114 case VT_PTR:
3115 pTD->vt = VT_PTR;
3116 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3117 sizeof(TYPEDESC));
3118 pTD = pTD->u.lptdesc;
3119 break;
3121 case VT_USERDEFINED:
3122 pTD->vt = VT_USERDEFINED;
3123 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3124 done = TRUE;
3125 break;
3127 case VT_CARRAY:
3129 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3130 array */
3132 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3134 pTD->vt = VT_CARRAY;
3135 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3136 sizeof(ARRAYDESC) +
3137 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3138 pTD->u.lpadesc->cDims = pSA->cDims;
3139 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3140 pSA->cDims * sizeof(SAFEARRAYBOUND));
3142 pTD = &pTD->u.lpadesc->tdescElem;
3143 break;
3146 case VT_SAFEARRAY:
3148 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3149 useful? */
3151 pType++;
3152 pTD->vt = VT_SAFEARRAY;
3153 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3154 sizeof(TYPEDESC));
3155 pTD = pTD->u.lptdesc;
3156 break;
3158 default:
3159 pTD->vt = *pType & 0x3f;
3160 done = TRUE;
3161 break;
3163 pType++;
3165 return pType;
3168 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3169 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3171 /* Handle [in/out] first */
3172 if((*pType & 0xc000) == 0xc000)
3173 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3174 else if(*pType & 0x8000)
3175 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3176 else if(*pType & 0x4000)
3177 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3178 else
3179 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3181 if(*pType & 0x2000)
3182 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3184 if(*pType & 0x80)
3185 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3187 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3191 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3192 char *pNameTable)
3194 unsigned int ref;
3195 char *name;
3196 TLBRefType *ref_type;
3197 sltg_ref_lookup_t *table;
3198 HREFTYPE typelib_ref;
3200 if(pRef->magic != SLTG_REF_MAGIC) {
3201 FIXME("Ref magic = %x\n", pRef->magic);
3202 return NULL;
3204 name = ( (char*)pRef->names + pRef->number);
3206 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3207 table->num = pRef->number >> 3;
3209 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3211 /* We don't want the first href to be 0 */
3212 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3214 for(ref = 0; ref < pRef->number >> 3; ref++) {
3215 char *refname;
3216 unsigned int lib_offs, type_num;
3218 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3220 name += SLTG_ReadStringA(name, &refname);
3221 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3222 FIXME_(typelib)("Can't sscanf ref\n");
3223 if(lib_offs != 0xffff) {
3224 TLBImpLib **import = &pTL->pImpLibs;
3226 while(*import) {
3227 if((*import)->offset == lib_offs)
3228 break;
3229 import = &(*import)->next;
3231 if(!*import) {
3232 char fname[MAX_PATH+1];
3233 int len;
3235 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3236 sizeof(**import));
3237 (*import)->offset = lib_offs;
3238 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3239 &(*import)->guid);
3240 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3241 &(*import)->wVersionMajor,
3242 &(*import)->wVersionMinor,
3243 &(*import)->lcid, fname) != 4) {
3244 FIXME_(typelib)("can't sscanf ref %s\n",
3245 pNameTable + lib_offs + 40);
3247 len = strlen(fname);
3248 if(fname[len-1] != '#')
3249 FIXME("fname = %s\n", fname);
3250 fname[len-1] = '\0';
3251 (*import)->name = TLB_MultiByteToBSTR(fname);
3253 ref_type->pImpTLInfo = *import;
3255 /* Store a reference to IDispatch */
3256 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3257 pTL->dispatch_href = typelib_ref;
3259 } else { /* internal ref */
3260 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3262 ref_type->reference = typelib_ref;
3263 ref_type->index = type_num;
3265 HeapFree(GetProcessHeap(), 0, refname);
3266 list_add_tail(&pTL->ref_list, &ref_type->entry);
3268 table->refs[ref] = typelib_ref;
3269 typelib_ref += 4;
3271 if((BYTE)*name != SLTG_REF_MAGIC)
3272 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3273 dump_TLBRefType(pTL);
3274 return table;
3277 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3278 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3280 SLTG_ImplInfo *info;
3281 TLBImplType **ppImplType = &pTI->impltypelist;
3282 /* I don't really get this structure, usually it's 0x16 bytes
3283 long, but iuser.tlb contains some that are 0x18 bytes long.
3284 That's ok because we can use the next ptr to jump to the next
3285 one. But how do we know the length of the last one? The WORD
3286 at offs 0x8 might be the clue. For now I'm just assuming that
3287 the last one is the regular 0x16 bytes. */
3289 info = (SLTG_ImplInfo*)pBlk;
3290 while(1) {
3291 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3292 sizeof(**ppImplType));
3293 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3294 (*ppImplType)->implflags = info->impltypeflags;
3295 pTI->TypeAttr.cImplTypes++;
3296 ppImplType = &(*ppImplType)->next;
3298 if(info->next == 0xffff)
3299 break;
3300 if(OneOnly)
3301 FIXME_(typelib)("Interface inheriting more than one interface\n");
3302 info = (SLTG_ImplInfo*)(pBlk + info->next);
3304 info++; /* see comment at top of function */
3305 return (char*)info;
3308 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3309 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3311 TLBVarDesc **ppVarDesc = &pTI->varlist;
3312 BSTR bstrPrevName = NULL;
3313 SLTG_Variable *pItem;
3314 unsigned short i;
3315 WORD *pType;
3317 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3318 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3320 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3321 sizeof(**ppVarDesc));
3322 (*ppVarDesc)->vardesc.memid = pItem->memid;
3324 if (pItem->magic != SLTG_VAR_MAGIC &&
3325 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3326 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3327 return;
3330 if (pItem->name == 0xfffe)
3331 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3332 else
3333 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3335 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3336 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3337 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3339 if(pItem->flags & 0x02)
3340 pType = &pItem->type;
3341 else
3342 pType = (WORD*)(pBlk + pItem->type);
3344 if (pItem->flags & ~0xda)
3345 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3347 SLTG_DoElem(pType, pBlk,
3348 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3350 if (TRACE_ON(typelib)) {
3351 char buf[300];
3352 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3353 TRACE_(typelib)("elemdescVar: %s\n", buf);
3356 if (pItem->flags & 0x40) {
3357 TRACE_(typelib)("VAR_DISPATCH\n");
3358 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3360 else if (pItem->flags & 0x10) {
3361 TRACE_(typelib)("VAR_CONST\n");
3362 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3363 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3364 sizeof(VARIANT));
3365 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3366 if (pItem->flags & 0x08)
3367 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3368 else {
3369 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3371 case VT_LPSTR:
3372 case VT_LPWSTR:
3373 case VT_BSTR:
3375 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3376 BSTR str;
3377 TRACE_(typelib)("len = %u\n", len);
3378 if (len == 0xffff) {
3379 str = NULL;
3380 } else {
3381 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3382 str = SysAllocStringLen(NULL, alloc_len);
3383 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3385 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3386 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3387 break;
3389 case VT_I2:
3390 case VT_UI2:
3391 case VT_I4:
3392 case VT_UI4:
3393 case VT_INT:
3394 case VT_UINT:
3395 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3396 *(INT*)(pBlk + pItem->byte_offs);
3397 break;
3398 default:
3399 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3403 else {
3404 TRACE_(typelib)("VAR_PERINSTANCE\n");
3405 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3406 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3409 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3410 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3412 if (pItem->flags & 0x80)
3413 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3415 bstrPrevName = (*ppVarDesc)->Name;
3416 ppVarDesc = &((*ppVarDesc)->next);
3418 pTI->TypeAttr.cVars = cVars;
3421 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3422 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3424 SLTG_Function *pFunc;
3425 unsigned short i;
3426 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3428 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3429 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3431 int param;
3432 WORD *pType, *pArg;
3434 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3435 sizeof(**ppFuncDesc));
3437 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3438 case SLTG_FUNCTION_MAGIC:
3439 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3440 break;
3441 case SLTG_DISPATCH_FUNCTION_MAGIC:
3442 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3443 break;
3444 case SLTG_STATIC_FUNCTION_MAGIC:
3445 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3446 break;
3447 default:
3448 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3449 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3450 *ppFuncDesc = NULL;
3451 return;
3453 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3455 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3456 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3457 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3458 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3459 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3460 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3462 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3463 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3465 if(pFunc->retnextopt & 0x80)
3466 pType = &pFunc->rettype;
3467 else
3468 pType = (WORD*)(pBlk + pFunc->rettype);
3470 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3472 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3473 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3474 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3475 (*ppFuncDesc)->pParamDesc =
3476 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3477 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3479 pArg = (WORD*)(pBlk + pFunc->arg_off);
3481 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3482 char *paramName = pNameTable + *pArg;
3483 BOOL HaveOffs;
3484 /* If arg type follows then paramName points to the 2nd
3485 letter of the name, else the next WORD is an offset to
3486 the arg type and paramName points to the first letter.
3487 So let's take one char off paramName and see if we're
3488 pointing at an alpha-numeric char. However if *pArg is
3489 0xffff or 0xfffe then the param has no name, the former
3490 meaning that the next WORD is the type, the latter
3491 meaning that the next WORD is an offset to the type. */
3493 HaveOffs = FALSE;
3494 if(*pArg == 0xffff)
3495 paramName = NULL;
3496 else if(*pArg == 0xfffe) {
3497 paramName = NULL;
3498 HaveOffs = TRUE;
3500 else if(paramName[-1] && !isalnum(paramName[-1]))
3501 HaveOffs = TRUE;
3503 pArg++;
3505 if(HaveOffs) { /* the next word is an offset to type */
3506 pType = (WORD*)(pBlk + *pArg);
3507 SLTG_DoElem(pType, pBlk,
3508 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3509 pArg++;
3510 } else {
3511 if(paramName)
3512 paramName--;
3513 pArg = SLTG_DoElem(pArg, pBlk,
3514 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3517 /* Are we an optional param ? */
3518 if((*ppFuncDesc)->funcdesc.cParams - param <=
3519 (*ppFuncDesc)->funcdesc.cParamsOpt)
3520 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3522 if(paramName) {
3523 (*ppFuncDesc)->pParamDesc[param].Name =
3524 TLB_MultiByteToBSTR(paramName);
3525 } else {
3526 (*ppFuncDesc)->pParamDesc[param].Name =
3527 SysAllocString((*ppFuncDesc)->Name);
3531 ppFuncDesc = &((*ppFuncDesc)->next);
3532 if(pFunc->next == 0xffff) break;
3534 pTI->TypeAttr.cFuncs = cFuncs;
3537 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3538 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3539 SLTG_TypeInfoTail *pTITail)
3541 char *pFirstItem;
3542 sltg_ref_lookup_t *ref_lookup = NULL;
3544 if(pTIHeader->href_table != 0xffffffff) {
3545 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3546 pNameTable);
3549 pFirstItem = pBlk;
3551 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3552 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3554 HeapFree(GetProcessHeap(), 0, ref_lookup);
3558 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3559 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3560 const 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, TRUE, ref_lookup);
3576 if (pTITail->funcs_off != 0xffff)
3577 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3579 HeapFree(GetProcessHeap(), 0, ref_lookup);
3581 if (TRACE_ON(typelib))
3582 dump_TLBFuncDesc(pTI->funclist);
3585 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3586 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3587 const SLTG_TypeInfoTail *pTITail)
3589 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3592 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3593 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3594 const SLTG_TypeInfoTail *pTITail)
3596 WORD *pType;
3597 sltg_ref_lookup_t *ref_lookup = NULL;
3599 if (pTITail->simple_alias) {
3600 /* if simple alias, no more processing required */
3601 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3602 return;
3605 if(pTIHeader->href_table != 0xffffffff) {
3606 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3607 pNameTable);
3610 /* otherwise it is an offset to a type */
3611 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3613 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3615 HeapFree(GetProcessHeap(), 0, ref_lookup);
3618 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3619 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3620 const SLTG_TypeInfoTail *pTITail)
3622 sltg_ref_lookup_t *ref_lookup = NULL;
3623 if (pTIHeader->href_table != 0xffffffff)
3624 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3625 pNameTable);
3627 if (pTITail->vars_off != 0xffff)
3628 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3630 if (pTITail->funcs_off != 0xffff)
3631 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3633 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3634 * of dispinterface functions including the IDispatch ones, so
3635 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3636 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3638 HeapFree(GetProcessHeap(), 0, ref_lookup);
3639 if (TRACE_ON(typelib))
3640 dump_TLBFuncDesc(pTI->funclist);
3643 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3644 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3645 const SLTG_TypeInfoTail *pTITail)
3647 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3650 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3651 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3652 const SLTG_TypeInfoTail *pTITail)
3654 sltg_ref_lookup_t *ref_lookup = NULL;
3655 if (pTIHeader->href_table != 0xffffffff)
3656 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3657 pNameTable);
3659 if (pTITail->vars_off != 0xffff)
3660 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3662 if (pTITail->funcs_off != 0xffff)
3663 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3664 HeapFree(GetProcessHeap(), 0, ref_lookup);
3665 if (TRACE_ON(typelib))
3666 dump_TypeInfo(pTI);
3669 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3670 managable copy of it into this */
3671 typedef struct {
3672 WORD small_no;
3673 char *index_name;
3674 char *other_name;
3675 WORD res1a;
3676 WORD name_offs;
3677 WORD more_bytes;
3678 char *extra;
3679 WORD res20;
3680 DWORD helpcontext;
3681 WORD res26;
3682 GUID uuid;
3683 } SLTG_InternalOtherTypeInfo;
3685 /****************************************************************************
3686 * ITypeLib2_Constructor_SLTG
3688 * loading a SLTG typelib from an in-memory image
3690 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3692 ITypeLibImpl *pTypeLibImpl;
3693 SLTG_Header *pHeader;
3694 SLTG_BlkEntry *pBlkEntry;
3695 SLTG_Magic *pMagic;
3696 SLTG_Index *pIndex;
3697 SLTG_Pad9 *pPad9;
3698 LPVOID pBlk, pFirstBlk;
3699 SLTG_LibBlk *pLibBlk;
3700 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3701 char *pAfterOTIBlks = NULL;
3702 char *pNameTable, *ptr;
3703 int i;
3704 DWORD len, order;
3705 ITypeInfoImpl **ppTypeInfoImpl;
3707 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3710 pTypeLibImpl = TypeLibImpl_Constructor();
3711 if (!pTypeLibImpl) return NULL;
3713 pHeader = pLib;
3715 TRACE_(typelib)("header:\n");
3716 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3717 pHeader->nrOfFileBlks );
3718 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3719 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3720 pHeader->SLTG_magic);
3721 return NULL;
3724 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3725 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3727 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3728 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3730 /* Next we have a magic block */
3731 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3733 /* Let's see if we're still in sync */
3734 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3735 sizeof(SLTG_COMPOBJ_MAGIC))) {
3736 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3737 return NULL;
3739 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3740 sizeof(SLTG_DIR_MAGIC))) {
3741 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3742 return NULL;
3745 pIndex = (SLTG_Index*)(pMagic+1);
3747 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3749 pFirstBlk = (LPVOID)(pPad9 + 1);
3751 /* We'll set up a ptr to the main library block, which is the last one. */
3753 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3754 pBlkEntry[order].next != 0;
3755 order = pBlkEntry[order].next - 1, i++) {
3756 pBlk = (char*)pBlk + pBlkEntry[order].len;
3758 pLibBlk = pBlk;
3760 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3762 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3763 interspersed */
3765 len += 0x40;
3767 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3769 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3770 sizeof(*pOtherTypeInfoBlks) *
3771 pTypeLibImpl->TypeInfoCount);
3774 ptr = (char*)pLibBlk + len;
3776 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3777 WORD w, extra;
3778 len = 0;
3780 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3782 w = *(WORD*)(ptr + 2);
3783 if(w != 0xffff) {
3784 len += w;
3785 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3786 w+1);
3787 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3788 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3790 w = *(WORD*)(ptr + 4 + len);
3791 if(w != 0xffff) {
3792 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3793 len += w;
3794 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3795 w+1);
3796 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3797 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3799 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3800 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3801 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3802 if(extra) {
3803 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3804 extra);
3805 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3806 len += extra;
3808 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3809 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3810 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3811 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3812 len += sizeof(SLTG_OtherTypeInfo);
3813 ptr += len;
3816 pAfterOTIBlks = ptr;
3818 /* Skip this WORD and get the next DWORD */
3819 len = *(DWORD*)(pAfterOTIBlks + 2);
3821 /* Now add this to pLibBLk look at what we're pointing at and
3822 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3823 dust and we should be pointing at the beginning of the name
3824 table */
3826 pNameTable = (char*)pLibBlk + len;
3828 switch(*(WORD*)pNameTable) {
3829 case 0xffff:
3830 break;
3831 case 0x0200:
3832 pNameTable += 0x20;
3833 break;
3834 default:
3835 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3836 break;
3839 pNameTable += 0x216;
3841 pNameTable += 2;
3843 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3845 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3848 /* Hopefully we now have enough ptrs set up to actually read in
3849 some TypeInfos. It's not clear which order to do them in, so
3850 I'll just follow the links along the BlkEntry chain and read
3851 them in the order in which they are in the file */
3853 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3855 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3856 pBlkEntry[order].next != 0;
3857 order = pBlkEntry[order].next - 1, i++) {
3859 SLTG_TypeInfoHeader *pTIHeader;
3860 SLTG_TypeInfoTail *pTITail;
3861 SLTG_MemberHeader *pMemHeader;
3863 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3864 pOtherTypeInfoBlks[i].index_name)) {
3865 FIXME_(typelib)("Index strings don't match\n");
3866 return NULL;
3869 pTIHeader = pBlk;
3870 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3871 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3872 return NULL;
3874 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3875 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3876 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3878 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3879 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3880 (*ppTypeInfoImpl)->index = i;
3881 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3882 pOtherTypeInfoBlks[i].name_offs +
3883 pNameTable);
3884 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3885 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3886 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3887 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3888 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3889 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3890 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3892 if((pTIHeader->typeflags1 & 7) != 2)
3893 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3894 if(pTIHeader->typeflags3 != 2)
3895 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3897 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3898 debugstr_w((*ppTypeInfoImpl)->Name),
3899 typekind_desc[pTIHeader->typekind],
3900 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3901 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3903 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3905 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3907 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3908 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3909 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3911 switch(pTIHeader->typekind) {
3912 case TKIND_ENUM:
3913 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3914 pTIHeader, pTITail);
3915 break;
3917 case TKIND_RECORD:
3918 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3919 pTIHeader, pTITail);
3920 break;
3922 case TKIND_INTERFACE:
3923 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3924 pTIHeader, pTITail);
3925 break;
3927 case TKIND_COCLASS:
3928 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3929 pTIHeader, pTITail);
3930 break;
3932 case TKIND_ALIAS:
3933 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3934 pTIHeader, pTITail);
3935 break;
3937 case TKIND_DISPATCH:
3938 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3939 pTIHeader, pTITail);
3940 break;
3942 case TKIND_MODULE:
3943 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3944 pTIHeader, pTITail);
3945 break;
3947 default:
3948 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3949 break;
3953 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3954 but we've already set those */
3955 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3956 X(06);
3957 X(16);
3958 X(18);
3959 X(1a);
3960 X(1e);
3961 X(24);
3962 X(26);
3963 X(2a);
3964 X(2c);
3965 X(2e);
3966 X(30);
3967 X(32);
3968 X(34);
3970 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3971 pBlk = (char*)pBlk + pBlkEntry[order].len;
3974 if(i != pTypeLibImpl->TypeInfoCount) {
3975 FIXME("Somehow processed %d TypeInfos\n", i);
3976 return NULL;
3979 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3980 return (ITypeLib2*)pTypeLibImpl;
3983 /* ITypeLib::QueryInterface
3985 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3986 ITypeLib2 * iface,
3987 REFIID riid,
3988 VOID **ppvObject)
3990 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3992 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3994 *ppvObject=NULL;
3995 if(IsEqualIID(riid, &IID_IUnknown) ||
3996 IsEqualIID(riid,&IID_ITypeLib)||
3997 IsEqualIID(riid,&IID_ITypeLib2))
3999 *ppvObject = This;
4002 if(*ppvObject)
4004 ITypeLib2_AddRef(iface);
4005 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4006 return S_OK;
4008 TRACE("-- Interface: E_NOINTERFACE\n");
4009 return E_NOINTERFACE;
4012 /* ITypeLib::AddRef
4014 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4016 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4017 ULONG ref = InterlockedIncrement(&This->ref);
4019 TRACE("(%p)->ref was %u\n",This, ref - 1);
4021 return ref;
4024 /* ITypeLib::Release
4026 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4028 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4029 ULONG ref = InterlockedDecrement(&This->ref);
4031 TRACE("(%p)->(%u)\n",This, ref);
4033 if (!ref)
4035 TLBImpLib *pImpLib, *pImpLibNext;
4036 TLBCustData *pCustData, *pCustDataNext;
4037 TLBRefType *ref_type;
4038 void *cursor2;
4039 int i;
4041 /* remove cache entry */
4042 if(This->path)
4044 TRACE("removing from cache list\n");
4045 EnterCriticalSection(&cache_section);
4046 if (This->next) This->next->prev = This->prev;
4047 if (This->prev) This->prev->next = This->next;
4048 else tlb_cache_first = This->next;
4049 LeaveCriticalSection(&cache_section);
4050 HeapFree(GetProcessHeap(), 0, This->path);
4052 TRACE(" destroying ITypeLib(%p)\n",This);
4054 SysFreeString(This->Name);
4055 This->Name = NULL;
4057 SysFreeString(This->DocString);
4058 This->DocString = NULL;
4060 SysFreeString(This->HelpFile);
4061 This->HelpFile = NULL;
4063 SysFreeString(This->HelpStringDll);
4064 This->HelpStringDll = NULL;
4066 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4068 VariantClear(&pCustData->data);
4070 pCustDataNext = pCustData->next;
4071 TLB_Free(pCustData);
4074 for (i = 0; i < This->ctTypeDesc; i++)
4075 if (This->pTypeDesc[i].vt == VT_CARRAY)
4076 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4078 TLB_Free(This->pTypeDesc);
4080 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4082 if (pImpLib->pImpTypeLib)
4083 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4084 SysFreeString(pImpLib->name);
4086 pImpLibNext = pImpLib->next;
4087 TLB_Free(pImpLib);
4090 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4092 list_remove(&ref_type->entry);
4093 TLB_Free(ref_type);
4096 if (This->pTypeInfo) /* can be NULL */
4097 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4098 HeapFree(GetProcessHeap(),0,This);
4099 return 0;
4102 return ref;
4105 /* ITypeLib::GetTypeInfoCount
4107 * Returns the number of type descriptions in the type library
4109 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4111 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4112 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4113 return This->TypeInfoCount;
4116 /* ITypeLib::GetTypeInfo
4118 * retrieves the specified type description in the library.
4120 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4121 ITypeLib2 *iface,
4122 UINT index,
4123 ITypeInfo **ppTInfo)
4125 UINT i;
4127 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4128 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4130 TRACE("(%p)->(index=%d)\n", This, index);
4132 if (!ppTInfo) return E_INVALIDARG;
4134 /* search element n in list */
4135 for(i=0; i < index; i++)
4137 pTypeInfo = pTypeInfo->next;
4138 if (!pTypeInfo)
4140 TRACE("-- element not found\n");
4141 return TYPE_E_ELEMENTNOTFOUND;
4145 *ppTInfo = (ITypeInfo *) pTypeInfo;
4147 ITypeInfo_AddRef(*ppTInfo);
4148 TRACE("-- found (%p)\n",*ppTInfo);
4149 return S_OK;
4153 /* ITypeLibs::GetTypeInfoType
4155 * Retrieves the type of a type description.
4157 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4158 ITypeLib2 *iface,
4159 UINT index,
4160 TYPEKIND *pTKind)
4162 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4163 UINT i;
4164 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4166 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4167 return TYPE_E_ELEMENTNOTFOUND;
4169 TRACE("(%p) index %d\n", This, index);
4171 if(!pTKind) return E_INVALIDARG;
4173 /* search element n in list */
4174 for(i=0; i < index; i++)
4176 if(!pTInfo)
4178 TRACE("-- element not found\n");
4179 return TYPE_E_ELEMENTNOTFOUND;
4181 pTInfo = pTInfo->next;
4184 *pTKind = pTInfo->TypeAttr.typekind;
4185 TRACE("-- found Type (%d)\n", *pTKind);
4186 return S_OK;
4189 /* ITypeLib::GetTypeInfoOfGuid
4191 * Retrieves the type description that corresponds to the specified GUID.
4194 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4195 ITypeLib2 *iface,
4196 REFGUID guid,
4197 ITypeInfo **ppTInfo)
4199 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4200 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4202 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4204 if (!pTypeInfo)
4206 WARN("-- element not found\n");
4207 return TYPE_E_ELEMENTNOTFOUND;
4210 /* search linked list for guid */
4211 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4213 pTypeInfo = pTypeInfo->next;
4215 if (!pTypeInfo)
4217 /* end of list reached */
4218 WARN("-- element not found\n");
4219 return TYPE_E_ELEMENTNOTFOUND;
4223 TRACE("-- found (%p, %s)\n",
4224 pTypeInfo,
4225 debugstr_w(pTypeInfo->Name));
4227 *ppTInfo = (ITypeInfo*)pTypeInfo;
4228 ITypeInfo_AddRef(*ppTInfo);
4229 return S_OK;
4232 /* ITypeLib::GetLibAttr
4234 * Retrieves the structure that contains the library's attributes.
4237 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4238 ITypeLib2 *iface,
4239 LPTLIBATTR *ppTLibAttr)
4241 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4242 TRACE("(%p)\n",This);
4243 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4244 **ppTLibAttr = This->LibAttr;
4245 return S_OK;
4248 /* ITypeLib::GetTypeComp
4250 * Enables a client compiler to bind to a library's types, variables,
4251 * constants, and global functions.
4254 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4255 ITypeLib2 *iface,
4256 ITypeComp **ppTComp)
4258 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4260 TRACE("(%p)->(%p)\n",This,ppTComp);
4261 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4262 ITypeComp_AddRef(*ppTComp);
4264 return S_OK;
4267 /* ITypeLib::GetDocumentation
4269 * Retrieves the library's documentation string, the complete Help file name
4270 * and path, and the context identifier for the library Help topic in the Help
4271 * file.
4273 * On a successful return all non-null BSTR pointers will have been set,
4274 * possibly to NULL.
4276 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4277 ITypeLib2 *iface,
4278 INT index,
4279 BSTR *pBstrName,
4280 BSTR *pBstrDocString,
4281 DWORD *pdwHelpContext,
4282 BSTR *pBstrHelpFile)
4284 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4286 HRESULT result = E_INVALIDARG;
4288 ITypeInfo *pTInfo;
4291 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4292 This, index,
4293 pBstrName, pBstrDocString,
4294 pdwHelpContext, pBstrHelpFile);
4296 if(index<0)
4298 /* documentation for the typelib */
4299 if(pBstrName)
4301 if (This->Name)
4303 if(!(*pBstrName = SysAllocString(This->Name)))
4304 goto memerr1;
4306 else
4307 *pBstrName = NULL;
4309 if(pBstrDocString)
4311 if (This->DocString)
4313 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4314 goto memerr2;
4316 else if (This->Name)
4318 if(!(*pBstrDocString = SysAllocString(This->Name)))
4319 goto memerr2;
4321 else
4322 *pBstrDocString = NULL;
4324 if(pdwHelpContext)
4326 *pdwHelpContext = This->dwHelpContext;
4328 if(pBstrHelpFile)
4330 if (This->HelpFile)
4332 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4333 goto memerr3;
4335 else
4336 *pBstrHelpFile = NULL;
4339 result = S_OK;
4341 else
4343 /* for a typeinfo */
4344 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4346 if(SUCCEEDED(result))
4348 result = ITypeInfo_GetDocumentation(pTInfo,
4349 MEMBERID_NIL,
4350 pBstrName,
4351 pBstrDocString,
4352 pdwHelpContext, pBstrHelpFile);
4354 ITypeInfo_Release(pTInfo);
4357 return result;
4358 memerr3:
4359 if (pBstrDocString) SysFreeString (*pBstrDocString);
4360 memerr2:
4361 if (pBstrName) SysFreeString (*pBstrName);
4362 memerr1:
4363 return STG_E_INSUFFICIENTMEMORY;
4366 /* ITypeLib::IsName
4368 * Indicates whether a passed-in string contains the name of a type or member
4369 * described in the library.
4372 static HRESULT WINAPI ITypeLib2_fnIsName(
4373 ITypeLib2 *iface,
4374 LPOLESTR szNameBuf,
4375 ULONG lHashVal,
4376 BOOL *pfName)
4378 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4379 ITypeInfoImpl *pTInfo;
4380 TLBFuncDesc *pFInfo;
4381 TLBVarDesc *pVInfo;
4382 int i;
4383 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4385 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4386 pfName);
4388 *pfName=TRUE;
4389 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4390 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4391 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4392 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4393 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4394 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4395 goto ITypeLib2_fnIsName_exit;
4397 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4398 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4401 *pfName=FALSE;
4403 ITypeLib2_fnIsName_exit:
4404 TRACE("(%p)slow! search for %s: %s found!\n", This,
4405 debugstr_w(szNameBuf), *pfName?"NOT":"");
4407 return S_OK;
4410 /* ITypeLib::FindName
4412 * Finds occurrences of a type description in a type library. This may be used
4413 * to quickly verify that a name exists in a type library.
4416 static HRESULT WINAPI ITypeLib2_fnFindName(
4417 ITypeLib2 *iface,
4418 LPOLESTR szNameBuf,
4419 ULONG lHashVal,
4420 ITypeInfo **ppTInfo,
4421 MEMBERID *rgMemId,
4422 UINT16 *pcFound)
4424 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4425 ITypeInfoImpl *pTInfo;
4426 TLBFuncDesc *pFInfo;
4427 TLBVarDesc *pVInfo;
4428 int i,j = 0;
4429 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4431 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4432 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4433 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4434 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4435 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4436 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4437 goto ITypeLib2_fnFindName_exit;
4440 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4441 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4442 continue;
4443 ITypeLib2_fnFindName_exit:
4444 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4445 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4446 j++;
4448 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4449 This, *pcFound, debugstr_w(szNameBuf), j);
4451 *pcFound=j;
4453 return S_OK;
4456 /* ITypeLib::ReleaseTLibAttr
4458 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4461 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4462 ITypeLib2 *iface,
4463 TLIBATTR *pTLibAttr)
4465 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4466 TRACE("freeing (%p)\n",This);
4467 HeapFree(GetProcessHeap(),0,pTLibAttr);
4471 /* ITypeLib2::GetCustData
4473 * gets the custom data
4475 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4476 ITypeLib2 * iface,
4477 REFGUID guid,
4478 VARIANT *pVarVal)
4480 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4481 TLBCustData *pCData;
4483 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4485 if( IsEqualIID(guid, &pCData->guid)) break;
4488 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4490 if(pCData)
4492 VariantInit( pVarVal);
4493 VariantCopy( pVarVal, &pCData->data);
4494 return S_OK;
4496 return E_INVALIDARG; /* FIXME: correct? */
4499 /* ITypeLib2::GetLibStatistics
4501 * Returns statistics about a type library that are required for efficient
4502 * sizing of hash tables.
4505 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4506 ITypeLib2 * iface,
4507 ULONG *pcUniqueNames,
4508 ULONG *pcchUniqueNames)
4510 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4512 FIXME("(%p): stub!\n", This);
4514 if(pcUniqueNames) *pcUniqueNames=1;
4515 if(pcchUniqueNames) *pcchUniqueNames=1;
4516 return S_OK;
4519 /* ITypeLib2::GetDocumentation2
4521 * Retrieves the library's documentation string, the complete Help file name
4522 * and path, the localization context to use, and the context ID for the
4523 * library Help topic in the Help file.
4526 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4527 ITypeLib2 * iface,
4528 INT index,
4529 LCID lcid,
4530 BSTR *pbstrHelpString,
4531 DWORD *pdwHelpStringContext,
4532 BSTR *pbstrHelpStringDll)
4534 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4535 HRESULT result;
4536 ITypeInfo *pTInfo;
4538 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4540 /* the help string should be obtained from the helpstringdll,
4541 * using the _DLLGetDocumentation function, based on the supplied
4542 * lcid. Nice to do sometime...
4544 if(index<0)
4546 /* documentation for the typelib */
4547 if(pbstrHelpString)
4548 *pbstrHelpString=SysAllocString(This->DocString);
4549 if(pdwHelpStringContext)
4550 *pdwHelpStringContext=This->dwHelpContext;
4551 if(pbstrHelpStringDll)
4552 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4554 result = S_OK;
4556 else
4558 /* for a typeinfo */
4559 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4561 if(SUCCEEDED(result))
4563 ITypeInfo2 * pTInfo2;
4564 result = ITypeInfo_QueryInterface(pTInfo,
4565 &IID_ITypeInfo2,
4566 (LPVOID*) &pTInfo2);
4568 if(SUCCEEDED(result))
4570 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4571 MEMBERID_NIL,
4572 lcid,
4573 pbstrHelpString,
4574 pdwHelpStringContext,
4575 pbstrHelpStringDll);
4577 ITypeInfo2_Release(pTInfo2);
4580 ITypeInfo_Release(pTInfo);
4583 return result;
4586 /* ITypeLib2::GetAllCustData
4588 * Gets all custom data items for the library.
4591 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4592 ITypeLib2 * iface,
4593 CUSTDATA *pCustData)
4595 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4596 TLBCustData *pCData;
4597 int i;
4598 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4599 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4600 if(pCustData->prgCustData ){
4601 pCustData->cCustData=This->ctCustData;
4602 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4603 pCustData->prgCustData[i].guid=pCData->guid;
4604 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4606 }else{
4607 ERR(" OUT OF MEMORY!\n");
4608 return E_OUTOFMEMORY;
4610 return S_OK;
4613 static const ITypeLib2Vtbl tlbvt = {
4614 ITypeLib2_fnQueryInterface,
4615 ITypeLib2_fnAddRef,
4616 ITypeLib2_fnRelease,
4617 ITypeLib2_fnGetTypeInfoCount,
4618 ITypeLib2_fnGetTypeInfo,
4619 ITypeLib2_fnGetTypeInfoType,
4620 ITypeLib2_fnGetTypeInfoOfGuid,
4621 ITypeLib2_fnGetLibAttr,
4622 ITypeLib2_fnGetTypeComp,
4623 ITypeLib2_fnGetDocumentation,
4624 ITypeLib2_fnIsName,
4625 ITypeLib2_fnFindName,
4626 ITypeLib2_fnReleaseTLibAttr,
4628 ITypeLib2_fnGetCustData,
4629 ITypeLib2_fnGetLibStatistics,
4630 ITypeLib2_fnGetDocumentation2,
4631 ITypeLib2_fnGetAllCustData
4635 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4637 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4639 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4642 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4644 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4646 return ITypeLib2_AddRef((ITypeLib2 *)This);
4649 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4651 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4653 return ITypeLib2_Release((ITypeLib2 *)This);
4656 static HRESULT WINAPI ITypeLibComp_fnBind(
4657 ITypeComp * iface,
4658 OLECHAR * szName,
4659 ULONG lHash,
4660 WORD wFlags,
4661 ITypeInfo ** ppTInfo,
4662 DESCKIND * pDescKind,
4663 BINDPTR * pBindPtr)
4665 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4666 ITypeInfoImpl *pTypeInfo;
4668 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4670 *pDescKind = DESCKIND_NONE;
4671 pBindPtr->lptcomp = NULL;
4672 *ppTInfo = NULL;
4674 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4676 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4678 /* FIXME: check wFlags here? */
4679 /* FIXME: we should use a hash table to look this info up using lHash
4680 * instead of an O(n) search */
4681 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4682 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4684 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4686 *pDescKind = DESCKIND_TYPECOMP;
4687 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4688 ITypeComp_AddRef(pBindPtr->lptcomp);
4689 TRACE("module or enum: %s\n", debugstr_w(szName));
4690 return S_OK;
4694 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4695 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4697 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4698 HRESULT hr;
4700 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4701 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4703 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4704 return S_OK;
4708 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4709 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4711 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4712 HRESULT hr;
4713 ITypeInfo *subtypeinfo;
4714 BINDPTR subbindptr;
4715 DESCKIND subdesckind;
4717 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4718 &subtypeinfo, &subdesckind, &subbindptr);
4719 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4721 TYPEDESC tdesc_appobject =
4724 (TYPEDESC *)pTypeInfo->hreftype
4726 VT_USERDEFINED
4728 const VARDESC vardesc_appobject =
4730 -2, /* memid */
4731 NULL, /* lpstrSchema */
4733 0 /* oInst */
4736 /* ELEMDESC */
4738 /* TYPEDESC */
4740 &tdesc_appobject
4742 VT_PTR
4745 0, /* wVarFlags */
4746 VAR_STATIC /* varkind */
4749 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4751 /* cleanup things filled in by Bind call so we can put our
4752 * application object data in there instead */
4753 switch (subdesckind)
4755 case DESCKIND_FUNCDESC:
4756 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4757 break;
4758 case DESCKIND_VARDESC:
4759 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4760 break;
4761 default:
4762 break;
4764 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4766 if (pTypeInfo->hreftype == -1)
4767 FIXME("no hreftype for interface %p\n", pTypeInfo);
4769 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4770 if (FAILED(hr))
4771 return hr;
4773 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4774 *ppTInfo = (ITypeInfo *)pTypeInfo;
4775 ITypeInfo_AddRef(*ppTInfo);
4776 return S_OK;
4781 TRACE("name not found %s\n", debugstr_w(szName));
4782 return S_OK;
4785 static HRESULT WINAPI ITypeLibComp_fnBindType(
4786 ITypeComp * iface,
4787 OLECHAR * szName,
4788 ULONG lHash,
4789 ITypeInfo ** ppTInfo,
4790 ITypeComp ** ppTComp)
4792 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4793 return E_NOTIMPL;
4796 static const ITypeCompVtbl tlbtcvt =
4799 ITypeLibComp_fnQueryInterface,
4800 ITypeLibComp_fnAddRef,
4801 ITypeLibComp_fnRelease,
4803 ITypeLibComp_fnBind,
4804 ITypeLibComp_fnBindType
4807 /*================== ITypeInfo(2) Methods ===================================*/
4808 static ITypeInfo2 * ITypeInfo_Constructor(void)
4810 ITypeInfoImpl * pTypeInfoImpl;
4812 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4813 if (pTypeInfoImpl)
4815 pTypeInfoImpl->lpVtbl = &tinfvt;
4816 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4817 pTypeInfoImpl->ref=1;
4818 pTypeInfoImpl->hreftype = -1;
4819 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4820 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4822 TRACE("(%p)\n", pTypeInfoImpl);
4823 return (ITypeInfo2*) pTypeInfoImpl;
4826 /* ITypeInfo::QueryInterface
4828 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4829 ITypeInfo2 *iface,
4830 REFIID riid,
4831 VOID **ppvObject)
4833 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4835 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4837 *ppvObject=NULL;
4838 if(IsEqualIID(riid, &IID_IUnknown) ||
4839 IsEqualIID(riid,&IID_ITypeInfo)||
4840 IsEqualIID(riid,&IID_ITypeInfo2))
4841 *ppvObject = This;
4843 if(*ppvObject){
4844 ITypeInfo_AddRef(iface);
4845 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4846 return S_OK;
4848 TRACE("-- Interface: E_NOINTERFACE\n");
4849 return E_NOINTERFACE;
4852 /* ITypeInfo::AddRef
4854 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4856 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4857 ULONG ref = InterlockedIncrement(&This->ref);
4859 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4861 TRACE("(%p)->ref is %u\n",This, ref);
4862 return ref;
4865 /* ITypeInfo::Release
4867 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4869 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4870 ULONG ref = InterlockedDecrement(&This->ref);
4872 TRACE("(%p)->(%u)\n",This, ref);
4874 if (ref) {
4875 /* We don't release ITypeLib when ref=0 because
4876 it means that function is called by ITypeLib2_Release */
4877 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4878 } else {
4879 TLBFuncDesc *pFInfo, *pFInfoNext;
4880 TLBVarDesc *pVInfo, *pVInfoNext;
4881 TLBImplType *pImpl, *pImplNext;
4883 TRACE("destroying ITypeInfo(%p)\n",This);
4885 if (This->no_free_data)
4886 goto finish_free;
4888 SysFreeString(This->Name);
4889 This->Name = NULL;
4891 SysFreeString(This->DocString);
4892 This->DocString = NULL;
4894 SysFreeString(This->DllName);
4895 This->DllName = NULL;
4897 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4899 INT i;
4900 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4902 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4903 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4905 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4906 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4908 SysFreeString(pFInfo->pParamDesc[i].Name);
4910 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4911 TLB_Free(pFInfo->pParamDesc);
4912 TLB_FreeCustData(pFInfo->pCustData);
4913 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4914 SysFreeString(pFInfo->Entry);
4915 SysFreeString(pFInfo->HelpString);
4916 SysFreeString(pFInfo->Name);
4918 pFInfoNext = pFInfo->next;
4919 TLB_Free(pFInfo);
4921 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4923 if (pVInfo->vardesc.varkind == VAR_CONST)
4925 VariantClear(pVInfo->vardesc.u.lpvarValue);
4926 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4928 TLB_FreeCustData(pVInfo->pCustData);
4929 SysFreeString(pVInfo->Name);
4930 pVInfoNext = pVInfo->next;
4931 TLB_Free(pVInfo);
4933 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4935 TLB_FreeCustData(pImpl->pCustData);
4936 pImplNext = pImpl->next;
4937 TLB_Free(pImpl);
4939 TLB_FreeCustData(This->pCustData);
4941 finish_free:
4942 if (This->next)
4944 ITypeInfo_Release((ITypeInfo*)This->next);
4947 HeapFree(GetProcessHeap(),0,This);
4948 return 0;
4950 return ref;
4953 /* ITypeInfo::GetTypeAttr
4955 * Retrieves a TYPEATTR structure that contains the attributes of the type
4956 * description.
4959 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4960 LPTYPEATTR *ppTypeAttr)
4962 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4963 SIZE_T size;
4965 TRACE("(%p)\n",This);
4967 size = sizeof(**ppTypeAttr);
4968 if (This->TypeAttr.typekind == TKIND_ALIAS)
4969 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4971 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4972 if (!*ppTypeAttr)
4973 return E_OUTOFMEMORY;
4975 **ppTypeAttr = This->TypeAttr;
4977 if (This->TypeAttr.typekind == TKIND_ALIAS)
4978 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4979 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4981 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4982 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4983 funcs */
4984 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4985 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4987 return S_OK;
4990 /* ITypeInfo::GetTypeComp
4992 * Retrieves the ITypeComp interface for the type description, which enables a
4993 * client compiler to bind to the type description's members.
4996 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4997 ITypeComp * *ppTComp)
4999 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5001 TRACE("(%p)->(%p)\n", This, ppTComp);
5003 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5004 ITypeComp_AddRef(*ppTComp);
5005 return S_OK;
5008 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5010 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5011 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5012 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5013 return size;
5016 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5018 *dest = *src;
5019 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5020 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5022 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5023 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5024 *buffer += sizeof(PARAMDESCEX);
5025 *pparamdescex_dest = *pparamdescex_src;
5026 VariantInit(&pparamdescex_dest->varDefaultValue);
5027 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5028 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5030 else
5031 dest->u.paramdesc.pparamdescex = NULL;
5032 return S_OK;
5035 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5037 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5038 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5041 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5043 FUNCDESC *dest;
5044 char *buffer;
5045 SIZE_T size = sizeof(*src);
5046 SHORT i;
5047 HRESULT hr;
5049 size += sizeof(*src->lprgscode) * src->cScodes;
5050 size += TLB_SizeElemDesc(&src->elemdescFunc);
5051 for (i = 0; i < src->cParams; i++)
5053 size += sizeof(ELEMDESC);
5054 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5057 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5058 if (!dest) return E_OUTOFMEMORY;
5060 *dest = *src;
5061 if (dispinterface) /* overwrite funckind */
5062 dest->funckind = FUNC_DISPATCH;
5063 buffer = (char *)(dest + 1);
5065 dest->lprgscode = (SCODE *)buffer;
5066 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5067 buffer += sizeof(*src->lprgscode) * src->cScodes;
5069 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5070 if (FAILED(hr))
5072 SysFreeString((BSTR)dest);
5073 return hr;
5076 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5077 buffer += sizeof(ELEMDESC) * src->cParams;
5078 for (i = 0; i < src->cParams; i++)
5080 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5081 if (FAILED(hr))
5082 break;
5084 if (FAILED(hr))
5086 /* undo the above actions */
5087 for (i = i - 1; i >= 0; i--)
5088 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5089 TLB_FreeElemDesc(&dest->elemdescFunc);
5090 SysFreeString((BSTR)dest);
5091 return hr;
5094 /* special treatment for dispinterfaces: this makes functions appear
5095 * to return their [retval] value when it is really returning an
5096 * HRESULT */
5097 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5099 if (dest->cParams &&
5100 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5102 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5103 if (elemdesc->tdesc.vt != VT_PTR)
5105 ERR("elemdesc should have started with VT_PTR instead of:\n");
5106 if (ERR_ON(ole))
5107 dump_ELEMDESC(elemdesc);
5108 return E_UNEXPECTED;
5111 /* copy last parameter to the return value. we are using a flat
5112 * buffer so there is no danger of leaking memory in
5113 * elemdescFunc */
5114 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5116 /* remove the last parameter */
5117 dest->cParams--;
5119 else
5120 /* otherwise this function is made to appear to have no return
5121 * value */
5122 dest->elemdescFunc.tdesc.vt = VT_VOID;
5126 *dest_ptr = dest;
5127 return S_OK;
5130 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5132 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5133 const TLBFuncDesc *pFDesc;
5134 UINT i;
5136 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5139 if (pFDesc)
5141 *ppFuncDesc = &pFDesc->funcdesc;
5142 return S_OK;
5145 return TYPE_E_ELEMENTNOTFOUND;
5148 /* internal function to make the inherited interfaces' methods appear
5149 * part of the interface */
5150 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5151 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5153 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5154 HRESULT hr;
5155 UINT implemented_funcs = 0;
5157 if (funcs)
5158 *funcs = 0;
5159 else
5160 *hrefoffset = DISPATCH_HREF_OFFSET;
5162 if(This->impltypelist)
5164 ITypeInfo *pSubTypeInfo;
5165 UINT sub_funcs;
5167 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5168 if (FAILED(hr))
5169 return hr;
5171 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5172 index,
5173 ppFuncDesc,
5174 &sub_funcs, hrefoffset);
5175 implemented_funcs += sub_funcs;
5176 ITypeInfo_Release(pSubTypeInfo);
5177 if (SUCCEEDED(hr))
5178 return hr;
5179 *hrefoffset += DISPATCH_HREF_OFFSET;
5182 if (funcs)
5183 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5184 else
5185 *hrefoffset = 0;
5187 if (index < implemented_funcs)
5188 return E_INVALIDARG;
5189 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5190 ppFuncDesc);
5193 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5195 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5196 while (TRUE)
5198 switch (pTypeDesc->vt)
5200 case VT_USERDEFINED:
5201 pTypeDesc->u.hreftype += hrefoffset;
5202 return;
5203 case VT_PTR:
5204 case VT_SAFEARRAY:
5205 pTypeDesc = pTypeDesc->u.lptdesc;
5206 break;
5207 case VT_CARRAY:
5208 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5209 break;
5210 default:
5211 return;
5216 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5218 SHORT i;
5219 for (i = 0; i < pFuncDesc->cParams; i++)
5220 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5221 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5224 /* ITypeInfo::GetFuncDesc
5226 * Retrieves the FUNCDESC structure that contains information about a
5227 * specified function.
5230 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5231 LPFUNCDESC *ppFuncDesc)
5233 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5234 const FUNCDESC *internal_funcdesc;
5235 HRESULT hr;
5236 UINT hrefoffset = 0;
5238 TRACE("(%p) index %d\n", This, index);
5240 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5241 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5242 &internal_funcdesc, NULL,
5243 &hrefoffset);
5244 else
5245 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5246 &internal_funcdesc);
5247 if (FAILED(hr))
5249 WARN("description for function %d not found\n", index);
5250 return hr;
5253 hr = TLB_AllocAndInitFuncDesc(
5254 internal_funcdesc,
5255 ppFuncDesc,
5256 This->TypeAttr.typekind == TKIND_DISPATCH);
5258 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5259 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5261 TRACE("-- 0x%08x\n", hr);
5262 return hr;
5265 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5267 VARDESC *dest;
5268 char *buffer;
5269 SIZE_T size = sizeof(*src);
5270 HRESULT hr;
5272 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5273 if (src->varkind == VAR_CONST)
5274 size += sizeof(VARIANT);
5275 size += TLB_SizeElemDesc(&src->elemdescVar);
5277 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5278 if (!dest) return E_OUTOFMEMORY;
5280 *dest = *src;
5281 buffer = (char *)(dest + 1);
5282 if (src->lpstrSchema)
5284 int len;
5285 dest->lpstrSchema = (LPOLESTR)buffer;
5286 len = strlenW(src->lpstrSchema);
5287 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5288 buffer += (len + 1) * sizeof(WCHAR);
5291 if (src->varkind == VAR_CONST)
5293 HRESULT hr;
5295 dest->u.lpvarValue = (VARIANT *)buffer;
5296 *dest->u.lpvarValue = *src->u.lpvarValue;
5297 buffer += sizeof(VARIANT);
5298 VariantInit(dest->u.lpvarValue);
5299 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5300 if (FAILED(hr))
5302 SysFreeString((BSTR)dest_ptr);
5303 return hr;
5306 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5307 if (FAILED(hr))
5309 if (src->varkind == VAR_CONST)
5310 VariantClear(dest->u.lpvarValue);
5311 SysFreeString((BSTR)dest);
5312 return hr;
5314 *dest_ptr = dest;
5315 return S_OK;
5318 /* ITypeInfo::GetVarDesc
5320 * Retrieves a VARDESC structure that describes the specified variable.
5323 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5324 LPVARDESC *ppVarDesc)
5326 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5327 UINT i;
5328 const TLBVarDesc *pVDesc;
5330 TRACE("(%p) index %d\n", This, index);
5332 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5335 if (pVDesc)
5336 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5338 return E_INVALIDARG;
5341 /* ITypeInfo_GetNames
5343 * Retrieves the variable with the specified member ID (or the name of the
5344 * property or method and its parameters) that correspond to the specified
5345 * function ID.
5347 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5348 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5350 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5351 const TLBFuncDesc *pFDesc;
5352 const TLBVarDesc *pVDesc;
5353 int i;
5354 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5355 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5356 if(pFDesc)
5358 /* function found, now return function and parameter names */
5359 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5361 if(!i)
5362 *rgBstrNames=SysAllocString(pFDesc->Name);
5363 else
5364 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5366 *pcNames=i;
5368 else
5370 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5371 if(pVDesc)
5373 *rgBstrNames=SysAllocString(pVDesc->Name);
5374 *pcNames=1;
5376 else
5378 if(This->impltypelist &&
5379 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5380 /* recursive search */
5381 ITypeInfo *pTInfo;
5382 HRESULT result;
5383 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5384 &pTInfo);
5385 if(SUCCEEDED(result))
5387 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5388 ITypeInfo_Release(pTInfo);
5389 return result;
5391 WARN("Could not search inherited interface!\n");
5393 else
5395 WARN("no names found\n");
5397 *pcNames=0;
5398 return TYPE_E_ELEMENTNOTFOUND;
5401 return S_OK;
5405 /* ITypeInfo::GetRefTypeOfImplType
5407 * If a type description describes a COM class, it retrieves the type
5408 * description of the implemented interface types. For an interface,
5409 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5410 * if any exist.
5413 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5414 ITypeInfo2 *iface,
5415 UINT index,
5416 HREFTYPE *pRefType)
5418 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5419 UINT i;
5420 HRESULT hr = S_OK;
5421 const TLBImplType *pImpl = This->impltypelist;
5423 TRACE("(%p) index %d\n", This, index);
5424 if (TRACE_ON(ole)) dump_TypeInfo(This);
5426 if(index==(UINT)-1)
5428 /* only valid on dual interfaces;
5429 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5431 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5433 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5434 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5436 *pRefType = -1;
5438 else
5440 hr = TYPE_E_ELEMENTNOTFOUND;
5443 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5445 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5446 *pRefType = This->pTypeLib->dispatch_href;
5448 else
5450 /* get element n from linked list */
5451 for(i=0; pImpl && i<index; i++)
5453 pImpl = pImpl->next;
5456 if (pImpl)
5457 *pRefType = pImpl->hRef;
5458 else
5459 hr = TYPE_E_ELEMENTNOTFOUND;
5462 if(TRACE_ON(ole))
5464 if(SUCCEEDED(hr))
5465 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5466 else
5467 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5470 return hr;
5473 /* ITypeInfo::GetImplTypeFlags
5475 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5476 * or base interface in a type description.
5478 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5479 UINT index, INT *pImplTypeFlags)
5481 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5482 UINT i;
5483 TLBImplType *pImpl;
5485 TRACE("(%p) index %d\n", This, index);
5486 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5487 i++, pImpl=pImpl->next)
5489 if(i==index && pImpl){
5490 *pImplTypeFlags=pImpl->implflags;
5491 return S_OK;
5493 *pImplTypeFlags=0;
5494 return TYPE_E_ELEMENTNOTFOUND;
5497 /* GetIDsOfNames
5498 * Maps between member names and member IDs, and parameter names and
5499 * parameter IDs.
5501 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5502 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5504 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5505 const TLBFuncDesc *pFDesc;
5506 const TLBVarDesc *pVDesc;
5507 HRESULT ret=S_OK;
5508 UINT i;
5510 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5511 cNames);
5513 /* init out parameters in case of failure */
5514 for (i = 0; i < cNames; i++)
5515 pMemId[i] = MEMBERID_NIL;
5517 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5518 int j;
5519 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5520 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5521 for(i=1; i < cNames; i++){
5522 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5523 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5524 break;
5525 if( j<pFDesc->funcdesc.cParams)
5526 pMemId[i]=j;
5527 else
5528 ret=DISP_E_UNKNOWNNAME;
5530 TRACE("-- 0x%08x\n", ret);
5531 return ret;
5534 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5535 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5536 if(cNames) *pMemId=pVDesc->vardesc.memid;
5537 return ret;
5540 /* not found, see if it can be found in an inherited interface */
5541 if(This->impltypelist) {
5542 /* recursive search */
5543 ITypeInfo *pTInfo;
5544 ret=ITypeInfo_GetRefTypeInfo(iface,
5545 This->impltypelist->hRef, &pTInfo);
5546 if(SUCCEEDED(ret)){
5547 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5548 ITypeInfo_Release(pTInfo);
5549 return ret;
5551 WARN("Could not search inherited interface!\n");
5552 } else
5553 WARN("no names found\n");
5554 return DISP_E_UNKNOWNNAME;
5557 /* ITypeInfo::Invoke
5559 * Invokes a method, or accesses a property of an object, that implements the
5560 * interface described by the type description.
5562 DWORD
5563 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5564 DWORD res;
5566 if (TRACE_ON(ole)) {
5567 int i;
5568 TRACE("Calling %p(",func);
5569 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5570 TRACE(")\n");
5573 switch (callconv) {
5574 case CC_STDCALL:
5576 switch (nrargs) {
5577 case 0:
5578 res = func();
5579 break;
5580 case 1:
5581 res = func(args[0]);
5582 break;
5583 case 2:
5584 res = func(args[0],args[1]);
5585 break;
5586 case 3:
5587 res = func(args[0],args[1],args[2]);
5588 break;
5589 case 4:
5590 res = func(args[0],args[1],args[2],args[3]);
5591 break;
5592 case 5:
5593 res = func(args[0],args[1],args[2],args[3],args[4]);
5594 break;
5595 case 6:
5596 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5597 break;
5598 case 7:
5599 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5600 break;
5601 case 8:
5602 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5603 break;
5604 case 9:
5605 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5606 break;
5607 case 10:
5608 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5609 break;
5610 case 11:
5611 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5612 break;
5613 case 12:
5614 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]);
5615 break;
5616 case 13:
5617 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]);
5618 break;
5619 case 14:
5620 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]);
5621 break;
5622 case 15:
5623 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]);
5624 break;
5625 case 16:
5626 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]);
5627 break;
5628 case 17:
5629 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]);
5630 break;
5631 case 18:
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],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5633 break;
5634 case 19:
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],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5636 break;
5637 case 20:
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],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5639 break;
5640 case 21:
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],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5642 break;
5643 case 22:
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],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5645 break;
5646 case 23:
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],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5648 break;
5649 case 24:
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],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5651 break;
5652 case 25:
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],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5654 break;
5655 case 26:
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],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5657 break;
5658 case 27:
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],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5660 break;
5661 case 28:
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],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5663 break;
5664 case 29:
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],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5666 break;
5667 case 30:
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],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5669 break;
5670 default:
5671 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5672 res = -1;
5673 break;
5675 break;
5676 default:
5677 FIXME("unsupported calling convention %d\n",callconv);
5678 res = -1;
5679 break;
5681 TRACE("returns %08x\n",res);
5682 return res;
5685 /* The size of the argument on the stack in DWORD units (in all x86 call
5686 * convetions the arguments on the stack are DWORD-aligned)
5688 static int _dispargsize(VARTYPE vt)
5690 switch (vt) {
5691 case VT_I8:
5692 case VT_UI8:
5693 return 8/sizeof(DWORD);
5694 case VT_R8:
5695 return sizeof(double)/sizeof(DWORD);
5696 case VT_DECIMAL:
5697 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5698 case VT_CY:
5699 return sizeof(CY)/sizeof(DWORD);
5700 case VT_DATE:
5701 return sizeof(DATE)/sizeof(DWORD);
5702 case VT_VARIANT:
5703 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5704 case VT_RECORD:
5705 FIXME("VT_RECORD not implemented\n");
5706 return 1;
5707 default:
5708 return 1;
5712 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5714 HRESULT hr = S_OK;
5715 ITypeInfo *tinfo2 = NULL;
5716 TYPEATTR *tattr = NULL;
5718 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5719 if (hr)
5721 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5722 "hr = 0x%08x\n",
5723 tdesc->u.hreftype, hr);
5724 return hr;
5726 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5727 if (hr)
5729 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5730 ITypeInfo_Release(tinfo2);
5731 return hr;
5734 switch (tattr->typekind)
5736 case TKIND_ENUM:
5737 *vt |= VT_I4;
5738 break;
5740 case TKIND_ALIAS:
5741 tdesc = &tattr->tdescAlias;
5742 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5743 break;
5745 case TKIND_INTERFACE:
5746 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5747 *vt |= VT_DISPATCH;
5748 else
5749 *vt |= VT_UNKNOWN;
5750 break;
5752 case TKIND_DISPATCH:
5753 *vt |= VT_DISPATCH;
5754 break;
5756 case TKIND_COCLASS:
5757 *vt |= VT_DISPATCH;
5758 break;
5760 case TKIND_RECORD:
5761 FIXME("TKIND_RECORD unhandled.\n");
5762 hr = E_NOTIMPL;
5763 break;
5765 case TKIND_UNION:
5766 FIXME("TKIND_UNION unhandled.\n");
5767 hr = E_NOTIMPL;
5768 break;
5770 default:
5771 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5772 hr = E_NOTIMPL;
5773 break;
5775 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5776 ITypeInfo_Release(tinfo2);
5777 return hr;
5780 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5782 HRESULT hr = S_OK;
5784 /* enforce only one level of pointer indirection */
5785 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5787 tdesc = tdesc->u.lptdesc;
5789 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5790 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5791 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5792 if ((tdesc->vt == VT_USERDEFINED) ||
5793 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5795 VARTYPE vt_userdefined = 0;
5796 const TYPEDESC *tdesc_userdefined = tdesc;
5797 if (tdesc->vt == VT_PTR)
5799 vt_userdefined = VT_BYREF;
5800 tdesc_userdefined = tdesc->u.lptdesc;
5802 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5803 if ((hr == S_OK) &&
5804 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5805 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5807 *vt |= vt_userdefined;
5808 return S_OK;
5811 *vt = VT_BYREF;
5814 switch (tdesc->vt)
5816 case VT_HRESULT:
5817 *vt |= VT_ERROR;
5818 break;
5819 case VT_USERDEFINED:
5820 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5821 break;
5822 case VT_VOID:
5823 case VT_CARRAY:
5824 case VT_PTR:
5825 case VT_LPSTR:
5826 case VT_LPWSTR:
5827 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5828 hr = DISP_E_BADVARTYPE;
5829 break;
5830 case VT_SAFEARRAY:
5831 *vt |= VT_ARRAY;
5832 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5833 break;
5834 default:
5835 *vt |= tdesc->vt;
5836 break;
5838 return hr;
5841 /***********************************************************************
5842 * DispCallFunc (OLEAUT32.@)
5844 * Invokes a function of the specified calling convention, passing the
5845 * specified arguments and returns the result.
5847 * PARAMS
5848 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5849 * oVft [I] The offset in the vtable. See notes.
5850 * cc [I] Calling convention of the function to call.
5851 * vtReturn [I] The return type of the function.
5852 * cActuals [I] Number of parameters.
5853 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5854 * prgpvarg [I] The arguments to pass.
5855 * pvargResult [O] The return value of the function. Can be NULL.
5857 * RETURNS
5858 * Success: S_OK.
5859 * Failure: HRESULT code.
5861 * NOTES
5862 * The HRESULT return value of this function is not affected by the return
5863 * value of the user supplied function, which is returned in pvargResult.
5865 * If pvInstance is NULL then a non-object function is to be called and oVft
5866 * is the address of the function to call.
5868 * The cc parameter can be one of the following values:
5869 *|CC_FASTCALL
5870 *|CC_CDECL
5871 *|CC_PASCAL
5872 *|CC_STDCALL
5873 *|CC_FPFASTCALL
5874 *|CC_SYSCALL
5875 *|CC_MPWCDECL
5876 *|CC_MPWPASCAL
5879 HRESULT WINAPI
5880 DispCallFunc(
5881 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5882 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5884 int argsize, argspos;
5885 UINT i;
5886 DWORD *args;
5887 HRESULT hres;
5889 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5890 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5891 pvargResult, V_VT(pvargResult));
5893 argsize = 0;
5894 if (pvInstance)
5895 argsize++; /* for This pointer */
5897 for (i=0;i<cActuals;i++)
5899 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5900 dump_Variant(prgpvarg[i]);
5901 argsize += _dispargsize(prgvt[i]);
5903 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5905 argspos = 0;
5906 if (pvInstance)
5908 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5909 argspos++;
5912 for (i=0;i<cActuals;i++)
5914 VARIANT *arg = prgpvarg[i];
5915 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5916 if (prgvt[i] == VT_VARIANT)
5917 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5918 else
5919 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5920 argspos += _dispargsize(prgvt[i]);
5923 if (pvInstance)
5925 FARPROC *vtable = *(FARPROC**)pvInstance;
5926 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5928 else
5929 /* if we aren't invoking an object then the function pointer is stored
5930 * in oVft */
5931 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5933 if (pvargResult && (vtReturn != VT_EMPTY))
5935 TRACE("Method returned 0x%08x\n",hres);
5936 V_VT(pvargResult) = vtReturn;
5937 V_UI4(pvargResult) = hres;
5940 HeapFree(GetProcessHeap(),0,args);
5941 return S_OK;
5944 #define INVBUF_ELEMENT_SIZE \
5945 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5946 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5947 ((VARIANTARG *)(buffer))
5948 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5949 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5950 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5951 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5952 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5953 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5955 static HRESULT WINAPI ITypeInfo_fnInvoke(
5956 ITypeInfo2 *iface,
5957 VOID *pIUnk,
5958 MEMBERID memid,
5959 UINT16 wFlags,
5960 DISPPARAMS *pDispParams,
5961 VARIANT *pVarResult,
5962 EXCEPINFO *pExcepInfo,
5963 UINT *pArgErr)
5965 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5966 int i;
5967 unsigned int var_index;
5968 TYPEKIND type_kind;
5969 HRESULT hres;
5970 const TLBFuncDesc *pFuncInfo;
5972 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5973 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5976 if (!pDispParams)
5978 ERR("NULL pDispParams not allowed\n");
5979 return E_INVALIDARG;
5982 dump_DispParms(pDispParams);
5984 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5986 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5987 pDispParams->cNamedArgs, pDispParams->cArgs);
5988 return E_INVALIDARG;
5991 /* we do this instead of using GetFuncDesc since it will return a fake
5992 * FUNCDESC for dispinterfaces and we want the real function description */
5993 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5994 if ((memid == pFuncInfo->funcdesc.memid) &&
5995 (wFlags & pFuncInfo->funcdesc.invkind))
5996 break;
5998 if (pFuncInfo) {
5999 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6001 if (TRACE_ON(ole))
6003 TRACE("invoking:\n");
6004 dump_TLBFuncDescOne(pFuncInfo);
6007 switch (func_desc->funckind) {
6008 case FUNC_PUREVIRTUAL:
6009 case FUNC_VIRTUAL: {
6010 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6011 VARIANT varresult;
6012 VARIANT retval; /* pointer for storing byref retvals in */
6013 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6014 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6015 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6016 UINT cNamedArgs = pDispParams->cNamedArgs;
6017 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6019 hres = S_OK;
6021 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6023 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6025 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6026 hres = DISP_E_PARAMNOTFOUND;
6027 goto func_fail;
6029 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6030 cNamedArgs--;
6031 rgdispidNamedArgs++;
6034 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6036 ERR("functions with the vararg attribute do not support named arguments\n");
6037 hres = DISP_E_NONAMEDARGS;
6038 goto func_fail;
6041 for (i = 0; i < func_desc->cParams; i++)
6043 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6044 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6045 if (FAILED(hres))
6046 goto func_fail;
6049 TRACE("changing args\n");
6050 for (i = 0; i < func_desc->cParams; i++)
6052 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6053 VARIANTARG *src_arg;
6055 if (cNamedArgs)
6057 USHORT j;
6058 src_arg = NULL;
6059 for (j = 0; j < cNamedArgs; j++)
6060 if (rgdispidNamedArgs[j] == i)
6062 src_arg = &pDispParams->rgvarg[j];
6063 break;
6066 else
6067 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6069 if (wParamFlags & PARAMFLAG_FRETVAL)
6071 /* under most conditions the caller is not allowed to
6072 * pass in a dispparam arg in the index of what would be
6073 * the retval parameter. however, there is an exception
6074 * where the extra parameter is used in an extra
6075 * IDispatch::Invoke below */
6076 if ((i < pDispParams->cArgs) &&
6077 ((func_desc->cParams != 1) || !pVarResult ||
6078 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6080 hres = DISP_E_BADPARAMCOUNT;
6081 break;
6084 /* note: this check is placed so that if the caller passes
6085 * in a VARIANTARG for the retval we just ignore it, like
6086 * native does */
6087 if (i == func_desc->cParams - 1)
6089 VARIANTARG *arg;
6090 arg = prgpvarg[i] = &rgvarg[i];
6091 memset(arg, 0, sizeof(*arg));
6092 V_VT(arg) = rgvt[i];
6093 memset(&retval, 0, sizeof(retval));
6094 V_BYREF(arg) = &retval;
6096 else
6098 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6099 hres = E_UNEXPECTED;
6100 break;
6103 else if (src_arg)
6105 dump_Variant(src_arg);
6107 if (rgvt[i] == VT_VARIANT)
6108 hres = VariantCopy(&rgvarg[i], src_arg);
6109 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6111 if (rgvt[i] == V_VT(src_arg))
6112 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6113 else
6115 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6116 hres = VariantCopy(&missing_arg[i], src_arg);
6117 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6119 V_VT(&rgvarg[i]) = rgvt[i];
6121 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6123 SAFEARRAY *a;
6124 SAFEARRAYBOUND bound;
6125 VARIANT *v;
6126 LONG j;
6127 bound.lLbound = 0;
6128 bound.cElements = pDispParams->cArgs-i;
6129 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6131 ERR("SafeArrayCreate failed\n");
6132 break;
6134 hres = SafeArrayAccessData(a, (LPVOID)&v);
6135 if (hres != S_OK)
6137 ERR("SafeArrayAccessData failed with %x\n", hres);
6138 break;
6140 for (j = 0; j < bound.cElements; j++)
6141 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6142 hres = SafeArrayUnaccessData(a);
6143 if (hres != S_OK)
6145 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6146 break;
6148 V_ARRAY(&rgvarg[i]) = a;
6149 V_VT(&rgvarg[i]) = rgvt[i];
6151 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6153 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6154 V_VT(&missing_arg[i]) = V_VT(src_arg);
6155 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6156 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6157 V_VT(&rgvarg[i]) = rgvt[i];
6159 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6161 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6162 V_VT(&rgvarg[i]) = rgvt[i];
6164 else
6166 /* FIXME: this doesn't work for VT_BYREF arguments if
6167 * they are not the same type as in the paramdesc */
6168 V_VT(&rgvarg[i]) = V_VT(src_arg);
6169 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6170 V_VT(&rgvarg[i]) = rgvt[i];
6173 if (FAILED(hres))
6175 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6176 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6177 debugstr_VT(src_arg), debugstr_VF(src_arg));
6178 break;
6180 prgpvarg[i] = &rgvarg[i];
6182 else if (wParamFlags & PARAMFLAG_FOPT)
6184 VARIANTARG *arg;
6185 arg = prgpvarg[i] = &rgvarg[i];
6186 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6188 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6189 if (FAILED(hres))
6190 break;
6192 else
6194 VARIANTARG *missing_arg;
6195 /* if the function wants a pointer to a variant then
6196 * set that up, otherwise just pass the VT_ERROR in
6197 * the argument by value */
6198 if (rgvt[i] & VT_BYREF)
6200 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6201 V_VT(arg) = VT_VARIANT | VT_BYREF;
6202 V_VARIANTREF(arg) = missing_arg;
6204 else
6205 missing_arg = arg;
6206 V_VT(missing_arg) = VT_ERROR;
6207 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6210 else
6212 hres = DISP_E_BADPARAMCOUNT;
6213 break;
6216 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6218 /* VT_VOID is a special case for return types, so it is not
6219 * handled in the general function */
6220 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6221 V_VT(&varresult) = VT_EMPTY;
6222 else
6224 V_VT(&varresult) = 0;
6225 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6226 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6229 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6230 V_VT(&varresult), func_desc->cParams, rgvt,
6231 prgpvarg, &varresult);
6233 for (i = 0; i < func_desc->cParams; i++)
6235 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6236 if (wParamFlags & PARAMFLAG_FRETVAL)
6238 if (TRACE_ON(ole))
6240 TRACE("[retval] value: ");
6241 dump_Variant(prgpvarg[i]);
6244 if (pVarResult)
6246 VariantInit(pVarResult);
6247 /* deref return value */
6248 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6251 /* free data stored in varresult. Note that
6252 * VariantClear doesn't do what we want because we are
6253 * working with byref types. */
6254 /* FIXME: clear safearrays, bstrs, records and
6255 * variants here too */
6256 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6257 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6259 if(*V_UNKNOWNREF(prgpvarg[i]))
6260 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6262 break;
6264 else if (i < pDispParams->cArgs)
6266 if (wParamFlags & PARAMFLAG_FOUT)
6268 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6270 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6271 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6273 if (FAILED(hres))
6275 ERR("failed to convert param %d to vt %d\n", i,
6276 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6277 break;
6280 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6281 func_desc->cParamsOpt < 0 &&
6282 i == func_desc->cParams-1)
6284 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6285 LONG j, ubound;
6286 VARIANT *v;
6287 hres = SafeArrayGetUBound(a, 1, &ubound);
6288 if (hres != S_OK)
6290 ERR("SafeArrayGetUBound failed with %x\n", hres);
6291 break;
6293 hres = SafeArrayAccessData(a, (LPVOID)&v);
6294 if (hres != S_OK)
6296 ERR("SafeArrayAccessData failed with %x\n", hres);
6297 break;
6299 for (j = 0; j <= ubound; j++)
6300 VariantClear(&v[j]);
6301 hres = SafeArrayUnaccessData(a);
6302 if (hres != S_OK)
6304 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6305 break;
6308 VariantClear(&rgvarg[i]);
6310 else if (wParamFlags & PARAMFLAG_FOPT)
6312 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6313 VariantClear(&rgvarg[i]);
6317 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6319 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6320 hres = DISP_E_EXCEPTION;
6321 if (pExcepInfo)
6323 IErrorInfo *pErrorInfo;
6324 pExcepInfo->scode = V_ERROR(&varresult);
6325 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6327 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6328 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6329 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6330 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6332 IErrorInfo_Release(pErrorInfo);
6336 if (V_VT(&varresult) != VT_ERROR)
6338 TRACE("varresult value: ");
6339 dump_Variant(&varresult);
6341 if (pVarResult)
6343 VariantClear(pVarResult);
6344 *pVarResult = varresult;
6346 else
6347 VariantClear(&varresult);
6350 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6351 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6352 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6353 (pDispParams->cArgs != 0))
6355 if (V_VT(pVarResult) == VT_DISPATCH)
6357 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6358 /* Note: not VariantClear; we still need the dispatch
6359 * pointer to be valid */
6360 VariantInit(pVarResult);
6361 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6362 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6363 pDispParams, pVarResult, pExcepInfo, pArgErr);
6364 IDispatch_Release(pDispatch);
6366 else
6368 VariantClear(pVarResult);
6369 hres = DISP_E_NOTACOLLECTION;
6373 func_fail:
6374 HeapFree(GetProcessHeap(), 0, buffer);
6375 break;
6377 case FUNC_DISPATCH: {
6378 IDispatch *disp;
6380 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6381 if (SUCCEEDED(hres)) {
6382 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6383 hres = IDispatch_Invoke(
6384 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6385 pVarResult,pExcepInfo,pArgErr
6387 if (FAILED(hres))
6388 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6389 IDispatch_Release(disp);
6390 } else
6391 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6392 break;
6394 default:
6395 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6396 hres = E_FAIL;
6397 break;
6400 TRACE("-- 0x%08x\n", hres);
6401 return hres;
6403 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6404 VARDESC *var_desc;
6406 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6407 if(FAILED(hres)) return hres;
6409 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6410 dump_VARDESC(var_desc);
6411 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6412 return E_NOTIMPL;
6415 /* not found, look for it in inherited interfaces */
6416 ITypeInfo2_GetTypeKind(iface, &type_kind);
6417 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6418 if(This->impltypelist) {
6419 /* recursive search */
6420 ITypeInfo *pTInfo;
6421 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6422 if(SUCCEEDED(hres)){
6423 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6424 ITypeInfo_Release(pTInfo);
6425 return hres;
6427 WARN("Could not search inherited interface!\n");
6430 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6431 return DISP_E_MEMBERNOTFOUND;
6434 /* ITypeInfo::GetDocumentation
6436 * Retrieves the documentation string, the complete Help file name and path,
6437 * and the context ID for the Help topic for a specified type description.
6439 * (Can be tested by the Visual Basic Editor in Word for instance.)
6441 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6442 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6443 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6445 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6446 const TLBFuncDesc *pFDesc;
6447 const TLBVarDesc *pVDesc;
6448 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6449 " HelpContext(%p) HelpFile(%p)\n",
6450 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6451 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6452 if(pBstrName)
6453 *pBstrName=SysAllocString(This->Name);
6454 if(pBstrDocString)
6455 *pBstrDocString=SysAllocString(This->DocString);
6456 if(pdwHelpContext)
6457 *pdwHelpContext=This->dwHelpContext;
6458 if(pBstrHelpFile)
6459 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6460 return S_OK;
6461 }else {/* for a member */
6462 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6463 if(pFDesc->funcdesc.memid==memid){
6464 if(pBstrName)
6465 *pBstrName = SysAllocString(pFDesc->Name);
6466 if(pBstrDocString)
6467 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6468 if(pdwHelpContext)
6469 *pdwHelpContext=pFDesc->helpcontext;
6470 return S_OK;
6472 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6473 if(pVDesc->vardesc.memid==memid){
6474 if(pBstrName)
6475 *pBstrName = SysAllocString(pVDesc->Name);
6476 if(pBstrDocString)
6477 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6478 if(pdwHelpContext)
6479 *pdwHelpContext=pVDesc->HelpContext;
6480 return S_OK;
6484 if(This->impltypelist &&
6485 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6486 /* recursive search */
6487 ITypeInfo *pTInfo;
6488 HRESULT result;
6489 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6490 &pTInfo);
6491 if(SUCCEEDED(result)) {
6492 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6493 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6494 ITypeInfo_Release(pTInfo);
6495 return result;
6497 WARN("Could not search inherited interface!\n");
6500 WARN("member %d not found\n", memid);
6501 return TYPE_E_ELEMENTNOTFOUND;
6504 /* ITypeInfo::GetDllEntry
6506 * Retrieves a description or specification of an entry point for a function
6507 * in a DLL.
6509 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6510 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6511 WORD *pwOrdinal)
6513 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6514 const TLBFuncDesc *pFDesc;
6516 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6518 if (pBstrDllName) *pBstrDllName = NULL;
6519 if (pBstrName) *pBstrName = NULL;
6520 if (pwOrdinal) *pwOrdinal = 0;
6522 if (This->TypeAttr.typekind != TKIND_MODULE)
6523 return TYPE_E_BADMODULEKIND;
6525 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6526 if(pFDesc->funcdesc.memid==memid){
6527 dump_TypeInfo(This);
6528 if (TRACE_ON(ole))
6529 dump_TLBFuncDescOne(pFDesc);
6531 if (pBstrDllName)
6532 *pBstrDllName = SysAllocString(This->DllName);
6534 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6535 if (pBstrName)
6536 *pBstrName = SysAllocString(pFDesc->Entry);
6537 if (pwOrdinal)
6538 *pwOrdinal = -1;
6539 return S_OK;
6541 if (pBstrName)
6542 *pBstrName = NULL;
6543 if (pwOrdinal)
6544 *pwOrdinal = (DWORD)pFDesc->Entry;
6545 return S_OK;
6547 return TYPE_E_ELEMENTNOTFOUND;
6550 /* internal function to make the inherited interfaces' methods appear
6551 * part of the interface */
6552 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6553 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6556 HRESULT hr;
6558 TRACE("%p, 0x%x\n", iface, *hRefType);
6560 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6562 ITypeInfo *pSubTypeInfo;
6564 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6565 if (FAILED(hr))
6566 return hr;
6568 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6569 hRefType, ppTInfo);
6570 ITypeInfo_Release(pSubTypeInfo);
6571 if (SUCCEEDED(hr))
6572 return hr;
6574 *hRefType -= DISPATCH_HREF_OFFSET;
6576 if (!(*hRefType & DISPATCH_HREF_MASK))
6577 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6578 else
6579 return E_FAIL;
6582 /* ITypeInfo::GetRefTypeInfo
6584 * If a type description references other type descriptions, it retrieves
6585 * the referenced type descriptions.
6587 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6588 ITypeInfo2 *iface,
6589 HREFTYPE hRefType,
6590 ITypeInfo **ppTInfo)
6592 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6593 HRESULT result = E_FAIL;
6595 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6597 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6598 ITypeInfo_AddRef(*ppTInfo);
6599 result = S_OK;
6601 else if (hRefType == -1 &&
6602 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6603 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6605 /* when we meet a DUAL dispinterface, we must create the interface
6606 * version of it.
6608 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6611 /* the interface version contains the same information as the dispinterface
6612 * copy the contents of the structs.
6614 *pTypeInfoImpl = *This;
6615 pTypeInfoImpl->ref = 0;
6617 /* change the type to interface */
6618 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6620 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6622 /* we use data structures from This, so we need to keep a reference
6623 * to it to stop it being destroyed and signal to the new instance to
6624 * not free its data structures when it is destroyed */
6625 pTypeInfoImpl->no_free_data = TRUE;
6626 pTypeInfoImpl->next = This;
6627 ITypeInfo_AddRef((ITypeInfo*) This);
6629 ITypeInfo_AddRef(*ppTInfo);
6631 result = S_OK;
6633 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6634 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6635 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6637 HREFTYPE href_dispatch = hRefType;
6638 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6639 } else {
6640 TLBRefType *ref_type;
6641 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6643 if(ref_type->reference == hRefType)
6644 break;
6646 if(&ref_type->entry == &This->pTypeLib->ref_list)
6648 FIXME("Can't find pRefType for ref %x\n", hRefType);
6649 goto end;
6651 if(hRefType != -1) {
6652 ITypeLib *pTLib = NULL;
6654 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6655 UINT Index;
6656 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6657 } else {
6658 if(ref_type->pImpTLInfo->pImpTypeLib) {
6659 TRACE("typeinfo in imported typelib that is already loaded\n");
6660 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6661 ITypeLib2_AddRef(pTLib);
6662 result = S_OK;
6663 } else {
6664 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6665 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6666 ref_type->pImpTLInfo->wVersionMajor,
6667 ref_type->pImpTLInfo->wVersionMinor,
6668 ref_type->pImpTLInfo->lcid,
6669 &pTLib);
6671 if(FAILED(result)) {
6672 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6673 result=LoadTypeLib(libnam, &pTLib);
6674 SysFreeString(libnam);
6676 if(SUCCEEDED(result)) {
6677 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6678 ITypeLib2_AddRef(pTLib);
6682 if(SUCCEEDED(result)) {
6683 if(ref_type->index == TLB_REF_USE_GUID)
6684 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6685 &ref_type->guid,
6686 ppTInfo);
6687 else
6688 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6689 ppTInfo);
6691 if (pTLib != NULL)
6692 ITypeLib2_Release(pTLib);
6696 end:
6697 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6698 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6699 return result;
6702 /* ITypeInfo::AddressOfMember
6704 * Retrieves the addresses of static functions or variables, such as those
6705 * defined in a DLL.
6707 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6708 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6710 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6711 HRESULT hr;
6712 BSTR dll, entry;
6713 WORD ordinal;
6714 HMODULE module;
6716 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6718 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6719 if (FAILED(hr))
6720 return hr;
6722 module = LoadLibraryW(dll);
6723 if (!module)
6725 ERR("couldn't load %s\n", debugstr_w(dll));
6726 SysFreeString(dll);
6727 SysFreeString(entry);
6728 return STG_E_FILENOTFOUND;
6730 /* FIXME: store library somewhere where we can free it */
6732 if (entry)
6734 LPSTR entryA;
6735 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6736 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6737 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6739 *ppv = GetProcAddress(module, entryA);
6740 if (!*ppv)
6741 ERR("function not found %s\n", debugstr_a(entryA));
6743 HeapFree(GetProcessHeap(), 0, entryA);
6745 else
6747 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6748 if (!*ppv)
6749 ERR("function not found %d\n", ordinal);
6752 SysFreeString(dll);
6753 SysFreeString(entry);
6755 if (!*ppv)
6756 return TYPE_E_DLLFUNCTIONNOTFOUND;
6758 return S_OK;
6761 /* ITypeInfo::CreateInstance
6763 * Creates a new instance of a type that describes a component object class
6764 * (coclass).
6766 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6767 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6769 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6770 HRESULT hr;
6771 TYPEATTR *pTA;
6773 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6775 *ppvObj = NULL;
6777 if(pOuterUnk)
6779 WARN("Not able to aggregate\n");
6780 return CLASS_E_NOAGGREGATION;
6783 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6784 if(FAILED(hr)) return hr;
6786 if(pTA->typekind != TKIND_COCLASS)
6788 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6789 hr = E_INVALIDARG;
6790 goto end;
6793 hr = S_FALSE;
6794 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6796 IUnknown *pUnk;
6797 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6798 TRACE("GetActiveObject rets %08x\n", hr);
6799 if(hr == S_OK)
6801 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6802 IUnknown_Release(pUnk);
6806 if(hr != S_OK)
6807 hr = CoCreateInstance(&pTA->guid, NULL,
6808 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6809 riid, ppvObj);
6811 end:
6812 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6813 return hr;
6816 /* ITypeInfo::GetMops
6818 * Retrieves marshalling information.
6820 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6821 BSTR *pBstrMops)
6823 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6824 FIXME("(%p) stub!\n", This);
6825 return S_OK;
6828 /* ITypeInfo::GetContainingTypeLib
6830 * Retrieves the containing type library and the index of the type description
6831 * within that type library.
6833 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6834 ITypeLib * *ppTLib, UINT *pIndex)
6836 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6838 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6839 if (pIndex) {
6840 *pIndex=This->index;
6841 TRACE("returning pIndex=%d\n", *pIndex);
6844 if (ppTLib) {
6845 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6846 ITypeLib2_AddRef(*ppTLib);
6847 TRACE("returning ppTLib=%p\n", *ppTLib);
6850 return S_OK;
6853 /* ITypeInfo::ReleaseTypeAttr
6855 * Releases a TYPEATTR previously returned by GetTypeAttr.
6858 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6859 TYPEATTR* pTypeAttr)
6861 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6862 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6863 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6866 /* ITypeInfo::ReleaseFuncDesc
6868 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6870 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6871 ITypeInfo2 *iface,
6872 FUNCDESC *pFuncDesc)
6874 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6875 SHORT i;
6877 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6879 for (i = 0; i < pFuncDesc->cParams; i++)
6880 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6881 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6883 SysFreeString((BSTR)pFuncDesc);
6886 /* ITypeInfo::ReleaseVarDesc
6888 * Releases a VARDESC previously returned by GetVarDesc.
6890 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6891 VARDESC *pVarDesc)
6893 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6894 TRACE("(%p)->(%p)\n", This, pVarDesc);
6896 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6897 if (pVarDesc->varkind == VAR_CONST)
6898 VariantClear(pVarDesc->u.lpvarValue);
6899 SysFreeString((BSTR)pVarDesc);
6902 /* ITypeInfo2::GetTypeKind
6904 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6907 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6908 TYPEKIND *pTypeKind)
6910 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6911 *pTypeKind=This->TypeAttr.typekind;
6912 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6913 return S_OK;
6916 /* ITypeInfo2::GetTypeFlags
6918 * Returns the type flags without any allocations. This returns a DWORD type
6919 * flag, which expands the type flags without growing the TYPEATTR (type
6920 * attribute).
6923 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6925 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6926 *pTypeFlags=This->TypeAttr.wTypeFlags;
6927 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6928 return S_OK;
6931 /* ITypeInfo2::GetFuncIndexOfMemId
6932 * Binds to a specific member based on a known DISPID, where the member name
6933 * is not known (for example, when binding to a default member).
6936 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6937 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6939 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6940 const TLBFuncDesc *pFuncInfo;
6941 int i;
6942 HRESULT result;
6944 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6945 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6946 break;
6947 if(pFuncInfo) {
6948 *pFuncIndex = i;
6949 result = S_OK;
6950 } else
6951 result = TYPE_E_ELEMENTNOTFOUND;
6953 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6954 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6955 return result;
6958 /* TypeInfo2::GetVarIndexOfMemId
6960 * Binds to a specific member based on a known DISPID, where the member name
6961 * is not known (for example, when binding to a default member).
6964 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6965 MEMBERID memid, UINT *pVarIndex)
6967 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6968 TLBVarDesc *pVarInfo;
6969 int i;
6970 HRESULT result;
6971 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6972 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6974 if(pVarInfo) {
6975 *pVarIndex = i;
6976 result = S_OK;
6977 } else
6978 result = TYPE_E_ELEMENTNOTFOUND;
6980 TRACE("(%p) memid 0x%08x -> %s\n", This,
6981 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6982 return result;
6985 /* ITypeInfo2::GetCustData
6987 * Gets the custom data
6989 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6990 ITypeInfo2 * iface,
6991 REFGUID guid,
6992 VARIANT *pVarVal)
6994 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6995 TLBCustData *pCData;
6997 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6998 if( IsEqualIID(guid, &pCData->guid)) break;
7000 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7002 if(pCData)
7004 VariantInit( pVarVal);
7005 VariantCopy( pVarVal, &pCData->data);
7006 return S_OK;
7008 return E_INVALIDARG; /* FIXME: correct? */
7011 /* ITypeInfo2::GetFuncCustData
7013 * Gets the custom data
7015 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7016 ITypeInfo2 * iface,
7017 UINT index,
7018 REFGUID guid,
7019 VARIANT *pVarVal)
7021 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7022 TLBCustData *pCData=NULL;
7023 TLBFuncDesc * pFDesc;
7024 UINT i;
7025 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7026 pFDesc=pFDesc->next);
7028 if(pFDesc)
7029 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7030 if( IsEqualIID(guid, &pCData->guid)) break;
7032 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7034 if(pCData){
7035 VariantInit( pVarVal);
7036 VariantCopy( pVarVal, &pCData->data);
7037 return S_OK;
7039 return E_INVALIDARG; /* FIXME: correct? */
7042 /* ITypeInfo2::GetParamCustData
7044 * Gets the custom data
7046 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7047 ITypeInfo2 * iface,
7048 UINT indexFunc,
7049 UINT indexParam,
7050 REFGUID guid,
7051 VARIANT *pVarVal)
7053 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7054 TLBCustData *pCData=NULL;
7055 TLBFuncDesc * pFDesc;
7056 UINT i;
7058 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7060 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7061 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7062 pCData = pCData->next)
7063 if( IsEqualIID(guid, &pCData->guid)) break;
7065 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7067 if(pCData)
7069 VariantInit( pVarVal);
7070 VariantCopy( pVarVal, &pCData->data);
7071 return S_OK;
7073 return E_INVALIDARG; /* FIXME: correct? */
7076 /* ITypeInfo2::GetVarCustData
7078 * Gets the custom data
7080 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7081 ITypeInfo2 * iface,
7082 UINT index,
7083 REFGUID guid,
7084 VARIANT *pVarVal)
7086 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7087 TLBCustData *pCData=NULL;
7088 TLBVarDesc * pVDesc;
7089 UINT i;
7091 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7093 if(pVDesc)
7095 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7097 if( IsEqualIID(guid, &pCData->guid)) break;
7101 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7103 if(pCData)
7105 VariantInit( pVarVal);
7106 VariantCopy( pVarVal, &pCData->data);
7107 return S_OK;
7109 return E_INVALIDARG; /* FIXME: correct? */
7112 /* ITypeInfo2::GetImplCustData
7114 * Gets the custom data
7116 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7117 ITypeInfo2 * iface,
7118 UINT index,
7119 REFGUID guid,
7120 VARIANT *pVarVal)
7122 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7123 TLBCustData *pCData=NULL;
7124 TLBImplType * pRDesc;
7125 UINT i;
7127 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7129 if(pRDesc)
7131 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7133 if( IsEqualIID(guid, &pCData->guid)) break;
7137 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7139 if(pCData)
7141 VariantInit( pVarVal);
7142 VariantCopy( pVarVal, &pCData->data);
7143 return S_OK;
7145 return E_INVALIDARG; /* FIXME: correct? */
7148 /* ITypeInfo2::GetDocumentation2
7150 * Retrieves the documentation string, the complete Help file name and path,
7151 * the localization context to use, and the context ID for the library Help
7152 * topic in the Help file.
7155 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7156 ITypeInfo2 * iface,
7157 MEMBERID memid,
7158 LCID lcid,
7159 BSTR *pbstrHelpString,
7160 DWORD *pdwHelpStringContext,
7161 BSTR *pbstrHelpStringDll)
7163 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7164 const TLBFuncDesc *pFDesc;
7165 const TLBVarDesc *pVDesc;
7166 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7167 "HelpStringContext(%p) HelpStringDll(%p)\n",
7168 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7169 pbstrHelpStringDll );
7170 /* the help string should be obtained from the helpstringdll,
7171 * using the _DLLGetDocumentation function, based on the supplied
7172 * lcid. Nice to do sometime...
7174 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7175 if(pbstrHelpString)
7176 *pbstrHelpString=SysAllocString(This->Name);
7177 if(pdwHelpStringContext)
7178 *pdwHelpStringContext=This->dwHelpStringContext;
7179 if(pbstrHelpStringDll)
7180 *pbstrHelpStringDll=
7181 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7182 return S_OK;
7183 }else {/* for a member */
7184 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7185 if(pFDesc->funcdesc.memid==memid){
7186 if(pbstrHelpString)
7187 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7188 if(pdwHelpStringContext)
7189 *pdwHelpStringContext=pFDesc->HelpStringContext;
7190 if(pbstrHelpStringDll)
7191 *pbstrHelpStringDll=
7192 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7193 return S_OK;
7195 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7196 if(pVDesc->vardesc.memid==memid){
7197 if(pbstrHelpString)
7198 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7199 if(pdwHelpStringContext)
7200 *pdwHelpStringContext=pVDesc->HelpStringContext;
7201 if(pbstrHelpStringDll)
7202 *pbstrHelpStringDll=
7203 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7204 return S_OK;
7207 return TYPE_E_ELEMENTNOTFOUND;
7210 /* ITypeInfo2::GetAllCustData
7212 * Gets all custom data items for the Type info.
7215 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7216 ITypeInfo2 * iface,
7217 CUSTDATA *pCustData)
7219 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7220 TLBCustData *pCData;
7221 int i;
7223 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7225 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7226 if(pCustData->prgCustData ){
7227 pCustData->cCustData=This->ctCustData;
7228 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7229 pCustData->prgCustData[i].guid=pCData->guid;
7230 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7232 }else{
7233 ERR(" OUT OF MEMORY!\n");
7234 return E_OUTOFMEMORY;
7236 return S_OK;
7239 /* ITypeInfo2::GetAllFuncCustData
7241 * Gets all custom data items for the specified Function
7244 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7245 ITypeInfo2 * iface,
7246 UINT index,
7247 CUSTDATA *pCustData)
7249 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7250 TLBCustData *pCData;
7251 TLBFuncDesc * pFDesc;
7252 UINT i;
7253 TRACE("(%p) index %d\n", This, index);
7254 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7255 pFDesc=pFDesc->next)
7257 if(pFDesc){
7258 pCustData->prgCustData =
7259 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7260 if(pCustData->prgCustData ){
7261 pCustData->cCustData=pFDesc->ctCustData;
7262 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7263 pCData = pCData->next){
7264 pCustData->prgCustData[i].guid=pCData->guid;
7265 VariantCopy(& pCustData->prgCustData[i].varValue,
7266 & pCData->data);
7268 }else{
7269 ERR(" OUT OF MEMORY!\n");
7270 return E_OUTOFMEMORY;
7272 return S_OK;
7274 return TYPE_E_ELEMENTNOTFOUND;
7277 /* ITypeInfo2::GetAllParamCustData
7279 * Gets all custom data items for the Functions
7282 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7283 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7285 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7286 TLBCustData *pCData=NULL;
7287 TLBFuncDesc * pFDesc;
7288 UINT i;
7289 TRACE("(%p) index %d\n", This, indexFunc);
7290 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7291 pFDesc=pFDesc->next)
7293 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7294 pCustData->prgCustData =
7295 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7296 sizeof(CUSTDATAITEM));
7297 if(pCustData->prgCustData ){
7298 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7299 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7300 pCData; i++, pCData = pCData->next){
7301 pCustData->prgCustData[i].guid=pCData->guid;
7302 VariantCopy(& pCustData->prgCustData[i].varValue,
7303 & pCData->data);
7305 }else{
7306 ERR(" OUT OF MEMORY!\n");
7307 return E_OUTOFMEMORY;
7309 return S_OK;
7311 return TYPE_E_ELEMENTNOTFOUND;
7314 /* ITypeInfo2::GetAllVarCustData
7316 * Gets all custom data items for the specified Variable
7319 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7320 UINT index, CUSTDATA *pCustData)
7322 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7323 TLBCustData *pCData;
7324 TLBVarDesc * pVDesc;
7325 UINT i;
7326 TRACE("(%p) index %d\n", This, index);
7327 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7328 pVDesc=pVDesc->next)
7330 if(pVDesc){
7331 pCustData->prgCustData =
7332 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7333 if(pCustData->prgCustData ){
7334 pCustData->cCustData=pVDesc->ctCustData;
7335 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7336 pCData = pCData->next){
7337 pCustData->prgCustData[i].guid=pCData->guid;
7338 VariantCopy(& pCustData->prgCustData[i].varValue,
7339 & pCData->data);
7341 }else{
7342 ERR(" OUT OF MEMORY!\n");
7343 return E_OUTOFMEMORY;
7345 return S_OK;
7347 return TYPE_E_ELEMENTNOTFOUND;
7350 /* ITypeInfo2::GetAllImplCustData
7352 * Gets all custom data items for the specified implementation type
7355 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7356 ITypeInfo2 * iface,
7357 UINT index,
7358 CUSTDATA *pCustData)
7360 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7361 TLBCustData *pCData;
7362 TLBImplType * pRDesc;
7363 UINT i;
7364 TRACE("(%p) index %d\n", This, index);
7365 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7366 pRDesc=pRDesc->next)
7368 if(pRDesc){
7369 pCustData->prgCustData =
7370 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7371 if(pCustData->prgCustData ){
7372 pCustData->cCustData=pRDesc->ctCustData;
7373 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7374 pCData = pCData->next){
7375 pCustData->prgCustData[i].guid=pCData->guid;
7376 VariantCopy(& pCustData->prgCustData[i].varValue,
7377 & pCData->data);
7379 }else{
7380 ERR(" OUT OF MEMORY!\n");
7381 return E_OUTOFMEMORY;
7383 return S_OK;
7385 return TYPE_E_ELEMENTNOTFOUND;
7388 static const ITypeInfo2Vtbl tinfvt =
7391 ITypeInfo_fnQueryInterface,
7392 ITypeInfo_fnAddRef,
7393 ITypeInfo_fnRelease,
7395 ITypeInfo_fnGetTypeAttr,
7396 ITypeInfo_fnGetTypeComp,
7397 ITypeInfo_fnGetFuncDesc,
7398 ITypeInfo_fnGetVarDesc,
7399 ITypeInfo_fnGetNames,
7400 ITypeInfo_fnGetRefTypeOfImplType,
7401 ITypeInfo_fnGetImplTypeFlags,
7402 ITypeInfo_fnGetIDsOfNames,
7403 ITypeInfo_fnInvoke,
7404 ITypeInfo_fnGetDocumentation,
7405 ITypeInfo_fnGetDllEntry,
7406 ITypeInfo_fnGetRefTypeInfo,
7407 ITypeInfo_fnAddressOfMember,
7408 ITypeInfo_fnCreateInstance,
7409 ITypeInfo_fnGetMops,
7410 ITypeInfo_fnGetContainingTypeLib,
7411 ITypeInfo_fnReleaseTypeAttr,
7412 ITypeInfo_fnReleaseFuncDesc,
7413 ITypeInfo_fnReleaseVarDesc,
7415 ITypeInfo2_fnGetTypeKind,
7416 ITypeInfo2_fnGetTypeFlags,
7417 ITypeInfo2_fnGetFuncIndexOfMemId,
7418 ITypeInfo2_fnGetVarIndexOfMemId,
7419 ITypeInfo2_fnGetCustData,
7420 ITypeInfo2_fnGetFuncCustData,
7421 ITypeInfo2_fnGetParamCustData,
7422 ITypeInfo2_fnGetVarCustData,
7423 ITypeInfo2_fnGetImplTypeCustData,
7424 ITypeInfo2_fnGetDocumentation2,
7425 ITypeInfo2_fnGetAllCustData,
7426 ITypeInfo2_fnGetAllFuncCustData,
7427 ITypeInfo2_fnGetAllParamCustData,
7428 ITypeInfo2_fnGetAllVarCustData,
7429 ITypeInfo2_fnGetAllImplTypeCustData,
7432 /******************************************************************************
7433 * CreateDispTypeInfo [OLEAUT32.31]
7435 * Build type information for an object so it can be called through an
7436 * IDispatch interface.
7438 * RETURNS
7439 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7440 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7442 * NOTES
7443 * This call allows an objects methods to be accessed through IDispatch, by
7444 * building an ITypeInfo object that IDispatch can use to call through.
7446 HRESULT WINAPI CreateDispTypeInfo(
7447 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7448 LCID lcid, /* [I] Locale Id */
7449 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7451 ITypeInfoImpl *pTIClass, *pTIIface;
7452 ITypeLibImpl *pTypeLibImpl;
7453 unsigned int param, func;
7454 TLBFuncDesc **ppFuncDesc;
7455 TLBRefType *ref;
7457 TRACE("\n");
7458 pTypeLibImpl = TypeLibImpl_Constructor();
7459 if (!pTypeLibImpl) return E_FAIL;
7461 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7462 pTIIface->pTypeLib = pTypeLibImpl;
7463 pTIIface->index = 0;
7464 pTIIface->Name = NULL;
7465 pTIIface->dwHelpContext = -1;
7466 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7467 pTIIface->TypeAttr.lcid = lcid;
7468 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7469 pTIIface->TypeAttr.wMajorVerNum = 0;
7470 pTIIface->TypeAttr.wMinorVerNum = 0;
7471 pTIIface->TypeAttr.cbAlignment = 2;
7472 pTIIface->TypeAttr.cbSizeInstance = -1;
7473 pTIIface->TypeAttr.cbSizeVft = -1;
7474 pTIIface->TypeAttr.cFuncs = 0;
7475 pTIIface->TypeAttr.cImplTypes = 0;
7476 pTIIface->TypeAttr.cVars = 0;
7477 pTIIface->TypeAttr.wTypeFlags = 0;
7479 ppFuncDesc = &pTIIface->funclist;
7480 for(func = 0; func < pidata->cMembers; func++) {
7481 METHODDATA *md = pidata->pmethdata + func;
7482 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7483 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7484 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7485 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7486 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7487 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7488 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7489 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7490 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7491 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7492 (*ppFuncDesc)->funcdesc.cScodes = 0;
7493 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7494 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7495 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7496 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7497 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7498 md->cArgs * sizeof(ELEMDESC));
7499 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7500 md->cArgs * sizeof(TLBParDesc));
7501 for(param = 0; param < md->cArgs; param++) {
7502 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7503 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7505 (*ppFuncDesc)->helpcontext = 0;
7506 (*ppFuncDesc)->HelpStringContext = 0;
7507 (*ppFuncDesc)->HelpString = NULL;
7508 (*ppFuncDesc)->Entry = NULL;
7509 (*ppFuncDesc)->ctCustData = 0;
7510 (*ppFuncDesc)->pCustData = NULL;
7511 (*ppFuncDesc)->next = NULL;
7512 pTIIface->TypeAttr.cFuncs++;
7513 ppFuncDesc = &(*ppFuncDesc)->next;
7516 dump_TypeInfo(pTIIface);
7518 pTypeLibImpl->pTypeInfo = pTIIface;
7519 pTypeLibImpl->TypeInfoCount++;
7521 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7522 pTIClass->pTypeLib = pTypeLibImpl;
7523 pTIClass->index = 1;
7524 pTIClass->Name = NULL;
7525 pTIClass->dwHelpContext = -1;
7526 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7527 pTIClass->TypeAttr.lcid = lcid;
7528 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7529 pTIClass->TypeAttr.wMajorVerNum = 0;
7530 pTIClass->TypeAttr.wMinorVerNum = 0;
7531 pTIClass->TypeAttr.cbAlignment = 2;
7532 pTIClass->TypeAttr.cbSizeInstance = -1;
7533 pTIClass->TypeAttr.cbSizeVft = -1;
7534 pTIClass->TypeAttr.cFuncs = 0;
7535 pTIClass->TypeAttr.cImplTypes = 1;
7536 pTIClass->TypeAttr.cVars = 0;
7537 pTIClass->TypeAttr.wTypeFlags = 0;
7539 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7540 pTIClass->impltypelist->hRef = 0;
7542 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7543 ref->index = 0;
7544 ref->reference = 0;
7545 ref->pImpTLInfo = TLB_REF_INTERNAL;
7546 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7548 dump_TypeInfo(pTIClass);
7550 pTIIface->next = pTIClass;
7551 pTypeLibImpl->TypeInfoCount++;
7553 *pptinfo = (ITypeInfo*)pTIClass;
7555 ITypeInfo_AddRef(*pptinfo);
7556 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7558 return S_OK;
7562 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7564 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7566 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7569 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7571 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7573 return ITypeInfo_AddRef((ITypeInfo *)This);
7576 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7578 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7580 return ITypeInfo_Release((ITypeInfo *)This);
7583 static HRESULT WINAPI ITypeComp_fnBind(
7584 ITypeComp * iface,
7585 OLECHAR * szName,
7586 ULONG lHash,
7587 WORD wFlags,
7588 ITypeInfo ** ppTInfo,
7589 DESCKIND * pDescKind,
7590 BINDPTR * pBindPtr)
7592 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7593 const TLBFuncDesc *pFDesc;
7594 const TLBVarDesc *pVDesc;
7595 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7597 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7599 *pDescKind = DESCKIND_NONE;
7600 pBindPtr->lpfuncdesc = NULL;
7601 *ppTInfo = NULL;
7603 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7604 if (!strcmpiW(pFDesc->Name, szName)) {
7605 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7606 break;
7607 else
7608 /* name found, but wrong flags */
7609 hr = TYPE_E_TYPEMISMATCH;
7612 if (pFDesc)
7614 HRESULT hr = TLB_AllocAndInitFuncDesc(
7615 &pFDesc->funcdesc,
7616 &pBindPtr->lpfuncdesc,
7617 This->TypeAttr.typekind == TKIND_DISPATCH);
7618 if (FAILED(hr))
7619 return hr;
7620 *pDescKind = DESCKIND_FUNCDESC;
7621 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7622 ITypeInfo_AddRef(*ppTInfo);
7623 return S_OK;
7624 } else {
7625 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7626 if (!strcmpiW(pVDesc->Name, szName)) {
7627 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7628 if (FAILED(hr))
7629 return hr;
7630 *pDescKind = DESCKIND_VARDESC;
7631 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7632 ITypeInfo_AddRef(*ppTInfo);
7633 return S_OK;
7637 /* FIXME: search each inherited interface, not just the first */
7638 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7639 /* recursive search */
7640 ITypeInfo *pTInfo;
7641 ITypeComp *pTComp;
7642 HRESULT hr;
7643 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7644 if (SUCCEEDED(hr))
7646 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7647 ITypeInfo_Release(pTInfo);
7649 if (SUCCEEDED(hr))
7651 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7652 ITypeComp_Release(pTComp);
7653 return hr;
7655 WARN("Could not search inherited interface!\n");
7657 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7658 return hr;
7661 static HRESULT WINAPI ITypeComp_fnBindType(
7662 ITypeComp * iface,
7663 OLECHAR * szName,
7664 ULONG lHash,
7665 ITypeInfo ** ppTInfo,
7666 ITypeComp ** ppTComp)
7668 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7670 /* strange behaviour (does nothing) but like the
7671 * original */
7673 if (!ppTInfo || !ppTComp)
7674 return E_POINTER;
7676 *ppTInfo = NULL;
7677 *ppTComp = NULL;
7679 return S_OK;
7682 static const ITypeCompVtbl tcompvt =
7685 ITypeComp_fnQueryInterface,
7686 ITypeComp_fnAddRef,
7687 ITypeComp_fnRelease,
7689 ITypeComp_fnBind,
7690 ITypeComp_fnBindType