msvfw32: Replace const pointer parameter with correct pointer to const.
[wine/wine-kai.git] / dlls / oleaut32 / typelib.c
blobd75e7bc4b00ae7d74d7fa7a2f73ae3bccf895999
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"
68 #include "wine/unicode.h"
69 #include "objbase.h"
70 #include "typelib.h"
71 #include "wine/debug.h"
72 #include "variant.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(ole);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib);
77 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
78 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
80 /****************************************************************************
81 * FromLExxx
83 * Takes p_iVal (which is in little endian) and returns it
84 * in the host machine's byte order.
86 #ifdef WORDS_BIGENDIAN
87 static WORD FromLEWord(WORD p_iVal)
89 return (((p_iVal & 0x00FF) << 8) |
90 ((p_iVal & 0xFF00) >> 8));
94 static DWORD FromLEDWord(DWORD p_iVal)
96 return (((p_iVal & 0x000000FF) << 24) |
97 ((p_iVal & 0x0000FF00) << 8) |
98 ((p_iVal & 0x00FF0000) >> 8) |
99 ((p_iVal & 0xFF000000) >> 24));
101 #else
102 #define FromLEWord(X) (X)
103 #define FromLEDWord(X) (X)
104 #endif
107 /****************************************************************************
108 * FromLExxx
110 * Fix byte order in any structure if necessary
112 #ifdef WORDS_BIGENDIAN
113 static void FromLEWords(void *p_Val, int p_iSize)
115 WORD *Val = p_Val;
117 p_iSize /= sizeof(WORD);
119 while (p_iSize) {
120 *Val = FromLEWord(*Val);
121 Val++;
122 p_iSize--;
127 static void FromLEDWords(void *p_Val, int p_iSize)
129 DWORD *Val = p_Val;
131 p_iSize /= sizeof(DWORD);
133 while (p_iSize) {
134 *Val = FromLEDWord(*Val);
135 Val++;
136 p_iSize--;
139 #else
140 #define FromLEWords(X,Y) /*nothing*/
141 #define FromLEDWords(X,Y) /*nothing*/
142 #endif
145 * Find a typelib key which matches a requested maj.min version.
147 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
149 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
150 WCHAR buffer[60];
151 char key_name[16];
152 DWORD len, i;
153 INT best_min = -1;
154 HKEY hkey;
156 memcpy( buffer, typelibW, sizeof(typelibW) );
157 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
159 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
160 return FALSE;
162 len = sizeof(key_name);
163 i = 0;
164 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
166 INT v_maj, v_min;
168 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
170 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
172 if (*wMaj == v_maj)
174 if (*wMin == v_min)
176 best_min = v_min;
177 break; /* exact match */
179 if (v_min > best_min) best_min = v_min;
182 len = sizeof(key_name);
184 RegCloseKey( hkey );
185 if (best_min >= 0)
187 *wMin = best_min;
188 return TRUE;
190 return FALSE;
193 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
194 /* buffer must be at least 60 characters long */
195 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
197 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
198 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
200 memcpy( buffer, TypelibW, sizeof(TypelibW) );
201 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
202 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
203 return buffer;
206 /* get the path of an interface key, in the form "Interface\\<guid>" */
207 /* buffer must be at least 50 characters long */
208 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
210 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
212 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
213 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
214 return buffer;
217 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
218 /* buffer must be at least 16 characters long */
219 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
221 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
222 static const WCHAR win16W[] = {'w','i','n','1','6',0};
223 static const WCHAR win32W[] = {'w','i','n','3','2',0};
225 sprintfW( buffer, LcidFormatW, lcid );
226 switch(syskind)
228 case SYS_WIN16: strcatW( buffer, win16W ); break;
229 case SYS_WIN32: strcatW( buffer, win32W ); break;
230 default:
231 TRACE("Typelib is for unsupported syskind %i\n", syskind);
232 return NULL;
234 return buffer;
237 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
240 /****************************************************************************
241 * QueryPathOfRegTypeLib [OLEAUT32.164]
243 * Gets the path to a registered type library.
245 * PARAMS
246 * guid [I] referenced guid
247 * wMaj [I] major version
248 * wMin [I] minor version
249 * lcid [I] locale id
250 * path [O] path of typelib
252 * RETURNS
253 * Success: S_OK.
254 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
255 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
256 * opened.
258 HRESULT WINAPI QueryPathOfRegTypeLib(
259 REFGUID guid,
260 WORD wMaj,
261 WORD wMin,
262 LCID lcid,
263 LPBSTR path )
265 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
266 LCID myLCID = lcid;
267 HKEY hkey;
268 WCHAR buffer[60];
269 WCHAR Path[MAX_PATH];
270 LONG res;
272 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
274 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
275 get_typelib_key( guid, wMaj, wMin, buffer );
277 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
278 if (res == ERROR_FILE_NOT_FOUND)
280 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
281 return TYPE_E_LIBNOTREGISTERED;
283 else if (res != ERROR_SUCCESS)
285 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
286 return TYPE_E_REGISTRYACCESS;
289 while (hr != S_OK)
291 LONG dwPathLen = sizeof(Path);
293 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
295 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
297 if (!lcid)
298 break;
299 else if (myLCID == lcid)
301 /* try with sub-langid */
302 myLCID = SUBLANGID(lcid);
304 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
306 /* try with system langid */
307 myLCID = 0;
309 else
311 break;
314 else
316 *path = SysAllocString( Path );
317 hr = S_OK;
320 RegCloseKey( hkey );
321 TRACE_(typelib)("-- 0x%08x\n", hr);
322 return hr;
325 /******************************************************************************
326 * CreateTypeLib [OLEAUT32.160] creates a typelib
328 * RETURNS
329 * Success: S_OK
330 * Failure: Status
332 HRESULT WINAPI CreateTypeLib(
333 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
335 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
336 return E_FAIL;
339 /******************************************************************************
340 * LoadTypeLib [OLEAUT32.161]
342 * Loads a type library
344 * PARAMS
345 * szFile [I] Name of file to load from.
346 * pptLib [O] Pointer that receives ITypeLib object on success.
348 * RETURNS
349 * Success: S_OK
350 * Failure: Status
352 * SEE
353 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
355 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
357 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
358 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
361 /******************************************************************************
362 * LoadTypeLibEx [OLEAUT32.183]
364 * Loads and optionally registers a type library
366 * RETURNS
367 * Success: S_OK
368 * Failure: Status
370 HRESULT WINAPI LoadTypeLibEx(
371 LPCOLESTR szFile, /* [in] Name of file to load from */
372 REGKIND regkind, /* [in] Specify kind of registration */
373 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
375 WCHAR szPath[MAX_PATH+1];
376 HRESULT res;
378 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
380 *pptLib = NULL;
382 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
384 if (SUCCEEDED(res))
385 switch(regkind)
387 case REGKIND_DEFAULT:
388 /* don't register typelibs supplied with full path. Experimentation confirms the following */
389 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
390 (szFile[0] && (szFile[1] == ':'))) break;
391 /* else fall-through */
393 case REGKIND_REGISTER:
394 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
396 IUnknown_Release(*pptLib);
397 *pptLib = 0;
399 break;
400 case REGKIND_NONE:
401 break;
404 TRACE(" returns %08x\n",res);
405 return res;
408 /******************************************************************************
409 * LoadRegTypeLib [OLEAUT32.162]
411 * Loads a registered type library.
413 * PARAMS
414 * rguid [I] GUID of the registered type library.
415 * wVerMajor [I] major version.
416 * wVerMinor [I] minor version.
417 * lcid [I] locale ID.
418 * ppTLib [O] pointer that receives an ITypeLib object on success.
420 * RETURNS
421 * Success: S_OK.
422 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
423 * LoadTypeLib.
425 HRESULT WINAPI LoadRegTypeLib(
426 REFGUID rguid,
427 WORD wVerMajor,
428 WORD wVerMinor,
429 LCID lcid,
430 ITypeLib **ppTLib)
432 BSTR bstr=NULL;
433 HRESULT res;
435 *ppTLib = NULL;
437 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
439 if(SUCCEEDED(res))
441 res= LoadTypeLib(bstr, ppTLib);
442 SysFreeString(bstr);
445 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
447 return res;
451 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
452 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
453 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
454 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
455 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
456 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
458 /******************************************************************************
459 * RegisterTypeLib [OLEAUT32.163]
460 * Adds information about a type library to the System Registry
461 * NOTES
462 * Docs: ITypeLib FAR * ptlib
463 * Docs: OLECHAR FAR* szFullPath
464 * Docs: OLECHAR FAR* szHelpDir
466 * RETURNS
467 * Success: S_OK
468 * Failure: Status
470 HRESULT WINAPI RegisterTypeLib(
471 ITypeLib * ptlib, /* [in] Pointer to the library*/
472 OLECHAR * szFullPath, /* [in] full Path of the library*/
473 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
474 may be NULL*/
476 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
477 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
478 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
479 HRESULT res;
480 TLIBATTR *attr;
481 WCHAR keyName[60];
482 WCHAR tmp[16];
483 HKEY key, subKey;
484 UINT types, tidx;
485 TYPEKIND kind;
486 DWORD disposition;
488 if (ptlib == NULL || szFullPath == NULL)
489 return E_INVALIDARG;
491 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
492 return E_FAIL;
494 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
496 res = S_OK;
497 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
498 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
500 LPOLESTR doc;
502 /* Set the human-readable name of the typelib */
503 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
505 if (RegSetValueExW(key, NULL, 0, REG_SZ,
506 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
507 res = E_FAIL;
509 SysFreeString(doc);
511 else
512 res = E_FAIL;
514 /* Make up the name of the typelib path subkey */
515 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
517 /* Create the typelib path subkey */
518 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
519 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
521 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
522 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
523 res = E_FAIL;
525 RegCloseKey(subKey);
527 else
528 res = E_FAIL;
530 /* Create the flags subkey */
531 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
532 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
534 /* FIXME: is %u correct? */
535 static const WCHAR formatW[] = {'%','u',0};
536 WCHAR buf[20];
537 sprintfW(buf, formatW, attr->wLibFlags);
538 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
539 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
540 res = E_FAIL;
542 RegCloseKey(subKey);
544 else
545 res = E_FAIL;
547 /* create the helpdir subkey */
548 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
549 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
551 BOOL freeHelpDir = FALSE;
552 OLECHAR* pIndexStr;
554 /* if we created a new key, and helpDir was null, set the helpdir
555 to the directory which contains the typelib. However,
556 if we just opened an existing key, we leave the helpdir alone */
557 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
558 szHelpDir = SysAllocString(szFullPath);
559 pIndexStr = strrchrW(szHelpDir, '\\');
560 if (pIndexStr) {
561 *pIndexStr = 0;
563 freeHelpDir = TRUE;
566 /* if we have an szHelpDir, set it! */
567 if (szHelpDir != NULL) {
568 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
569 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
570 res = E_FAIL;
574 /* tidy up */
575 if (freeHelpDir) SysFreeString(szHelpDir);
576 RegCloseKey(subKey);
578 } else {
579 res = E_FAIL;
582 RegCloseKey(key);
584 else
585 res = E_FAIL;
587 /* register OLE Automation-compatible interfaces for this typelib */
588 types = ITypeLib_GetTypeInfoCount(ptlib);
589 for (tidx=0; tidx<types; tidx++) {
590 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
591 LPOLESTR name = NULL;
592 ITypeInfo *tinfo = NULL;
594 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
596 switch (kind) {
597 case TKIND_INTERFACE:
598 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
599 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
600 break;
602 case TKIND_DISPATCH:
603 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
604 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
605 break;
607 default:
608 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
609 break;
612 if (tinfo) {
613 TYPEATTR *tattr = NULL;
614 ITypeInfo_GetTypeAttr(tinfo, &tattr);
616 if (tattr) {
617 TRACE_(typelib)("guid=%s, flags=%04x (",
618 debugstr_guid(&tattr->guid),
619 tattr->wTypeFlags);
621 if (TRACE_ON(typelib)) {
622 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
623 XX(FAPPOBJECT);
624 XX(FCANCREATE);
625 XX(FLICENSED);
626 XX(FPREDECLID);
627 XX(FHIDDEN);
628 XX(FCONTROL);
629 XX(FDUAL);
630 XX(FNONEXTENSIBLE);
631 XX(FOLEAUTOMATION);
632 XX(FRESTRICTED);
633 XX(FAGGREGATABLE);
634 XX(FREPLACEABLE);
635 XX(FDISPATCHABLE);
636 XX(FREVERSEBIND);
637 XX(FPROXY);
638 #undef XX
639 MESSAGE("\n");
642 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
644 /* register interface<->typelib coupling */
645 get_interface_key( &tattr->guid, keyName );
646 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
647 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
649 if (name)
650 RegSetValueExW(key, NULL, 0, REG_SZ,
651 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
653 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
654 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
655 RegSetValueExW(subKey, NULL, 0, REG_SZ,
656 (const BYTE *)PSOA, sizeof PSOA);
657 RegCloseKey(subKey);
660 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
661 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
662 RegSetValueExW(subKey, NULL, 0, REG_SZ,
663 (const BYTE *)PSOA, sizeof PSOA);
664 RegCloseKey(subKey);
667 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
668 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
670 WCHAR buffer[40];
671 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
672 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
674 StringFromGUID2(&attr->guid, buffer, 40);
675 RegSetValueExW(subKey, NULL, 0, REG_SZ,
676 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
677 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
678 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
679 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680 RegCloseKey(subKey);
683 RegCloseKey(key);
687 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
690 ITypeInfo_Release(tinfo);
693 SysFreeString(name);
697 ITypeLib_ReleaseTLibAttr(ptlib, attr);
699 return res;
703 /******************************************************************************
704 * UnRegisterTypeLib [OLEAUT32.186]
705 * Removes information about a type library from the System Registry
706 * NOTES
708 * RETURNS
709 * Success: S_OK
710 * Failure: Status
712 HRESULT WINAPI UnRegisterTypeLib(
713 REFGUID libid, /* [in] Guid of the library */
714 WORD wVerMajor, /* [in] major version */
715 WORD wVerMinor, /* [in] minor version */
716 LCID lcid, /* [in] locale id */
717 SYSKIND syskind)
719 BSTR tlibPath = NULL;
720 DWORD tmpLength;
721 WCHAR keyName[60];
722 WCHAR subKeyName[50];
723 int result = S_OK;
724 DWORD i = 0;
725 BOOL deleteOtherStuff;
726 HKEY key = NULL;
727 HKEY subKey = NULL;
728 TYPEATTR* typeAttr = NULL;
729 TYPEKIND kind;
730 ITypeInfo* typeInfo = NULL;
731 ITypeLib* typeLib = NULL;
732 int numTypes;
734 TRACE("(IID: %s)\n",debugstr_guid(libid));
736 /* Create the path to the key */
737 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
739 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
741 TRACE("Unsupported syskind %i\n", syskind);
742 result = E_INVALIDARG;
743 goto end;
746 /* get the path to the typelib on disk */
747 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
748 result = E_INVALIDARG;
749 goto end;
752 /* Try and open the key to the type library. */
753 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
754 result = E_INVALIDARG;
755 goto end;
758 /* Try and load the type library */
759 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
760 result = TYPE_E_INVALIDSTATE;
761 goto end;
764 /* remove any types registered with this typelib */
765 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
766 for (i=0; i<numTypes; i++) {
767 /* get the kind of type */
768 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
769 goto enddeleteloop;
772 /* skip non-interfaces, and get type info for the type */
773 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
774 goto enddeleteloop;
776 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
777 goto enddeleteloop;
779 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
780 goto enddeleteloop;
783 /* the path to the type */
784 get_interface_key( &typeAttr->guid, subKeyName );
786 /* Delete its bits */
787 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
788 goto enddeleteloop;
790 RegDeleteKeyW(subKey, ProxyStubClsidW);
791 RegDeleteKeyW(subKey, ProxyStubClsid32W);
792 RegDeleteKeyW(subKey, TypeLibW);
793 RegCloseKey(subKey);
794 subKey = NULL;
795 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
797 enddeleteloop:
798 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
799 typeAttr = NULL;
800 if (typeInfo) ITypeInfo_Release(typeInfo);
801 typeInfo = NULL;
804 /* Now, delete the type library path subkey */
805 get_lcid_subkey( lcid, syskind, subKeyName );
806 RegDeleteKeyW(key, subKeyName);
807 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
808 RegDeleteKeyW(key, subKeyName);
810 /* check if there is anything besides the FLAGS/HELPDIR keys.
811 If there is, we don't delete them */
812 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
813 deleteOtherStuff = TRUE;
814 i = 0;
815 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
816 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
818 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
819 if (!strcmpW(subKeyName, FLAGSW)) continue;
820 if (!strcmpW(subKeyName, HELPDIRW)) continue;
821 deleteOtherStuff = FALSE;
822 break;
825 /* only delete the other parts of the key if we're absolutely sure */
826 if (deleteOtherStuff) {
827 RegDeleteKeyW(key, FLAGSW);
828 RegDeleteKeyW(key, HELPDIRW);
829 RegCloseKey(key);
830 key = NULL;
832 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
833 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
834 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
837 end:
838 if (tlibPath) SysFreeString(tlibPath);
839 if (typeLib) ITypeLib_Release(typeLib);
840 if (subKey) RegCloseKey(subKey);
841 if (key) RegCloseKey(key);
842 return result;
845 /*======================= ITypeLib implementation =======================*/
847 typedef struct tagTLBCustData
849 GUID guid;
850 VARIANT data;
851 struct tagTLBCustData* next;
852 } TLBCustData;
854 /* data structure for import typelibs */
855 typedef struct tagTLBImpLib
857 int offset; /* offset in the file (MSFT)
858 offset in nametable (SLTG)
859 just used to identify library while reading
860 data from file */
861 GUID guid; /* libid */
862 BSTR name; /* name */
864 LCID lcid; /* lcid of imported typelib */
866 WORD wVersionMajor; /* major version number */
867 WORD wVersionMinor; /* minor version number */
869 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
870 NULL if not yet loaded */
871 struct tagTLBImpLib * next;
872 } TLBImpLib;
874 /* internal ITypeLib data */
875 typedef struct tagITypeLibImpl
877 const ITypeLib2Vtbl *lpVtbl;
878 const ITypeCompVtbl *lpVtblTypeComp;
879 LONG ref;
880 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
882 /* strings can be stored in tlb as multibyte strings BUT they are *always*
883 * exported to the application as a UNICODE string.
885 BSTR Name;
886 BSTR DocString;
887 BSTR HelpFile;
888 BSTR HelpStringDll;
889 unsigned long dwHelpContext;
890 int TypeInfoCount; /* nr of typeinfo's in librarry */
891 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
892 int ctCustData; /* number of items in cust data list */
893 TLBCustData * pCustData; /* linked list to cust data */
894 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
895 int ctTypeDesc; /* number of items in type desc array */
896 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
897 library. Only used while read MSFT
898 typelibs */
900 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
901 struct tagITypeLibImpl *next, *prev;
902 WCHAR *path;
903 INT index;
904 } ITypeLibImpl;
906 static const ITypeLib2Vtbl tlbvt;
907 static const ITypeCompVtbl tlbtcvt;
909 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
911 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
914 /* ITypeLib methods */
915 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
916 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
918 /*======================= ITypeInfo implementation =======================*/
920 /* data for referenced types */
921 typedef struct tagTLBRefType
923 INT index; /* Type index for internal ref or for external ref
924 it the format is SLTG. -2 indicates to
925 use guid */
927 GUID guid; /* guid of the referenced type */
928 /* if index == TLB_REF_USE_GUID */
930 HREFTYPE reference; /* The href of this ref */
931 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
932 TLB_REF_INTERNAL for internal refs
933 TLB_REF_NOT_FOUND for broken refs */
935 struct tagTLBRefType * next;
936 } TLBRefType;
938 #define TLB_REF_USE_GUID -2
940 #define TLB_REF_INTERNAL (void*)-2
941 #define TLB_REF_NOT_FOUND (void*)-1
943 /* internal Parameter data */
944 typedef struct tagTLBParDesc
946 BSTR Name;
947 int ctCustData;
948 TLBCustData * pCustData; /* linked list to cust data */
949 } TLBParDesc;
951 /* internal Function data */
952 typedef struct tagTLBFuncDesc
954 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
955 BSTR Name; /* the name of this function */
956 TLBParDesc *pParamDesc; /* array with param names and custom data */
957 int helpcontext;
958 int HelpStringContext;
959 BSTR HelpString;
960 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
961 int ctCustData;
962 TLBCustData * pCustData; /* linked list to cust data; */
963 struct tagTLBFuncDesc * next;
964 } TLBFuncDesc;
966 /* internal Variable data */
967 typedef struct tagTLBVarDesc
969 VARDESC vardesc; /* lots of info on the variable and its attributes. */
970 BSTR Name; /* the name of this variable */
971 int HelpContext;
972 int HelpStringContext; /* FIXME: where? */
973 BSTR HelpString;
974 int ctCustData;
975 TLBCustData * pCustData;/* linked list to cust data; */
976 struct tagTLBVarDesc * next;
977 } TLBVarDesc;
979 /* internal implemented interface data */
980 typedef struct tagTLBImplType
982 HREFTYPE hRef; /* hRef of interface */
983 int implflags; /* IMPLFLAG_*s */
984 int ctCustData;
985 TLBCustData * pCustData;/* linked list to custom data; */
986 struct tagTLBImplType *next;
987 } TLBImplType;
989 /* internal TypeInfo data */
990 typedef struct tagITypeInfoImpl
992 const ITypeInfo2Vtbl *lpVtbl;
993 const ITypeCompVtbl *lpVtblTypeComp;
994 LONG ref;
995 BOOL no_free_data; /* don't free data structurees */
996 TYPEATTR TypeAttr ; /* _lots_ of type information. */
997 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
998 int index; /* index in this typelib; */
999 HREFTYPE hreftype; /* hreftype for app object binding */
1000 /* type libs seem to store the doc strings in ascii
1001 * so why should we do it in unicode?
1003 BSTR Name;
1004 BSTR DocString;
1005 BSTR DllName;
1006 unsigned long dwHelpContext;
1007 unsigned long dwHelpStringContext;
1009 /* functions */
1010 TLBFuncDesc * funclist; /* linked list with function descriptions */
1012 /* variables */
1013 TLBVarDesc * varlist; /* linked list with variable descriptions */
1015 /* Implemented Interfaces */
1016 TLBImplType * impltypelist;
1018 TLBRefType * reflist;
1019 int ctCustData;
1020 TLBCustData * pCustData; /* linked list to cust data; */
1021 struct tagITypeInfoImpl * next;
1022 } ITypeInfoImpl;
1024 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1026 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1029 static const ITypeInfo2Vtbl tinfvt;
1030 static const ITypeCompVtbl tcompvt;
1032 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1034 typedef struct tagTLBContext
1036 unsigned int oStart; /* start of TLB in file */
1037 unsigned int pos; /* current pos */
1038 unsigned int length; /* total length */
1039 void *mapping; /* memory mapping */
1040 MSFT_SegDir * pTblDir;
1041 ITypeLibImpl* pLibInfo;
1042 } TLBContext;
1045 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1048 debug
1050 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1051 if (pTD->vt & VT_RESERVED)
1052 szVarType += strlen(strcpy(szVarType, "reserved | "));
1053 if (pTD->vt & VT_BYREF)
1054 szVarType += strlen(strcpy(szVarType, "ref to "));
1055 if (pTD->vt & VT_ARRAY)
1056 szVarType += strlen(strcpy(szVarType, "array of "));
1057 if (pTD->vt & VT_VECTOR)
1058 szVarType += strlen(strcpy(szVarType, "vector of "));
1059 switch(pTD->vt & VT_TYPEMASK) {
1060 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1061 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1062 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1063 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1064 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1065 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1066 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1067 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1068 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1069 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1070 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1071 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1072 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1073 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1074 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1075 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1076 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1077 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1078 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1079 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1080 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1081 pTD->u.hreftype); break;
1082 case VT_PTR: sprintf(szVarType, "ptr to ");
1083 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1084 break;
1085 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1086 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1087 break;
1088 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1089 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1090 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1091 break;
1093 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1097 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1098 char buf[200];
1099 USHORT flags = edesc->u.paramdesc.wParamFlags;
1100 dump_TypeDesc(&edesc->tdesc,buf);
1101 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1102 MESSAGE("\t\tu.paramdesc.wParamFlags");
1103 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1104 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1105 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1106 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1107 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1108 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1109 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1110 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1111 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1113 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1114 int i;
1115 MESSAGE("memid is %08x\n",funcdesc->memid);
1116 for (i=0;i<funcdesc->cParams;i++) {
1117 MESSAGE("Param %d:\n",i);
1118 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1120 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1121 switch (funcdesc->funckind) {
1122 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1123 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1124 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1125 case FUNC_STATIC: MESSAGE("static");break;
1126 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1127 default: MESSAGE("unknown");break;
1129 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1130 switch (funcdesc->invkind) {
1131 case INVOKE_FUNC: MESSAGE("func");break;
1132 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1133 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1134 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1136 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1137 switch (funcdesc->callconv) {
1138 case CC_CDECL: MESSAGE("cdecl");break;
1139 case CC_PASCAL: MESSAGE("pascal");break;
1140 case CC_STDCALL: MESSAGE("stdcall");break;
1141 case CC_SYSCALL: MESSAGE("syscall");break;
1142 default:break;
1144 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1145 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1146 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1148 MESSAGE("\telemdescFunc (return value type):\n");
1149 dump_ELEMDESC(&funcdesc->elemdescFunc);
1152 static const char * const typekind_desc[] =
1154 "TKIND_ENUM",
1155 "TKIND_RECORD",
1156 "TKIND_MODULE",
1157 "TKIND_INTERFACE",
1158 "TKIND_DISPATCH",
1159 "TKIND_COCLASS",
1160 "TKIND_ALIAS",
1161 "TKIND_UNION",
1162 "TKIND_MAX"
1165 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1167 int i;
1168 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1169 for (i=0;i<pfd->funcdesc.cParams;i++)
1170 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1173 dump_FUNCDESC(&(pfd->funcdesc));
1175 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1176 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1178 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1180 while (pfd)
1182 dump_TLBFuncDescOne(pfd);
1183 pfd = pfd->next;
1186 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1188 while (pvd)
1190 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1191 pvd = pvd->next;
1195 static void dump_TLBImpLib(const TLBImpLib *import)
1197 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1198 debugstr_w(import->name));
1199 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1200 import->wVersionMinor, import->lcid, import->offset);
1203 static void dump_TLBRefType(const TLBRefType * prt)
1205 while (prt)
1207 TRACE_(typelib)("href:0x%08x\n", prt->reference);
1208 if(prt->index == -1)
1209 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1210 else
1211 TRACE_(typelib)("type no: %d\n", prt->index);
1213 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1214 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1215 TRACE_(typelib)("in lib\n");
1216 dump_TLBImpLib(prt->pImpTLInfo);
1218 prt = prt->next;
1222 static void dump_TLBImplType(const TLBImplType * impl)
1224 while (impl) {
1225 TRACE_(typelib)(
1226 "implementing/inheriting interface hRef = %x implflags %x\n",
1227 impl->hRef, impl->implflags);
1228 impl = impl->next;
1232 static void dump_Variant(const VARIANT * pvar)
1234 SYSTEMTIME st;
1236 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1238 if (pvar)
1240 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1241 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1243 TRACE(",%p", V_BYREF(pvar));
1245 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1247 TRACE(",%p", V_ARRAY(pvar));
1249 else switch (V_TYPE(pvar))
1251 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1252 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1253 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1254 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1255 case VT_INT:
1256 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1257 case VT_UINT:
1258 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1259 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1260 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1261 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1262 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1263 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1264 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1265 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1266 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1267 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1268 V_CY(pvar).s.Lo); break;
1269 case VT_DATE:
1270 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1271 TRACE(",<invalid>");
1272 else
1273 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1274 st.wHour, st.wMinute, st.wSecond);
1275 break;
1276 case VT_ERROR:
1277 case VT_VOID:
1278 case VT_USERDEFINED:
1279 case VT_EMPTY:
1280 case VT_NULL: break;
1281 default: TRACE(",?"); break;
1284 TRACE("}\n");
1287 static void dump_DispParms(const DISPPARAMS * pdp)
1289 int index;
1291 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1293 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1295 TRACE("named args:\n");
1296 for (index = 0; index < pdp->cNamedArgs; index++)
1297 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1300 if (pdp->cArgs && pdp->rgvarg)
1302 TRACE("args:\n");
1303 for (index = 0; index < pdp->cArgs; index++)
1304 dump_Variant( &pdp->rgvarg[index] );
1308 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1310 TRACE("%p ref=%u\n", pty, pty->ref);
1311 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1312 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1313 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1314 TRACE("fct:%u var:%u impl:%u\n",
1315 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1316 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1317 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1318 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1319 if (TRACE_ON(ole))
1320 dump_TLBFuncDesc(pty->funclist);
1321 dump_TLBVarDesc(pty->varlist);
1322 dump_TLBImplType(pty->impltypelist);
1325 static void dump_VARDESC(const VARDESC *v)
1327 MESSAGE("memid %d\n",v->memid);
1328 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1329 MESSAGE("oInst %d\n",v->u.oInst);
1330 dump_ELEMDESC(&(v->elemdescVar));
1331 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1332 MESSAGE("varkind %d\n",v->varkind);
1335 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1337 /* VT_LPWSTR is largest type that */
1338 /* may appear in type description*/
1339 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1340 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1341 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1342 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1343 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1344 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1345 {{0},30},{{0},31}
1348 static void TLB_abort(void)
1350 DebugBreak();
1352 static void * TLB_Alloc(unsigned size)
1354 void * ret;
1355 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1356 /* FIXME */
1357 ERR("cannot allocate memory\n");
1359 return ret;
1362 static void TLB_Free(void * ptr)
1364 HeapFree(GetProcessHeap(), 0, ptr);
1367 /* returns the size required for a deep copy of a typedesc into a
1368 * flat buffer */
1369 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1371 SIZE_T size = 0;
1373 if (alloc_initial_space)
1374 size += sizeof(TYPEDESC);
1376 switch (tdesc->vt)
1378 case VT_PTR:
1379 case VT_SAFEARRAY:
1380 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1381 break;
1382 case VT_CARRAY:
1383 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1384 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1385 break;
1387 return size;
1390 /* deep copy a typedesc into a flat buffer */
1391 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1393 if (!dest)
1395 dest = buffer;
1396 buffer = (char *)buffer + sizeof(TYPEDESC);
1399 *dest = *src;
1401 switch (src->vt)
1403 case VT_PTR:
1404 case VT_SAFEARRAY:
1405 dest->u.lptdesc = buffer;
1406 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1407 break;
1408 case VT_CARRAY:
1409 dest->u.lpadesc = buffer;
1410 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1411 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1412 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1413 break;
1415 return buffer;
1418 /**********************************************************************
1420 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1422 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1424 return pcx->pos;
1427 static inline void MSFT_Seek(TLBContext *pcx, long where)
1429 if (where != DO_NOT_SEEK)
1431 where += pcx->oStart;
1432 if (where > pcx->length)
1434 /* FIXME */
1435 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1436 TLB_abort();
1438 pcx->pos = where;
1442 /* read function */
1443 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1445 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1446 pcx->pos, count, pcx->oStart, pcx->length, where);
1448 MSFT_Seek(pcx, where);
1449 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1450 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1451 pcx->pos += count;
1452 return count;
1455 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1456 long where )
1458 DWORD ret;
1460 ret = MSFT_Read(buffer, count, pcx, where);
1461 FromLEDWords(buffer, ret);
1463 return ret;
1466 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1467 long where )
1469 DWORD ret;
1471 ret = MSFT_Read(buffer, count, pcx, where);
1472 FromLEWords(buffer, ret);
1474 return ret;
1477 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1479 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1480 memset(pGuid,0, sizeof(GUID));
1481 return;
1483 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1484 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1485 pGuid->Data2 = FromLEWord(pGuid->Data2);
1486 pGuid->Data3 = FromLEWord(pGuid->Data3);
1487 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1490 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1492 MSFT_NameIntro niName;
1494 if (offset < 0)
1496 ERR_(typelib)("bad offset %d\n", offset);
1497 return -1;
1500 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1501 pcx->pTblDir->pNametab.offset+offset);
1503 return niName.hreftype;
1506 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1508 char * name;
1509 MSFT_NameIntro niName;
1510 int lengthInChars;
1511 BSTR bstrName = NULL;
1513 if (offset < 0)
1515 ERR_(typelib)("bad offset %d\n", offset);
1516 return NULL;
1518 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1519 pcx->pTblDir->pNametab.offset+offset);
1520 niName.namelen &= 0xFF; /* FIXME: correct ? */
1521 name=TLB_Alloc((niName.namelen & 0xff) +1);
1522 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1523 name[niName.namelen & 0xff]='\0';
1525 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1526 name, -1, NULL, 0);
1528 /* no invalid characters in string */
1529 if (lengthInChars)
1531 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1533 /* don't check for invalid character since this has been done previously */
1534 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1536 TLB_Free(name);
1538 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1539 return bstrName;
1542 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1544 char * string;
1545 INT16 length;
1546 int lengthInChars;
1547 BSTR bstr = NULL;
1549 if(offset<0) return NULL;
1550 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1551 if(length <= 0) return 0;
1552 string=TLB_Alloc(length +1);
1553 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1554 string[length]='\0';
1556 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1557 string, -1, NULL, 0);
1559 /* no invalid characters in string */
1560 if (lengthInChars)
1562 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1564 /* don't check for invalid character since this has been done previously */
1565 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1567 TLB_Free(string);
1569 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1570 return bstr;
1573 * read a value and fill a VARIANT structure
1575 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1577 int size;
1579 TRACE_(typelib)("\n");
1581 if(offset <0) { /* data are packed in here */
1582 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1583 V_I4(pVar) = offset & 0x3ffffff;
1584 return;
1586 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1587 pcx->pTblDir->pCustData.offset + offset );
1588 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1589 switch (V_VT(pVar)){
1590 case VT_EMPTY: /* FIXME: is this right? */
1591 case VT_NULL: /* FIXME: is this right? */
1592 case VT_I2 : /* this should not happen */
1593 case VT_I4 :
1594 case VT_R4 :
1595 case VT_ERROR :
1596 case VT_BOOL :
1597 case VT_I1 :
1598 case VT_UI1 :
1599 case VT_UI2 :
1600 case VT_UI4 :
1601 case VT_INT :
1602 case VT_UINT :
1603 case VT_VOID : /* FIXME: is this right? */
1604 case VT_HRESULT :
1605 size=4; break;
1606 case VT_R8 :
1607 case VT_CY :
1608 case VT_DATE :
1609 case VT_I8 :
1610 case VT_UI8 :
1611 case VT_DECIMAL : /* FIXME: is this right? */
1612 case VT_FILETIME :
1613 size=8;break;
1614 /* pointer types with known behaviour */
1615 case VT_BSTR :{
1616 char * ptr;
1617 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1618 if(size < 0) {
1619 char next;
1620 DWORD origPos = MSFT_Tell(pcx), nullPos;
1622 do {
1623 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1624 } while (next);
1625 nullPos = MSFT_Tell(pcx);
1626 size = nullPos - origPos;
1627 MSFT_Seek(pcx, origPos);
1629 ptr=TLB_Alloc(size);/* allocate temp buffer */
1630 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1631 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1632 /* FIXME: do we need a AtoW conversion here? */
1633 V_UNION(pVar, bstrVal[size])=L'\0';
1634 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1635 TLB_Free(ptr);
1637 size=-4; break;
1638 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1639 case VT_DISPATCH :
1640 case VT_VARIANT :
1641 case VT_UNKNOWN :
1642 case VT_PTR :
1643 case VT_SAFEARRAY :
1644 case VT_CARRAY :
1645 case VT_USERDEFINED :
1646 case VT_LPSTR :
1647 case VT_LPWSTR :
1648 case VT_BLOB :
1649 case VT_STREAM :
1650 case VT_STORAGE :
1651 case VT_STREAMED_OBJECT :
1652 case VT_STORED_OBJECT :
1653 case VT_BLOB_OBJECT :
1654 case VT_CF :
1655 case VT_CLSID :
1656 default:
1657 size=0;
1658 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1659 V_VT(pVar));
1662 if(size>0) /* (big|small) endian correct? */
1663 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1664 return;
1667 * create a linked list with custom data
1669 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1671 MSFT_CDGuid entry;
1672 TLBCustData* pNew;
1673 int count=0;
1675 TRACE_(typelib)("\n");
1677 while(offset >=0){
1678 count++;
1679 pNew=TLB_Alloc(sizeof(TLBCustData));
1680 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1681 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1682 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1683 /* add new custom data at head of the list */
1684 pNew->next=*ppCustData;
1685 *ppCustData=pNew;
1686 offset = entry.next;
1688 return count;
1691 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1692 ITypeInfoImpl *pTI)
1694 if(type <0)
1695 pTd->vt=type & VT_TYPEMASK;
1696 else
1697 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1699 if(pTd->vt == VT_USERDEFINED)
1700 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1702 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1705 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1707 /* resolve referenced type if any */
1708 while (lpTypeDesc)
1710 switch (lpTypeDesc->vt)
1712 case VT_PTR:
1713 lpTypeDesc = lpTypeDesc->u.lptdesc;
1714 break;
1716 case VT_CARRAY:
1717 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1718 break;
1720 case VT_USERDEFINED:
1721 MSFT_DoRefType(pcx, pTI,
1722 lpTypeDesc->u.hreftype);
1724 lpTypeDesc = NULL;
1725 break;
1727 default:
1728 lpTypeDesc = NULL;
1733 static void
1734 MSFT_DoFuncs(TLBContext* pcx,
1735 ITypeInfoImpl* pTI,
1736 int cFuncs,
1737 int cVars,
1738 int offset,
1739 TLBFuncDesc** pptfd)
1742 * member information is stored in a data structure at offset
1743 * indicated by the memoffset field of the typeinfo structure
1744 * There are several distinctive parts.
1745 * The first part starts with a field that holds the total length
1746 * of this (first) part excluding this field. Then follow the records,
1747 * for each member there is one record.
1749 * The first entry is always the length of the record (including this
1750 * length word).
1751 * The rest of the record depends on the type of the member. If there is
1752 * a field indicating the member type (function, variable, interface, etc)
1753 * I have not found it yet. At this time we depend on the information
1754 * in the type info and the usual order how things are stored.
1756 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1757 * for each member;
1759 * Third is an equal sized array with file offsets to the name entry
1760 * of each member.
1762 * The fourth and last (?) part is an array with offsets to the records
1763 * in the first part of this file segment.
1766 int infolen, nameoffset, reclength, nrattributes, i;
1767 int recoffset = offset + sizeof(INT);
1769 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1770 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1771 TLBFuncDesc *ptfd_prev = NULL;
1773 TRACE_(typelib)("\n");
1775 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1777 for ( i = 0; i < cFuncs ; i++ )
1779 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1781 /* name, eventually add to a hash table */
1782 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1783 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1785 /* nameoffset is sometimes -1 on the second half of a propget/propput
1786 * pair of functions */
1787 if ((nameoffset == -1) && (i > 0))
1788 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1789 else
1790 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1792 /* read the function information record */
1793 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1795 reclength &= 0xffff;
1797 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1799 /* do the attributes */
1800 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1801 / sizeof(int);
1803 if ( nrattributes > 0 )
1805 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1807 if ( nrattributes > 1 )
1809 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1810 pFuncRec->OptAttr[1]) ;
1812 if ( nrattributes > 2 )
1814 if ( pFuncRec->FKCCIC & 0x2000 )
1816 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1817 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1818 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1820 else
1822 (*pptfd)->Entry = MSFT_ReadString(pcx,
1823 pFuncRec->OptAttr[2]);
1825 if( nrattributes > 5 )
1827 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1829 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1831 MSFT_CustData(pcx,
1832 pFuncRec->OptAttr[6],
1833 &(*pptfd)->pCustData);
1837 else
1839 (*pptfd)->Entry = (BSTR)-1;
1844 /* fill the FuncDesc Structure */
1845 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1846 offset + infolen + ( i + 1) * sizeof(INT));
1848 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1849 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1850 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1851 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1852 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1853 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1854 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1856 MSFT_GetTdesc(pcx,
1857 pFuncRec->DataType,
1858 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1859 pTI);
1860 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1862 /* do the parameters/arguments */
1863 if(pFuncRec->nrargs)
1865 int j = 0;
1866 MSFT_ParameterInfo paraminfo;
1868 (*pptfd)->funcdesc.lprgelemdescParam =
1869 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1871 (*pptfd)->pParamDesc =
1872 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1874 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1875 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1877 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1879 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1881 MSFT_GetTdesc(pcx,
1882 paraminfo.DataType,
1883 &elemdesc->tdesc,
1884 pTI);
1886 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1888 /* name */
1889 if (paraminfo.oName == -1)
1890 /* this occurs for [propput] or [propget] methods, so
1891 * we should just set the name of the parameter to the
1892 * name of the method. */
1893 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1894 else
1895 (*pptfd)->pParamDesc[j].Name =
1896 MSFT_ReadName( pcx, paraminfo.oName );
1897 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1899 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1901 /* default value */
1902 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1903 (pFuncRec->FKCCIC & 0x1000) )
1905 INT* pInt = (INT *)((char *)pFuncRec +
1906 reclength -
1907 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1909 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1911 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1912 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1914 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1915 pInt[j], pcx);
1917 else
1918 elemdesc->u.paramdesc.pparamdescex = NULL;
1919 /* custom info */
1920 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1922 MSFT_CustData(pcx,
1923 pFuncRec->OptAttr[7+j],
1924 &(*pptfd)->pParamDesc[j].pCustData);
1927 /* SEEK value = jump to offset,
1928 * from there jump to the end of record,
1929 * go back by (j-1) arguments
1931 MSFT_ReadLEDWords( &paraminfo ,
1932 sizeof(MSFT_ParameterInfo), pcx,
1933 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1934 * sizeof(MSFT_ParameterInfo)));
1938 /* scode is not used: archaic win16 stuff FIXME: right? */
1939 (*pptfd)->funcdesc.cScodes = 0 ;
1940 (*pptfd)->funcdesc.lprgscode = NULL ;
1942 ptfd_prev = *pptfd;
1943 pptfd = & ((*pptfd)->next);
1944 recoffset += reclength;
1946 HeapFree(GetProcessHeap(), 0, recbuf);
1949 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1950 int cVars, int offset, TLBVarDesc ** pptvd)
1952 int infolen, nameoffset, reclength;
1953 char recbuf[256];
1954 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1955 int i;
1956 int recoffset;
1958 TRACE_(typelib)("\n");
1960 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1961 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1962 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1963 recoffset += offset+sizeof(INT);
1964 for(i=0;i<cVars;i++){
1965 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1966 /* name, eventually add to a hash table */
1967 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1968 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1969 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1970 /* read the variable information record */
1971 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1972 reclength &=0xff;
1973 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1974 /* Optional data */
1975 if(reclength >(6*sizeof(INT)) )
1976 (*pptvd)->HelpContext=pVarRec->HelpContext;
1977 if(reclength >(7*sizeof(INT)) )
1978 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1979 if(reclength >(8*sizeof(INT)) )
1980 if(reclength >(9*sizeof(INT)) )
1981 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1982 /* fill the VarDesc Structure */
1983 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1984 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1985 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1986 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1987 MSFT_GetTdesc(pcx, pVarRec->DataType,
1988 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1989 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1990 if(pVarRec->VarKind == VAR_CONST ){
1991 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1992 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1993 pVarRec->OffsValue, pcx);
1994 } else
1995 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1996 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1997 pptvd=&((*pptvd)->next);
1998 recoffset += reclength;
2001 /* fill in data for a hreftype (offset). When the referenced type is contained
2002 * in the typelib, it's just an (file) offset in the type info base dir.
2003 * If comes from import, it's an offset+1 in the ImpInfo table
2004 * */
2005 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
2006 int offset)
2008 int j;
2009 TLBRefType **ppRefType = &pTI->reflist;
2011 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2013 while(*ppRefType) {
2014 if((*ppRefType)->reference == offset)
2015 return;
2016 ppRefType = &(*ppRefType)->next;
2019 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2020 sizeof(**ppRefType));
2022 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2023 /* external typelib */
2024 MSFT_ImpInfo impinfo;
2025 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2027 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2029 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2030 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2031 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2032 if(pImpLib->offset==impinfo.oImpFile) break;
2033 pImpLib=pImpLib->next;
2035 if(pImpLib){
2036 (*ppRefType)->reference=offset;
2037 (*ppRefType)->pImpTLInfo = pImpLib;
2038 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2039 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2040 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
2041 (*ppRefType)->index = TLB_REF_USE_GUID;
2042 } else
2043 (*ppRefType)->index = impinfo.oGuid;
2044 }else{
2045 ERR("Cannot find a reference\n");
2046 (*ppRefType)->reference=-1;
2047 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2049 }else{
2050 /* in this typelib */
2051 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2052 (*ppRefType)->reference=offset;
2053 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2057 /* process Implemented Interfaces of a com class */
2058 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2059 int offset)
2061 int i;
2062 MSFT_RefRecord refrec;
2063 TLBImplType **ppImpl = &pTI->impltypelist;
2065 TRACE_(typelib)("\n");
2067 for(i=0;i<count;i++){
2068 if(offset<0) break; /* paranoia */
2069 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2070 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2071 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2072 (*ppImpl)->hRef = refrec.reftype;
2073 (*ppImpl)->implflags=refrec.flags;
2074 (*ppImpl)->ctCustData=
2075 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2076 offset=refrec.onext;
2077 ppImpl=&((*ppImpl)->next);
2081 * process a typeinfo record
2083 static ITypeInfoImpl * MSFT_DoTypeInfo(
2084 TLBContext *pcx,
2085 int count,
2086 INT dispatch_href,
2087 ITypeLibImpl * pLibInfo)
2089 MSFT_TypeInfoBase tiBase;
2090 ITypeInfoImpl *ptiRet;
2092 TRACE_(typelib)("count=%u\n", count);
2094 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2095 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2096 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2098 /* this is where we are coming from */
2099 ptiRet->pTypeLib = pLibInfo;
2100 ptiRet->index=count;
2101 /* fill in the typeattr fields */
2103 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2104 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2105 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2106 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2107 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2108 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2109 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2110 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2111 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2112 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2113 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2114 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2115 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2116 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2117 MSFT_GetTdesc(pcx, tiBase.datatype1,
2118 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2120 /* FIXME: */
2121 /* IDLDESC idldescType; *//* never saw this one != zero */
2123 /* name, eventually add to a hash table */
2124 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2125 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2126 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2127 /* help info */
2128 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2129 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2130 ptiRet->dwHelpContext=tiBase.helpcontext;
2132 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2133 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2135 /* note: InfoType's Help file and HelpStringDll come from the containing
2136 * library. Further HelpString and Docstring appear to be the same thing :(
2138 /* functions */
2139 if(ptiRet->TypeAttr.cFuncs >0 )
2140 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2141 ptiRet->TypeAttr.cVars,
2142 tiBase.memoffset, & ptiRet->funclist);
2143 /* variables */
2144 if(ptiRet->TypeAttr.cVars >0 )
2145 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2146 ptiRet->TypeAttr.cVars,
2147 tiBase.memoffset, & ptiRet->varlist);
2148 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2149 switch(ptiRet->TypeAttr.typekind)
2151 case TKIND_COCLASS:
2152 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2153 tiBase.datatype1);
2154 break;
2155 case TKIND_DISPATCH:
2156 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2158 if (tiBase.datatype1 != -1)
2160 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2161 ptiRet->impltypelist->hRef = tiBase.datatype1;
2163 else
2165 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2166 ptiRet->impltypelist->hRef = dispatch_href;
2168 break;
2169 default:
2170 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2171 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2172 ptiRet->impltypelist->hRef = tiBase.datatype1;
2173 break;
2176 ptiRet->ctCustData=
2177 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2179 TRACE_(typelib)("%s guid: %s kind:%s\n",
2180 debugstr_w(ptiRet->Name),
2181 debugstr_guid(&ptiRet->TypeAttr.guid),
2182 typekind_desc[ptiRet->TypeAttr.typekind]);
2184 return ptiRet;
2187 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2188 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2189 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2190 * tradeoff here.
2192 static ITypeLibImpl *tlb_cache_first;
2193 static CRITICAL_SECTION cache_section;
2194 static CRITICAL_SECTION_DEBUG cache_section_debug =
2196 0, 0, &cache_section,
2197 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2198 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2200 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2203 /****************************************************************************
2204 * TLB_ReadTypeLib
2206 * find the type of the typelib file and map the typelib resource into
2207 * the memory
2209 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2210 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2211 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2213 ITypeLibImpl *entry;
2214 int ret = TYPE_E_CANTLOADLIBRARY;
2215 INT index = 1;
2216 HINSTANCE hinstDLL;
2217 LPWSTR index_str, file = (LPWSTR)pszFileName;
2219 *ppTypeLib = NULL;
2221 index_str = strrchrW(pszFileName, '\\');
2222 if(index_str && *++index_str != '\0')
2224 LPWSTR end_ptr;
2225 long idx = strtolW(index_str, &end_ptr, 10);
2226 if(*end_ptr == '\0')
2228 int str_len = index_str - pszFileName - 1;
2229 index = idx;
2230 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2231 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2232 file[str_len] = 0;
2236 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2238 if(strchrW(file, '\\'))
2240 lstrcpyW(pszPath, file);
2242 else
2244 int len = GetSystemDirectoryW(pszPath, cchPath);
2245 pszPath[len] = '\\';
2246 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2250 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2252 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2254 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2255 EnterCriticalSection(&cache_section);
2256 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2258 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2260 TRACE("cache hit\n");
2261 *ppTypeLib = (ITypeLib2*)entry;
2262 ITypeLib_AddRef(*ppTypeLib);
2263 LeaveCriticalSection(&cache_section);
2264 return S_OK;
2267 LeaveCriticalSection(&cache_section);
2269 /* now actually load and parse the typelib */
2271 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2272 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2274 if (hinstDLL)
2276 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2277 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2278 if (hrsrc)
2280 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2281 if (hGlobal)
2283 LPVOID pBase = LockResource(hGlobal);
2284 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2286 if (pBase)
2288 /* try to load as incore resource */
2289 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2290 if (dwSignature == MSFT_SIGNATURE)
2291 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2292 else if (dwSignature == SLTG_SIGNATURE)
2293 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2294 else
2295 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2297 FreeResource( hGlobal );
2300 FreeLibrary(hinstDLL);
2302 else
2304 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2305 if (INVALID_HANDLE_VALUE != hFile)
2307 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2308 if (hMapping)
2310 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2311 if(pBase)
2313 /* retrieve file size */
2314 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2315 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2317 if (dwSignature == MSFT_SIGNATURE)
2318 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2319 else if (dwSignature == SLTG_SIGNATURE)
2320 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2322 UnmapViewOfFile(pBase);
2324 CloseHandle(hMapping);
2326 CloseHandle(hFile);
2330 if(*ppTypeLib) {
2331 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2333 TRACE("adding to cache\n");
2334 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2335 lstrcpyW(impl->path, pszPath);
2336 /* We should really canonicalise the path here. */
2337 impl->index = index;
2339 /* FIXME: check if it has added already in the meantime */
2340 EnterCriticalSection(&cache_section);
2341 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2342 impl->prev = NULL;
2343 tlb_cache_first = impl;
2344 LeaveCriticalSection(&cache_section);
2345 ret = S_OK;
2346 } else
2347 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2349 return ret;
2352 /*================== ITypeLib(2) Methods ===================================*/
2354 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2356 ITypeLibImpl* pTypeLibImpl;
2358 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2359 if (!pTypeLibImpl) return NULL;
2361 pTypeLibImpl->lpVtbl = &tlbvt;
2362 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2363 pTypeLibImpl->ref = 1;
2365 return pTypeLibImpl;
2368 /****************************************************************************
2369 * ITypeLib2_Constructor_MSFT
2371 * loading an MSFT typelib from an in-memory image
2373 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2375 TLBContext cx;
2376 long lPSegDir;
2377 MSFT_Header tlbHeader;
2378 MSFT_SegDir tlbSegDir;
2379 ITypeLibImpl * pTypeLibImpl;
2381 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2383 pTypeLibImpl = TypeLibImpl_Constructor();
2384 if (!pTypeLibImpl) return NULL;
2386 /* get pointer to beginning of typelib data */
2387 cx.pos = 0;
2388 cx.oStart=0;
2389 cx.mapping = pLib;
2390 cx.pLibInfo = pTypeLibImpl;
2391 cx.length = dwTLBLength;
2393 /* read header */
2394 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2395 TRACE_(typelib)("header:\n");
2396 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2397 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2398 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2399 return NULL;
2401 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2403 /* there is a small amount of information here until the next important
2404 * part:
2405 * the segment directory . Try to calculate the amount of data */
2406 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2408 /* now read the segment directory */
2409 TRACE("read segment directory (at %ld)\n",lPSegDir);
2410 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2411 cx.pTblDir = &tlbSegDir;
2413 /* just check two entries */
2414 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2416 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2417 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2418 return NULL;
2421 /* now fill our internal data */
2422 /* TLIBATTR fields */
2423 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2425 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2426 /* Windows seems to have zero here, is this correct? */
2427 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2428 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2429 else
2430 pTypeLibImpl->LibAttr.lcid = 0;
2432 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2433 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2434 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2435 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2437 /* name, eventually add to a hash table */
2438 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2440 /* help info */
2441 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2442 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2444 if( tlbHeader.varflags & HELPDLLFLAG)
2446 int offset;
2447 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2448 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2451 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2453 /* custom data */
2454 if(tlbHeader.CustomDataOffset >= 0)
2456 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2459 /* fill in typedescriptions */
2460 if(tlbSegDir.pTypdescTab.length > 0)
2462 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2463 INT16 td[4];
2464 pTypeLibImpl->ctTypeDesc = cTD;
2465 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2466 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2467 for(i=0; i<cTD; )
2469 /* FIXME: add several sanity checks here */
2470 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2471 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2473 /* FIXME: check safearray */
2474 if(td[3] < 0)
2475 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2476 else
2477 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2479 else if(td[0] == VT_CARRAY)
2481 /* array descr table here */
2482 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2484 else if(td[0] == VT_USERDEFINED)
2486 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2488 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2491 /* second time around to fill the array subscript info */
2492 for(i=0;i<cTD;i++)
2494 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2495 if(tlbSegDir.pArrayDescriptions.offset>0)
2497 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2498 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2500 if(td[1]<0)
2501 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2502 else
2503 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2505 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2507 for(j = 0; j<td[2]; j++)
2509 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2510 sizeof(INT), &cx, DO_NOT_SEEK);
2511 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2512 sizeof(INT), &cx, DO_NOT_SEEK);
2515 else
2517 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2518 ERR("didn't find array description data\n");
2523 /* imported type libs */
2524 if(tlbSegDir.pImpFiles.offset>0)
2526 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2527 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2528 UINT16 size;
2530 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2532 char *name;
2533 DWORD len;
2535 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2536 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2537 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2539 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2540 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2541 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2542 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2544 size >>= 2;
2545 name = TLB_Alloc(size+1);
2546 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2547 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2548 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2549 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2550 TLB_Free(name);
2552 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2553 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2555 ppImpLib = &(*ppImpLib)->next;
2559 /* type info's */
2560 if(tlbHeader.nrtypeinfos >= 0 )
2562 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2563 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2564 int i;
2566 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2568 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2570 ppTI = &((*ppTI)->next);
2571 (pTypeLibImpl->TypeInfoCount)++;
2575 TRACE("(%p)\n", pTypeLibImpl);
2576 return (ITypeLib2*) pTypeLibImpl;
2580 static BSTR TLB_MultiByteToBSTR(char *ptr)
2582 DWORD len;
2583 WCHAR *nameW;
2584 BSTR ret;
2586 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2587 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2588 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2589 ret = SysAllocString(nameW);
2590 HeapFree(GetProcessHeap(), 0, nameW);
2591 return ret;
2594 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2596 char b[3];
2597 int i;
2598 short s;
2600 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2601 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2602 return FALSE;
2605 guid->Data4[0] = s >> 8;
2606 guid->Data4[1] = s & 0xff;
2608 b[2] = '\0';
2609 for(i = 0; i < 6; i++) {
2610 memcpy(b, str + 24 + 2 * i, 2);
2611 guid->Data4[i + 2] = strtol(b, NULL, 16);
2613 return TRUE;
2616 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2618 WORD bytelen;
2619 DWORD len;
2620 WCHAR *nameW;
2622 *pBstr = NULL;
2623 bytelen = *(WORD*)ptr;
2624 if(bytelen == 0xffff) return 2;
2625 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2626 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2627 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2628 *pBstr = SysAllocStringLen(nameW, len);
2629 HeapFree(GetProcessHeap(), 0, nameW);
2630 return bytelen + 2;
2633 static WORD SLTG_ReadStringA(char *ptr, char **str)
2635 WORD bytelen;
2637 *str = NULL;
2638 bytelen = *(WORD*)ptr;
2639 if(bytelen == 0xffff) return 2;
2640 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2641 memcpy(*str, ptr + 2, bytelen);
2642 (*str)[bytelen] = '\0';
2643 return bytelen + 2;
2646 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2648 char *ptr = pLibBlk;
2649 WORD w;
2651 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2652 FIXME("libblk magic = %04x\n", w);
2653 return 0;
2656 ptr += 6;
2657 if((w = *(WORD*)ptr) != 0xffff) {
2658 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2659 ptr += w;
2661 ptr += 2;
2663 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2665 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2667 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2668 ptr += 4;
2670 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2671 ptr += 2;
2673 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2674 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2675 else
2676 pTypeLibImpl->LibAttr.lcid = 0;
2677 ptr += 2;
2679 ptr += 4; /* skip res12 */
2681 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2682 ptr += 2;
2684 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2685 ptr += 2;
2687 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2688 ptr += 2;
2690 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2691 ptr += sizeof(GUID);
2693 return ptr - (char*)pLibBlk;
2696 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2698 BOOL done = FALSE;
2700 while(!done) {
2701 if((*pType & 0xe00) == 0xe00) {
2702 pTD->vt = VT_PTR;
2703 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2704 sizeof(TYPEDESC));
2705 pTD = pTD->u.lptdesc;
2707 switch(*pType & 0x3f) {
2708 case VT_PTR:
2709 pTD->vt = VT_PTR;
2710 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2711 sizeof(TYPEDESC));
2712 pTD = pTD->u.lptdesc;
2713 break;
2715 case VT_USERDEFINED:
2716 pTD->vt = VT_USERDEFINED;
2717 pTD->u.hreftype = *(++pType) / 4;
2718 done = TRUE;
2719 break;
2721 case VT_CARRAY:
2723 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2724 array */
2726 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2728 pTD->vt = VT_CARRAY;
2729 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2730 sizeof(ARRAYDESC) +
2731 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2732 pTD->u.lpadesc->cDims = pSA->cDims;
2733 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2734 pSA->cDims * sizeof(SAFEARRAYBOUND));
2736 pTD = &pTD->u.lpadesc->tdescElem;
2737 break;
2740 case VT_SAFEARRAY:
2742 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2743 useful? */
2745 pType++;
2746 pTD->vt = VT_SAFEARRAY;
2747 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2748 sizeof(TYPEDESC));
2749 pTD = pTD->u.lptdesc;
2750 break;
2752 default:
2753 pTD->vt = *pType & 0x3f;
2754 done = TRUE;
2755 break;
2757 pType++;
2759 return pType;
2762 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2764 /* Handle [in/out] first */
2765 if((*pType & 0xc000) == 0xc000)
2766 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2767 else if(*pType & 0x8000)
2768 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2769 else if(*pType & 0x4000)
2770 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2771 else
2772 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2774 if(*pType & 0x2000)
2775 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2777 if(*pType & 0x80)
2778 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2780 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2784 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2785 char *pNameTable)
2787 int ref;
2788 char *name;
2789 TLBRefType **ppRefType;
2791 if(pRef->magic != SLTG_REF_MAGIC) {
2792 FIXME("Ref magic = %x\n", pRef->magic);
2793 return;
2795 name = ( (char*)(&pRef->names) + pRef->number);
2797 ppRefType = &pTI->reflist;
2798 for(ref = 0; ref < pRef->number >> 3; ref++) {
2799 char *refname;
2800 unsigned int lib_offs, type_num;
2802 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2803 sizeof(**ppRefType));
2805 name += SLTG_ReadStringA(name, &refname);
2806 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2807 FIXME("Can't sscanf ref\n");
2808 if(lib_offs != 0xffff) {
2809 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2811 while(*import) {
2812 if((*import)->offset == lib_offs)
2813 break;
2814 import = &(*import)->next;
2816 if(!*import) {
2817 char fname[MAX_PATH+1];
2818 int len;
2820 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2821 sizeof(**import));
2822 (*import)->offset = lib_offs;
2823 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2824 &(*import)->guid);
2825 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2826 &(*import)->wVersionMajor,
2827 &(*import)->wVersionMinor,
2828 &(*import)->lcid, fname) != 4) {
2829 FIXME("can't sscanf ref %s\n",
2830 pNameTable + lib_offs + 40);
2832 len = strlen(fname);
2833 if(fname[len-1] != '#')
2834 FIXME("fname = %s\n", fname);
2835 fname[len-1] = '\0';
2836 (*import)->name = TLB_MultiByteToBSTR(fname);
2838 (*ppRefType)->pImpTLInfo = *import;
2839 } else { /* internal ref */
2840 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2842 (*ppRefType)->reference = ref;
2843 (*ppRefType)->index = type_num;
2845 HeapFree(GetProcessHeap(), 0, refname);
2846 ppRefType = &(*ppRefType)->next;
2848 if((BYTE)*name != SLTG_REF_MAGIC)
2849 FIXME("End of ref block magic = %x\n", *name);
2850 dump_TLBRefType(pTI->reflist);
2853 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2854 BOOL OneOnly)
2856 SLTG_ImplInfo *info;
2857 TLBImplType **ppImplType = &pTI->impltypelist;
2858 /* I don't really get this structure, usually it's 0x16 bytes
2859 long, but iuser.tlb contains some that are 0x18 bytes long.
2860 That's ok because we can use the next ptr to jump to the next
2861 one. But how do we know the length of the last one? The WORD
2862 at offs 0x8 might be the clue. For now I'm just assuming that
2863 the last one is the regular 0x16 bytes. */
2865 info = (SLTG_ImplInfo*)pBlk;
2866 while(1) {
2867 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2868 sizeof(**ppImplType));
2869 (*ppImplType)->hRef = info->ref;
2870 (*ppImplType)->implflags = info->impltypeflags;
2871 pTI->TypeAttr.cImplTypes++;
2872 ppImplType = &(*ppImplType)->next;
2874 if(info->next == 0xffff)
2875 break;
2876 if(OneOnly)
2877 FIXME("Interface inheriting more than one interface\n");
2878 info = (SLTG_ImplInfo*)(pBlk + info->next);
2880 info++; /* see comment at top of function */
2881 return (char*)info;
2884 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2886 TLBVarDesc **ppVarDesc = &pTI->varlist;
2887 BSTR bstrPrevName = NULL;
2888 SLTG_Variable *pItem;
2889 unsigned short i;
2890 WORD *pType;
2891 char buf[300];
2893 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2894 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2896 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2897 sizeof(**ppVarDesc));
2898 (*ppVarDesc)->vardesc.memid = pItem->memid;
2900 if (pItem->magic != SLTG_VAR_MAGIC &&
2901 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2902 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2903 return;
2906 if (pItem->name == 0xfffe)
2907 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2908 else
2909 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2911 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2912 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2914 if (pItem->flags & 0x40) {
2915 TRACE_(typelib)("VAR_DISPATCH\n");
2916 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2918 else if (pItem->flags & 0x10) {
2919 TRACE_(typelib)("VAR_CONST\n");
2920 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2921 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2922 sizeof(VARIANT));
2923 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2924 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2925 *(INT*)(pBlk + pItem->byte_offs);
2927 else {
2928 TRACE_(typelib)("VAR_PERINSTANCE\n");
2929 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2930 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2933 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2934 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2936 if (pItem->flags & 0x80)
2937 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2939 if(pItem->flags & 0x02)
2940 pType = &pItem->type;
2941 else
2942 pType = (WORD*)(pBlk + pItem->type);
2944 if (pItem->flags & ~0xd2)
2945 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2947 SLTG_DoElem(pType, pBlk,
2948 &(*ppVarDesc)->vardesc.elemdescVar);
2950 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2952 bstrPrevName = (*ppVarDesc)->Name;
2953 ppVarDesc = &((*ppVarDesc)->next);
2955 pTI->TypeAttr.cVars = cVars;
2958 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2960 SLTG_Function *pFunc;
2961 unsigned short i;
2962 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2964 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2965 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2967 int param;
2968 WORD *pType, *pArg;
2970 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2971 sizeof(**ppFuncDesc));
2973 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2974 case SLTG_FUNCTION_MAGIC:
2975 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2976 break;
2977 case SLTG_DISPATCH_FUNCTION_MAGIC:
2978 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2979 break;
2980 case SLTG_STATIC_FUNCTION_MAGIC:
2981 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2982 break;
2983 default:
2984 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2985 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2986 *ppFuncDesc = NULL;
2987 return;
2989 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2991 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2992 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2993 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2994 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2995 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2996 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2998 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2999 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3001 if(pFunc->retnextopt & 0x80)
3002 pType = &pFunc->rettype;
3003 else
3004 pType = (WORD*)(pBlk + pFunc->rettype);
3006 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
3008 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3009 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3010 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3011 (*ppFuncDesc)->pParamDesc =
3012 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3013 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3015 pArg = (WORD*)(pBlk + pFunc->arg_off);
3017 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3018 char *paramName = pNameTable + *pArg;
3019 BOOL HaveOffs;
3020 /* If arg type follows then paramName points to the 2nd
3021 letter of the name, else the next WORD is an offset to
3022 the arg type and paramName points to the first letter.
3023 So let's take one char off paramName and see if we're
3024 pointing at an alpha-numeric char. However if *pArg is
3025 0xffff or 0xfffe then the param has no name, the former
3026 meaning that the next WORD is the type, the latter
3027 meaning the the next WORD is an offset to the type. */
3029 HaveOffs = FALSE;
3030 if(*pArg == 0xffff)
3031 paramName = NULL;
3032 else if(*pArg == 0xfffe) {
3033 paramName = NULL;
3034 HaveOffs = TRUE;
3036 else if(paramName[-1] && !isalnum(paramName[-1]))
3037 HaveOffs = TRUE;
3039 pArg++;
3041 if(HaveOffs) { /* the next word is an offset to type */
3042 pType = (WORD*)(pBlk + *pArg);
3043 SLTG_DoElem(pType, pBlk,
3044 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3045 pArg++;
3046 } else {
3047 if(paramName)
3048 paramName--;
3049 pArg = SLTG_DoElem(pArg, pBlk,
3050 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3053 /* Are we an optional param ? */
3054 if((*ppFuncDesc)->funcdesc.cParams - param <=
3055 (*ppFuncDesc)->funcdesc.cParamsOpt)
3056 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3058 if(paramName) {
3059 (*ppFuncDesc)->pParamDesc[param].Name =
3060 TLB_MultiByteToBSTR(paramName);
3064 ppFuncDesc = &((*ppFuncDesc)->next);
3065 if(pFunc->next == 0xffff) break;
3067 pTI->TypeAttr.cFuncs = cFuncs;
3070 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3071 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3072 SLTG_TypeInfoTail *pTITail)
3074 char *pFirstItem, *pNextItem;
3076 if(pTIHeader->href_table != 0xffffffff) {
3077 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3078 pNameTable);
3081 pFirstItem = pNextItem = pBlk;
3083 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3084 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3089 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3090 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3091 SLTG_TypeInfoTail *pTITail)
3093 char *pFirstItem, *pNextItem;
3095 if(pTIHeader->href_table != 0xffffffff) {
3096 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3097 pNameTable);
3100 pFirstItem = pNextItem = pBlk;
3102 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3103 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3106 if (pTITail->funcs_off != 0xffff)
3107 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3109 if (TRACE_ON(typelib))
3110 dump_TLBFuncDesc(pTI->funclist);
3113 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3114 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3115 SLTG_TypeInfoTail *pTITail)
3117 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3120 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3121 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3122 SLTG_TypeInfoTail *pTITail)
3124 WORD *pType;
3126 if (pTITail->simple_alias) {
3127 /* if simple alias, no more processing required */
3128 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3129 return;
3132 if(pTIHeader->href_table != 0xffffffff) {
3133 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3134 pNameTable);
3137 /* otherwise it is an offset to a type */
3138 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3140 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3143 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3144 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3145 SLTG_TypeInfoTail *pTITail)
3147 if (pTIHeader->href_table != 0xffffffff)
3148 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3149 pNameTable);
3151 if (pTITail->vars_off != 0xffff)
3152 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3154 if (pTITail->funcs_off != 0xffff)
3155 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3157 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3158 * of dispinterface functons including the IDispatch ones, so
3159 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3160 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3162 if (TRACE_ON(typelib))
3163 dump_TLBFuncDesc(pTI->funclist);
3166 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3167 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3168 SLTG_TypeInfoTail *pTITail)
3170 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3173 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3174 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3175 SLTG_TypeInfoTail *pTITail)
3177 if (pTIHeader->href_table != 0xffffffff)
3178 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3179 pNameTable);
3181 if (pTITail->vars_off != 0xffff)
3182 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3184 if (pTITail->funcs_off != 0xffff)
3185 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3188 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3189 managable copy of it into this */
3190 typedef struct {
3191 WORD small_no;
3192 char *index_name;
3193 char *other_name;
3194 WORD res1a;
3195 WORD name_offs;
3196 WORD more_bytes;
3197 char *extra;
3198 WORD res20;
3199 DWORD helpcontext;
3200 WORD res26;
3201 GUID uuid;
3202 } SLTG_InternalOtherTypeInfo;
3204 /****************************************************************************
3205 * ITypeLib2_Constructor_SLTG
3207 * loading a SLTG typelib from an in-memory image
3209 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3211 ITypeLibImpl *pTypeLibImpl;
3212 SLTG_Header *pHeader;
3213 SLTG_BlkEntry *pBlkEntry;
3214 SLTG_Magic *pMagic;
3215 SLTG_Index *pIndex;
3216 SLTG_Pad9 *pPad9;
3217 LPVOID pBlk, pFirstBlk;
3218 SLTG_LibBlk *pLibBlk;
3219 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3220 char *pAfterOTIBlks = NULL;
3221 char *pNameTable, *ptr;
3222 int i;
3223 DWORD len, order;
3224 ITypeInfoImpl **ppTypeInfoImpl;
3226 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3229 pTypeLibImpl = TypeLibImpl_Constructor();
3230 if (!pTypeLibImpl) return NULL;
3232 pHeader = pLib;
3234 TRACE_(typelib)("header:\n");
3235 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3236 pHeader->nrOfFileBlks );
3237 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3238 FIXME("Header type magic 0x%08x not supported.\n",
3239 pHeader->SLTG_magic);
3240 return NULL;
3243 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3244 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3246 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3247 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3249 /* Next we have a magic block */
3250 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3252 /* Let's see if we're still in sync */
3253 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3254 sizeof(SLTG_COMPOBJ_MAGIC))) {
3255 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3256 return NULL;
3258 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3259 sizeof(SLTG_DIR_MAGIC))) {
3260 FIXME("dir magic = %s\n", pMagic->dir_magic);
3261 return NULL;
3264 pIndex = (SLTG_Index*)(pMagic+1);
3266 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3268 pFirstBlk = (LPVOID)(pPad9 + 1);
3270 /* We'll set up a ptr to the main library block, which is the last one. */
3272 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3273 pBlkEntry[order].next != 0;
3274 order = pBlkEntry[order].next - 1, i++) {
3275 pBlk = (char*)pBlk + pBlkEntry[order].len;
3277 pLibBlk = pBlk;
3279 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3281 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3282 interspersed */
3284 len += 0x40;
3286 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3288 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3289 sizeof(*pOtherTypeInfoBlks) *
3290 pTypeLibImpl->TypeInfoCount);
3293 ptr = (char*)pLibBlk + len;
3295 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3296 WORD w, extra;
3297 len = 0;
3299 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3301 w = *(WORD*)(ptr + 2);
3302 if(w != 0xffff) {
3303 len += w;
3304 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3305 w+1);
3306 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3307 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3309 w = *(WORD*)(ptr + 4 + len);
3310 if(w != 0xffff) {
3311 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3312 len += w;
3313 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3314 w+1);
3315 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3316 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3318 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3319 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3320 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3321 if(extra) {
3322 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3323 extra);
3324 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3325 len += extra;
3327 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3328 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3329 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3330 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3331 len += sizeof(SLTG_OtherTypeInfo);
3332 ptr += len;
3335 pAfterOTIBlks = ptr;
3337 /* Skip this WORD and get the next DWORD */
3338 len = *(DWORD*)(pAfterOTIBlks + 2);
3340 /* Now add this to pLibBLk look at what we're pointing at and
3341 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3342 dust and we should be pointing at the beginning of the name
3343 table */
3345 pNameTable = (char*)pLibBlk + len;
3347 switch(*(WORD*)pNameTable) {
3348 case 0xffff:
3349 break;
3350 case 0x0200:
3351 pNameTable += 0x20;
3352 break;
3353 default:
3354 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3355 break;
3358 pNameTable += 0x216;
3360 pNameTable += 2;
3362 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3364 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3367 /* Hopefully we now have enough ptrs set up to actually read in
3368 some TypeInfos. It's not clear which order to do them in, so
3369 I'll just follow the links along the BlkEntry chain and read
3370 them in the order in which they are in the file */
3372 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3374 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3375 pBlkEntry[order].next != 0;
3376 order = pBlkEntry[order].next - 1, i++) {
3378 SLTG_TypeInfoHeader *pTIHeader;
3379 SLTG_TypeInfoTail *pTITail;
3380 SLTG_MemberHeader *pMemHeader;
3382 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3383 pOtherTypeInfoBlks[i].index_name)) {
3384 FIXME("Index strings don't match\n");
3385 return NULL;
3388 pTIHeader = pBlk;
3389 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3390 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3391 return NULL;
3393 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3394 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3396 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3397 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3398 (*ppTypeInfoImpl)->index = i;
3399 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3400 pOtherTypeInfoBlks[i].name_offs +
3401 pNameTable);
3402 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3403 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3404 sizeof(GUID));
3405 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3406 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3407 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3408 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3409 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3411 if((pTIHeader->typeflags1 & 7) != 2)
3412 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3413 if(pTIHeader->typeflags3 != 2)
3414 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3416 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3417 debugstr_w((*ppTypeInfoImpl)->Name),
3418 typekind_desc[pTIHeader->typekind],
3419 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3420 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3422 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3424 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3426 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3427 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3428 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3430 switch(pTIHeader->typekind) {
3431 case TKIND_ENUM:
3432 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3433 pTIHeader, pTITail);
3434 break;
3436 case TKIND_RECORD:
3437 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3438 pTIHeader, pTITail);
3439 break;
3441 case TKIND_INTERFACE:
3442 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3443 pTIHeader, pTITail);
3444 break;
3446 case TKIND_COCLASS:
3447 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3448 pTIHeader, pTITail);
3449 break;
3451 case TKIND_ALIAS:
3452 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3453 pTIHeader, pTITail);
3454 break;
3456 case TKIND_DISPATCH:
3457 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3458 pTIHeader, pTITail);
3459 break;
3461 case TKIND_MODULE:
3462 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3463 pTIHeader, pTITail);
3464 break;
3466 default:
3467 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3468 break;
3472 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3473 but we've already set those */
3474 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3475 X(06);
3476 X(16);
3477 X(18);
3478 X(1a);
3479 X(1e);
3480 X(24);
3481 X(26);
3482 X(2a);
3483 X(2c);
3484 X(2e);
3485 X(30);
3486 X(32);
3487 X(34);
3489 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3490 pBlk = (char*)pBlk + pBlkEntry[order].len;
3493 if(i != pTypeLibImpl->TypeInfoCount) {
3494 FIXME("Somehow processed %d TypeInfos\n", i);
3495 return NULL;
3498 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3499 return (ITypeLib2*)pTypeLibImpl;
3502 /* ITypeLib::QueryInterface
3504 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3505 ITypeLib2 * iface,
3506 REFIID riid,
3507 VOID **ppvObject)
3509 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3511 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3513 *ppvObject=NULL;
3514 if(IsEqualIID(riid, &IID_IUnknown) ||
3515 IsEqualIID(riid,&IID_ITypeLib)||
3516 IsEqualIID(riid,&IID_ITypeLib2))
3518 *ppvObject = This;
3521 if(*ppvObject)
3523 ITypeLib2_AddRef(iface);
3524 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3525 return S_OK;
3527 TRACE("-- Interface: E_NOINTERFACE\n");
3528 return E_NOINTERFACE;
3531 /* ITypeLib::AddRef
3533 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3535 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3536 ULONG ref = InterlockedIncrement(&This->ref);
3538 TRACE("(%p)->ref was %u\n",This, ref - 1);
3540 return ref;
3543 /* ITypeLib::Release
3545 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3548 ULONG ref = InterlockedDecrement(&This->ref);
3550 TRACE("(%p)->(%u)\n",This, ref);
3552 if (!ref)
3554 TLBImpLib *pImpLib, *pImpLibNext;
3555 TLBCustData *pCustData, *pCustDataNext;
3556 int i;
3558 /* remove cache entry */
3559 if(This->path)
3561 TRACE("removing from cache list\n");
3562 EnterCriticalSection(&cache_section);
3563 if (This->next) This->next->prev = This->prev;
3564 if (This->prev) This->prev->next = This->next;
3565 else tlb_cache_first = This->next;
3566 LeaveCriticalSection(&cache_section);
3567 HeapFree(GetProcessHeap(), 0, This->path);
3569 TRACE(" destroying ITypeLib(%p)\n",This);
3571 if (This->Name)
3573 SysFreeString(This->Name);
3574 This->Name = NULL;
3577 if (This->DocString)
3579 SysFreeString(This->DocString);
3580 This->DocString = NULL;
3583 if (This->HelpFile)
3585 SysFreeString(This->HelpFile);
3586 This->HelpFile = NULL;
3589 if (This->HelpStringDll)
3591 SysFreeString(This->HelpStringDll);
3592 This->HelpStringDll = NULL;
3595 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3597 VariantClear(&pCustData->data);
3599 pCustDataNext = pCustData->next;
3600 TLB_Free(pCustData);
3603 for (i = 0; i < This->ctTypeDesc; i++)
3604 if (This->pTypeDesc[i].vt == VT_CARRAY)
3605 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3607 TLB_Free(This->pTypeDesc);
3609 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3611 if (pImpLib->pImpTypeLib)
3612 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3613 TLB_Free(pImpLib->name);
3615 pImpLibNext = pImpLib->next;
3616 TLB_Free(pImpLib);
3619 if (This->pTypeInfo) /* can be NULL */
3620 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3621 HeapFree(GetProcessHeap(),0,This);
3622 return 0;
3625 return ref;
3628 /* ITypeLib::GetTypeInfoCount
3630 * Returns the number of type descriptions in the type library
3632 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3634 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3635 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3636 return This->TypeInfoCount;
3639 /* ITypeLib::GetTypeInfo
3641 * retrieves the specified type description in the library.
3643 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3644 ITypeLib2 *iface,
3645 UINT index,
3646 ITypeInfo **ppTInfo)
3648 int i;
3650 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3651 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3653 TRACE("(%p)->(index=%d)\n", This, index);
3655 if (!ppTInfo) return E_INVALIDARG;
3657 /* search element n in list */
3658 for(i=0; i < index; i++)
3660 pTypeInfo = pTypeInfo->next;
3661 if (!pTypeInfo)
3663 TRACE("-- element not found\n");
3664 return TYPE_E_ELEMENTNOTFOUND;
3668 *ppTInfo = (ITypeInfo *) pTypeInfo;
3670 ITypeInfo_AddRef(*ppTInfo);
3671 TRACE("-- found (%p)\n",*ppTInfo);
3672 return S_OK;
3676 /* ITypeLibs::GetTypeInfoType
3678 * Retrieves the type of a type description.
3680 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3681 ITypeLib2 *iface,
3682 UINT index,
3683 TYPEKIND *pTKind)
3685 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3686 int i;
3687 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3689 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3690 return TYPE_E_ELEMENTNOTFOUND;
3692 TRACE("(%p) index %d\n", This, index);
3694 if(!pTKind) return E_INVALIDARG;
3696 /* search element n in list */
3697 for(i=0; i < index; i++)
3699 if(!pTInfo)
3701 TRACE("-- element not found\n");
3702 return TYPE_E_ELEMENTNOTFOUND;
3704 pTInfo = pTInfo->next;
3707 *pTKind = pTInfo->TypeAttr.typekind;
3708 TRACE("-- found Type (%d)\n", *pTKind);
3709 return S_OK;
3712 /* ITypeLib::GetTypeInfoOfGuid
3714 * Retrieves the type description that corresponds to the specified GUID.
3717 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3718 ITypeLib2 *iface,
3719 REFGUID guid,
3720 ITypeInfo **ppTInfo)
3722 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3723 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3725 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3727 if (!pTypeInfo)
3729 WARN("-- element not found\n");
3730 return TYPE_E_ELEMENTNOTFOUND;
3733 /* search linked list for guid */
3734 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3736 pTypeInfo = pTypeInfo->next;
3738 if (!pTypeInfo)
3740 /* end of list reached */
3741 WARN("-- element not found\n");
3742 return TYPE_E_ELEMENTNOTFOUND;
3746 TRACE("-- found (%p, %s)\n",
3747 pTypeInfo,
3748 debugstr_w(pTypeInfo->Name));
3750 *ppTInfo = (ITypeInfo*)pTypeInfo;
3751 ITypeInfo_AddRef(*ppTInfo);
3752 return S_OK;
3755 /* ITypeLib::GetLibAttr
3757 * Retrieves the structure that contains the library's attributes.
3760 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3761 ITypeLib2 *iface,
3762 LPTLIBATTR *ppTLibAttr)
3764 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3765 TRACE("(%p)\n",This);
3766 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3767 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3768 return S_OK;
3771 /* ITypeLib::GetTypeComp
3773 * Enables a client compiler to bind to a library's types, variables,
3774 * constants, and global functions.
3777 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3778 ITypeLib2 *iface,
3779 ITypeComp **ppTComp)
3781 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3783 TRACE("(%p)->(%p)\n",This,ppTComp);
3784 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3785 ITypeComp_AddRef(*ppTComp);
3787 return S_OK;
3790 /* ITypeLib::GetDocumentation
3792 * Retrieves the library's documentation string, the complete Help file name
3793 * and path, and the context identifier for the library Help topic in the Help
3794 * file.
3796 * On a successful return all non-null BSTR pointers will have been set,
3797 * possibly to NULL.
3799 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3800 ITypeLib2 *iface,
3801 INT index,
3802 BSTR *pBstrName,
3803 BSTR *pBstrDocString,
3804 DWORD *pdwHelpContext,
3805 BSTR *pBstrHelpFile)
3807 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3809 HRESULT result = E_INVALIDARG;
3811 ITypeInfo *pTInfo;
3814 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3815 This, index,
3816 pBstrName, pBstrDocString,
3817 pdwHelpContext, pBstrHelpFile);
3819 if(index<0)
3821 /* documentation for the typelib */
3822 if(pBstrName)
3824 if (This->Name)
3826 if(!(*pBstrName = SysAllocString(This->Name)))
3827 goto memerr1;
3829 else
3830 *pBstrName = NULL;
3832 if(pBstrDocString)
3834 if (This->DocString)
3836 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3837 goto memerr2;
3839 else if (This->Name)
3841 if(!(*pBstrDocString = SysAllocString(This->Name)))
3842 goto memerr2;
3844 else
3845 *pBstrDocString = NULL;
3847 if(pdwHelpContext)
3849 *pdwHelpContext = This->dwHelpContext;
3851 if(pBstrHelpFile)
3853 if (This->HelpFile)
3855 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3856 goto memerr3;
3858 else
3859 *pBstrHelpFile = NULL;
3862 result = S_OK;
3864 else
3866 /* for a typeinfo */
3867 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3869 if(SUCCEEDED(result))
3871 result = ITypeInfo_GetDocumentation(pTInfo,
3872 MEMBERID_NIL,
3873 pBstrName,
3874 pBstrDocString,
3875 pdwHelpContext, pBstrHelpFile);
3877 ITypeInfo_Release(pTInfo);
3880 return result;
3881 memerr3:
3882 if (pBstrDocString) SysFreeString (*pBstrDocString);
3883 memerr2:
3884 if (pBstrName) SysFreeString (*pBstrName);
3885 memerr1:
3886 return STG_E_INSUFFICIENTMEMORY;
3889 /* ITypeLib::IsName
3891 * Indicates whether a passed-in string contains the name of a type or member
3892 * described in the library.
3895 static HRESULT WINAPI ITypeLib2_fnIsName(
3896 ITypeLib2 *iface,
3897 LPOLESTR szNameBuf,
3898 ULONG lHashVal,
3899 BOOL *pfName)
3901 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3902 ITypeInfoImpl *pTInfo;
3903 TLBFuncDesc *pFInfo;
3904 TLBVarDesc *pVInfo;
3905 int i;
3906 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3908 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3909 pfName);
3911 *pfName=TRUE;
3912 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3913 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3914 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3915 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3916 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3917 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3918 goto ITypeLib2_fnIsName_exit;
3920 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3921 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3924 *pfName=FALSE;
3926 ITypeLib2_fnIsName_exit:
3927 TRACE("(%p)slow! search for %s: %s found!\n", This,
3928 debugstr_w(szNameBuf), *pfName?"NOT":"");
3930 return S_OK;
3933 /* ITypeLib::FindName
3935 * Finds occurrences of a type description in a type library. This may be used
3936 * to quickly verify that a name exists in a type library.
3939 static HRESULT WINAPI ITypeLib2_fnFindName(
3940 ITypeLib2 *iface,
3941 LPOLESTR szNameBuf,
3942 ULONG lHashVal,
3943 ITypeInfo **ppTInfo,
3944 MEMBERID *rgMemId,
3945 UINT16 *pcFound)
3947 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3948 ITypeInfoImpl *pTInfo;
3949 TLBFuncDesc *pFInfo;
3950 TLBVarDesc *pVInfo;
3951 int i,j = 0;
3952 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3954 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3955 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3956 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3957 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3958 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3959 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3960 goto ITypeLib2_fnFindName_exit;
3963 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3964 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3965 continue;
3966 ITypeLib2_fnFindName_exit:
3967 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3968 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3969 j++;
3971 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3972 This, *pcFound, debugstr_w(szNameBuf), j);
3974 *pcFound=j;
3976 return S_OK;
3979 /* ITypeLib::ReleaseTLibAttr
3981 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3984 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3985 ITypeLib2 *iface,
3986 TLIBATTR *pTLibAttr)
3988 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3989 TRACE("freeing (%p)\n",This);
3990 HeapFree(GetProcessHeap(),0,pTLibAttr);
3994 /* ITypeLib2::GetCustData
3996 * gets the custom data
3998 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3999 ITypeLib2 * iface,
4000 REFGUID guid,
4001 VARIANT *pVarVal)
4003 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4004 TLBCustData *pCData;
4006 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4008 if( IsEqualIID(guid, &pCData->guid)) break;
4011 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4013 if(pCData)
4015 VariantInit( pVarVal);
4016 VariantCopy( pVarVal, &pCData->data);
4017 return S_OK;
4019 return E_INVALIDARG; /* FIXME: correct? */
4022 /* ITypeLib2::GetLibStatistics
4024 * Returns statistics about a type library that are required for efficient
4025 * sizing of hash tables.
4028 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4029 ITypeLib2 * iface,
4030 ULONG *pcUniqueNames,
4031 ULONG *pcchUniqueNames)
4033 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4035 FIXME("(%p): stub!\n", This);
4037 if(pcUniqueNames) *pcUniqueNames=1;
4038 if(pcchUniqueNames) *pcchUniqueNames=1;
4039 return S_OK;
4042 /* ITypeLib2::GetDocumentation2
4044 * Retrieves the library's documentation string, the complete Help file name
4045 * and path, the localization context to use, and the context ID for the
4046 * library Help topic in the Help file.
4049 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4050 ITypeLib2 * iface,
4051 INT index,
4052 LCID lcid,
4053 BSTR *pbstrHelpString,
4054 DWORD *pdwHelpStringContext,
4055 BSTR *pbstrHelpStringDll)
4057 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4058 HRESULT result;
4059 ITypeInfo *pTInfo;
4061 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4063 /* the help string should be obtained from the helpstringdll,
4064 * using the _DLLGetDocumentation function, based on the supplied
4065 * lcid. Nice to do sometime...
4067 if(index<0)
4069 /* documentation for the typelib */
4070 if(pbstrHelpString)
4071 *pbstrHelpString=SysAllocString(This->DocString);
4072 if(pdwHelpStringContext)
4073 *pdwHelpStringContext=This->dwHelpContext;
4074 if(pbstrHelpStringDll)
4075 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4077 result = S_OK;
4079 else
4081 /* for a typeinfo */
4082 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4084 if(SUCCEEDED(result))
4086 ITypeInfo2 * pTInfo2;
4087 result = ITypeInfo_QueryInterface(pTInfo,
4088 &IID_ITypeInfo2,
4089 (LPVOID*) &pTInfo2);
4091 if(SUCCEEDED(result))
4093 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4094 MEMBERID_NIL,
4095 lcid,
4096 pbstrHelpString,
4097 pdwHelpStringContext,
4098 pbstrHelpStringDll);
4100 ITypeInfo2_Release(pTInfo2);
4103 ITypeInfo_Release(pTInfo);
4106 return result;
4109 /* ITypeLib2::GetAllCustData
4111 * Gets all custom data items for the library.
4114 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4115 ITypeLib2 * iface,
4116 CUSTDATA *pCustData)
4118 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4119 TLBCustData *pCData;
4120 int i;
4121 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4122 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4123 if(pCustData->prgCustData ){
4124 pCustData->cCustData=This->ctCustData;
4125 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4126 pCustData->prgCustData[i].guid=pCData->guid;
4127 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4129 }else{
4130 ERR(" OUT OF MEMORY!\n");
4131 return E_OUTOFMEMORY;
4133 return S_OK;
4136 static const ITypeLib2Vtbl tlbvt = {
4137 ITypeLib2_fnQueryInterface,
4138 ITypeLib2_fnAddRef,
4139 ITypeLib2_fnRelease,
4140 ITypeLib2_fnGetTypeInfoCount,
4141 ITypeLib2_fnGetTypeInfo,
4142 ITypeLib2_fnGetTypeInfoType,
4143 ITypeLib2_fnGetTypeInfoOfGuid,
4144 ITypeLib2_fnGetLibAttr,
4145 ITypeLib2_fnGetTypeComp,
4146 ITypeLib2_fnGetDocumentation,
4147 ITypeLib2_fnIsName,
4148 ITypeLib2_fnFindName,
4149 ITypeLib2_fnReleaseTLibAttr,
4151 ITypeLib2_fnGetCustData,
4152 ITypeLib2_fnGetLibStatistics,
4153 ITypeLib2_fnGetDocumentation2,
4154 ITypeLib2_fnGetAllCustData
4158 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4160 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4162 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4165 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4167 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4169 return ITypeLib2_AddRef((ITypeLib2 *)This);
4172 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4174 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4176 return ITypeLib2_Release((ITypeLib2 *)This);
4179 static HRESULT WINAPI ITypeLibComp_fnBind(
4180 ITypeComp * iface,
4181 OLECHAR * szName,
4182 ULONG lHash,
4183 WORD wFlags,
4184 ITypeInfo ** ppTInfo,
4185 DESCKIND * pDescKind,
4186 BINDPTR * pBindPtr)
4188 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4189 ITypeInfoImpl *pTypeInfo;
4191 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4193 *pDescKind = DESCKIND_NONE;
4194 pBindPtr->lptcomp = NULL;
4195 *ppTInfo = NULL;
4197 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4199 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4201 /* FIXME: check wFlags here? */
4202 /* FIXME: we should use a hash table to look this info up using lHash
4203 * instead of an O(n) search */
4204 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4205 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4207 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4209 *pDescKind = DESCKIND_TYPECOMP;
4210 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4211 ITypeComp_AddRef(pBindPtr->lptcomp);
4212 TRACE("module or enum: %s\n", debugstr_w(szName));
4213 return S_OK;
4217 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4218 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4220 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4221 HRESULT hr;
4223 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4224 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4226 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4227 return S_OK;
4231 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4232 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4234 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4235 HRESULT hr;
4236 ITypeInfo *subtypeinfo;
4237 BINDPTR subbindptr;
4238 DESCKIND subdesckind;
4240 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4241 &subtypeinfo, &subdesckind, &subbindptr);
4242 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4244 TYPEDESC tdesc_appobject =
4247 (TYPEDESC *)pTypeInfo->hreftype
4249 VT_USERDEFINED
4251 const VARDESC vardesc_appobject =
4253 -2, /* memid */
4254 NULL, /* lpstrSchema */
4256 0 /* oInst */
4259 /* ELEMDESC */
4261 /* TYPEDESC */
4263 &tdesc_appobject
4265 VT_PTR
4268 0, /* wVarFlags */
4269 VAR_STATIC /* varkind */
4272 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4274 /* cleanup things filled in by Bind call so we can put our
4275 * application object data in there instead */
4276 switch (subdesckind)
4278 case DESCKIND_FUNCDESC:
4279 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4280 break;
4281 case DESCKIND_VARDESC:
4282 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4283 break;
4284 default:
4285 break;
4287 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4289 if (pTypeInfo->hreftype == -1)
4290 FIXME("no hreftype for interface %p\n", pTypeInfo);
4292 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4293 if (FAILED(hr))
4294 return hr;
4296 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4297 *ppTInfo = (ITypeInfo *)pTypeInfo;
4298 ITypeInfo_AddRef(*ppTInfo);
4299 return S_OK;
4304 TRACE("name not found %s\n", debugstr_w(szName));
4305 return S_OK;
4308 static HRESULT WINAPI ITypeLibComp_fnBindType(
4309 ITypeComp * iface,
4310 OLECHAR * szName,
4311 ULONG lHash,
4312 ITypeInfo ** ppTInfo,
4313 ITypeComp ** ppTComp)
4315 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4316 return E_NOTIMPL;
4319 static const ITypeCompVtbl tlbtcvt =
4322 ITypeLibComp_fnQueryInterface,
4323 ITypeLibComp_fnAddRef,
4324 ITypeLibComp_fnRelease,
4326 ITypeLibComp_fnBind,
4327 ITypeLibComp_fnBindType
4330 /*================== ITypeInfo(2) Methods ===================================*/
4331 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4333 ITypeInfoImpl * pTypeInfoImpl;
4335 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4336 if (pTypeInfoImpl)
4338 pTypeInfoImpl->lpVtbl = &tinfvt;
4339 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4340 pTypeInfoImpl->ref=1;
4341 pTypeInfoImpl->hreftype = -1;
4342 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4343 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4345 TRACE("(%p)\n", pTypeInfoImpl);
4346 return (ITypeInfo2*) pTypeInfoImpl;
4349 /* ITypeInfo::QueryInterface
4351 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4352 ITypeInfo2 *iface,
4353 REFIID riid,
4354 VOID **ppvObject)
4356 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4358 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4360 *ppvObject=NULL;
4361 if(IsEqualIID(riid, &IID_IUnknown) ||
4362 IsEqualIID(riid,&IID_ITypeInfo)||
4363 IsEqualIID(riid,&IID_ITypeInfo2))
4364 *ppvObject = This;
4366 if(*ppvObject){
4367 ITypeInfo_AddRef(iface);
4368 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4369 return S_OK;
4371 TRACE("-- Interface: E_NOINTERFACE\n");
4372 return E_NOINTERFACE;
4375 /* ITypeInfo::AddRef
4377 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4379 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4380 ULONG ref = InterlockedIncrement(&This->ref);
4382 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4384 TRACE("(%p)->ref is %u\n",This, ref);
4385 return ref;
4388 /* ITypeInfo::Release
4390 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4392 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4393 ULONG ref = InterlockedDecrement(&This->ref);
4395 TRACE("(%p)->(%u)\n",This, ref);
4397 if (ref) {
4398 /* We don't release ITypeLib when ref=0 because
4399 it means that function is called by ITypeLib2_Release */
4400 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4401 } else {
4402 TLBFuncDesc *pFInfo, *pFInfoNext;
4403 TLBVarDesc *pVInfo, *pVInfoNext;
4404 TLBImplType *pImpl, *pImplNext;
4405 TLBRefType *pRefType,*pRefTypeNext;
4406 TLBCustData *pCustData, *pCustDataNext;
4408 TRACE("destroying ITypeInfo(%p)\n",This);
4410 if (This->no_free_data)
4411 goto finish_free;
4413 if (This->Name)
4415 SysFreeString(This->Name);
4416 This->Name = 0;
4419 if (This->DocString)
4421 SysFreeString(This->DocString);
4422 This->DocString = 0;
4425 if (This->DllName)
4427 SysFreeString(This->DllName);
4428 This->DllName = 0;
4431 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4433 UINT i;
4434 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4436 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4437 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4439 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4440 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4442 SysFreeString(pFInfo->pParamDesc[i].Name);
4444 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4445 TLB_Free(pFInfo->pParamDesc);
4446 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4448 VariantClear(&pCustData->data);
4450 pCustDataNext = pCustData->next;
4451 TLB_Free(pCustData);
4453 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4454 SysFreeString(pFInfo->Entry);
4455 SysFreeString(pFInfo->HelpString);
4456 SysFreeString(pFInfo->Name);
4458 pFInfoNext = pFInfo->next;
4459 TLB_Free(pFInfo);
4461 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4463 if (pVInfo->vardesc.varkind == VAR_CONST)
4465 VariantClear(pVInfo->vardesc.u.lpvarValue);
4466 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4468 SysFreeString(pVInfo->Name);
4469 pVInfoNext = pVInfo->next;
4470 TLB_Free(pVInfo);
4472 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4474 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4476 VariantClear(&pCustData->data);
4478 pCustDataNext = pCustData->next;
4479 TLB_Free(pCustData);
4481 pImplNext = pImpl->next;
4482 TLB_Free(pImpl);
4484 for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext)
4486 pRefTypeNext = pRefType->next;
4487 TLB_Free(pRefType);
4489 TLB_Free(This->pCustData);
4491 finish_free:
4492 if (This->next)
4494 ITypeInfo_Release((ITypeInfo*)This->next);
4497 HeapFree(GetProcessHeap(),0,This);
4498 return 0;
4500 return ref;
4503 /* ITypeInfo::GetTypeAttr
4505 * Retrieves a TYPEATTR structure that contains the attributes of the type
4506 * description.
4509 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4510 LPTYPEATTR *ppTypeAttr)
4512 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4513 SIZE_T size;
4515 TRACE("(%p)\n",This);
4517 size = sizeof(**ppTypeAttr);
4518 if (This->TypeAttr.typekind == TKIND_ALIAS)
4519 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4521 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4522 if (!*ppTypeAttr)
4523 return E_OUTOFMEMORY;
4525 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4527 if (This->TypeAttr.typekind == TKIND_ALIAS)
4528 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4529 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4531 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4532 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4533 funcs */
4534 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4535 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4537 return S_OK;
4540 /* ITypeInfo::GetTypeComp
4542 * Retrieves the ITypeComp interface for the type description, which enables a
4543 * client compiler to bind to the type description's members.
4546 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4547 ITypeComp * *ppTComp)
4549 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4551 TRACE("(%p)->(%p)\n", This, ppTComp);
4553 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4554 ITypeComp_AddRef(*ppTComp);
4555 return S_OK;
4558 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4560 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4561 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4562 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4563 return size;
4566 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4568 memcpy(dest, src, sizeof(ELEMDESC));
4569 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4570 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4572 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4573 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4574 *buffer += sizeof(PARAMDESCEX);
4575 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4576 VariantInit(&pparamdescex_dest->varDefaultValue);
4577 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4578 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4580 else
4581 dest->u.paramdesc.pparamdescex = NULL;
4582 return S_OK;
4585 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4587 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4588 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4591 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4593 FUNCDESC *dest;
4594 char *buffer;
4595 SIZE_T size = sizeof(*src);
4596 SHORT i;
4597 HRESULT hr;
4599 size += sizeof(*src->lprgscode) * src->cScodes;
4600 size += TLB_SizeElemDesc(&src->elemdescFunc);
4601 for (i = 0; i < src->cParams; i++)
4603 size += sizeof(ELEMDESC);
4604 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4607 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4608 if (!dest) return E_OUTOFMEMORY;
4610 memcpy(dest, src, sizeof(FUNCDESC));
4611 buffer = (char *)(dest + 1);
4613 dest->lprgscode = (SCODE *)buffer;
4614 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4615 buffer += sizeof(*src->lprgscode) * src->cScodes;
4617 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4618 if (FAILED(hr))
4620 SysFreeString((BSTR)dest);
4621 return hr;
4624 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4625 buffer += sizeof(ELEMDESC) * src->cParams;
4626 for (i = 0; i < src->cParams; i++)
4628 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4629 if (FAILED(hr))
4630 break;
4632 if (FAILED(hr))
4634 /* undo the above actions */
4635 for (i = i - 1; i >= 0; i--)
4636 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4637 TLB_FreeElemDesc(&dest->elemdescFunc);
4638 SysFreeString((BSTR)dest);
4639 return hr;
4642 /* special treatment for dispinterfaces: this makes functions appear
4643 * to return their [retval] value when it is really returning an
4644 * HRESULT */
4645 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4647 if (dest->cParams &&
4648 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4650 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4651 if (elemdesc->tdesc.vt != VT_PTR)
4653 ERR("elemdesc should have started with VT_PTR instead of:\n");
4654 if (ERR_ON(ole))
4655 dump_ELEMDESC(elemdesc);
4656 return E_UNEXPECTED;
4659 /* copy last parameter to the return value. we are using a flat
4660 * buffer so there is no danger of leaking memory in
4661 * elemdescFunc */
4662 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4664 /* remove the last parameter */
4665 dest->cParams--;
4667 else
4668 /* otherwise this function is made to appear to have no return
4669 * value */
4670 dest->elemdescFunc.tdesc.vt = VT_VOID;
4674 *dest_ptr = dest;
4675 return S_OK;
4678 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4680 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4681 const TLBFuncDesc *pFDesc;
4682 int i;
4684 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4687 if (pFDesc)
4689 *ppFuncDesc = &pFDesc->funcdesc;
4690 return S_OK;
4693 return E_INVALIDARG;
4696 /* internal function to make the inherited interfaces' methods appear
4697 * part of the interface */
4698 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4699 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4701 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4702 HRESULT hr;
4703 UINT i;
4704 UINT implemented_funcs = 0;
4706 if (funcs)
4707 *funcs = 0;
4709 for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4711 HREFTYPE href;
4712 ITypeInfo *pSubTypeInfo;
4713 UINT sub_funcs;
4715 hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4716 if (FAILED(hr))
4717 return hr;
4718 hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4719 if (FAILED(hr))
4720 return hr;
4722 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4723 index,
4724 ppFuncDesc,
4725 &sub_funcs);
4726 implemented_funcs += sub_funcs;
4727 ITypeInfo_Release(pSubTypeInfo);
4728 if (SUCCEEDED(hr))
4729 return hr;
4732 if (funcs)
4733 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4735 if (index < implemented_funcs)
4736 return E_INVALIDARG;
4737 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4738 ppFuncDesc);
4741 /* ITypeInfo::GetFuncDesc
4743 * Retrieves the FUNCDESC structure that contains information about a
4744 * specified function.
4747 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4748 LPFUNCDESC *ppFuncDesc)
4750 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4751 const FUNCDESC *internal_funcdesc;
4752 HRESULT hr;
4754 TRACE("(%p) index %d\n", This, index);
4756 if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4757 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4758 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4759 &internal_funcdesc, NULL);
4760 else
4761 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4762 &internal_funcdesc);
4763 if (FAILED(hr))
4765 WARN("description for function %d not found\n", index);
4766 return hr;
4769 return TLB_AllocAndInitFuncDesc(
4770 internal_funcdesc,
4771 ppFuncDesc,
4772 This->TypeAttr.typekind == TKIND_DISPATCH);
4775 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4777 VARDESC *dest;
4778 char *buffer;
4779 SIZE_T size = sizeof(*src);
4780 HRESULT hr;
4782 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4783 if (src->varkind == VAR_CONST)
4784 size += sizeof(VARIANT);
4785 size += TLB_SizeElemDesc(&src->elemdescVar);
4787 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4788 if (!dest) return E_OUTOFMEMORY;
4790 *dest = *src;
4791 buffer = (char *)(dest + 1);
4792 if (src->lpstrSchema)
4794 int len;
4795 dest->lpstrSchema = (LPOLESTR)buffer;
4796 len = strlenW(src->lpstrSchema);
4797 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4798 buffer += (len + 1) * sizeof(WCHAR);
4801 if (src->varkind == VAR_CONST)
4803 HRESULT hr;
4805 dest->u.lpvarValue = (VARIANT *)buffer;
4806 *dest->u.lpvarValue = *src->u.lpvarValue;
4807 buffer += sizeof(VARIANT);
4808 VariantInit(dest->u.lpvarValue);
4809 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4810 if (FAILED(hr))
4812 SysFreeString((BSTR)dest_ptr);
4813 return hr;
4816 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4817 if (FAILED(hr))
4819 if (src->varkind == VAR_CONST)
4820 VariantClear(dest->u.lpvarValue);
4821 SysFreeString((BSTR)dest);
4822 return hr;
4824 *dest_ptr = dest;
4825 return S_OK;
4828 /* ITypeInfo::GetVarDesc
4830 * Retrieves a VARDESC structure that describes the specified variable.
4833 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4834 LPVARDESC *ppVarDesc)
4836 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4837 int i;
4838 const TLBVarDesc *pVDesc;
4840 TRACE("(%p) index %d\n", This, index);
4842 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4845 if (pVDesc)
4846 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4848 return E_INVALIDARG;
4851 /* ITypeInfo_GetNames
4853 * Retrieves the variable with the specified member ID (or the name of the
4854 * property or method and its parameters) that correspond to the specified
4855 * function ID.
4857 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4858 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4860 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4861 const TLBFuncDesc *pFDesc;
4862 const TLBVarDesc *pVDesc;
4863 int i;
4864 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4865 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4866 if(pFDesc)
4868 /* function found, now return function and parameter names */
4869 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4871 if(!i)
4872 *rgBstrNames=SysAllocString(pFDesc->Name);
4873 else
4874 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4876 *pcNames=i;
4878 else
4880 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4881 if(pVDesc)
4883 *rgBstrNames=SysAllocString(pVDesc->Name);
4884 *pcNames=1;
4886 else
4888 if(This->TypeAttr.cImplTypes &&
4889 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4890 /* recursive search */
4891 ITypeInfo *pTInfo;
4892 HRESULT result;
4893 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4894 &pTInfo);
4895 if(SUCCEEDED(result))
4897 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4898 ITypeInfo_Release(pTInfo);
4899 return result;
4901 WARN("Could not search inherited interface!\n");
4903 else
4905 WARN("no names found\n");
4907 *pcNames=0;
4908 return TYPE_E_ELEMENTNOTFOUND;
4911 return S_OK;
4915 /* ITypeInfo::GetRefTypeOfImplType
4917 * If a type description describes a COM class, it retrieves the type
4918 * description of the implemented interface types. For an interface,
4919 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4920 * if any exist.
4923 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4924 ITypeInfo2 *iface,
4925 UINT index,
4926 HREFTYPE *pRefType)
4928 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4929 int i;
4930 HRESULT hr = S_OK;
4931 const TLBImplType *pImpl = This->impltypelist;
4933 TRACE("(%p) index %d\n", This, index);
4934 if (TRACE_ON(ole)) dump_TypeInfo(This);
4936 if(index==(UINT)-1)
4938 /* only valid on dual interfaces;
4939 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4941 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4943 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4944 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4946 *pRefType = -1;
4948 else
4950 hr = TYPE_E_ELEMENTNOTFOUND;
4953 else
4955 /* get element n from linked list */
4956 for(i=0; pImpl && i<index; i++)
4958 pImpl = pImpl->next;
4961 if (pImpl)
4962 *pRefType = pImpl->hRef;
4963 else
4964 hr = TYPE_E_ELEMENTNOTFOUND;
4967 if(TRACE_ON(ole))
4969 if(SUCCEEDED(hr))
4970 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4971 else
4972 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4975 return hr;
4978 /* ITypeInfo::GetImplTypeFlags
4980 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4981 * or base interface in a type description.
4983 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4984 UINT index, INT *pImplTypeFlags)
4986 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4987 int i;
4988 TLBImplType *pImpl;
4990 TRACE("(%p) index %d\n", This, index);
4991 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4992 i++, pImpl=pImpl->next)
4994 if(i==index && pImpl){
4995 *pImplTypeFlags=pImpl->implflags;
4996 return S_OK;
4998 *pImplTypeFlags=0;
4999 return TYPE_E_ELEMENTNOTFOUND;
5002 /* GetIDsOfNames
5003 * Maps between member names and member IDs, and parameter names and
5004 * parameter IDs.
5006 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5007 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5009 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5010 const TLBFuncDesc *pFDesc;
5011 const TLBVarDesc *pVDesc;
5012 HRESULT ret=S_OK;
5013 int i;
5015 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5016 cNames);
5018 /* init out parameters in case of failure */
5019 for (i = 0; i < cNames; i++)
5020 pMemId[i] = MEMBERID_NIL;
5022 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5023 int j;
5024 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5025 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5026 for(i=1; i < cNames; i++){
5027 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5028 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5029 break;
5030 if( j<pFDesc->funcdesc.cParams)
5031 pMemId[i]=j;
5032 else
5033 ret=DISP_E_UNKNOWNNAME;
5035 TRACE("-- 0x%08x\n", ret);
5036 return ret;
5039 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5040 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5041 if(cNames) *pMemId=pVDesc->vardesc.memid;
5042 return ret;
5045 /* not found, see if it can be found in an inherited interface */
5046 if(This->TypeAttr.cImplTypes) {
5047 /* recursive search */
5048 ITypeInfo *pTInfo;
5049 ret=ITypeInfo_GetRefTypeInfo(iface,
5050 This->impltypelist->hRef, &pTInfo);
5051 if(SUCCEEDED(ret)){
5052 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5053 ITypeInfo_Release(pTInfo);
5054 return ret;
5056 WARN("Could not search inherited interface!\n");
5057 } else
5058 WARN("no names found\n");
5059 return DISP_E_UNKNOWNNAME;
5062 /* ITypeInfo::Invoke
5064 * Invokes a method, or accesses a property of an object, that implements the
5065 * interface described by the type description.
5067 DWORD
5068 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5069 DWORD res;
5071 if (TRACE_ON(ole)) {
5072 int i;
5073 TRACE("Calling %p(",func);
5074 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5075 TRACE(")\n");
5078 switch (callconv) {
5079 case CC_STDCALL:
5081 switch (nrargs) {
5082 case 0:
5083 res = func();
5084 break;
5085 case 1:
5086 res = func(args[0]);
5087 break;
5088 case 2:
5089 res = func(args[0],args[1]);
5090 break;
5091 case 3:
5092 res = func(args[0],args[1],args[2]);
5093 break;
5094 case 4:
5095 res = func(args[0],args[1],args[2],args[3]);
5096 break;
5097 case 5:
5098 res = func(args[0],args[1],args[2],args[3],args[4]);
5099 break;
5100 case 6:
5101 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5102 break;
5103 case 7:
5104 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5105 break;
5106 case 8:
5107 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5108 break;
5109 case 9:
5110 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5111 break;
5112 case 10:
5113 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5114 break;
5115 case 11:
5116 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5117 break;
5118 case 12:
5119 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]);
5120 break;
5121 case 13:
5122 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]);
5123 break;
5124 case 14:
5125 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]);
5126 break;
5127 case 15:
5128 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]);
5129 break;
5130 case 16:
5131 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]);
5132 break;
5133 case 17:
5134 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]);
5135 break;
5136 case 18:
5137 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]);
5138 break;
5139 case 19:
5140 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]);
5141 break;
5142 case 20:
5143 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]);
5144 break;
5145 case 21:
5146 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]);
5147 break;
5148 case 22:
5149 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]);
5150 break;
5151 case 23:
5152 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]);
5153 break;
5154 default:
5155 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5156 res = -1;
5157 break;
5159 break;
5160 default:
5161 FIXME("unsupported calling convention %d\n",callconv);
5162 res = -1;
5163 break;
5165 TRACE("returns %08x\n",res);
5166 return res;
5169 extern int _argsize(DWORD vt);
5171 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5173 HRESULT hr = S_OK;
5174 ITypeInfo *tinfo2 = NULL;
5175 TYPEATTR *tattr = NULL;
5177 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5178 if (hr)
5180 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5181 "hr = 0x%08x\n",
5182 tdesc->u.hreftype, hr);
5183 return hr;
5185 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5186 if (hr)
5188 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5189 ITypeInfo_Release(tinfo2);
5190 return hr;
5193 switch (tattr->typekind)
5195 case TKIND_ENUM:
5196 *vt |= VT_I4;
5197 break;
5199 case TKIND_ALIAS:
5200 tdesc = &tattr->tdescAlias;
5201 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5202 break;
5204 case TKIND_INTERFACE:
5205 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5206 *vt |= VT_DISPATCH;
5207 else
5208 *vt |= VT_UNKNOWN;
5209 break;
5211 case TKIND_DISPATCH:
5212 *vt |= VT_DISPATCH;
5213 break;
5215 case TKIND_COCLASS:
5216 *vt |= VT_UNKNOWN;
5217 break;
5219 case TKIND_RECORD:
5220 FIXME("TKIND_RECORD unhandled.\n");
5221 hr = E_NOTIMPL;
5222 break;
5224 case TKIND_UNION:
5225 FIXME("TKIND_UNION unhandled.\n");
5226 hr = E_NOTIMPL;
5227 break;
5229 default:
5230 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5231 hr = E_NOTIMPL;
5232 break;
5234 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5235 ITypeInfo_Release(tinfo2);
5236 return hr;
5239 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5241 HRESULT hr = S_OK;
5243 /* enforce only one level of pointer indirection */
5244 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5246 tdesc = tdesc->u.lptdesc;
5248 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5249 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5250 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5251 if ((tdesc->vt == VT_USERDEFINED) ||
5252 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5254 VARTYPE vt_userdefined = 0;
5255 const TYPEDESC *tdesc_userdefined = tdesc;
5256 if (tdesc->vt == VT_PTR)
5258 vt_userdefined = VT_BYREF;
5259 tdesc_userdefined = tdesc->u.lptdesc;
5261 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5262 if ((hr == S_OK) &&
5263 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5264 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5266 *vt |= vt_userdefined;
5267 return S_OK;
5270 *vt = VT_BYREF;
5273 switch (tdesc->vt)
5275 case VT_HRESULT:
5276 *vt |= VT_ERROR;
5277 break;
5278 case VT_USERDEFINED:
5279 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5280 break;
5281 case VT_VOID:
5282 case VT_CARRAY:
5283 case VT_PTR:
5284 case VT_LPSTR:
5285 case VT_LPWSTR:
5286 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5287 hr = DISP_E_BADVARTYPE;
5288 break;
5289 case VT_SAFEARRAY:
5290 *vt |= VT_ARRAY;
5291 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5292 break;
5293 default:
5294 *vt |= tdesc->vt;
5295 break;
5297 return hr;
5300 /***********************************************************************
5301 * DispCallFunc (OLEAUT32.@)
5303 * Invokes a function of the specifed calling convention, passing the
5304 * specified arguments and returns the result.
5306 * PARAMS
5307 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5308 * oVft [I] The offset in the vtable. See notes.
5309 * cc [I] Calling convention of the function to call.
5310 * vtReturn [I] The return type of the function.
5311 * cActuals [I] Number of parameters.
5312 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5313 * prgpvarg [I] The arguments to pass.
5314 * pvargResult [O] The return value of the function. Can be NULL.
5316 * RETURNS
5317 * Success: S_OK.
5318 * Failure: HRESULT code.
5320 * NOTES
5321 * The HRESULT return value of this function is not affected by the return
5322 * value of the user supplied function, which is returned in pvargResult.
5324 * If pvInstance is NULL then a non-object function is to be called and oVft
5325 * is the address of the function to call.
5327 * The cc parameter can be one of the following values:
5328 *|CC_FASTCALL
5329 *|CC_CDECL
5330 *|CC_PASCAL
5331 *|CC_STDCALL
5332 *|CC_FPFASTCALL
5333 *|CC_SYSCALL
5334 *|CC_MPWCDECL
5335 *|CC_MPWPASCAL
5338 HRESULT WINAPI
5339 DispCallFunc(
5340 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5341 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5343 int i, argsize, argspos;
5344 DWORD *args;
5345 HRESULT hres;
5347 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5348 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5349 pvargResult, V_VT(pvargResult));
5351 argsize = 0;
5352 if (pvInstance)
5353 argsize++; /* for This pointer */
5355 for (i=0;i<cActuals;i++)
5357 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5358 dump_Variant(prgpvarg[i]);
5359 argsize += _argsize(prgvt[i]);
5361 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5363 argspos = 0;
5364 if (pvInstance)
5366 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5367 argspos++;
5370 for (i=0;i<cActuals;i++)
5372 VARIANT *arg = prgpvarg[i];
5373 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5374 if (prgvt[i] == VT_VARIANT)
5375 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5376 else
5377 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5378 argspos += _argsize(prgvt[i]);
5381 if (pvInstance)
5383 FARPROC *vtable = *(FARPROC**)pvInstance;
5384 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5386 else
5387 /* if we aren't invoking an object then the function pointer is stored
5388 * in oVft */
5389 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5391 if (pvargResult && (vtReturn != VT_EMPTY))
5393 TRACE("Method returned 0x%08x\n",hres);
5394 V_VT(pvargResult) = vtReturn;
5395 V_UI4(pvargResult) = hres;
5398 HeapFree(GetProcessHeap(),0,args);
5399 return S_OK;
5402 #define INVBUF_ELEMENT_SIZE \
5403 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5404 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5405 ((VARIANTARG *)(buffer))
5406 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5407 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5408 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5409 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5410 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5411 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5413 static HRESULT WINAPI ITypeInfo_fnInvoke(
5414 ITypeInfo2 *iface,
5415 VOID *pIUnk,
5416 MEMBERID memid,
5417 UINT16 wFlags,
5418 DISPPARAMS *pDispParams,
5419 VARIANT *pVarResult,
5420 EXCEPINFO *pExcepInfo,
5421 UINT *pArgErr)
5423 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5424 int i;
5425 unsigned int var_index;
5426 TYPEKIND type_kind;
5427 HRESULT hres;
5428 const TLBFuncDesc *pFuncInfo;
5430 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5431 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5434 if (!pDispParams)
5436 ERR("NULL pDispParams not allowed\n");
5437 return E_INVALIDARG;
5440 dump_DispParms(pDispParams);
5442 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5444 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5445 pDispParams->cNamedArgs, pDispParams->cArgs);
5446 return E_INVALIDARG;
5449 /* we do this instead of using GetFuncDesc since it will return a fake
5450 * FUNCDESC for dispinterfaces and we want the real function description */
5451 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5452 if ((memid == pFuncInfo->funcdesc.memid) &&
5453 (wFlags & pFuncInfo->funcdesc.invkind))
5454 break;
5456 if (pFuncInfo) {
5457 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5459 if (TRACE_ON(ole))
5461 TRACE("invoking:\n");
5462 dump_TLBFuncDescOne(pFuncInfo);
5465 switch (func_desc->funckind) {
5466 case FUNC_PUREVIRTUAL:
5467 case FUNC_VIRTUAL: {
5468 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5469 VARIANT varresult;
5470 VARIANT retval; /* pointer for storing byref retvals in */
5471 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5472 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5473 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5474 UINT cNamedArgs = pDispParams->cNamedArgs;
5475 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5477 hres = S_OK;
5479 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5481 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5483 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5484 hres = DISP_E_PARAMNOTFOUND;
5485 goto func_fail;
5487 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5488 cNamedArgs--;
5489 rgdispidNamedArgs++;
5492 for (i = 0; i < func_desc->cParams; i++)
5494 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5495 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5496 if (FAILED(hres))
5497 goto func_fail;
5500 TRACE("changing args\n");
5501 for (i = 0; i < func_desc->cParams; i++)
5503 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5504 VARIANTARG *src_arg;
5506 if (cNamedArgs)
5508 USHORT j;
5509 src_arg = NULL;
5510 for (j = 0; j < cNamedArgs; j++)
5511 if (rgdispidNamedArgs[j] == i)
5513 src_arg = &pDispParams->rgvarg[j];
5514 break;
5517 else
5518 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5520 if (wParamFlags & PARAMFLAG_FRETVAL)
5522 /* under most conditions the caller is not allowed to
5523 * pass in a dispparam arg in the index of what would be
5524 * the retval parameter. however, there is an exception
5525 * where the extra parameter is used in an extra
5526 * IDispatch::Invoke below */
5527 if ((i < pDispParams->cArgs) &&
5528 ((func_desc->cParams != 1) || !pVarResult ||
5529 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5531 hres = DISP_E_BADPARAMCOUNT;
5532 break;
5535 /* note: this check is placed so that if the caller passes
5536 * in a VARIANTARG for the retval we just ignore it, like
5537 * native does */
5538 if (i == func_desc->cParams - 1)
5540 VARIANTARG *arg;
5541 arg = prgpvarg[i] = &rgvarg[i];
5542 memset(arg, 0, sizeof(*arg));
5543 V_VT(arg) = rgvt[i];
5544 memset(&retval, 0, sizeof(retval));
5545 V_BYREF(arg) = &retval;
5547 else
5549 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5550 hres = E_UNEXPECTED;
5551 break;
5554 else if (src_arg)
5556 dump_Variant(src_arg);
5558 if (rgvt[i] == VT_VARIANT)
5559 hres = VariantCopy(&rgvarg[i], src_arg);
5560 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5562 if (rgvt[i] == V_VT(src_arg))
5563 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5564 else
5566 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5567 hres = VariantCopy(&missing_arg[i], src_arg);
5568 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5570 V_VT(&rgvarg[i]) = rgvt[i];
5572 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5574 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5575 V_VT(&missing_arg[i]) = V_VT(src_arg);
5576 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5577 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5578 V_VT(&rgvarg[i]) = rgvt[i];
5580 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5582 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5583 V_VT(&rgvarg[i]) = rgvt[i];
5585 else
5587 /* FIXME: this doesn't work for VT_BYREF arguments if
5588 * they are not the same type as in the paramdesc */
5589 V_VT(&rgvarg[i]) = V_VT(src_arg);
5590 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5591 V_VT(&rgvarg[i]) = rgvt[i];
5594 if (FAILED(hres))
5596 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5597 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5598 debugstr_VT(src_arg), debugstr_VF(src_arg));
5599 break;
5601 prgpvarg[i] = &rgvarg[i];
5603 else if (wParamFlags & PARAMFLAG_FOPT)
5605 VARIANTARG *arg;
5606 arg = prgpvarg[i] = &rgvarg[i];
5607 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5609 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5610 if (FAILED(hres))
5611 break;
5613 else
5615 VARIANTARG *missing_arg;
5616 /* if the function wants a pointer to a variant then
5617 * set that up, otherwise just pass the VT_ERROR in
5618 * the argument by value */
5619 if (rgvt[i] & VT_BYREF)
5621 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5622 V_VT(arg) = VT_VARIANT | VT_BYREF;
5623 V_VARIANTREF(arg) = missing_arg;
5625 else
5626 missing_arg = arg;
5627 V_VT(missing_arg) = VT_ERROR;
5628 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5631 else
5633 hres = DISP_E_BADPARAMCOUNT;
5634 break;
5637 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5638 if (func_desc->cParamsOpt < 0)
5640 FIXME("Does not support safearray optional parameters\n");
5641 hres = DISP_E_BADPARAMCOUNT;
5642 goto func_fail; /* FIXME: we don't free changed types here */
5645 /* VT_VOID is a special case for return types, so it is not
5646 * handled in the general function */
5647 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5648 V_VT(&varresult) = VT_EMPTY;
5649 else
5651 V_VT(&varresult) = 0;
5652 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5653 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5656 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5657 V_VT(&varresult), func_desc->cParams, rgvt,
5658 prgpvarg, &varresult);
5660 for (i = 0; i < func_desc->cParams; i++)
5662 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5663 if (wParamFlags & PARAMFLAG_FRETVAL)
5665 if (TRACE_ON(ole))
5667 TRACE("[retval] value: ");
5668 dump_Variant(prgpvarg[i]);
5671 if (pVarResult)
5673 VariantInit(pVarResult);
5674 /* deref return value */
5675 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5678 /* free data stored in varresult. Note that
5679 * VariantClear doesn't do what we want because we are
5680 * working with byref types. */
5681 /* FIXME: clear safearrays, bstrs, records and
5682 * variants here too */
5683 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5684 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5686 if(*V_UNKNOWNREF(prgpvarg[i]))
5687 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5689 break;
5691 else if (i < pDispParams->cArgs)
5693 if (wParamFlags & PARAMFLAG_FOUT)
5695 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5697 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5698 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5700 if (FAILED(hres))
5702 ERR("failed to convert param %d to vt %d\n", i,
5703 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5704 break;
5707 VariantClear(&rgvarg[i]);
5709 else if (wParamFlags & PARAMFLAG_FOPT)
5711 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5712 VariantClear(&rgvarg[i]);
5716 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5718 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5719 hres = DISP_E_EXCEPTION;
5720 if (pExcepInfo)
5722 IErrorInfo *pErrorInfo;
5723 pExcepInfo->scode = V_ERROR(&varresult);
5724 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
5726 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
5727 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
5728 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
5729 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
5731 IErrorInfo_Release(pErrorInfo);
5735 if (V_VT(&varresult) != VT_ERROR)
5737 TRACE("varresult value: ");
5738 dump_Variant(&varresult);
5740 if (pVarResult)
5742 VariantClear(pVarResult);
5743 *pVarResult = varresult;
5745 else
5746 VariantClear(&varresult);
5749 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
5750 (wFlags == INVOKE_PROPERTYGET) &&
5751 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
5752 (pDispParams->cArgs != 0))
5754 if (V_VT(pVarResult) == VT_DISPATCH)
5756 IDispatch *pDispatch = V_DISPATCH(pVarResult);
5757 /* Note: not VariantClear; we still need the dispatch
5758 * pointer to be valid */
5759 VariantInit(pVarResult);
5760 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
5761 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
5762 pDispParams, pVarResult, pExcepInfo, pArgErr);
5763 IDispatch_Release(pDispatch);
5765 else
5767 VariantClear(pVarResult);
5768 hres = DISP_E_NOTACOLLECTION;
5772 func_fail:
5773 HeapFree(GetProcessHeap(), 0, buffer);
5774 break;
5776 case FUNC_DISPATCH: {
5777 IDispatch *disp;
5779 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5780 if (SUCCEEDED(hres)) {
5781 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5782 hres = IDispatch_Invoke(
5783 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5784 pVarResult,pExcepInfo,pArgErr
5786 if (FAILED(hres))
5787 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5788 IDispatch_Release(disp);
5789 } else
5790 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5791 break;
5793 default:
5794 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5795 hres = E_FAIL;
5796 break;
5799 TRACE("-- 0x%08x\n", hres);
5800 return hres;
5802 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5803 VARDESC *var_desc;
5805 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5806 if(FAILED(hres)) return hres;
5808 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5809 dump_VARDESC(var_desc);
5810 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5811 return E_NOTIMPL;
5814 /* not found, look for it in inherited interfaces */
5815 ITypeInfo2_GetTypeKind(iface, &type_kind);
5816 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5817 HREFTYPE ref_type;
5818 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5819 /* recursive search */
5820 ITypeInfo *pTInfo;
5821 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5822 if(SUCCEEDED(hres)){
5823 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5824 ITypeInfo_Release(pTInfo);
5825 return hres;
5827 WARN("Could not search inherited interface!\n");
5830 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5831 return DISP_E_MEMBERNOTFOUND;
5834 /* ITypeInfo::GetDocumentation
5836 * Retrieves the documentation string, the complete Help file name and path,
5837 * and the context ID for the Help topic for a specified type description.
5839 * (Can be tested by the Visual Basic Editor in Word for instance.)
5841 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5842 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5843 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5845 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5846 const TLBFuncDesc *pFDesc;
5847 const TLBVarDesc *pVDesc;
5848 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5849 " HelpContext(%p) HelpFile(%p)\n",
5850 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5851 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5852 if(pBstrName)
5853 *pBstrName=SysAllocString(This->Name);
5854 if(pBstrDocString)
5855 *pBstrDocString=SysAllocString(This->DocString);
5856 if(pdwHelpContext)
5857 *pdwHelpContext=This->dwHelpContext;
5858 if(pBstrHelpFile)
5859 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5860 return S_OK;
5861 }else {/* for a member */
5862 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5863 if(pFDesc->funcdesc.memid==memid){
5864 if(pBstrName)
5865 *pBstrName = SysAllocString(pFDesc->Name);
5866 if(pBstrDocString)
5867 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5868 if(pdwHelpContext)
5869 *pdwHelpContext=pFDesc->helpcontext;
5870 return S_OK;
5872 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5873 if(pVDesc->vardesc.memid==memid){
5874 if(pBstrName)
5875 *pBstrName = SysAllocString(pVDesc->Name);
5876 if(pBstrDocString)
5877 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5878 if(pdwHelpContext)
5879 *pdwHelpContext=pVDesc->HelpContext;
5880 return S_OK;
5884 if(This->TypeAttr.cImplTypes &&
5885 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5886 /* recursive search */
5887 ITypeInfo *pTInfo;
5888 HRESULT result;
5889 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5890 &pTInfo);
5891 if(SUCCEEDED(result)) {
5892 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5893 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5894 ITypeInfo_Release(pTInfo);
5895 return result;
5897 WARN("Could not search inherited interface!\n");
5900 WARN("member %d not found\n", memid);
5901 return TYPE_E_ELEMENTNOTFOUND;
5904 /* ITypeInfo::GetDllEntry
5906 * Retrieves a description or specification of an entry point for a function
5907 * in a DLL.
5909 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5910 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5911 WORD *pwOrdinal)
5913 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5914 const TLBFuncDesc *pFDesc;
5916 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5918 if (pBstrDllName) *pBstrDllName = NULL;
5919 if (pBstrName) *pBstrName = NULL;
5920 if (pwOrdinal) *pwOrdinal = 0;
5922 if (This->TypeAttr.typekind != TKIND_MODULE)
5923 return TYPE_E_BADMODULEKIND;
5925 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5926 if(pFDesc->funcdesc.memid==memid){
5927 dump_TypeInfo(This);
5928 if (TRACE_ON(ole))
5929 dump_TLBFuncDescOne(pFDesc);
5931 if (pBstrDllName)
5932 *pBstrDllName = SysAllocString(This->DllName);
5934 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5935 if (pBstrName)
5936 *pBstrName = SysAllocString(pFDesc->Entry);
5937 if (pwOrdinal)
5938 *pwOrdinal = -1;
5939 return S_OK;
5941 if (pBstrName)
5942 *pBstrName = NULL;
5943 if (pwOrdinal)
5944 *pwOrdinal = (DWORD)pFDesc->Entry;
5945 return S_OK;
5947 return TYPE_E_ELEMENTNOTFOUND;
5950 /* ITypeInfo::GetRefTypeInfo
5952 * If a type description references other type descriptions, it retrieves
5953 * the referenced type descriptions.
5955 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5956 ITypeInfo2 *iface,
5957 HREFTYPE hRefType,
5958 ITypeInfo **ppTInfo)
5960 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5961 HRESULT result = E_FAIL;
5963 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5965 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5966 ITypeInfo_AddRef(*ppTInfo);
5967 result = S_OK;
5969 else if (hRefType == -1 &&
5970 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5971 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5973 /* when we meet a DUAL dispinterface, we must create the interface
5974 * version of it.
5976 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5979 /* the interface version contains the same information as the dispinterface
5980 * copy the contents of the structs.
5982 *pTypeInfoImpl = *This;
5983 pTypeInfoImpl->ref = 0;
5985 /* change the type to interface */
5986 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5988 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5990 /* we use data structures from This, so we need to keep a reference
5991 * to it to stop it being destroyed and signal to the new instance to
5992 * not free its data structures when it is destroyed */
5993 pTypeInfoImpl->no_free_data = TRUE;
5994 pTypeInfoImpl->next = This;
5995 ITypeInfo_AddRef((ITypeInfo*) This);
5997 ITypeInfo_AddRef(*ppTInfo);
5999 result = S_OK;
6001 } else {
6002 TLBRefType *pRefType;
6003 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
6004 if(pRefType->reference == hRefType)
6005 break;
6007 if(!pRefType)
6008 FIXME("Can't find pRefType for ref %x\n", hRefType);
6009 if(pRefType && hRefType != -1) {
6010 ITypeLib *pTLib = NULL;
6012 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
6013 UINT Index;
6014 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6015 } else {
6016 if(pRefType->pImpTLInfo->pImpTypeLib) {
6017 TRACE("typeinfo in imported typelib that is already loaded\n");
6018 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
6019 ITypeLib2_AddRef((ITypeLib*) pTLib);
6020 result = S_OK;
6021 } else {
6022 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6023 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
6024 pRefType->pImpTLInfo->wVersionMajor,
6025 pRefType->pImpTLInfo->wVersionMinor,
6026 pRefType->pImpTLInfo->lcid,
6027 &pTLib);
6029 if(!SUCCEEDED(result)) {
6030 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
6031 result=LoadTypeLib(libnam, &pTLib);
6032 SysFreeString(libnam);
6034 if(SUCCEEDED(result)) {
6035 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6036 ITypeLib2_AddRef(pTLib);
6040 if(SUCCEEDED(result)) {
6041 if(pRefType->index == TLB_REF_USE_GUID)
6042 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6043 &pRefType->guid,
6044 ppTInfo);
6045 else
6046 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
6047 ppTInfo);
6049 if (pTLib != NULL)
6050 ITypeLib2_Release(pTLib);
6054 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6055 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6056 return result;
6059 /* ITypeInfo::AddressOfMember
6061 * Retrieves the addresses of static functions or variables, such as those
6062 * defined in a DLL.
6064 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6065 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6067 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6068 HRESULT hr;
6069 BSTR dll, entry;
6070 WORD ordinal;
6071 HMODULE module;
6073 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6075 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6076 if (FAILED(hr))
6077 return hr;
6079 module = LoadLibraryW(dll);
6080 if (!module)
6082 ERR("couldn't load %s\n", debugstr_w(dll));
6083 SysFreeString(dll);
6084 if (entry) SysFreeString(entry);
6085 return STG_E_FILENOTFOUND;
6087 /* FIXME: store library somewhere where we can free it */
6089 if (entry)
6091 LPSTR entryA;
6092 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6093 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6094 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6096 *ppv = GetProcAddress(module, entryA);
6097 if (!*ppv)
6098 ERR("function not found %s\n", debugstr_a(entryA));
6100 HeapFree(GetProcessHeap(), 0, entryA);
6102 else
6104 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6105 if (!*ppv)
6106 ERR("function not found %d\n", ordinal);
6109 SysFreeString(dll);
6110 if (entry) SysFreeString(entry);
6112 if (!*ppv)
6113 return TYPE_E_DLLFUNCTIONNOTFOUND;
6115 return S_OK;
6118 /* ITypeInfo::CreateInstance
6120 * Creates a new instance of a type that describes a component object class
6121 * (coclass).
6123 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6124 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6126 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6127 HRESULT hr;
6128 TYPEATTR *pTA;
6130 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6132 *ppvObj = NULL;
6134 if(pOuterUnk)
6136 WARN("Not able to aggregate\n");
6137 return CLASS_E_NOAGGREGATION;
6140 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6141 if(FAILED(hr)) return hr;
6143 if(pTA->typekind != TKIND_COCLASS)
6145 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6146 hr = E_INVALIDARG;
6147 goto end;
6150 hr = S_FALSE;
6151 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6153 IUnknown *pUnk;
6154 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6155 TRACE("GetActiveObject rets %08x\n", hr);
6156 if(hr == S_OK)
6158 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6159 IUnknown_Release(pUnk);
6163 if(hr != S_OK)
6164 hr = CoCreateInstance(&pTA->guid, NULL,
6165 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6166 riid, ppvObj);
6168 end:
6169 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6170 return hr;
6173 /* ITypeInfo::GetMops
6175 * Retrieves marshalling information.
6177 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6178 BSTR *pBstrMops)
6180 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6181 FIXME("(%p) stub!\n", This);
6182 return S_OK;
6185 /* ITypeInfo::GetContainingTypeLib
6187 * Retrieves the containing type library and the index of the type description
6188 * within that type library.
6190 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6191 ITypeLib * *ppTLib, UINT *pIndex)
6193 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6195 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6196 if (pIndex) {
6197 *pIndex=This->index;
6198 TRACE("returning pIndex=%d\n", *pIndex);
6201 if (ppTLib) {
6202 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6203 ITypeLib2_AddRef(*ppTLib);
6204 TRACE("returning ppTLib=%p\n", *ppTLib);
6207 return S_OK;
6210 /* ITypeInfo::ReleaseTypeAttr
6212 * Releases a TYPEATTR previously returned by GetTypeAttr.
6215 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6216 TYPEATTR* pTypeAttr)
6218 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6219 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6220 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6223 /* ITypeInfo::ReleaseFuncDesc
6225 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6227 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6228 ITypeInfo2 *iface,
6229 FUNCDESC *pFuncDesc)
6231 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6232 SHORT i;
6234 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6236 for (i = 0; i < pFuncDesc->cParams; i++)
6237 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6238 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6240 SysFreeString((BSTR)pFuncDesc);
6243 /* ITypeInfo::ReleaseVarDesc
6245 * Releases a VARDESC previously returned by GetVarDesc.
6247 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6248 VARDESC *pVarDesc)
6250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6251 TRACE("(%p)->(%p)\n", This, pVarDesc);
6253 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6254 if (pVarDesc->varkind == VAR_CONST)
6255 VariantClear(pVarDesc->u.lpvarValue);
6256 SysFreeString((BSTR)pVarDesc);
6259 /* ITypeInfo2::GetTypeKind
6261 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6264 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6265 TYPEKIND *pTypeKind)
6267 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6268 *pTypeKind=This->TypeAttr.typekind;
6269 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6270 return S_OK;
6273 /* ITypeInfo2::GetTypeFlags
6275 * Returns the type flags without any allocations. This returns a DWORD type
6276 * flag, which expands the type flags without growing the TYPEATTR (type
6277 * attribute).
6280 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6282 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6283 *pTypeFlags=This->TypeAttr.wTypeFlags;
6284 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6285 return S_OK;
6288 /* ITypeInfo2::GetFuncIndexOfMemId
6289 * Binds to a specific member based on a known DISPID, where the member name
6290 * is not known (for example, when binding to a default member).
6293 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6294 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6296 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6297 const TLBFuncDesc *pFuncInfo;
6298 int i;
6299 HRESULT result;
6301 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6302 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6303 break;
6304 if(pFuncInfo) {
6305 *pFuncIndex = i;
6306 result = S_OK;
6307 } else
6308 result = TYPE_E_ELEMENTNOTFOUND;
6310 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6311 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6312 return result;
6315 /* TypeInfo2::GetVarIndexOfMemId
6317 * Binds to a specific member based on a known DISPID, where the member name
6318 * is not known (for example, when binding to a default member).
6321 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6322 MEMBERID memid, UINT *pVarIndex)
6324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6325 TLBVarDesc *pVarInfo;
6326 int i;
6327 HRESULT result;
6328 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6329 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6331 if(pVarInfo) {
6332 *pVarIndex = i;
6333 result = S_OK;
6334 } else
6335 result = TYPE_E_ELEMENTNOTFOUND;
6337 TRACE("(%p) memid 0x%08x -> %s\n", This,
6338 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6339 return result;
6342 /* ITypeInfo2::GetCustData
6344 * Gets the custom data
6346 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6347 ITypeInfo2 * iface,
6348 REFGUID guid,
6349 VARIANT *pVarVal)
6351 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6352 TLBCustData *pCData;
6354 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6355 if( IsEqualIID(guid, &pCData->guid)) break;
6357 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6359 if(pCData)
6361 VariantInit( pVarVal);
6362 VariantCopy( pVarVal, &pCData->data);
6363 return S_OK;
6365 return E_INVALIDARG; /* FIXME: correct? */
6368 /* ITypeInfo2::GetFuncCustData
6370 * Gets the custom data
6372 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6373 ITypeInfo2 * iface,
6374 UINT index,
6375 REFGUID guid,
6376 VARIANT *pVarVal)
6378 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6379 TLBCustData *pCData=NULL;
6380 TLBFuncDesc * pFDesc;
6381 int i;
6382 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6383 pFDesc=pFDesc->next);
6385 if(pFDesc)
6386 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6387 if( IsEqualIID(guid, &pCData->guid)) break;
6389 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6391 if(pCData){
6392 VariantInit( pVarVal);
6393 VariantCopy( pVarVal, &pCData->data);
6394 return S_OK;
6396 return E_INVALIDARG; /* FIXME: correct? */
6399 /* ITypeInfo2::GetParamCustData
6401 * Gets the custom data
6403 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6404 ITypeInfo2 * iface,
6405 UINT indexFunc,
6406 UINT indexParam,
6407 REFGUID guid,
6408 VARIANT *pVarVal)
6410 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6411 TLBCustData *pCData=NULL;
6412 TLBFuncDesc * pFDesc;
6413 int i;
6415 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6417 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6418 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6419 pCData = pCData->next)
6420 if( IsEqualIID(guid, &pCData->guid)) break;
6422 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6424 if(pCData)
6426 VariantInit( pVarVal);
6427 VariantCopy( pVarVal, &pCData->data);
6428 return S_OK;
6430 return E_INVALIDARG; /* FIXME: correct? */
6433 /* ITypeInfo2::GetVarCustData
6435 * Gets the custom data
6437 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6438 ITypeInfo2 * iface,
6439 UINT index,
6440 REFGUID guid,
6441 VARIANT *pVarVal)
6443 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6444 TLBCustData *pCData=NULL;
6445 TLBVarDesc * pVDesc;
6446 int i;
6448 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6450 if(pVDesc)
6452 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6454 if( IsEqualIID(guid, &pCData->guid)) break;
6458 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6460 if(pCData)
6462 VariantInit( pVarVal);
6463 VariantCopy( pVarVal, &pCData->data);
6464 return S_OK;
6466 return E_INVALIDARG; /* FIXME: correct? */
6469 /* ITypeInfo2::GetImplCustData
6471 * Gets the custom data
6473 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6474 ITypeInfo2 * iface,
6475 UINT index,
6476 REFGUID guid,
6477 VARIANT *pVarVal)
6479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6480 TLBCustData *pCData=NULL;
6481 TLBImplType * pRDesc;
6482 int i;
6484 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6486 if(pRDesc)
6488 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6490 if( IsEqualIID(guid, &pCData->guid)) break;
6494 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6496 if(pCData)
6498 VariantInit( pVarVal);
6499 VariantCopy( pVarVal, &pCData->data);
6500 return S_OK;
6502 return E_INVALIDARG; /* FIXME: correct? */
6505 /* ITypeInfo2::GetDocumentation2
6507 * Retrieves the documentation string, the complete Help file name and path,
6508 * the localization context to use, and the context ID for the library Help
6509 * topic in the Help file.
6512 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6513 ITypeInfo2 * iface,
6514 MEMBERID memid,
6515 LCID lcid,
6516 BSTR *pbstrHelpString,
6517 DWORD *pdwHelpStringContext,
6518 BSTR *pbstrHelpStringDll)
6520 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6521 const TLBFuncDesc *pFDesc;
6522 const TLBVarDesc *pVDesc;
6523 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6524 "HelpStringContext(%p) HelpStringDll(%p)\n",
6525 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6526 pbstrHelpStringDll );
6527 /* the help string should be obtained from the helpstringdll,
6528 * using the _DLLGetDocumentation function, based on the supplied
6529 * lcid. Nice to do sometime...
6531 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6532 if(pbstrHelpString)
6533 *pbstrHelpString=SysAllocString(This->Name);
6534 if(pdwHelpStringContext)
6535 *pdwHelpStringContext=This->dwHelpStringContext;
6536 if(pbstrHelpStringDll)
6537 *pbstrHelpStringDll=
6538 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6539 return S_OK;
6540 }else {/* for a member */
6541 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6542 if(pFDesc->funcdesc.memid==memid){
6543 if(pbstrHelpString)
6544 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6545 if(pdwHelpStringContext)
6546 *pdwHelpStringContext=pFDesc->HelpStringContext;
6547 if(pbstrHelpStringDll)
6548 *pbstrHelpStringDll=
6549 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6550 return S_OK;
6552 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6553 if(pVDesc->vardesc.memid==memid){
6554 if(pbstrHelpString)
6555 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6556 if(pdwHelpStringContext)
6557 *pdwHelpStringContext=pVDesc->HelpStringContext;
6558 if(pbstrHelpStringDll)
6559 *pbstrHelpStringDll=
6560 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6561 return S_OK;
6564 return TYPE_E_ELEMENTNOTFOUND;
6567 /* ITypeInfo2::GetAllCustData
6569 * Gets all custom data items for the Type info.
6572 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6573 ITypeInfo2 * iface,
6574 CUSTDATA *pCustData)
6576 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6577 TLBCustData *pCData;
6578 int i;
6580 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6582 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6583 if(pCustData->prgCustData ){
6584 pCustData->cCustData=This->ctCustData;
6585 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6586 pCustData->prgCustData[i].guid=pCData->guid;
6587 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6589 }else{
6590 ERR(" OUT OF MEMORY!\n");
6591 return E_OUTOFMEMORY;
6593 return S_OK;
6596 /* ITypeInfo2::GetAllFuncCustData
6598 * Gets all custom data items for the specified Function
6601 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6602 ITypeInfo2 * iface,
6603 UINT index,
6604 CUSTDATA *pCustData)
6606 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6607 TLBCustData *pCData;
6608 TLBFuncDesc * pFDesc;
6609 int i;
6610 TRACE("(%p) index %d\n", This, index);
6611 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6612 pFDesc=pFDesc->next)
6614 if(pFDesc){
6615 pCustData->prgCustData =
6616 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6617 if(pCustData->prgCustData ){
6618 pCustData->cCustData=pFDesc->ctCustData;
6619 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6620 pCData = pCData->next){
6621 pCustData->prgCustData[i].guid=pCData->guid;
6622 VariantCopy(& pCustData->prgCustData[i].varValue,
6623 & pCData->data);
6625 }else{
6626 ERR(" OUT OF MEMORY!\n");
6627 return E_OUTOFMEMORY;
6629 return S_OK;
6631 return TYPE_E_ELEMENTNOTFOUND;
6634 /* ITypeInfo2::GetAllParamCustData
6636 * Gets all custom data items for the Functions
6639 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6640 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6642 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6643 TLBCustData *pCData=NULL;
6644 TLBFuncDesc * pFDesc;
6645 int i;
6646 TRACE("(%p) index %d\n", This, indexFunc);
6647 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6648 pFDesc=pFDesc->next)
6650 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6651 pCustData->prgCustData =
6652 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6653 sizeof(CUSTDATAITEM));
6654 if(pCustData->prgCustData ){
6655 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6656 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6657 pCData; i++, pCData = pCData->next){
6658 pCustData->prgCustData[i].guid=pCData->guid;
6659 VariantCopy(& pCustData->prgCustData[i].varValue,
6660 & pCData->data);
6662 }else{
6663 ERR(" OUT OF MEMORY!\n");
6664 return E_OUTOFMEMORY;
6666 return S_OK;
6668 return TYPE_E_ELEMENTNOTFOUND;
6671 /* ITypeInfo2::GetAllVarCustData
6673 * Gets all custom data items for the specified Variable
6676 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6677 UINT index, CUSTDATA *pCustData)
6679 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6680 TLBCustData *pCData;
6681 TLBVarDesc * pVDesc;
6682 int i;
6683 TRACE("(%p) index %d\n", This, index);
6684 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6685 pVDesc=pVDesc->next)
6687 if(pVDesc){
6688 pCustData->prgCustData =
6689 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6690 if(pCustData->prgCustData ){
6691 pCustData->cCustData=pVDesc->ctCustData;
6692 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6693 pCData = pCData->next){
6694 pCustData->prgCustData[i].guid=pCData->guid;
6695 VariantCopy(& pCustData->prgCustData[i].varValue,
6696 & pCData->data);
6698 }else{
6699 ERR(" OUT OF MEMORY!\n");
6700 return E_OUTOFMEMORY;
6702 return S_OK;
6704 return TYPE_E_ELEMENTNOTFOUND;
6707 /* ITypeInfo2::GetAllImplCustData
6709 * Gets all custom data items for the specified implementation type
6712 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6713 ITypeInfo2 * iface,
6714 UINT index,
6715 CUSTDATA *pCustData)
6717 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6718 TLBCustData *pCData;
6719 TLBImplType * pRDesc;
6720 int i;
6721 TRACE("(%p) index %d\n", This, index);
6722 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6723 pRDesc=pRDesc->next)
6725 if(pRDesc){
6726 pCustData->prgCustData =
6727 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6728 if(pCustData->prgCustData ){
6729 pCustData->cCustData=pRDesc->ctCustData;
6730 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6731 pCData = pCData->next){
6732 pCustData->prgCustData[i].guid=pCData->guid;
6733 VariantCopy(& pCustData->prgCustData[i].varValue,
6734 & pCData->data);
6736 }else{
6737 ERR(" OUT OF MEMORY!\n");
6738 return E_OUTOFMEMORY;
6740 return S_OK;
6742 return TYPE_E_ELEMENTNOTFOUND;
6745 static const ITypeInfo2Vtbl tinfvt =
6748 ITypeInfo_fnQueryInterface,
6749 ITypeInfo_fnAddRef,
6750 ITypeInfo_fnRelease,
6752 ITypeInfo_fnGetTypeAttr,
6753 ITypeInfo_fnGetTypeComp,
6754 ITypeInfo_fnGetFuncDesc,
6755 ITypeInfo_fnGetVarDesc,
6756 ITypeInfo_fnGetNames,
6757 ITypeInfo_fnGetRefTypeOfImplType,
6758 ITypeInfo_fnGetImplTypeFlags,
6759 ITypeInfo_fnGetIDsOfNames,
6760 ITypeInfo_fnInvoke,
6761 ITypeInfo_fnGetDocumentation,
6762 ITypeInfo_fnGetDllEntry,
6763 ITypeInfo_fnGetRefTypeInfo,
6764 ITypeInfo_fnAddressOfMember,
6765 ITypeInfo_fnCreateInstance,
6766 ITypeInfo_fnGetMops,
6767 ITypeInfo_fnGetContainingTypeLib,
6768 ITypeInfo_fnReleaseTypeAttr,
6769 ITypeInfo_fnReleaseFuncDesc,
6770 ITypeInfo_fnReleaseVarDesc,
6772 ITypeInfo2_fnGetTypeKind,
6773 ITypeInfo2_fnGetTypeFlags,
6774 ITypeInfo2_fnGetFuncIndexOfMemId,
6775 ITypeInfo2_fnGetVarIndexOfMemId,
6776 ITypeInfo2_fnGetCustData,
6777 ITypeInfo2_fnGetFuncCustData,
6778 ITypeInfo2_fnGetParamCustData,
6779 ITypeInfo2_fnGetVarCustData,
6780 ITypeInfo2_fnGetImplTypeCustData,
6781 ITypeInfo2_fnGetDocumentation2,
6782 ITypeInfo2_fnGetAllCustData,
6783 ITypeInfo2_fnGetAllFuncCustData,
6784 ITypeInfo2_fnGetAllParamCustData,
6785 ITypeInfo2_fnGetAllVarCustData,
6786 ITypeInfo2_fnGetAllImplTypeCustData,
6789 /******************************************************************************
6790 * CreateDispTypeInfo [OLEAUT32.31]
6792 * Build type information for an object so it can be called through an
6793 * IDispatch interface.
6795 * RETURNS
6796 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6797 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6799 * NOTES
6800 * This call allows an objects methods to be accessed through IDispatch, by
6801 * building an ITypeInfo object that IDispatch can use to call through.
6803 HRESULT WINAPI CreateDispTypeInfo(
6804 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6805 LCID lcid, /* [I] Locale Id */
6806 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6808 ITypeInfoImpl *pTIClass, *pTIIface;
6809 ITypeLibImpl *pTypeLibImpl;
6810 int param, func;
6811 TLBFuncDesc **ppFuncDesc;
6813 TRACE("\n");
6814 pTypeLibImpl = TypeLibImpl_Constructor();
6815 if (!pTypeLibImpl) return E_FAIL;
6817 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6818 pTIIface->pTypeLib = pTypeLibImpl;
6819 pTIIface->index = 0;
6820 pTIIface->Name = NULL;
6821 pTIIface->dwHelpContext = -1;
6822 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6823 pTIIface->TypeAttr.lcid = lcid;
6824 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6825 pTIIface->TypeAttr.wMajorVerNum = 0;
6826 pTIIface->TypeAttr.wMinorVerNum = 0;
6827 pTIIface->TypeAttr.cbAlignment = 2;
6828 pTIIface->TypeAttr.cbSizeInstance = -1;
6829 pTIIface->TypeAttr.cbSizeVft = -1;
6830 pTIIface->TypeAttr.cFuncs = 0;
6831 pTIIface->TypeAttr.cImplTypes = 0;
6832 pTIIface->TypeAttr.cVars = 0;
6833 pTIIface->TypeAttr.wTypeFlags = 0;
6835 ppFuncDesc = &pTIIface->funclist;
6836 for(func = 0; func < pidata->cMembers; func++) {
6837 METHODDATA *md = pidata->pmethdata + func;
6838 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6839 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6840 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6841 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6842 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6843 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6844 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6845 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6846 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6847 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6848 (*ppFuncDesc)->funcdesc.cScodes = 0;
6849 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6850 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6851 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6852 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6853 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6854 md->cArgs * sizeof(ELEMDESC));
6855 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6856 md->cArgs * sizeof(TLBParDesc));
6857 for(param = 0; param < md->cArgs; param++) {
6858 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6859 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6861 (*ppFuncDesc)->helpcontext = 0;
6862 (*ppFuncDesc)->HelpStringContext = 0;
6863 (*ppFuncDesc)->HelpString = NULL;
6864 (*ppFuncDesc)->Entry = NULL;
6865 (*ppFuncDesc)->ctCustData = 0;
6866 (*ppFuncDesc)->pCustData = NULL;
6867 (*ppFuncDesc)->next = NULL;
6868 ppFuncDesc = &(*ppFuncDesc)->next;
6871 dump_TypeInfo(pTIIface);
6873 pTypeLibImpl->pTypeInfo = pTIIface;
6874 pTypeLibImpl->TypeInfoCount++;
6876 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6877 pTIClass->pTypeLib = pTypeLibImpl;
6878 pTIClass->index = 1;
6879 pTIClass->Name = NULL;
6880 pTIClass->dwHelpContext = -1;
6881 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6882 pTIClass->TypeAttr.lcid = lcid;
6883 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6884 pTIClass->TypeAttr.wMajorVerNum = 0;
6885 pTIClass->TypeAttr.wMinorVerNum = 0;
6886 pTIClass->TypeAttr.cbAlignment = 2;
6887 pTIClass->TypeAttr.cbSizeInstance = -1;
6888 pTIClass->TypeAttr.cbSizeVft = -1;
6889 pTIClass->TypeAttr.cFuncs = 0;
6890 pTIClass->TypeAttr.cImplTypes = 1;
6891 pTIClass->TypeAttr.cVars = 0;
6892 pTIClass->TypeAttr.wTypeFlags = 0;
6894 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6895 pTIClass->impltypelist->hRef = 1;
6897 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6898 pTIClass->reflist->index = 0;
6899 pTIClass->reflist->reference = 1;
6900 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6902 dump_TypeInfo(pTIClass);
6904 pTIIface->next = pTIClass;
6905 pTypeLibImpl->TypeInfoCount++;
6907 *pptinfo = (ITypeInfo*)pTIClass;
6909 ITypeInfo_AddRef(*pptinfo);
6910 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6912 return S_OK;
6916 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6918 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6920 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6923 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6925 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6927 return ITypeInfo_AddRef((ITypeInfo *)This);
6930 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6932 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6934 return ITypeInfo_Release((ITypeInfo *)This);
6937 static HRESULT WINAPI ITypeComp_fnBind(
6938 ITypeComp * iface,
6939 OLECHAR * szName,
6940 ULONG lHash,
6941 WORD wFlags,
6942 ITypeInfo ** ppTInfo,
6943 DESCKIND * pDescKind,
6944 BINDPTR * pBindPtr)
6946 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6947 const TLBFuncDesc *pFDesc;
6948 const TLBVarDesc *pVDesc;
6949 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6951 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6953 *pDescKind = DESCKIND_NONE;
6954 pBindPtr->lpfuncdesc = NULL;
6955 *ppTInfo = NULL;
6957 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6958 if (!strcmpiW(pFDesc->Name, szName)) {
6959 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6960 break;
6961 else
6962 /* name found, but wrong flags */
6963 hr = TYPE_E_TYPEMISMATCH;
6966 if (pFDesc)
6968 HRESULT hr = TLB_AllocAndInitFuncDesc(
6969 &pFDesc->funcdesc,
6970 &pBindPtr->lpfuncdesc,
6971 This->TypeAttr.typekind == TKIND_DISPATCH);
6972 if (FAILED(hr))
6973 return hr;
6974 *pDescKind = DESCKIND_FUNCDESC;
6975 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6976 ITypeInfo_AddRef(*ppTInfo);
6977 return S_OK;
6978 } else {
6979 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6980 if (!strcmpiW(pVDesc->Name, szName)) {
6981 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6982 if (FAILED(hr))
6983 return hr;
6984 *pDescKind = DESCKIND_VARDESC;
6985 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6986 ITypeInfo_AddRef(*ppTInfo);
6987 return S_OK;
6991 /* FIXME: search each inherited interface, not just the first */
6992 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6993 /* recursive search */
6994 ITypeInfo *pTInfo;
6995 ITypeComp *pTComp;
6996 HRESULT hr;
6997 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6998 if (SUCCEEDED(hr))
7000 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7001 ITypeInfo_Release(pTInfo);
7003 if (SUCCEEDED(hr))
7005 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7006 ITypeComp_Release(pTComp);
7007 return hr;
7009 WARN("Could not search inherited interface!\n");
7011 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7012 return hr;
7015 static HRESULT WINAPI ITypeComp_fnBindType(
7016 ITypeComp * iface,
7017 OLECHAR * szName,
7018 ULONG lHash,
7019 ITypeInfo ** ppTInfo,
7020 ITypeComp ** ppTComp)
7022 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7024 /* strange behaviour (does nothing) but like the
7025 * original */
7027 if (!ppTInfo || !ppTComp)
7028 return E_POINTER;
7030 *ppTInfo = NULL;
7031 *ppTComp = NULL;
7033 return S_OK;
7036 static const ITypeCompVtbl tcompvt =
7039 ITypeComp_fnQueryInterface,
7040 ITypeComp_fnAddRef,
7041 ITypeComp_fnRelease,
7043 ITypeComp_fnBind,
7044 ITypeComp_fnBindType