oleaut32: Initialise all members of the FUNCDESC structure in CreateDispTypeInfo.
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob5485c7970e321d09a677653b3fe483003c491ff2
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.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
48 * behaviour.
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
56 #include "config.h"
57 #include "wine/port.h"
59 #include <stdlib.h>
60 #include <string.h>
61 #include <stdarg.h>
62 #include <stdio.h>
63 #include <ctype.h>
65 #define COBJMACROS
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
69 #include "winerror.h"
70 #include "windef.h"
71 #include "winbase.h"
72 #include "winnls.h"
73 #include "winreg.h"
74 #include "winuser.h"
76 #include "wine/unicode.h"
77 #include "objbase.h"
78 #include "typelib.h"
79 #include "wine/debug.h"
80 #include "variant.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib);
85 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
86 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
88 /****************************************************************************
89 * FromLExxx
91 * Takes p_iVal (which is in little endian) and returns it
92 * in the host machine's byte order.
94 #ifdef WORDS_BIGENDIAN
95 static WORD FromLEWord(WORD p_iVal)
97 return (((p_iVal & 0x00FF) << 8) |
98 ((p_iVal & 0xFF00) >> 8));
102 static DWORD FromLEDWord(DWORD p_iVal)
104 return (((p_iVal & 0x000000FF) << 24) |
105 ((p_iVal & 0x0000FF00) << 8) |
106 ((p_iVal & 0x00FF0000) >> 8) |
107 ((p_iVal & 0xFF000000) >> 24));
109 #else
110 #define FromLEWord(X) (X)
111 #define FromLEDWord(X) (X)
112 #endif
115 /****************************************************************************
116 * FromLExxx
118 * Fix byte order in any structure if necessary
120 #ifdef WORDS_BIGENDIAN
121 static void FromLEWords(void *p_Val, int p_iSize)
123 WORD *Val = p_Val;
125 p_iSize /= sizeof(WORD);
127 while (p_iSize) {
128 *Val = FromLEWord(*Val);
129 Val++;
130 p_iSize--;
135 static void FromLEDWords(void *p_Val, int p_iSize)
137 DWORD *Val = p_Val;
139 p_iSize /= sizeof(DWORD);
141 while (p_iSize) {
142 *Val = FromLEDWord(*Val);
143 Val++;
144 p_iSize--;
147 #else
148 #define FromLEWords(X,Y) /*nothing*/
149 #define FromLEDWords(X,Y) /*nothing*/
150 #endif
153 * Find a typelib key which matches a requested maj.min version.
155 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
157 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
158 WCHAR buffer[60];
159 char key_name[16];
160 DWORD len, i;
161 INT best_min = -1;
162 HKEY hkey;
164 memcpy( buffer, typelibW, sizeof(typelibW) );
165 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
167 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
168 return FALSE;
170 len = sizeof(key_name);
171 i = 0;
172 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
174 INT v_maj, v_min;
176 if (sscanf(key_name, "%u.%u", &v_maj, &v_min) == 2)
178 TRACE("found %s: %u.%u\n", debugstr_w(buffer), v_maj, v_min);
180 if (*wMaj == v_maj)
182 if (*wMin == v_min)
184 best_min = v_min;
185 break; /* exact match */
187 if (v_min > best_min) best_min = v_min;
190 len = sizeof(key_name);
192 RegCloseKey( hkey );
193 if (best_min >= 0)
195 *wMin = best_min;
196 return TRUE;
198 return FALSE;
201 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
202 /* buffer must be at least 60 characters long */
203 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
205 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
206 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
208 memcpy( buffer, TypelibW, sizeof(TypelibW) );
209 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
210 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
211 return buffer;
214 /* get the path of an interface key, in the form "Interface\\<guid>" */
215 /* buffer must be at least 50 characters long */
216 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
218 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
220 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
221 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
222 return buffer;
225 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
226 /* buffer must be at least 16 characters long */
227 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
229 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
230 static const WCHAR win16W[] = {'w','i','n','1','6',0};
231 static const WCHAR win32W[] = {'w','i','n','3','2',0};
233 sprintfW( buffer, LcidFormatW, lcid );
234 switch(syskind)
236 case SYS_WIN16: strcatW( buffer, win16W ); break;
237 case SYS_WIN32: strcatW( buffer, win32W ); break;
238 default:
239 TRACE("Typelib is for unsupported syskind %i\n", syskind);
240 return NULL;
242 return buffer;
245 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
248 /****************************************************************************
249 * QueryPathOfRegTypeLib [OLEAUT32.164]
251 * Gets the path to a registered type library.
253 * PARAMS
254 * guid [I] referenced guid
255 * wMaj [I] major version
256 * wMin [I] minor version
257 * lcid [I] locale id
258 * path [O] path of typelib
260 * RETURNS
261 * Success: S_OK.
262 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
263 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
264 * opened.
266 HRESULT WINAPI QueryPathOfRegTypeLib(
267 REFGUID guid,
268 WORD wMaj,
269 WORD wMin,
270 LCID lcid,
271 LPBSTR path )
273 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
274 LCID myLCID = lcid;
275 HKEY hkey;
276 WCHAR buffer[60];
277 WCHAR Path[MAX_PATH];
278 LONG res;
280 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
282 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
283 get_typelib_key( guid, wMaj, wMin, buffer );
285 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
286 if (res == ERROR_FILE_NOT_FOUND)
288 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
289 return TYPE_E_LIBNOTREGISTERED;
291 else if (res != ERROR_SUCCESS)
293 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
294 return TYPE_E_REGISTRYACCESS;
297 while (hr != S_OK)
299 LONG dwPathLen = sizeof(Path);
301 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
303 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
305 if (!lcid)
306 break;
307 else if (myLCID == lcid)
309 /* try with sub-langid */
310 myLCID = SUBLANGID(lcid);
312 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
314 /* try with system langid */
315 myLCID = 0;
317 else
319 break;
322 else
324 *path = SysAllocString( Path );
325 hr = S_OK;
328 RegCloseKey( hkey );
329 TRACE_(typelib)("-- 0x%08x\n", hr);
330 return hr;
333 /******************************************************************************
334 * CreateTypeLib [OLEAUT32.160] creates a typelib
336 * RETURNS
337 * Success: S_OK
338 * Failure: Status
340 HRESULT WINAPI CreateTypeLib(
341 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
343 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
344 return E_FAIL;
347 /******************************************************************************
348 * LoadTypeLib [OLEAUT32.161]
350 * Loads a type library
352 * PARAMS
353 * szFile [I] Name of file to load from.
354 * pptLib [O] Pointer that receives ITypeLib object on success.
356 * RETURNS
357 * Success: S_OK
358 * Failure: Status
360 * SEE
361 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
363 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
365 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
366 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
369 /******************************************************************************
370 * LoadTypeLibEx [OLEAUT32.183]
372 * Loads and optionally registers a type library
374 * RETURNS
375 * Success: S_OK
376 * Failure: Status
378 HRESULT WINAPI LoadTypeLibEx(
379 LPCOLESTR szFile, /* [in] Name of file to load from */
380 REGKIND regkind, /* [in] Specify kind of registration */
381 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
383 WCHAR szPath[MAX_PATH+1];
384 HRESULT res;
386 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
388 *pptLib = NULL;
390 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
392 if (SUCCEEDED(res))
393 switch(regkind)
395 case REGKIND_DEFAULT:
396 /* don't register typelibs supplied with full path. Experimentation confirms the following */
397 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
398 (szFile[0] && (szFile[1] == ':'))) break;
399 /* else fall-through */
401 case REGKIND_REGISTER:
402 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
404 IUnknown_Release(*pptLib);
405 *pptLib = 0;
407 break;
408 case REGKIND_NONE:
409 break;
412 TRACE(" returns %08x\n",res);
413 return res;
416 /******************************************************************************
417 * LoadRegTypeLib [OLEAUT32.162]
419 * Loads a registered type library.
421 * PARAMS
422 * rguid [I] GUID of the registered type library.
423 * wVerMajor [I] major version.
424 * wVerMinor [I] minor version.
425 * lcid [I] locale ID.
426 * ppTLib [O] pointer that receives an ITypeLib object on success.
428 * RETURNS
429 * Success: S_OK.
430 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
431 * LoadTypeLib.
433 HRESULT WINAPI LoadRegTypeLib(
434 REFGUID rguid,
435 WORD wVerMajor,
436 WORD wVerMinor,
437 LCID lcid,
438 ITypeLib **ppTLib)
440 BSTR bstr=NULL;
441 HRESULT res;
443 *ppTLib = NULL;
445 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
447 if(SUCCEEDED(res))
449 res= LoadTypeLib(bstr, ppTLib);
450 SysFreeString(bstr);
453 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
455 return res;
459 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
460 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
461 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
462 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
463 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
464 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
466 /******************************************************************************
467 * RegisterTypeLib [OLEAUT32.163]
468 * Adds information about a type library to the System Registry
469 * NOTES
470 * Docs: ITypeLib FAR * ptlib
471 * Docs: OLECHAR FAR* szFullPath
472 * Docs: OLECHAR FAR* szHelpDir
474 * RETURNS
475 * Success: S_OK
476 * Failure: Status
478 HRESULT WINAPI RegisterTypeLib(
479 ITypeLib * ptlib, /* [in] Pointer to the library*/
480 OLECHAR * szFullPath, /* [in] full Path of the library*/
481 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
482 may be NULL*/
484 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
485 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
486 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
487 HRESULT res;
488 TLIBATTR *attr;
489 WCHAR keyName[60];
490 WCHAR tmp[16];
491 HKEY key, subKey;
492 UINT types, tidx;
493 TYPEKIND kind;
494 DWORD disposition;
496 if (ptlib == NULL || szFullPath == NULL)
497 return E_INVALIDARG;
499 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
500 return E_FAIL;
502 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
504 res = S_OK;
505 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
506 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
508 LPOLESTR doc;
510 /* Set the human-readable name of the typelib */
511 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
513 if (RegSetValueExW(key, NULL, 0, REG_SZ,
514 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
515 res = E_FAIL;
517 SysFreeString(doc);
519 else
520 res = E_FAIL;
522 /* Make up the name of the typelib path subkey */
523 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
525 /* Create the typelib path subkey */
526 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
527 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
529 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
530 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
531 res = E_FAIL;
533 RegCloseKey(subKey);
535 else
536 res = E_FAIL;
538 /* Create the flags subkey */
539 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
540 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
542 /* FIXME: is %u correct? */
543 static const WCHAR formatW[] = {'%','u',0};
544 WCHAR buf[20];
545 sprintfW(buf, formatW, attr->wLibFlags);
546 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
547 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
548 res = E_FAIL;
550 RegCloseKey(subKey);
552 else
553 res = E_FAIL;
555 /* create the helpdir subkey */
556 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
557 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
559 BOOL freeHelpDir = FALSE;
560 OLECHAR* pIndexStr;
562 /* if we created a new key, and helpDir was null, set the helpdir
563 to the directory which contains the typelib. However,
564 if we just opened an existing key, we leave the helpdir alone */
565 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
566 szHelpDir = SysAllocString(szFullPath);
567 pIndexStr = strrchrW(szHelpDir, '\\');
568 if (pIndexStr) {
569 *pIndexStr = 0;
571 freeHelpDir = TRUE;
574 /* if we have an szHelpDir, set it! */
575 if (szHelpDir != NULL) {
576 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
577 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
578 res = E_FAIL;
582 /* tidy up */
583 if (freeHelpDir) SysFreeString(szHelpDir);
584 RegCloseKey(subKey);
586 } else {
587 res = E_FAIL;
590 RegCloseKey(key);
592 else
593 res = E_FAIL;
595 /* register OLE Automation-compatible interfaces for this typelib */
596 types = ITypeLib_GetTypeInfoCount(ptlib);
597 for (tidx=0; tidx<types; tidx++) {
598 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
599 LPOLESTR name = NULL;
600 ITypeInfo *tinfo = NULL;
602 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
604 switch (kind) {
605 case TKIND_INTERFACE:
606 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
607 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
608 break;
610 case TKIND_DISPATCH:
611 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
612 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
613 break;
615 default:
616 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
617 break;
620 if (tinfo) {
621 TYPEATTR *tattr = NULL;
622 ITypeInfo_GetTypeAttr(tinfo, &tattr);
624 if (tattr) {
625 TRACE_(typelib)("guid=%s, flags=%04x (",
626 debugstr_guid(&tattr->guid),
627 tattr->wTypeFlags);
629 if (TRACE_ON(typelib)) {
630 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
631 XX(FAPPOBJECT);
632 XX(FCANCREATE);
633 XX(FLICENSED);
634 XX(FPREDECLID);
635 XX(FHIDDEN);
636 XX(FCONTROL);
637 XX(FDUAL);
638 XX(FNONEXTENSIBLE);
639 XX(FOLEAUTOMATION);
640 XX(FRESTRICTED);
641 XX(FAGGREGATABLE);
642 XX(FREPLACEABLE);
643 XX(FDISPATCHABLE);
644 XX(FREVERSEBIND);
645 XX(FPROXY);
646 #undef XX
647 MESSAGE("\n");
650 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
652 /* register interface<->typelib coupling */
653 get_interface_key( &tattr->guid, keyName );
654 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
655 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
657 if (name)
658 RegSetValueExW(key, NULL, 0, REG_SZ,
659 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
661 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
662 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
663 RegSetValueExW(subKey, NULL, 0, REG_SZ,
664 (const BYTE *)PSOA, sizeof PSOA);
665 RegCloseKey(subKey);
668 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
669 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
670 RegSetValueExW(subKey, NULL, 0, REG_SZ,
671 (const BYTE *)PSOA, sizeof PSOA);
672 RegCloseKey(subKey);
675 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
676 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
678 WCHAR buffer[40];
679 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
680 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
682 StringFromGUID2(&attr->guid, buffer, 40);
683 RegSetValueExW(subKey, NULL, 0, REG_SZ,
684 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
685 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
686 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
687 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
688 RegCloseKey(subKey);
691 RegCloseKey(key);
695 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
698 ITypeInfo_Release(tinfo);
701 SysFreeString(name);
705 ITypeLib_ReleaseTLibAttr(ptlib, attr);
707 return res;
711 /******************************************************************************
712 * UnRegisterTypeLib [OLEAUT32.186]
713 * Removes information about a type library from the System Registry
714 * NOTES
716 * RETURNS
717 * Success: S_OK
718 * Failure: Status
720 HRESULT WINAPI UnRegisterTypeLib(
721 REFGUID libid, /* [in] Guid of the library */
722 WORD wVerMajor, /* [in] major version */
723 WORD wVerMinor, /* [in] minor version */
724 LCID lcid, /* [in] locale id */
725 SYSKIND syskind)
727 BSTR tlibPath = NULL;
728 DWORD tmpLength;
729 WCHAR keyName[60];
730 WCHAR subKeyName[50];
731 int result = S_OK;
732 DWORD i = 0;
733 BOOL deleteOtherStuff;
734 HKEY key = NULL;
735 HKEY subKey = NULL;
736 TYPEATTR* typeAttr = NULL;
737 TYPEKIND kind;
738 ITypeInfo* typeInfo = NULL;
739 ITypeLib* typeLib = NULL;
740 int numTypes;
742 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
744 /* Create the path to the key */
745 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
747 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
749 TRACE("Unsupported syskind %i\n", syskind);
750 result = E_INVALIDARG;
751 goto end;
754 /* get the path to the typelib on disk */
755 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
756 result = E_INVALIDARG;
757 goto end;
760 /* Try and open the key to the type library. */
761 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
762 result = E_INVALIDARG;
763 goto end;
766 /* Try and load the type library */
767 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
768 result = TYPE_E_INVALIDSTATE;
769 goto end;
772 /* remove any types registered with this typelib */
773 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
774 for (i=0; i<numTypes; i++) {
775 /* get the kind of type */
776 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
777 goto enddeleteloop;
780 /* skip non-interfaces, and get type info for the type */
781 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
782 goto enddeleteloop;
784 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
785 goto enddeleteloop;
787 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
788 goto enddeleteloop;
791 /* the path to the type */
792 get_interface_key( &typeAttr->guid, subKeyName );
794 /* Delete its bits */
795 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
796 goto enddeleteloop;
798 RegDeleteKeyW(subKey, ProxyStubClsidW);
799 RegDeleteKeyW(subKey, ProxyStubClsid32W);
800 RegDeleteKeyW(subKey, TypeLibW);
801 RegCloseKey(subKey);
802 subKey = NULL;
803 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
805 enddeleteloop:
806 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
807 typeAttr = NULL;
808 if (typeInfo) ITypeInfo_Release(typeInfo);
809 typeInfo = NULL;
812 /* Now, delete the type library path subkey */
813 get_lcid_subkey( lcid, syskind, subKeyName );
814 RegDeleteKeyW(key, subKeyName);
815 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
816 RegDeleteKeyW(key, subKeyName);
818 /* check if there is anything besides the FLAGS/HELPDIR keys.
819 If there is, we don't delete them */
820 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
821 deleteOtherStuff = TRUE;
822 i = 0;
823 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
824 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
826 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
827 if (!strcmpW(subKeyName, FLAGSW)) continue;
828 if (!strcmpW(subKeyName, HELPDIRW)) continue;
829 deleteOtherStuff = FALSE;
830 break;
833 /* only delete the other parts of the key if we're absolutely sure */
834 if (deleteOtherStuff) {
835 RegDeleteKeyW(key, FLAGSW);
836 RegDeleteKeyW(key, HELPDIRW);
837 RegCloseKey(key);
838 key = NULL;
840 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
841 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
842 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
845 end:
846 if (tlibPath) SysFreeString(tlibPath);
847 if (typeLib) ITypeLib_Release(typeLib);
848 if (subKey) RegCloseKey(subKey);
849 if (key) RegCloseKey(key);
850 return result;
853 /*======================= ITypeLib implementation =======================*/
855 typedef struct tagTLBCustData
857 GUID guid;
858 VARIANT data;
859 struct tagTLBCustData* next;
860 } TLBCustData;
862 /* data structure for import typelibs */
863 typedef struct tagTLBImpLib
865 int offset; /* offset in the file (MSFT)
866 offset in nametable (SLTG)
867 just used to identify library while reading
868 data from file */
869 GUID guid; /* libid */
870 BSTR name; /* name */
872 LCID lcid; /* lcid of imported typelib */
874 WORD wVersionMajor; /* major version number */
875 WORD wVersionMinor; /* minor version number */
877 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
878 NULL if not yet loaded */
879 struct tagTLBImpLib * next;
880 } TLBImpLib;
882 /* internal ITypeLib data */
883 typedef struct tagITypeLibImpl
885 const ITypeLib2Vtbl *lpVtbl;
886 const ITypeCompVtbl *lpVtblTypeComp;
887 LONG ref;
888 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
890 /* strings can be stored in tlb as multibyte strings BUT they are *always*
891 * exported to the application as a UNICODE string.
893 BSTR Name;
894 BSTR DocString;
895 BSTR HelpFile;
896 BSTR HelpStringDll;
897 unsigned long dwHelpContext;
898 int TypeInfoCount; /* nr of typeinfo's in librarry */
899 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
900 int ctCustData; /* number of items in cust data list */
901 TLBCustData * pCustData; /* linked list to cust data */
902 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
903 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
904 libary. Only used while read MSFT
905 typelibs */
907 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
908 struct tagITypeLibImpl *next, *prev;
909 WCHAR *path;
910 INT index;
911 } ITypeLibImpl;
913 static const ITypeLib2Vtbl tlbvt;
914 static const ITypeCompVtbl tlbtcvt;
916 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
918 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
921 /* ITypeLib methods */
922 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
923 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
925 /*======================= ITypeInfo implementation =======================*/
927 /* data for referenced types */
928 typedef struct tagTLBRefType
930 INT index; /* Type index for internal ref or for external ref
931 it the format is SLTG. -2 indicates to
932 use guid */
934 GUID guid; /* guid of the referenced type */
935 /* if index == TLB_REF_USE_GUID */
937 HREFTYPE reference; /* The href of this ref */
938 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
939 TLB_REF_INTERNAL for internal refs
940 TLB_REF_NOT_FOUND for broken refs */
942 struct tagTLBRefType * next;
943 } TLBRefType;
945 #define TLB_REF_USE_GUID -2
947 #define TLB_REF_INTERNAL (void*)-2
948 #define TLB_REF_NOT_FOUND (void*)-1
950 /* internal Parameter data */
951 typedef struct tagTLBParDesc
953 BSTR Name;
954 int ctCustData;
955 TLBCustData * pCustData; /* linked list to cust data */
956 } TLBParDesc;
958 /* internal Function data */
959 typedef struct tagTLBFuncDesc
961 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
962 BSTR Name; /* the name of this function */
963 TLBParDesc *pParamDesc; /* array with param names and custom data */
964 int helpcontext;
965 int HelpStringContext;
966 BSTR HelpString;
967 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
968 int ctCustData;
969 TLBCustData * pCustData; /* linked list to cust data; */
970 struct tagTLBFuncDesc * next;
971 } TLBFuncDesc;
973 /* internal Variable data */
974 typedef struct tagTLBVarDesc
976 VARDESC vardesc; /* lots of info on the variable and its attributes. */
977 BSTR Name; /* the name of this variable */
978 int HelpContext;
979 int HelpStringContext; /* FIXME: where? */
980 BSTR HelpString;
981 int ctCustData;
982 TLBCustData * pCustData;/* linked list to cust data; */
983 struct tagTLBVarDesc * next;
984 } TLBVarDesc;
986 /* internal implemented interface data */
987 typedef struct tagTLBImplType
989 HREFTYPE hRef; /* hRef of interface */
990 int implflags; /* IMPLFLAG_*s */
991 int ctCustData;
992 TLBCustData * pCustData;/* linked list to custom data; */
993 struct tagTLBImplType *next;
994 } TLBImplType;
996 /* internal TypeInfo data */
997 typedef struct tagITypeInfoImpl
999 const ITypeInfo2Vtbl *lpVtbl;
1000 const ITypeCompVtbl *lpVtblTypeComp;
1001 LONG ref;
1002 BOOL no_free_data; /* don't free data structurees */
1003 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1004 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1005 int index; /* index in this typelib; */
1006 HREFTYPE hreftype; /* hreftype for app object binding */
1007 /* type libs seem to store the doc strings in ascii
1008 * so why should we do it in unicode?
1010 BSTR Name;
1011 BSTR DocString;
1012 BSTR DllName;
1013 unsigned long dwHelpContext;
1014 unsigned long dwHelpStringContext;
1016 /* functions */
1017 TLBFuncDesc * funclist; /* linked list with function descriptions */
1019 /* variables */
1020 TLBVarDesc * varlist; /* linked list with variable descriptions */
1022 /* Implemented Interfaces */
1023 TLBImplType * impltypelist;
1025 TLBRefType * reflist;
1026 int ctCustData;
1027 TLBCustData * pCustData; /* linked list to cust data; */
1028 struct tagITypeInfoImpl * next;
1029 } ITypeInfoImpl;
1031 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1033 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1036 static const ITypeInfo2Vtbl tinfvt;
1037 static const ITypeCompVtbl tcompvt;
1039 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1041 typedef struct tagTLBContext
1043 unsigned int oStart; /* start of TLB in file */
1044 unsigned int pos; /* current pos */
1045 unsigned int length; /* total length */
1046 void *mapping; /* memory mapping */
1047 MSFT_SegDir * pTblDir;
1048 ITypeLibImpl* pLibInfo;
1049 } TLBContext;
1052 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1055 debug
1057 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1058 if (pTD->vt & VT_RESERVED)
1059 szVarType += strlen(strcpy(szVarType, "reserved | "));
1060 if (pTD->vt & VT_BYREF)
1061 szVarType += strlen(strcpy(szVarType, "ref to "));
1062 if (pTD->vt & VT_ARRAY)
1063 szVarType += strlen(strcpy(szVarType, "array of "));
1064 if (pTD->vt & VT_VECTOR)
1065 szVarType += strlen(strcpy(szVarType, "vector of "));
1066 switch(pTD->vt & VT_TYPEMASK) {
1067 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1068 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1069 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1070 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1071 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1072 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1073 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1074 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1075 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1076 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1077 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1078 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1079 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1080 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1081 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1082 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1083 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1084 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1085 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1086 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1087 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1088 pTD->u.hreftype); break;
1089 case VT_PTR: sprintf(szVarType, "ptr to ");
1090 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1091 break;
1092 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1093 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1094 break;
1095 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1096 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1097 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1098 break;
1100 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1104 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1105 char buf[200];
1106 USHORT flags = edesc->u.paramdesc.wParamFlags;
1107 dump_TypeDesc(&edesc->tdesc,buf);
1108 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1109 MESSAGE("\t\tu.paramdesc.wParamFlags");
1110 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1111 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1112 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1113 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1114 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1115 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1116 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1117 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1118 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1120 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1121 int i;
1122 MESSAGE("memid is %08x\n",funcdesc->memid);
1123 for (i=0;i<funcdesc->cParams;i++) {
1124 MESSAGE("Param %d:\n",i);
1125 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1127 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1128 switch (funcdesc->funckind) {
1129 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1130 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1131 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1132 case FUNC_STATIC: MESSAGE("static");break;
1133 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1134 default: MESSAGE("unknown");break;
1136 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1137 switch (funcdesc->invkind) {
1138 case INVOKE_FUNC: MESSAGE("func");break;
1139 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1140 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1141 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1143 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1144 switch (funcdesc->callconv) {
1145 case CC_CDECL: MESSAGE("cdecl");break;
1146 case CC_PASCAL: MESSAGE("pascal");break;
1147 case CC_STDCALL: MESSAGE("stdcall");break;
1148 case CC_SYSCALL: MESSAGE("syscall");break;
1149 default:break;
1151 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1152 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1153 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1155 MESSAGE("\telemdescFunc (return value type):\n");
1156 dump_ELEMDESC(&funcdesc->elemdescFunc);
1159 static const char * typekind_desc[] =
1161 "TKIND_ENUM",
1162 "TKIND_RECORD",
1163 "TKIND_MODULE",
1164 "TKIND_INTERFACE",
1165 "TKIND_DISPATCH",
1166 "TKIND_COCLASS",
1167 "TKIND_ALIAS",
1168 "TKIND_UNION",
1169 "TKIND_MAX"
1172 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1174 int i;
1175 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1176 for (i=0;i<pfd->funcdesc.cParams;i++)
1177 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1180 dump_FUNCDESC(&(pfd->funcdesc));
1182 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1183 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1185 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1187 while (pfd)
1189 dump_TLBFuncDescOne(pfd);
1190 pfd = pfd->next;
1193 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1195 while (pvd)
1197 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1198 pvd = pvd->next;
1202 static void dump_TLBImpLib(const TLBImpLib *import)
1204 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1205 debugstr_w(import->name));
1206 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1207 import->wVersionMinor, import->lcid, import->offset);
1210 static void dump_TLBRefType(const TLBRefType * prt)
1212 while (prt)
1214 TRACE_(typelib)("href:0x%08x\n", prt->reference);
1215 if(prt->index == -1)
1216 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1217 else
1218 TRACE_(typelib)("type no: %d\n", prt->index);
1220 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1221 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1222 TRACE_(typelib)("in lib\n");
1223 dump_TLBImpLib(prt->pImpTLInfo);
1225 prt = prt->next;
1229 static void dump_TLBImplType(const TLBImplType * impl)
1231 while (impl) {
1232 TRACE_(typelib)(
1233 "implementing/inheriting interface hRef = %x implflags %x\n",
1234 impl->hRef, impl->implflags);
1235 impl = impl->next;
1239 void dump_Variant(const VARIANT * pvar)
1241 SYSTEMTIME st;
1243 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1245 if (pvar)
1247 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1248 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1250 TRACE(",%p", V_BYREF(pvar));
1252 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1254 TRACE(",%p", V_ARRAY(pvar));
1256 else switch (V_TYPE(pvar))
1258 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1259 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1260 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1261 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1262 case VT_INT:
1263 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1264 case VT_UINT:
1265 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1266 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1267 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1268 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1269 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1270 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1271 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1272 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1273 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1274 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1275 V_CY(pvar).s.Lo); break;
1276 case VT_DATE:
1277 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1278 TRACE(",<invalid>");
1279 else
1280 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1281 st.wHour, st.wMinute, st.wSecond);
1282 break;
1283 case VT_ERROR:
1284 case VT_VOID:
1285 case VT_USERDEFINED:
1286 case VT_EMPTY:
1287 case VT_NULL: break;
1288 default: TRACE(",?"); break;
1291 TRACE("}\n");
1294 static void dump_DispParms(const DISPPARAMS * pdp)
1296 int index;
1298 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1300 if (pdp->cNamedArgs)
1301 TRACE("named args:\n");
1302 for (index = 0; index < pdp->cNamedArgs; index++)
1303 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1305 if (pdp->cArgs)
1306 TRACE("args:\n");
1307 for (index = 0; index < pdp->cArgs; index++)
1308 dump_Variant( &pdp->rgvarg[index] );
1311 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1313 TRACE("%p ref=%u\n", pty, pty->ref);
1314 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1315 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1316 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1317 TRACE("fct:%u var:%u impl:%u\n",
1318 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1319 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1320 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1321 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1322 if (TRACE_ON(ole))
1323 dump_TLBFuncDesc(pty->funclist);
1324 dump_TLBVarDesc(pty->varlist);
1325 dump_TLBImplType(pty->impltypelist);
1328 static void dump_VARDESC(const VARDESC *v)
1330 MESSAGE("memid %d\n",v->memid);
1331 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1332 MESSAGE("oInst %d\n",v->u.oInst);
1333 dump_ELEMDESC(&(v->elemdescVar));
1334 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1335 MESSAGE("varkind %d\n",v->varkind);
1338 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1340 /* VT_LPWSTR is largest type that */
1341 /* may appear in type description*/
1342 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1343 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1344 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1345 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1346 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1347 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1348 {{0},30},{{0},31}
1351 static void TLB_abort(void)
1353 DebugBreak();
1355 static void * TLB_Alloc(unsigned size)
1357 void * ret;
1358 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1359 /* FIXME */
1360 ERR("cannot allocate memory\n");
1362 return ret;
1365 static void TLB_Free(void * ptr)
1367 HeapFree(GetProcessHeap(), 0, ptr);
1370 /* returns the size required for a deep copy of a typedesc into a
1371 * flat buffer */
1372 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1374 SIZE_T size = 0;
1376 if (alloc_initial_space)
1377 size += sizeof(TYPEDESC);
1379 switch (tdesc->vt)
1381 case VT_PTR:
1382 case VT_SAFEARRAY:
1383 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1384 break;
1385 case VT_CARRAY:
1386 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1387 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1388 break;
1390 return size;
1393 /* deep copy a typedesc into a flat buffer */
1394 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1396 if (!dest)
1398 dest = buffer;
1399 buffer = (char *)buffer + sizeof(TYPEDESC);
1402 *dest = *src;
1404 switch (src->vt)
1406 case VT_PTR:
1407 case VT_SAFEARRAY:
1408 dest->u.lptdesc = buffer;
1409 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1410 break;
1411 case VT_CARRAY:
1412 dest->u.lpadesc = buffer;
1413 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1414 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1415 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1416 break;
1418 return buffer;
1421 /**********************************************************************
1423 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1425 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1427 return pcx->pos;
1430 static inline void MSFT_Seek(TLBContext *pcx, long where)
1432 if (where != DO_NOT_SEEK)
1434 where += pcx->oStart;
1435 if (where > pcx->length)
1437 /* FIXME */
1438 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1439 TLB_abort();
1441 pcx->pos = where;
1445 /* read function */
1446 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1448 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1449 pcx->pos, count, pcx->oStart, pcx->length, where);
1451 MSFT_Seek(pcx, where);
1452 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1453 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1454 pcx->pos += count;
1455 return count;
1458 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1459 long where )
1461 DWORD ret;
1463 ret = MSFT_Read(buffer, count, pcx, where);
1464 FromLEDWords(buffer, ret);
1466 return ret;
1469 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1470 long where )
1472 DWORD ret;
1474 ret = MSFT_Read(buffer, count, pcx, where);
1475 FromLEWords(buffer, ret);
1477 return ret;
1480 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1482 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1483 memset(pGuid,0, sizeof(GUID));
1484 return;
1486 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1487 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1488 pGuid->Data2 = FromLEWord(pGuid->Data2);
1489 pGuid->Data3 = FromLEWord(pGuid->Data3);
1490 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1493 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1495 MSFT_NameIntro niName;
1497 if (offset < 0)
1499 ERR_(typelib)("bad offset %d\n", offset);
1500 return -1;
1503 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1504 pcx->pTblDir->pNametab.offset+offset);
1506 return niName.hreftype;
1509 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1511 char * name;
1512 MSFT_NameIntro niName;
1513 int lengthInChars;
1514 BSTR bstrName = NULL;
1516 if (offset < 0)
1518 ERR_(typelib)("bad offset %d\n", offset);
1519 return NULL;
1521 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1522 pcx->pTblDir->pNametab.offset+offset);
1523 niName.namelen &= 0xFF; /* FIXME: correct ? */
1524 name=TLB_Alloc((niName.namelen & 0xff) +1);
1525 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1526 name[niName.namelen & 0xff]='\0';
1528 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1529 name, -1, NULL, 0);
1531 /* no invalid characters in string */
1532 if (lengthInChars)
1534 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1536 /* don't check for invalid character since this has been done previously */
1537 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1539 TLB_Free(name);
1541 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1542 return bstrName;
1545 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1547 char * string;
1548 INT16 length;
1549 int lengthInChars;
1550 BSTR bstr = NULL;
1552 if(offset<0) return NULL;
1553 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1554 if(length <= 0) return 0;
1555 string=TLB_Alloc(length +1);
1556 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1557 string[length]='\0';
1559 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1560 string, -1, NULL, 0);
1562 /* no invalid characters in string */
1563 if (lengthInChars)
1565 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1567 /* don't check for invalid character since this has been done previously */
1568 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1570 TLB_Free(string);
1572 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1573 return bstr;
1576 * read a value and fill a VARIANT structure
1578 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1580 int size;
1582 TRACE_(typelib)("\n");
1584 if(offset <0) { /* data are packed in here */
1585 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1586 V_I4(pVar) = offset & 0x3ffffff;
1587 return;
1589 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1590 pcx->pTblDir->pCustData.offset + offset );
1591 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1592 switch (V_VT(pVar)){
1593 case VT_EMPTY: /* FIXME: is this right? */
1594 case VT_NULL: /* FIXME: is this right? */
1595 case VT_I2 : /* this should not happen */
1596 case VT_I4 :
1597 case VT_R4 :
1598 case VT_ERROR :
1599 case VT_BOOL :
1600 case VT_I1 :
1601 case VT_UI1 :
1602 case VT_UI2 :
1603 case VT_UI4 :
1604 case VT_INT :
1605 case VT_UINT :
1606 case VT_VOID : /* FIXME: is this right? */
1607 case VT_HRESULT :
1608 size=4; break;
1609 case VT_R8 :
1610 case VT_CY :
1611 case VT_DATE :
1612 case VT_I8 :
1613 case VT_UI8 :
1614 case VT_DECIMAL : /* FIXME: is this right? */
1615 case VT_FILETIME :
1616 size=8;break;
1617 /* pointer types with known behaviour */
1618 case VT_BSTR :{
1619 char * ptr;
1620 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1621 if(size < 0) {
1622 char next;
1623 DWORD origPos = MSFT_Tell(pcx), nullPos;
1625 do {
1626 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1627 } while (next);
1628 nullPos = MSFT_Tell(pcx);
1629 size = nullPos - origPos;
1630 MSFT_Seek(pcx, origPos);
1632 ptr=TLB_Alloc(size);/* allocate temp buffer */
1633 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1634 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1635 /* FIXME: do we need a AtoW conversion here? */
1636 V_UNION(pVar, bstrVal[size])=L'\0';
1637 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1638 TLB_Free(ptr);
1640 size=-4; break;
1641 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1642 case VT_DISPATCH :
1643 case VT_VARIANT :
1644 case VT_UNKNOWN :
1645 case VT_PTR :
1646 case VT_SAFEARRAY :
1647 case VT_CARRAY :
1648 case VT_USERDEFINED :
1649 case VT_LPSTR :
1650 case VT_LPWSTR :
1651 case VT_BLOB :
1652 case VT_STREAM :
1653 case VT_STORAGE :
1654 case VT_STREAMED_OBJECT :
1655 case VT_STORED_OBJECT :
1656 case VT_BLOB_OBJECT :
1657 case VT_CF :
1658 case VT_CLSID :
1659 default:
1660 size=0;
1661 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1662 V_VT(pVar));
1665 if(size>0) /* (big|small) endian correct? */
1666 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1667 return;
1670 * create a linked list with custom data
1672 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1674 MSFT_CDGuid entry;
1675 TLBCustData* pNew;
1676 int count=0;
1678 TRACE_(typelib)("\n");
1680 while(offset >=0){
1681 count++;
1682 pNew=TLB_Alloc(sizeof(TLBCustData));
1683 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1684 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1685 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1686 /* add new custom data at head of the list */
1687 pNew->next=*ppCustData;
1688 *ppCustData=pNew;
1689 offset = entry.next;
1691 return count;
1694 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1695 ITypeInfoImpl *pTI)
1697 if(type <0)
1698 pTd->vt=type & VT_TYPEMASK;
1699 else
1700 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1702 if(pTd->vt == VT_USERDEFINED)
1703 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1705 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1708 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1710 /* resolve referenced type if any */
1711 while (lpTypeDesc)
1713 switch (lpTypeDesc->vt)
1715 case VT_PTR:
1716 lpTypeDesc = lpTypeDesc->u.lptdesc;
1717 break;
1719 case VT_CARRAY:
1720 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1721 break;
1723 case VT_USERDEFINED:
1724 MSFT_DoRefType(pcx, pTI,
1725 lpTypeDesc->u.hreftype);
1727 lpTypeDesc = NULL;
1728 break;
1730 default:
1731 lpTypeDesc = NULL;
1736 static void
1737 MSFT_DoFuncs(TLBContext* pcx,
1738 ITypeInfoImpl* pTI,
1739 int cFuncs,
1740 int cVars,
1741 int offset,
1742 TLBFuncDesc** pptfd)
1745 * member information is stored in a data structure at offset
1746 * indicated by the memoffset field of the typeinfo structure
1747 * There are several distinctive parts.
1748 * The first part starts with a field that holds the total length
1749 * of this (first) part excluding this field. Then follow the records,
1750 * for each member there is one record.
1752 * The first entry is always the length of the record (including this
1753 * length word).
1754 * The rest of the record depends on the type of the member. If there is
1755 * a field indicating the member type (function, variable, interface, etc)
1756 * I have not found it yet. At this time we depend on the information
1757 * in the type info and the usual order how things are stored.
1759 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1760 * for each member;
1762 * Third is an equal sized array with file offsets to the name entry
1763 * of each member.
1765 * The fourth and last (?) part is an array with offsets to the records
1766 * in the first part of this file segment.
1769 int infolen, nameoffset, reclength, nrattributes, i;
1770 int recoffset = offset + sizeof(INT);
1772 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1773 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1774 TLBFuncDesc *ptfd_prev = NULL;
1776 TRACE_(typelib)("\n");
1778 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1780 for ( i = 0; i < cFuncs ; i++ )
1782 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1784 /* name, eventually add to a hash table */
1785 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1786 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1788 /* nameoffset is sometimes -1 on the second half of a propget/propput
1789 * pair of functions */
1790 if ((nameoffset == -1) && (i > 0))
1791 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1792 else
1793 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1795 /* read the function information record */
1796 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1798 reclength &= 0xffff;
1800 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1802 /* do the attributes */
1803 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1804 / sizeof(int);
1806 if ( nrattributes > 0 )
1808 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1810 if ( nrattributes > 1 )
1812 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1813 pFuncRec->OptAttr[1]) ;
1815 if ( nrattributes > 2 )
1817 if ( pFuncRec->FKCCIC & 0x2000 )
1819 (*pptfd)->Entry = SysAllocString((WCHAR*)pFuncRec->OptAttr[2]);
1821 else
1823 (*pptfd)->Entry = MSFT_ReadString(pcx,
1824 pFuncRec->OptAttr[2]);
1826 if( nrattributes > 5 )
1828 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1830 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1832 MSFT_CustData(pcx,
1833 pFuncRec->OptAttr[6],
1834 &(*pptfd)->pCustData);
1841 /* fill the FuncDesc Structure */
1842 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1843 offset + infolen + ( i + 1) * sizeof(INT));
1845 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1846 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1847 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1848 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1849 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1850 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1851 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1853 MSFT_GetTdesc(pcx,
1854 pFuncRec->DataType,
1855 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1856 pTI);
1857 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1859 /* do the parameters/arguments */
1860 if(pFuncRec->nrargs)
1862 int j = 0;
1863 MSFT_ParameterInfo paraminfo;
1865 (*pptfd)->funcdesc.lprgelemdescParam =
1866 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1868 (*pptfd)->pParamDesc =
1869 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1871 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1872 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1874 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1876 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1878 MSFT_GetTdesc(pcx,
1879 paraminfo.DataType,
1880 &elemdesc->tdesc,
1881 pTI);
1883 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1885 /* name */
1886 if (paraminfo.oName == -1)
1887 /* this occurs for [propput] or [propget] methods, so
1888 * we should just set the name of the parameter to the
1889 * name of the method. */
1890 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1891 else
1892 (*pptfd)->pParamDesc[j].Name =
1893 MSFT_ReadName( pcx, paraminfo.oName );
1894 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1896 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1898 /* default value */
1899 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1900 (pFuncRec->FKCCIC & 0x1000) )
1902 INT* pInt = (INT *)((char *)pFuncRec +
1903 reclength -
1904 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1906 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1908 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1909 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1911 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1912 pInt[j], pcx);
1914 else
1915 elemdesc->u.paramdesc.pparamdescex = NULL;
1916 /* custom info */
1917 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1919 MSFT_CustData(pcx,
1920 pFuncRec->OptAttr[7+j],
1921 &(*pptfd)->pParamDesc[j].pCustData);
1924 /* SEEK value = jump to offset,
1925 * from there jump to the end of record,
1926 * go back by (j-1) arguments
1928 MSFT_ReadLEDWords( &paraminfo ,
1929 sizeof(MSFT_ParameterInfo), pcx,
1930 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1931 * sizeof(MSFT_ParameterInfo)));
1935 /* scode is not used: archaic win16 stuff FIXME: right? */
1936 (*pptfd)->funcdesc.cScodes = 0 ;
1937 (*pptfd)->funcdesc.lprgscode = NULL ;
1939 ptfd_prev = *pptfd;
1940 pptfd = & ((*pptfd)->next);
1941 recoffset += reclength;
1943 HeapFree(GetProcessHeap(), 0, recbuf);
1946 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1947 int cVars, int offset, TLBVarDesc ** pptvd)
1949 int infolen, nameoffset, reclength;
1950 char recbuf[256];
1951 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1952 int i;
1953 int recoffset;
1955 TRACE_(typelib)("\n");
1957 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1958 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1959 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1960 recoffset += offset+sizeof(INT);
1961 for(i=0;i<cVars;i++){
1962 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1963 /* name, eventually add to a hash table */
1964 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1965 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1966 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1967 /* read the variable information record */
1968 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1969 reclength &=0xff;
1970 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1971 /* Optional data */
1972 if(reclength >(6*sizeof(INT)) )
1973 (*pptvd)->HelpContext=pVarRec->HelpContext;
1974 if(reclength >(7*sizeof(INT)) )
1975 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1976 if(reclength >(8*sizeof(INT)) )
1977 if(reclength >(9*sizeof(INT)) )
1978 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1979 /* fill the VarDesc Structure */
1980 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1981 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1982 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1983 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1984 MSFT_GetTdesc(pcx, pVarRec->DataType,
1985 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1986 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1987 if(pVarRec->VarKind == VAR_CONST ){
1988 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1989 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1990 pVarRec->OffsValue, pcx);
1991 } else
1992 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1993 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1994 pptvd=&((*pptvd)->next);
1995 recoffset += reclength;
1998 /* fill in data for a hreftype (offset). When the referenced type is contained
1999 * in the typelib, it's just an (file) offset in the type info base dir.
2000 * If comes from import, it's an offset+1 in the ImpInfo table
2001 * */
2002 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
2003 int offset)
2005 int j;
2006 TLBRefType **ppRefType = &pTI->reflist;
2008 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2010 while(*ppRefType) {
2011 if((*ppRefType)->reference == offset)
2012 return;
2013 ppRefType = &(*ppRefType)->next;
2016 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2017 sizeof(**ppRefType));
2019 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2020 /* external typelib */
2021 MSFT_ImpInfo impinfo;
2022 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2024 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2026 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2027 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2028 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2029 if(pImpLib->offset==impinfo.oImpFile) break;
2030 pImpLib=pImpLib->next;
2032 if(pImpLib){
2033 (*ppRefType)->reference=offset;
2034 (*ppRefType)->pImpTLInfo = pImpLib;
2035 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2036 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2037 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
2038 (*ppRefType)->index = TLB_REF_USE_GUID;
2039 } else
2040 (*ppRefType)->index = impinfo.oGuid;
2041 }else{
2042 ERR("Cannot find a reference\n");
2043 (*ppRefType)->reference=-1;
2044 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2046 }else{
2047 /* in this typelib */
2048 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2049 (*ppRefType)->reference=offset;
2050 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2054 /* process Implemented Interfaces of a com class */
2055 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2056 int offset)
2058 int i;
2059 MSFT_RefRecord refrec;
2060 TLBImplType **ppImpl = &pTI->impltypelist;
2062 TRACE_(typelib)("\n");
2064 for(i=0;i<count;i++){
2065 if(offset<0) break; /* paranoia */
2066 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2067 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2068 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2069 (*ppImpl)->hRef = refrec.reftype;
2070 (*ppImpl)->implflags=refrec.flags;
2071 (*ppImpl)->ctCustData=
2072 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2073 offset=refrec.onext;
2074 ppImpl=&((*ppImpl)->next);
2078 * process a typeinfo record
2080 static ITypeInfoImpl * MSFT_DoTypeInfo(
2081 TLBContext *pcx,
2082 int count,
2083 INT dispatch_href,
2084 ITypeLibImpl * pLibInfo)
2086 MSFT_TypeInfoBase tiBase;
2087 ITypeInfoImpl *ptiRet;
2089 TRACE_(typelib)("count=%u\n", count);
2091 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2092 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2093 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2095 /* this is where we are coming from */
2096 ptiRet->pTypeLib = pLibInfo;
2097 ptiRet->index=count;
2098 /* fill in the typeattr fields */
2100 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2101 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2102 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2103 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2104 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2105 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2106 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2107 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2108 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2109 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2110 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2111 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2112 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2113 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2114 MSFT_GetTdesc(pcx, tiBase.datatype1,
2115 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2117 /* FIXME: */
2118 /* IDLDESC idldescType; *//* never saw this one != zero */
2120 /* name, eventually add to a hash table */
2121 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2122 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2123 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2124 /* help info */
2125 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2126 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2127 ptiRet->dwHelpContext=tiBase.helpcontext;
2129 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2130 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2132 /* note: InfoType's Help file and HelpStringDll come from the containing
2133 * library. Further HelpString and Docstring appear to be the same thing :(
2135 /* functions */
2136 if(ptiRet->TypeAttr.cFuncs >0 )
2137 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2138 ptiRet->TypeAttr.cVars,
2139 tiBase.memoffset, & ptiRet->funclist);
2140 /* variables */
2141 if(ptiRet->TypeAttr.cVars >0 )
2142 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2143 ptiRet->TypeAttr.cVars,
2144 tiBase.memoffset, & ptiRet->varlist);
2145 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2146 switch(ptiRet->TypeAttr.typekind)
2148 case TKIND_COCLASS:
2149 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2150 tiBase.datatype1);
2151 break;
2152 case TKIND_DISPATCH:
2153 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2155 if (tiBase.datatype1 != -1)
2157 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2158 ptiRet->impltypelist->hRef = tiBase.datatype1;
2160 else
2162 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2163 ptiRet->impltypelist->hRef = dispatch_href;
2165 break;
2166 default:
2167 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2168 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2169 ptiRet->impltypelist->hRef = tiBase.datatype1;
2170 break;
2173 ptiRet->ctCustData=
2174 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2176 TRACE_(typelib)("%s guid: %s kind:%s\n",
2177 debugstr_w(ptiRet->Name),
2178 debugstr_guid(&ptiRet->TypeAttr.guid),
2179 typekind_desc[ptiRet->TypeAttr.typekind]);
2181 return ptiRet;
2184 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2185 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2186 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2187 * tradeoff here.
2189 static ITypeLibImpl *tlb_cache_first;
2190 static CRITICAL_SECTION cache_section;
2191 static CRITICAL_SECTION_DEBUG cache_section_debug =
2193 0, 0, &cache_section,
2194 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2195 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2197 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2200 /****************************************************************************
2201 * TLB_ReadTypeLib
2203 * find the type of the typelib file and map the typelib resource into
2204 * the memory
2206 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2207 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2208 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2210 ITypeLibImpl *entry;
2211 int ret = TYPE_E_CANTLOADLIBRARY;
2212 INT index = 1;
2213 HINSTANCE hinstDLL;
2215 *ppTypeLib = NULL;
2217 lstrcpynW(pszPath, pszFileName, cchPath);
2219 /* first try loading as a dll and access the typelib as a resource */
2220 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2221 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2222 if (!hinstDLL)
2224 /* it may have been specified with resource index appended to the
2225 * path, so remove it and try again */
2226 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2227 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2229 index = atoiW(pIndexStr);
2230 pszPath[pIndexStr - pszFileName - 1] = '\0';
2232 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2233 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2237 /* get the path to the specified typelib file */
2238 if (!hinstDLL)
2240 /* otherwise, try loading as a regular file */
2241 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2242 return TYPE_E_CANTLOADLIBRARY;
2245 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2247 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2248 EnterCriticalSection(&cache_section);
2249 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2251 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2253 TRACE("cache hit\n");
2254 *ppTypeLib = (ITypeLib2*)entry;
2255 ITypeLib_AddRef(*ppTypeLib);
2256 LeaveCriticalSection(&cache_section);
2257 FreeLibrary(hinstDLL);
2258 return S_OK;
2261 LeaveCriticalSection(&cache_section);
2263 /* now actually load and parse the typelib */
2264 if (hinstDLL)
2266 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2267 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2268 if (hrsrc)
2270 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2271 if (hGlobal)
2273 LPVOID pBase = LockResource(hGlobal);
2274 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2276 if (pBase)
2278 /* try to load as incore resource */
2279 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2280 if (dwSignature == MSFT_SIGNATURE)
2281 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2282 else if (dwSignature == SLTG_SIGNATURE)
2283 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2284 else
2285 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2287 FreeResource( hGlobal );
2290 FreeLibrary(hinstDLL);
2292 else
2294 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2295 if (INVALID_HANDLE_VALUE != hFile)
2297 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2298 if (hMapping)
2300 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2301 if(pBase)
2303 /* retrieve file size */
2304 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2305 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2307 if (dwSignature == MSFT_SIGNATURE)
2308 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2309 else if (dwSignature == SLTG_SIGNATURE)
2310 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2312 UnmapViewOfFile(pBase);
2314 CloseHandle(hMapping);
2316 CloseHandle(hFile);
2320 if(*ppTypeLib) {
2321 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2323 TRACE("adding to cache\n");
2324 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2325 lstrcpyW(impl->path, pszPath);
2326 /* We should really canonicalise the path here. */
2327 impl->index = index;
2329 /* FIXME: check if it has added already in the meantime */
2330 EnterCriticalSection(&cache_section);
2331 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2332 impl->prev = NULL;
2333 tlb_cache_first = impl;
2334 LeaveCriticalSection(&cache_section);
2335 ret = S_OK;
2336 } else
2337 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2339 return ret;
2342 /*================== ITypeLib(2) Methods ===================================*/
2344 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2346 ITypeLibImpl* pTypeLibImpl;
2348 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2349 if (!pTypeLibImpl) return NULL;
2351 pTypeLibImpl->lpVtbl = &tlbvt;
2352 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2353 pTypeLibImpl->ref = 1;
2355 return pTypeLibImpl;
2358 /****************************************************************************
2359 * ITypeLib2_Constructor_MSFT
2361 * loading an MSFT typelib from an in-memory image
2363 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2365 TLBContext cx;
2366 long lPSegDir;
2367 MSFT_Header tlbHeader;
2368 MSFT_SegDir tlbSegDir;
2369 ITypeLibImpl * pTypeLibImpl;
2371 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2373 pTypeLibImpl = TypeLibImpl_Constructor();
2374 if (!pTypeLibImpl) return NULL;
2376 /* get pointer to beginning of typelib data */
2377 cx.pos = 0;
2378 cx.oStart=0;
2379 cx.mapping = pLib;
2380 cx.pLibInfo = pTypeLibImpl;
2381 cx.length = dwTLBLength;
2383 /* read header */
2384 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2385 TRACE_(typelib)("header:\n");
2386 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2387 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2388 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2389 return NULL;
2391 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2393 /* there is a small amount of information here until the next important
2394 * part:
2395 * the segment directory . Try to calculate the amount of data */
2396 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2398 /* now read the segment directory */
2399 TRACE("read segment directory (at %ld)\n",lPSegDir);
2400 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2401 cx.pTblDir = &tlbSegDir;
2403 /* just check two entries */
2404 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2406 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2407 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2408 return NULL;
2411 /* now fill our internal data */
2412 /* TLIBATTR fields */
2413 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2415 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2416 /* Windows seems to have zero here, is this correct? */
2417 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2418 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2419 else
2420 pTypeLibImpl->LibAttr.lcid = 0;
2422 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2423 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2424 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2425 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2427 /* name, eventually add to a hash table */
2428 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2430 /* help info */
2431 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2432 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2434 if( tlbHeader.varflags & HELPDLLFLAG)
2436 int offset;
2437 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2438 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2441 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2443 /* custom data */
2444 if(tlbHeader.CustomDataOffset >= 0)
2446 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2449 /* fill in typedescriptions */
2450 if(tlbSegDir.pTypdescTab.length > 0)
2452 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2453 INT16 td[4];
2454 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2455 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2456 for(i=0; i<cTD; )
2458 /* FIXME: add several sanity checks here */
2459 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2460 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2462 /* FIXME: check safearray */
2463 if(td[3] < 0)
2464 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2465 else
2466 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2468 else if(td[0] == VT_CARRAY)
2470 /* array descr table here */
2471 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2473 else if(td[0] == VT_USERDEFINED)
2475 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2477 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2480 /* second time around to fill the array subscript info */
2481 for(i=0;i<cTD;i++)
2483 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2484 if(tlbSegDir.pArrayDescriptions.offset>0)
2486 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2487 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2489 if(td[1]<0)
2490 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2491 else
2492 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2494 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2496 for(j = 0; j<td[2]; j++)
2498 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2499 sizeof(INT), &cx, DO_NOT_SEEK);
2500 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2501 sizeof(INT), &cx, DO_NOT_SEEK);
2504 else
2506 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2507 ERR("didn't find array description data\n");
2512 /* imported type libs */
2513 if(tlbSegDir.pImpFiles.offset>0)
2515 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2516 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2517 UINT16 size;
2519 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2521 char *name;
2522 DWORD len;
2524 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2525 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2526 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2528 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2529 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2530 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2531 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2533 size >>= 2;
2534 name = TLB_Alloc(size+1);
2535 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2536 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2537 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2538 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2539 TLB_Free(name);
2541 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2542 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2544 ppImpLib = &(*ppImpLib)->next;
2548 /* type info's */
2549 if(tlbHeader.nrtypeinfos >= 0 )
2551 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2552 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2553 int i;
2555 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2557 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2559 ppTI = &((*ppTI)->next);
2560 (pTypeLibImpl->TypeInfoCount)++;
2564 TRACE("(%p)\n", pTypeLibImpl);
2565 return (ITypeLib2*) pTypeLibImpl;
2569 static BSTR TLB_MultiByteToBSTR(char *ptr)
2571 DWORD len;
2572 WCHAR *nameW;
2573 BSTR ret;
2575 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2576 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2577 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2578 ret = SysAllocString(nameW);
2579 HeapFree(GetProcessHeap(), 0, nameW);
2580 return ret;
2583 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2585 char b[3];
2586 int i;
2587 short s;
2589 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2590 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2591 return FALSE;
2594 guid->Data4[0] = s >> 8;
2595 guid->Data4[1] = s & 0xff;
2597 b[2] = '\0';
2598 for(i = 0; i < 6; i++) {
2599 memcpy(b, str + 24 + 2 * i, 2);
2600 guid->Data4[i + 2] = strtol(b, NULL, 16);
2602 return TRUE;
2605 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2607 WORD bytelen;
2608 DWORD len;
2609 WCHAR *nameW;
2611 *pBstr = NULL;
2612 bytelen = *(WORD*)ptr;
2613 if(bytelen == 0xffff) return 2;
2614 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2615 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2616 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2617 *pBstr = SysAllocStringLen(nameW, len);
2618 HeapFree(GetProcessHeap(), 0, nameW);
2619 return bytelen + 2;
2622 static WORD SLTG_ReadStringA(char *ptr, char **str)
2624 WORD bytelen;
2626 *str = NULL;
2627 bytelen = *(WORD*)ptr;
2628 if(bytelen == 0xffff) return 2;
2629 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2630 memcpy(*str, ptr + 2, bytelen);
2631 (*str)[bytelen] = '\0';
2632 return bytelen + 2;
2635 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2637 char *ptr = pLibBlk;
2638 WORD w;
2640 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2641 FIXME("libblk magic = %04x\n", w);
2642 return 0;
2645 ptr += 6;
2646 if((w = *(WORD*)ptr) != 0xffff) {
2647 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2648 ptr += w;
2650 ptr += 2;
2652 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2654 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2656 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2657 ptr += 4;
2659 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2660 ptr += 2;
2662 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2663 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2664 else
2665 pTypeLibImpl->LibAttr.lcid = 0;
2666 ptr += 2;
2668 ptr += 4; /* skip res12 */
2670 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2671 ptr += 2;
2673 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2674 ptr += 2;
2676 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2677 ptr += 2;
2679 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2680 ptr += sizeof(GUID);
2682 return ptr - (char*)pLibBlk;
2685 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2687 BOOL done = FALSE;
2689 while(!done) {
2690 if((*pType & 0xe00) == 0xe00) {
2691 pTD->vt = VT_PTR;
2692 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2693 sizeof(TYPEDESC));
2694 pTD = pTD->u.lptdesc;
2696 switch(*pType & 0x3f) {
2697 case VT_PTR:
2698 pTD->vt = VT_PTR;
2699 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2700 sizeof(TYPEDESC));
2701 pTD = pTD->u.lptdesc;
2702 break;
2704 case VT_USERDEFINED:
2705 pTD->vt = VT_USERDEFINED;
2706 pTD->u.hreftype = *(++pType) / 4;
2707 done = TRUE;
2708 break;
2710 case VT_CARRAY:
2712 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2713 array */
2715 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2717 pTD->vt = VT_CARRAY;
2718 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2719 sizeof(ARRAYDESC) +
2720 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2721 pTD->u.lpadesc->cDims = pSA->cDims;
2722 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2723 pSA->cDims * sizeof(SAFEARRAYBOUND));
2725 pTD = &pTD->u.lpadesc->tdescElem;
2726 break;
2729 case VT_SAFEARRAY:
2731 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2732 useful? */
2734 pType++;
2735 pTD->vt = VT_SAFEARRAY;
2736 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2737 sizeof(TYPEDESC));
2738 pTD = pTD->u.lptdesc;
2739 break;
2741 default:
2742 pTD->vt = *pType & 0x3f;
2743 done = TRUE;
2744 break;
2746 pType++;
2748 return pType;
2751 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2753 /* Handle [in/out] first */
2754 if((*pType & 0xc000) == 0xc000)
2755 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2756 else if(*pType & 0x8000)
2757 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2758 else if(*pType & 0x4000)
2759 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2760 else
2761 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2763 if(*pType & 0x2000)
2764 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2766 if(*pType & 0x80)
2767 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2769 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2773 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2774 char *pNameTable)
2776 int ref;
2777 char *name;
2778 TLBRefType **ppRefType;
2780 if(pRef->magic != SLTG_REF_MAGIC) {
2781 FIXME("Ref magic = %x\n", pRef->magic);
2782 return;
2784 name = ( (char*)(&pRef->names) + pRef->number);
2786 ppRefType = &pTI->reflist;
2787 for(ref = 0; ref < pRef->number >> 3; ref++) {
2788 char *refname;
2789 unsigned int lib_offs, type_num;
2791 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2792 sizeof(**ppRefType));
2794 name += SLTG_ReadStringA(name, &refname);
2795 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2796 FIXME("Can't sscanf ref\n");
2797 if(lib_offs != 0xffff) {
2798 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2800 while(*import) {
2801 if((*import)->offset == lib_offs)
2802 break;
2803 import = &(*import)->next;
2805 if(!*import) {
2806 char fname[MAX_PATH+1];
2807 int len;
2809 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2810 sizeof(**import));
2811 (*import)->offset = lib_offs;
2812 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2813 &(*import)->guid);
2814 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2815 &(*import)->wVersionMajor,
2816 &(*import)->wVersionMinor,
2817 &(*import)->lcid, fname) != 4) {
2818 FIXME("can't sscanf ref %s\n",
2819 pNameTable + lib_offs + 40);
2821 len = strlen(fname);
2822 if(fname[len-1] != '#')
2823 FIXME("fname = %s\n", fname);
2824 fname[len-1] = '\0';
2825 (*import)->name = TLB_MultiByteToBSTR(fname);
2827 (*ppRefType)->pImpTLInfo = *import;
2828 } else { /* internal ref */
2829 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2831 (*ppRefType)->reference = ref;
2832 (*ppRefType)->index = type_num;
2834 HeapFree(GetProcessHeap(), 0, refname);
2835 ppRefType = &(*ppRefType)->next;
2837 if((BYTE)*name != SLTG_REF_MAGIC)
2838 FIXME("End of ref block magic = %x\n", *name);
2839 dump_TLBRefType(pTI->reflist);
2842 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2843 BOOL OneOnly)
2845 SLTG_ImplInfo *info;
2846 TLBImplType **ppImplType = &pTI->impltypelist;
2847 /* I don't really get this structure, usually it's 0x16 bytes
2848 long, but iuser.tlb contains some that are 0x18 bytes long.
2849 That's ok because we can use the next ptr to jump to the next
2850 one. But how do we know the length of the last one? The WORD
2851 at offs 0x8 might be the clue. For now I'm just assuming that
2852 the last one is the regular 0x16 bytes. */
2854 info = (SLTG_ImplInfo*)pBlk;
2855 while(1) {
2856 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2857 sizeof(**ppImplType));
2858 (*ppImplType)->hRef = info->ref;
2859 (*ppImplType)->implflags = info->impltypeflags;
2860 pTI->TypeAttr.cImplTypes++;
2861 ppImplType = &(*ppImplType)->next;
2863 if(info->next == 0xffff)
2864 break;
2865 if(OneOnly)
2866 FIXME("Interface inheriting more than one interface\n");
2867 info = (SLTG_ImplInfo*)(pBlk + info->next);
2869 info++; /* see comment at top of function */
2870 return (char*)info;
2873 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2875 TLBVarDesc **ppVarDesc = &pTI->varlist;
2876 BSTR bstrPrevName = NULL;
2877 SLTG_Variable *pItem;
2878 unsigned short i;
2879 WORD *pType;
2880 char buf[300];
2882 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2883 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2885 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2886 sizeof(**ppVarDesc));
2887 (*ppVarDesc)->vardesc.memid = pItem->memid;
2889 if (pItem->magic != SLTG_VAR_MAGIC &&
2890 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2891 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2892 return;
2895 if (pItem->name == 0xfffe)
2896 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2897 else
2898 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2900 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2901 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2903 if (pItem->flags & 0x40) {
2904 TRACE_(typelib)("VAR_DISPATCH\n");
2905 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2907 else if (pItem->flags & 0x10) {
2908 TRACE_(typelib)("VAR_CONST\n");
2909 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2910 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2911 sizeof(VARIANT));
2912 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2913 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2914 *(INT*)(pBlk + pItem->byte_offs);
2916 else {
2917 TRACE_(typelib)("VAR_PERINSTANCE\n");
2918 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2919 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2922 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2923 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2925 if (pItem->flags & 0x80)
2926 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2928 if(pItem->flags & 0x02)
2929 pType = &pItem->type;
2930 else
2931 pType = (WORD*)(pBlk + pItem->type);
2933 if (pItem->flags & ~0xd2)
2934 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2936 SLTG_DoElem(pType, pBlk,
2937 &(*ppVarDesc)->vardesc.elemdescVar);
2939 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2941 bstrPrevName = (*ppVarDesc)->Name;
2942 ppVarDesc = &((*ppVarDesc)->next);
2944 pTI->TypeAttr.cVars = cVars;
2947 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2949 SLTG_Function *pFunc;
2950 unsigned short i;
2951 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2953 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2954 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2956 int param;
2957 WORD *pType, *pArg;
2959 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2960 sizeof(**ppFuncDesc));
2962 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2963 case SLTG_FUNCTION_MAGIC:
2964 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2965 break;
2966 case SLTG_DISPATCH_FUNCTION_MAGIC:
2967 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2968 break;
2969 case SLTG_STATIC_FUNCTION_MAGIC:
2970 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2971 break;
2972 default:
2973 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2974 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2975 *ppFuncDesc = NULL;
2976 return;
2978 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2980 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2981 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2982 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2983 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2984 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2985 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2987 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2988 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2990 if(pFunc->retnextopt & 0x80)
2991 pType = &pFunc->rettype;
2992 else
2993 pType = (WORD*)(pBlk + pFunc->rettype);
2995 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2997 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2998 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2999 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3000 (*ppFuncDesc)->pParamDesc =
3001 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3002 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3004 pArg = (WORD*)(pBlk + pFunc->arg_off);
3006 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3007 char *paramName = pNameTable + *pArg;
3008 BOOL HaveOffs;
3009 /* If arg type follows then paramName points to the 2nd
3010 letter of the name, else the next WORD is an offset to
3011 the arg type and paramName points to the first letter.
3012 So let's take one char off paramName and see if we're
3013 pointing at an alpha-numeric char. However if *pArg is
3014 0xffff or 0xfffe then the param has no name, the former
3015 meaning that the next WORD is the type, the latter
3016 meaning the the next WORD is an offset to the type. */
3018 HaveOffs = FALSE;
3019 if(*pArg == 0xffff)
3020 paramName = NULL;
3021 else if(*pArg == 0xfffe) {
3022 paramName = NULL;
3023 HaveOffs = TRUE;
3025 else if(paramName[-1] && !isalnum(paramName[-1]))
3026 HaveOffs = TRUE;
3028 pArg++;
3030 if(HaveOffs) { /* the next word is an offset to type */
3031 pType = (WORD*)(pBlk + *pArg);
3032 SLTG_DoElem(pType, pBlk,
3033 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3034 pArg++;
3035 } else {
3036 if(paramName)
3037 paramName--;
3038 pArg = SLTG_DoElem(pArg, pBlk,
3039 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3042 /* Are we an optional param ? */
3043 if((*ppFuncDesc)->funcdesc.cParams - param <=
3044 (*ppFuncDesc)->funcdesc.cParamsOpt)
3045 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3047 if(paramName) {
3048 (*ppFuncDesc)->pParamDesc[param].Name =
3049 TLB_MultiByteToBSTR(paramName);
3053 ppFuncDesc = &((*ppFuncDesc)->next);
3054 if(pFunc->next == 0xffff) break;
3056 pTI->TypeAttr.cFuncs = cFuncs;
3059 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3060 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3061 SLTG_TypeInfoTail *pTITail)
3063 char *pFirstItem, *pNextItem;
3065 if(pTIHeader->href_table != 0xffffffff) {
3066 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3067 pNameTable);
3070 pFirstItem = pNextItem = pBlk;
3072 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3073 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3078 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3079 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3080 SLTG_TypeInfoTail *pTITail)
3082 char *pFirstItem, *pNextItem;
3084 if(pTIHeader->href_table != 0xffffffff) {
3085 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3086 pNameTable);
3089 pFirstItem = pNextItem = pBlk;
3091 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3092 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3095 if (pTITail->funcs_off != 0xffff)
3096 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3098 if (TRACE_ON(typelib))
3099 dump_TLBFuncDesc(pTI->funclist);
3102 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3103 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3104 SLTG_TypeInfoTail *pTITail)
3106 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3109 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3110 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3111 SLTG_TypeInfoTail *pTITail)
3113 WORD *pType;
3115 if (pTITail->simple_alias) {
3116 /* if simple alias, no more processing required */
3117 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3118 return;
3121 if(pTIHeader->href_table != 0xffffffff) {
3122 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3123 pNameTable);
3126 /* otherwise it is an offset to a type */
3127 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3129 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3132 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3133 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3134 SLTG_TypeInfoTail *pTITail)
3136 if (pTIHeader->href_table != 0xffffffff)
3137 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3138 pNameTable);
3140 if (pTITail->vars_off != 0xffff)
3141 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3143 if (pTITail->funcs_off != 0xffff)
3144 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3146 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3147 * of dispinterface functons including the IDispatch ones, so
3148 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3149 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3151 if (TRACE_ON(typelib))
3152 dump_TLBFuncDesc(pTI->funclist);
3155 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3156 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3157 SLTG_TypeInfoTail *pTITail)
3159 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3162 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3163 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3164 SLTG_TypeInfoTail *pTITail)
3166 if (pTIHeader->href_table != 0xffffffff)
3167 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3168 pNameTable);
3170 if (pTITail->vars_off != 0xffff)
3171 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3173 if (pTITail->funcs_off != 0xffff)
3174 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3177 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3178 managable copy of it into this */
3179 typedef struct {
3180 WORD small_no;
3181 char *index_name;
3182 char *other_name;
3183 WORD res1a;
3184 WORD name_offs;
3185 WORD more_bytes;
3186 char *extra;
3187 WORD res20;
3188 DWORD helpcontext;
3189 WORD res26;
3190 GUID uuid;
3191 } SLTG_InternalOtherTypeInfo;
3193 /****************************************************************************
3194 * ITypeLib2_Constructor_SLTG
3196 * loading a SLTG typelib from an in-memory image
3198 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3200 ITypeLibImpl *pTypeLibImpl;
3201 SLTG_Header *pHeader;
3202 SLTG_BlkEntry *pBlkEntry;
3203 SLTG_Magic *pMagic;
3204 SLTG_Index *pIndex;
3205 SLTG_Pad9 *pPad9;
3206 LPVOID pBlk, pFirstBlk;
3207 SLTG_LibBlk *pLibBlk;
3208 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3209 char *pAfterOTIBlks = NULL;
3210 char *pNameTable, *ptr;
3211 int i;
3212 DWORD len, order;
3213 ITypeInfoImpl **ppTypeInfoImpl;
3215 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3218 pTypeLibImpl = TypeLibImpl_Constructor();
3219 if (!pTypeLibImpl) return NULL;
3221 pHeader = pLib;
3223 TRACE_(typelib)("header:\n");
3224 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3225 pHeader->nrOfFileBlks );
3226 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3227 FIXME("Header type magic 0x%08x not supported.\n",
3228 pHeader->SLTG_magic);
3229 return NULL;
3232 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3233 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3235 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3236 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3238 /* Next we have a magic block */
3239 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3241 /* Let's see if we're still in sync */
3242 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3243 sizeof(SLTG_COMPOBJ_MAGIC))) {
3244 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3245 return NULL;
3247 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3248 sizeof(SLTG_DIR_MAGIC))) {
3249 FIXME("dir magic = %s\n", pMagic->dir_magic);
3250 return NULL;
3253 pIndex = (SLTG_Index*)(pMagic+1);
3255 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3257 pFirstBlk = (LPVOID)(pPad9 + 1);
3259 /* We'll set up a ptr to the main library block, which is the last one. */
3261 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3262 pBlkEntry[order].next != 0;
3263 order = pBlkEntry[order].next - 1, i++) {
3264 pBlk = (char*)pBlk + pBlkEntry[order].len;
3266 pLibBlk = pBlk;
3268 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3270 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3271 interspersed */
3273 len += 0x40;
3275 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3277 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3278 sizeof(*pOtherTypeInfoBlks) *
3279 pTypeLibImpl->TypeInfoCount);
3282 ptr = (char*)pLibBlk + len;
3284 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3285 WORD w, extra;
3286 len = 0;
3288 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3290 w = *(WORD*)(ptr + 2);
3291 if(w != 0xffff) {
3292 len += w;
3293 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3294 w+1);
3295 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3296 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3298 w = *(WORD*)(ptr + 4 + len);
3299 if(w != 0xffff) {
3300 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3301 len += w;
3302 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3303 w+1);
3304 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3305 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3307 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3308 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3309 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3310 if(extra) {
3311 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3312 extra);
3313 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3314 len += extra;
3316 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3317 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3318 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3319 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3320 len += sizeof(SLTG_OtherTypeInfo);
3321 ptr += len;
3324 pAfterOTIBlks = ptr;
3326 /* Skip this WORD and get the next DWORD */
3327 len = *(DWORD*)(pAfterOTIBlks + 2);
3329 /* Now add this to pLibBLk look at what we're pointing at and
3330 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3331 dust and we should be pointing at the beginning of the name
3332 table */
3334 pNameTable = (char*)pLibBlk + len;
3336 switch(*(WORD*)pNameTable) {
3337 case 0xffff:
3338 break;
3339 case 0x0200:
3340 pNameTable += 0x20;
3341 break;
3342 default:
3343 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3344 break;
3347 pNameTable += 0x216;
3349 pNameTable += 2;
3351 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3353 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3356 /* Hopefully we now have enough ptrs set up to actually read in
3357 some TypeInfos. It's not clear which order to do them in, so
3358 I'll just follow the links along the BlkEntry chain and read
3359 them in the order in which they are in the file */
3361 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3363 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3364 pBlkEntry[order].next != 0;
3365 order = pBlkEntry[order].next - 1, i++) {
3367 SLTG_TypeInfoHeader *pTIHeader;
3368 SLTG_TypeInfoTail *pTITail;
3369 SLTG_MemberHeader *pMemHeader;
3371 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3372 pOtherTypeInfoBlks[i].index_name)) {
3373 FIXME("Index strings don't match\n");
3374 return NULL;
3377 pTIHeader = pBlk;
3378 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3379 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3380 return NULL;
3382 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3383 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3385 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3386 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3387 (*ppTypeInfoImpl)->index = i;
3388 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3389 pOtherTypeInfoBlks[i].name_offs +
3390 pNameTable);
3391 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3392 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3393 sizeof(GUID));
3394 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3395 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3396 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3397 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3398 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3400 if((pTIHeader->typeflags1 & 7) != 2)
3401 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3402 if(pTIHeader->typeflags3 != 2)
3403 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3405 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3406 debugstr_w((*ppTypeInfoImpl)->Name),
3407 typekind_desc[pTIHeader->typekind],
3408 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3409 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3411 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3413 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3415 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3416 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3417 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3419 switch(pTIHeader->typekind) {
3420 case TKIND_ENUM:
3421 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3422 pTIHeader, pTITail);
3423 break;
3425 case TKIND_RECORD:
3426 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3427 pTIHeader, pTITail);
3428 break;
3430 case TKIND_INTERFACE:
3431 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3432 pTIHeader, pTITail);
3433 break;
3435 case TKIND_COCLASS:
3436 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3437 pTIHeader, pTITail);
3438 break;
3440 case TKIND_ALIAS:
3441 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3442 pTIHeader, pTITail);
3443 break;
3445 case TKIND_DISPATCH:
3446 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3447 pTIHeader, pTITail);
3448 break;
3450 case TKIND_MODULE:
3451 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3452 pTIHeader, pTITail);
3453 break;
3455 default:
3456 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3457 break;
3461 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3462 but we've already set those */
3463 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3464 X(06);
3465 X(16);
3466 X(18);
3467 X(1a);
3468 X(1e);
3469 X(24);
3470 X(26);
3471 X(2a);
3472 X(2c);
3473 X(2e);
3474 X(30);
3475 X(32);
3476 X(34);
3478 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3479 pBlk = (char*)pBlk + pBlkEntry[order].len;
3482 if(i != pTypeLibImpl->TypeInfoCount) {
3483 FIXME("Somehow processed %d TypeInfos\n", i);
3484 return NULL;
3487 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3488 return (ITypeLib2*)pTypeLibImpl;
3491 /* ITypeLib::QueryInterface
3493 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3494 ITypeLib2 * iface,
3495 REFIID riid,
3496 VOID **ppvObject)
3498 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3500 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3502 *ppvObject=NULL;
3503 if(IsEqualIID(riid, &IID_IUnknown) ||
3504 IsEqualIID(riid,&IID_ITypeLib)||
3505 IsEqualIID(riid,&IID_ITypeLib2))
3507 *ppvObject = This;
3510 if(*ppvObject)
3512 ITypeLib2_AddRef(iface);
3513 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3514 return S_OK;
3516 TRACE("-- Interface: E_NOINTERFACE\n");
3517 return E_NOINTERFACE;
3520 /* ITypeLib::AddRef
3522 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3524 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3525 ULONG ref = InterlockedIncrement(&This->ref);
3527 TRACE("(%p)->ref was %u\n",This, ref - 1);
3529 return ref;
3532 /* ITypeLib::Release
3534 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3536 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3537 ULONG ref = InterlockedDecrement(&This->ref);
3539 TRACE("(%p)->(%u)\n",This, ref);
3541 if (!ref)
3543 TLBImpLib *pImpLib, *pImpLibNext;
3544 TLBCustData *pCustData, *pCustDataNext;
3546 /* remove cache entry */
3547 if(This->path)
3549 TRACE("removing from cache list\n");
3550 EnterCriticalSection(&cache_section);
3551 if (This->next) This->next->prev = This->prev;
3552 if (This->prev) This->prev->next = This->next;
3553 else tlb_cache_first = This->next;
3554 LeaveCriticalSection(&cache_section);
3555 HeapFree(GetProcessHeap(), 0, This->path);
3557 TRACE(" destroying ITypeLib(%p)\n",This);
3559 if (This->Name)
3561 SysFreeString(This->Name);
3562 This->Name = NULL;
3565 if (This->DocString)
3567 SysFreeString(This->DocString);
3568 This->DocString = NULL;
3571 if (This->HelpFile)
3573 SysFreeString(This->HelpFile);
3574 This->HelpFile = NULL;
3577 if (This->HelpStringDll)
3579 SysFreeString(This->HelpStringDll);
3580 This->HelpStringDll = NULL;
3583 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3585 VariantClear(&pCustData->data);
3587 pCustDataNext = pCustData->next;
3588 TLB_Free(pCustData);
3591 /* FIXME: free arrays inside elements of This->pTypeDesc */
3592 TLB_Free(This->pTypeDesc);
3594 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3596 if (pImpLib->pImpTypeLib)
3597 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3598 TLB_Free(pImpLib->name);
3600 pImpLibNext = pImpLib->next;
3601 TLB_Free(pImpLib);
3604 if (This->pTypeInfo) /* can be NULL */
3605 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3606 HeapFree(GetProcessHeap(),0,This);
3607 return 0;
3610 return ref;
3613 /* ITypeLib::GetTypeInfoCount
3615 * Returns the number of type descriptions in the type library
3617 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3619 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3620 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3621 return This->TypeInfoCount;
3624 /* ITypeLib::GetTypeInfo
3626 * retrieves the specified type description in the library.
3628 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3629 ITypeLib2 *iface,
3630 UINT index,
3631 ITypeInfo **ppTInfo)
3633 int i;
3635 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3636 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3638 TRACE("(%p)->(index=%d)\n", This, index);
3640 if (!ppTInfo) return E_INVALIDARG;
3642 /* search element n in list */
3643 for(i=0; i < index; i++)
3645 pTypeInfo = pTypeInfo->next;
3646 if (!pTypeInfo)
3648 TRACE("-- element not found\n");
3649 return TYPE_E_ELEMENTNOTFOUND;
3653 *ppTInfo = (ITypeInfo *) pTypeInfo;
3655 ITypeInfo_AddRef(*ppTInfo);
3656 TRACE("-- found (%p)\n",*ppTInfo);
3657 return S_OK;
3661 /* ITypeLibs::GetTypeInfoType
3663 * Retrieves the type of a type description.
3665 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3666 ITypeLib2 *iface,
3667 UINT index,
3668 TYPEKIND *pTKind)
3670 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3671 int i;
3672 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3674 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3675 return TYPE_E_ELEMENTNOTFOUND;
3677 TRACE("(%p) index %d\n", This, index);
3679 if(!pTKind) return E_INVALIDARG;
3681 /* search element n in list */
3682 for(i=0; i < index; i++)
3684 if(!pTInfo)
3686 TRACE("-- element not found\n");
3687 return TYPE_E_ELEMENTNOTFOUND;
3689 pTInfo = pTInfo->next;
3692 *pTKind = pTInfo->TypeAttr.typekind;
3693 TRACE("-- found Type (%d)\n", *pTKind);
3694 return S_OK;
3697 /* ITypeLib::GetTypeInfoOfGuid
3699 * Retrieves the type description that corresponds to the specified GUID.
3702 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3703 ITypeLib2 *iface,
3704 REFGUID guid,
3705 ITypeInfo **ppTInfo)
3707 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3708 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3710 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3712 if (!pTypeInfo)
3714 WARN("-- element not found\n");
3715 return TYPE_E_ELEMENTNOTFOUND;
3718 /* search linked list for guid */
3719 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3721 pTypeInfo = pTypeInfo->next;
3723 if (!pTypeInfo)
3725 /* end of list reached */
3726 WARN("-- element not found\n");
3727 return TYPE_E_ELEMENTNOTFOUND;
3731 TRACE("-- found (%p, %s)\n",
3732 pTypeInfo,
3733 debugstr_w(pTypeInfo->Name));
3735 *ppTInfo = (ITypeInfo*)pTypeInfo;
3736 ITypeInfo_AddRef(*ppTInfo);
3737 return S_OK;
3740 /* ITypeLib::GetLibAttr
3742 * Retrieves the structure that contains the library's attributes.
3745 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3746 ITypeLib2 *iface,
3747 LPTLIBATTR *ppTLibAttr)
3749 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3750 TRACE("(%p)\n",This);
3751 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3752 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3753 return S_OK;
3756 /* ITypeLib::GetTypeComp
3758 * Enables a client compiler to bind to a library's types, variables,
3759 * constants, and global functions.
3762 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3763 ITypeLib2 *iface,
3764 ITypeComp **ppTComp)
3766 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3768 TRACE("(%p)->(%p)\n",This,ppTComp);
3769 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3770 ITypeComp_AddRef(*ppTComp);
3772 return S_OK;
3775 /* ITypeLib::GetDocumentation
3777 * Retrieves the library's documentation string, the complete Help file name
3778 * and path, and the context identifier for the library Help topic in the Help
3779 * file.
3781 * On a successful return all non-null BSTR pointers will have been set,
3782 * possibly to NULL.
3784 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3785 ITypeLib2 *iface,
3786 INT index,
3787 BSTR *pBstrName,
3788 BSTR *pBstrDocString,
3789 DWORD *pdwHelpContext,
3790 BSTR *pBstrHelpFile)
3792 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3794 HRESULT result = E_INVALIDARG;
3796 ITypeInfo *pTInfo;
3799 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3800 This, index,
3801 pBstrName, pBstrDocString,
3802 pdwHelpContext, pBstrHelpFile);
3804 if(index<0)
3806 /* documentation for the typelib */
3807 if(pBstrName)
3809 if (This->Name)
3811 if(!(*pBstrName = SysAllocString(This->Name)))
3812 goto memerr1;
3814 else
3815 *pBstrName = NULL;
3817 if(pBstrDocString)
3819 if (This->DocString)
3821 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3822 goto memerr2;
3824 else if (This->Name)
3826 if(!(*pBstrDocString = SysAllocString(This->Name)))
3827 goto memerr2;
3829 else
3830 *pBstrDocString = NULL;
3832 if(pdwHelpContext)
3834 *pdwHelpContext = This->dwHelpContext;
3836 if(pBstrHelpFile)
3838 if (This->HelpFile)
3840 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3841 goto memerr3;
3843 else
3844 *pBstrHelpFile = NULL;
3847 result = S_OK;
3849 else
3851 /* for a typeinfo */
3852 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3854 if(SUCCEEDED(result))
3856 result = ITypeInfo_GetDocumentation(pTInfo,
3857 MEMBERID_NIL,
3858 pBstrName,
3859 pBstrDocString,
3860 pdwHelpContext, pBstrHelpFile);
3862 ITypeInfo_Release(pTInfo);
3865 return result;
3866 memerr3:
3867 if (pBstrDocString) SysFreeString (*pBstrDocString);
3868 memerr2:
3869 if (pBstrName) SysFreeString (*pBstrName);
3870 memerr1:
3871 return STG_E_INSUFFICIENTMEMORY;
3874 /* ITypeLib::IsName
3876 * Indicates whether a passed-in string contains the name of a type or member
3877 * described in the library.
3880 static HRESULT WINAPI ITypeLib2_fnIsName(
3881 ITypeLib2 *iface,
3882 LPOLESTR szNameBuf,
3883 ULONG lHashVal,
3884 BOOL *pfName)
3886 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3887 ITypeInfoImpl *pTInfo;
3888 TLBFuncDesc *pFInfo;
3889 TLBVarDesc *pVInfo;
3890 int i;
3891 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3893 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3894 pfName);
3896 *pfName=TRUE;
3897 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3898 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3899 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3900 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3901 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3902 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3903 goto ITypeLib2_fnIsName_exit;
3905 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3906 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3909 *pfName=FALSE;
3911 ITypeLib2_fnIsName_exit:
3912 TRACE("(%p)slow! search for %s: %s found!\n", This,
3913 debugstr_w(szNameBuf), *pfName?"NOT":"");
3915 return S_OK;
3918 /* ITypeLib::FindName
3920 * Finds occurrences of a type description in a type library. This may be used
3921 * to quickly verify that a name exists in a type library.
3924 static HRESULT WINAPI ITypeLib2_fnFindName(
3925 ITypeLib2 *iface,
3926 LPOLESTR szNameBuf,
3927 ULONG lHashVal,
3928 ITypeInfo **ppTInfo,
3929 MEMBERID *rgMemId,
3930 UINT16 *pcFound)
3932 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3933 ITypeInfoImpl *pTInfo;
3934 TLBFuncDesc *pFInfo;
3935 TLBVarDesc *pVInfo;
3936 int i,j = 0;
3937 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3939 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3940 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3941 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3942 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3943 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3944 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3945 goto ITypeLib2_fnFindName_exit;
3948 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3949 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3950 continue;
3951 ITypeLib2_fnFindName_exit:
3952 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3953 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3954 j++;
3956 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3957 This, *pcFound, debugstr_w(szNameBuf), j);
3959 *pcFound=j;
3961 return S_OK;
3964 /* ITypeLib::ReleaseTLibAttr
3966 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3969 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3970 ITypeLib2 *iface,
3971 TLIBATTR *pTLibAttr)
3973 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3974 TRACE("freeing (%p)\n",This);
3975 HeapFree(GetProcessHeap(),0,pTLibAttr);
3979 /* ITypeLib2::GetCustData
3981 * gets the custom data
3983 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3984 ITypeLib2 * iface,
3985 REFGUID guid,
3986 VARIANT *pVarVal)
3988 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3989 TLBCustData *pCData;
3991 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3993 if( IsEqualIID(guid, &pCData->guid)) break;
3996 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3998 if(pCData)
4000 VariantInit( pVarVal);
4001 VariantCopy( pVarVal, &pCData->data);
4002 return S_OK;
4004 return E_INVALIDARG; /* FIXME: correct? */
4007 /* ITypeLib2::GetLibStatistics
4009 * Returns statistics about a type library that are required for efficient
4010 * sizing of hash tables.
4013 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4014 ITypeLib2 * iface,
4015 ULONG *pcUniqueNames,
4016 ULONG *pcchUniqueNames)
4018 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4020 FIXME("(%p): stub!\n", This);
4022 if(pcUniqueNames) *pcUniqueNames=1;
4023 if(pcchUniqueNames) *pcchUniqueNames=1;
4024 return S_OK;
4027 /* ITypeLib2::GetDocumentation2
4029 * Retrieves the library's documentation string, the complete Help file name
4030 * and path, the localization context to use, and the context ID for the
4031 * library Help topic in the Help file.
4034 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4035 ITypeLib2 * iface,
4036 INT index,
4037 LCID lcid,
4038 BSTR *pbstrHelpString,
4039 DWORD *pdwHelpStringContext,
4040 BSTR *pbstrHelpStringDll)
4042 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4043 HRESULT result;
4044 ITypeInfo *pTInfo;
4046 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4048 /* the help string should be obtained from the helpstringdll,
4049 * using the _DLLGetDocumentation function, based on the supplied
4050 * lcid. Nice to do sometime...
4052 if(index<0)
4054 /* documentation for the typelib */
4055 if(pbstrHelpString)
4056 *pbstrHelpString=SysAllocString(This->DocString);
4057 if(pdwHelpStringContext)
4058 *pdwHelpStringContext=This->dwHelpContext;
4059 if(pbstrHelpStringDll)
4060 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4062 result = S_OK;
4064 else
4066 /* for a typeinfo */
4067 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4069 if(SUCCEEDED(result))
4071 ITypeInfo2 * pTInfo2;
4072 result = ITypeInfo_QueryInterface(pTInfo,
4073 &IID_ITypeInfo2,
4074 (LPVOID*) &pTInfo2);
4076 if(SUCCEEDED(result))
4078 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4079 MEMBERID_NIL,
4080 lcid,
4081 pbstrHelpString,
4082 pdwHelpStringContext,
4083 pbstrHelpStringDll);
4085 ITypeInfo2_Release(pTInfo2);
4088 ITypeInfo_Release(pTInfo);
4091 return result;
4094 /* ITypeLib2::GetAllCustData
4096 * Gets all custom data items for the library.
4099 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4100 ITypeLib2 * iface,
4101 CUSTDATA *pCustData)
4103 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4104 TLBCustData *pCData;
4105 int i;
4106 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4107 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4108 if(pCustData->prgCustData ){
4109 pCustData->cCustData=This->ctCustData;
4110 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4111 pCustData->prgCustData[i].guid=pCData->guid;
4112 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4114 }else{
4115 ERR(" OUT OF MEMORY!\n");
4116 return E_OUTOFMEMORY;
4118 return S_OK;
4121 static const ITypeLib2Vtbl tlbvt = {
4122 ITypeLib2_fnQueryInterface,
4123 ITypeLib2_fnAddRef,
4124 ITypeLib2_fnRelease,
4125 ITypeLib2_fnGetTypeInfoCount,
4126 ITypeLib2_fnGetTypeInfo,
4127 ITypeLib2_fnGetTypeInfoType,
4128 ITypeLib2_fnGetTypeInfoOfGuid,
4129 ITypeLib2_fnGetLibAttr,
4130 ITypeLib2_fnGetTypeComp,
4131 ITypeLib2_fnGetDocumentation,
4132 ITypeLib2_fnIsName,
4133 ITypeLib2_fnFindName,
4134 ITypeLib2_fnReleaseTLibAttr,
4136 ITypeLib2_fnGetCustData,
4137 ITypeLib2_fnGetLibStatistics,
4138 ITypeLib2_fnGetDocumentation2,
4139 ITypeLib2_fnGetAllCustData
4143 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4145 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4147 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4150 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4152 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4154 return ITypeLib2_AddRef((ITypeLib2 *)This);
4157 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4159 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4161 return ITypeLib2_Release((ITypeLib2 *)This);
4164 static HRESULT WINAPI ITypeLibComp_fnBind(
4165 ITypeComp * iface,
4166 OLECHAR * szName,
4167 ULONG lHash,
4168 WORD wFlags,
4169 ITypeInfo ** ppTInfo,
4170 DESCKIND * pDescKind,
4171 BINDPTR * pBindPtr)
4173 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4174 ITypeInfoImpl *pTypeInfo;
4176 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4178 *pDescKind = DESCKIND_NONE;
4179 pBindPtr->lptcomp = NULL;
4180 *ppTInfo = NULL;
4182 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4184 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4186 /* FIXME: check wFlags here? */
4187 /* FIXME: we should use a hash table to look this info up using lHash
4188 * instead of an O(n) search */
4189 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4190 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4192 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4194 *pDescKind = DESCKIND_TYPECOMP;
4195 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4196 ITypeComp_AddRef(pBindPtr->lptcomp);
4197 TRACE("module or enum: %s\n", debugstr_w(szName));
4198 return S_OK;
4202 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4203 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4205 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4206 HRESULT hr;
4208 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4209 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4211 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4212 return S_OK;
4216 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4217 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4219 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4220 HRESULT hr;
4221 ITypeInfo *subtypeinfo;
4222 BINDPTR subbindptr;
4223 DESCKIND subdesckind;
4225 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4226 &subtypeinfo, &subdesckind, &subbindptr);
4227 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4229 TYPEDESC tdesc_appobject =
4232 (TYPEDESC *)pTypeInfo->hreftype
4234 VT_USERDEFINED
4236 const VARDESC vardesc_appobject =
4238 -2, /* memid */
4239 NULL, /* lpstrSchema */
4241 0 /* oInst */
4244 /* ELEMDESC */
4246 /* TYPEDESC */
4248 &tdesc_appobject
4250 VT_PTR
4253 0, /* wVarFlags */
4254 VAR_STATIC /* varkind */
4257 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4259 /* cleanup things filled in by Bind call so we can put our
4260 * application object data in there instead */
4261 switch (subdesckind)
4263 case DESCKIND_FUNCDESC:
4264 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4265 break;
4266 case DESCKIND_VARDESC:
4267 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4268 break;
4269 default:
4270 break;
4272 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4274 if (pTypeInfo->hreftype == -1)
4275 FIXME("no hreftype for interface %p\n", pTypeInfo);
4277 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4278 if (FAILED(hr))
4279 return hr;
4281 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4282 *ppTInfo = (ITypeInfo *)pTypeInfo;
4283 ITypeInfo_AddRef(*ppTInfo);
4284 return S_OK;
4289 TRACE("name not found %s\n", debugstr_w(szName));
4290 return S_OK;
4293 static HRESULT WINAPI ITypeLibComp_fnBindType(
4294 ITypeComp * iface,
4295 OLECHAR * szName,
4296 ULONG lHash,
4297 ITypeInfo ** ppTInfo,
4298 ITypeComp ** ppTComp)
4300 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4301 return E_NOTIMPL;
4304 static const ITypeCompVtbl tlbtcvt =
4307 ITypeLibComp_fnQueryInterface,
4308 ITypeLibComp_fnAddRef,
4309 ITypeLibComp_fnRelease,
4311 ITypeLibComp_fnBind,
4312 ITypeLibComp_fnBindType
4315 /*================== ITypeInfo(2) Methods ===================================*/
4316 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4318 ITypeInfoImpl * pTypeInfoImpl;
4320 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4321 if (pTypeInfoImpl)
4323 pTypeInfoImpl->lpVtbl = &tinfvt;
4324 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4325 pTypeInfoImpl->ref=1;
4326 pTypeInfoImpl->hreftype = -1;
4327 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4328 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4330 TRACE("(%p)\n", pTypeInfoImpl);
4331 return (ITypeInfo2*) pTypeInfoImpl;
4334 /* ITypeInfo::QueryInterface
4336 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4337 ITypeInfo2 *iface,
4338 REFIID riid,
4339 VOID **ppvObject)
4341 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4343 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4345 *ppvObject=NULL;
4346 if(IsEqualIID(riid, &IID_IUnknown) ||
4347 IsEqualIID(riid,&IID_ITypeInfo)||
4348 IsEqualIID(riid,&IID_ITypeInfo2))
4349 *ppvObject = This;
4351 if(*ppvObject){
4352 ITypeInfo_AddRef(iface);
4353 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4354 return S_OK;
4356 TRACE("-- Interface: E_NOINTERFACE\n");
4357 return E_NOINTERFACE;
4360 /* ITypeInfo::AddRef
4362 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4364 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4365 ULONG ref = InterlockedIncrement(&This->ref);
4367 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4369 TRACE("(%p)->ref is %u\n",This, ref);
4370 return ref;
4373 /* ITypeInfo::Release
4375 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4377 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4378 ULONG ref = InterlockedDecrement(&This->ref);
4380 TRACE("(%p)->(%u)\n",This, ref);
4382 if (ref) {
4383 /* We don't release ITypeLib when ref=0 because
4384 it means that function is called by ITypeLib2_Release */
4385 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4386 } else {
4387 TLBFuncDesc *pFInfo, *pFInfoNext;
4388 TLBVarDesc *pVInfo, *pVInfoNext;
4389 TLBImplType *pImpl, *pImplNext;
4390 TLBRefType *pRefType,*pRefTypeNext;
4391 TLBCustData *pCustData, *pCustDataNext;
4393 TRACE("destroying ITypeInfo(%p)\n",This);
4395 if (This->no_free_data)
4396 goto finish_free;
4398 if (This->Name)
4400 SysFreeString(This->Name);
4401 This->Name = 0;
4404 if (This->DocString)
4406 SysFreeString(This->DocString);
4407 This->DocString = 0;
4410 if (This->DllName)
4412 SysFreeString(This->DllName);
4413 This->DllName = 0;
4416 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4418 UINT i;
4419 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4421 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4422 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4424 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4425 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4427 SysFreeString(pFInfo->pParamDesc[i].Name);
4429 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4430 TLB_Free(pFInfo->pParamDesc);
4431 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4433 VariantClear(&pCustData->data);
4435 pCustDataNext = pCustData->next;
4436 TLB_Free(pCustData);
4438 SysFreeString(pFInfo->Entry);
4439 SysFreeString(pFInfo->HelpString);
4440 SysFreeString(pFInfo->Name);
4442 pFInfoNext = pFInfo->next;
4443 TLB_Free(pFInfo);
4445 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4447 if (pVInfo->vardesc.varkind == VAR_CONST)
4449 VariantClear(pVInfo->vardesc.u.lpvarValue);
4450 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4452 SysFreeString(pVInfo->Name);
4453 pVInfoNext = pVInfo->next;
4454 TLB_Free(pVInfo);
4456 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4458 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4460 VariantClear(&pCustData->data);
4462 pCustDataNext = pCustData->next;
4463 TLB_Free(pCustData);
4465 pImplNext = pImpl->next;
4466 TLB_Free(pImpl);
4468 for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext)
4470 pRefTypeNext = pRefType->next;
4471 TLB_Free(pRefType);
4473 TLB_Free(This->pCustData);
4475 finish_free:
4476 if (This->next)
4478 ITypeInfo_Release((ITypeInfo*)This->next);
4481 HeapFree(GetProcessHeap(),0,This);
4482 return 0;
4484 return ref;
4487 /* ITypeInfo::GetTypeAttr
4489 * Retrieves a TYPEATTR structure that contains the attributes of the type
4490 * description.
4493 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4494 LPTYPEATTR *ppTypeAttr)
4496 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4497 SIZE_T size;
4499 TRACE("(%p)\n",This);
4501 size = sizeof(**ppTypeAttr);
4502 if (This->TypeAttr.typekind == TKIND_ALIAS)
4503 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4505 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4506 if (!*ppTypeAttr)
4507 return E_OUTOFMEMORY;
4509 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4511 if (This->TypeAttr.typekind == TKIND_ALIAS)
4512 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4513 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4515 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4516 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4517 funcs */
4518 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4519 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4521 return S_OK;
4524 /* ITypeInfo::GetTypeComp
4526 * Retrieves the ITypeComp interface for the type description, which enables a
4527 * client compiler to bind to the type description's members.
4530 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4531 ITypeComp * *ppTComp)
4533 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4535 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4537 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4538 ITypeComp_AddRef(*ppTComp);
4539 return S_OK;
4542 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4544 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4545 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4546 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4547 return size;
4550 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4552 memcpy(dest, src, sizeof(ELEMDESC));
4553 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4554 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4556 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4557 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4558 *buffer += sizeof(PARAMDESCEX);
4559 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4560 VariantInit(&pparamdescex_dest->varDefaultValue);
4561 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4562 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4564 else
4565 dest->u.paramdesc.pparamdescex = NULL;
4566 return S_OK;
4569 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4571 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4572 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4575 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4577 FUNCDESC *dest;
4578 char *buffer;
4579 SIZE_T size = sizeof(*src);
4580 SHORT i;
4581 HRESULT hr;
4583 size += sizeof(*src->lprgscode) * src->cScodes;
4584 size += TLB_SizeElemDesc(&src->elemdescFunc);
4585 for (i = 0; i < src->cParams; i++)
4587 size += sizeof(ELEMDESC);
4588 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4591 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4592 if (!dest) return E_OUTOFMEMORY;
4594 memcpy(dest, src, sizeof(FUNCDESC));
4595 buffer = (char *)(dest + 1);
4597 dest->lprgscode = (SCODE *)buffer;
4598 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4599 buffer += sizeof(*src->lprgscode) * src->cScodes;
4601 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4602 if (FAILED(hr))
4604 SysFreeString((BSTR)dest);
4605 return hr;
4608 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4609 buffer += sizeof(ELEMDESC) * src->cParams;
4610 for (i = 0; i < src->cParams; i++)
4612 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4613 if (FAILED(hr))
4614 break;
4616 if (FAILED(hr))
4618 /* undo the above actions */
4619 for (i = i - 1; i >= 0; i--)
4620 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4621 TLB_FreeElemDesc(&dest->elemdescFunc);
4622 SysFreeString((BSTR)dest);
4623 return hr;
4626 /* special treatment for dispinterfaces: this makes functions appear
4627 * to return their [retval] value when it is really returning an
4628 * HRESULT */
4629 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4631 if (dest->cParams &&
4632 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4634 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4635 if (elemdesc->tdesc.vt != VT_PTR)
4637 ERR("elemdesc should have started with VT_PTR instead of:\n");
4638 if (ERR_ON(ole))
4639 dump_ELEMDESC(elemdesc);
4640 return E_UNEXPECTED;
4643 /* copy last parameter to the return value. we are using a flat
4644 * buffer so there is no danger of leaking memory in
4645 * elemdescFunc */
4646 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4648 /* remove the last parameter */
4649 dest->cParams--;
4651 else
4652 /* otherwise this function is made to appear to have no return
4653 * value */
4654 dest->elemdescFunc.tdesc.vt = VT_VOID;
4658 *dest_ptr = dest;
4659 return S_OK;
4662 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4664 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4665 const TLBFuncDesc *pFDesc;
4666 int i;
4668 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4671 if (pFDesc)
4673 *ppFuncDesc = &pFDesc->funcdesc;
4674 return S_OK;
4677 return E_INVALIDARG;
4680 /* internal function to make the inherited interfaces' methods appear
4681 * part of the interface */
4682 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4683 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4685 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4686 HRESULT hr;
4687 UINT i;
4688 UINT implemented_funcs = 0;
4690 if (funcs)
4691 *funcs = 0;
4693 for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4695 HREFTYPE href;
4696 ITypeInfo *pSubTypeInfo;
4697 UINT sub_funcs;
4699 hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4700 if (FAILED(hr))
4701 return hr;
4702 hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4703 if (FAILED(hr))
4704 return hr;
4706 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4707 index,
4708 ppFuncDesc,
4709 &sub_funcs);
4710 implemented_funcs += sub_funcs;
4711 ITypeInfo_Release(pSubTypeInfo);
4712 if (SUCCEEDED(hr))
4713 return hr;
4716 if (funcs)
4717 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4719 if (index < implemented_funcs)
4720 return E_INVALIDARG;
4721 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4722 ppFuncDesc);
4725 /* ITypeInfo::GetFuncDesc
4727 * Retrieves the FUNCDESC structure that contains information about a
4728 * specified function.
4731 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4732 LPFUNCDESC *ppFuncDesc)
4734 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4735 const FUNCDESC *internal_funcdesc;
4736 HRESULT hr;
4738 TRACE("(%p) index %d\n", This, index);
4740 if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4741 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4742 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4743 &internal_funcdesc, NULL);
4744 else
4745 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4746 &internal_funcdesc);
4747 if (FAILED(hr))
4749 WARN("description for function %d not found\n", index);
4750 return hr;
4753 return TLB_AllocAndInitFuncDesc(
4754 internal_funcdesc,
4755 ppFuncDesc,
4756 This->TypeAttr.typekind == TKIND_DISPATCH);
4759 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4761 VARDESC *dest;
4762 char *buffer;
4763 SIZE_T size = sizeof(*src);
4764 HRESULT hr;
4766 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4767 if (src->varkind == VAR_CONST)
4768 size += sizeof(VARIANT);
4769 size += TLB_SizeElemDesc(&src->elemdescVar);
4771 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4772 if (!dest) return E_OUTOFMEMORY;
4774 *dest = *src;
4775 buffer = (char *)(dest + 1);
4776 if (src->lpstrSchema)
4778 int len;
4779 dest->lpstrSchema = (LPOLESTR)buffer;
4780 len = strlenW(src->lpstrSchema);
4781 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4782 buffer += (len + 1) * sizeof(WCHAR);
4785 if (src->varkind == VAR_CONST)
4787 HRESULT hr;
4789 dest->u.lpvarValue = (VARIANT *)buffer;
4790 *dest->u.lpvarValue = *src->u.lpvarValue;
4791 buffer += sizeof(VARIANT);
4792 VariantInit(dest->u.lpvarValue);
4793 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4794 if (FAILED(hr))
4796 SysFreeString((BSTR)dest_ptr);
4797 return hr;
4800 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4801 if (FAILED(hr))
4803 if (src->varkind == VAR_CONST)
4804 VariantClear(dest->u.lpvarValue);
4805 SysFreeString((BSTR)dest);
4806 return hr;
4808 *dest_ptr = dest;
4809 return S_OK;
4812 /* ITypeInfo::GetVarDesc
4814 * Retrieves a VARDESC structure that describes the specified variable.
4817 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4818 LPVARDESC *ppVarDesc)
4820 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4821 int i;
4822 const TLBVarDesc *pVDesc;
4824 TRACE("(%p) index %d\n", This, index);
4826 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4829 if (pVDesc)
4830 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4832 return E_INVALIDARG;
4835 /* ITypeInfo_GetNames
4837 * Retrieves the variable with the specified member ID (or the name of the
4838 * property or method and its parameters) that correspond to the specified
4839 * function ID.
4841 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4842 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4844 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4845 const TLBFuncDesc *pFDesc;
4846 const TLBVarDesc *pVDesc;
4847 int i;
4848 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4849 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4850 if(pFDesc)
4852 /* function found, now return function and parameter names */
4853 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4855 if(!i)
4856 *rgBstrNames=SysAllocString(pFDesc->Name);
4857 else
4858 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4860 *pcNames=i;
4862 else
4864 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4865 if(pVDesc)
4867 *rgBstrNames=SysAllocString(pVDesc->Name);
4868 *pcNames=1;
4870 else
4872 if(This->TypeAttr.cImplTypes &&
4873 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4874 /* recursive search */
4875 ITypeInfo *pTInfo;
4876 HRESULT result;
4877 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4878 &pTInfo);
4879 if(SUCCEEDED(result))
4881 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4882 ITypeInfo_Release(pTInfo);
4883 return result;
4885 WARN("Could not search inherited interface!\n");
4887 else
4889 WARN("no names found\n");
4891 *pcNames=0;
4892 return TYPE_E_ELEMENTNOTFOUND;
4895 return S_OK;
4899 /* ITypeInfo::GetRefTypeOfImplType
4901 * If a type description describes a COM class, it retrieves the type
4902 * description of the implemented interface types. For an interface,
4903 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4904 * if any exist.
4907 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4908 ITypeInfo2 *iface,
4909 UINT index,
4910 HREFTYPE *pRefType)
4912 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4913 int i;
4914 HRESULT hr = S_OK;
4915 const TLBImplType *pImpl = This->impltypelist;
4917 TRACE("(%p) index %d\n", This, index);
4918 if (TRACE_ON(ole)) dump_TypeInfo(This);
4920 if(index==(UINT)-1)
4922 /* only valid on dual interfaces;
4923 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4925 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4927 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4928 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4930 *pRefType = -1;
4932 else
4934 hr = TYPE_E_ELEMENTNOTFOUND;
4937 else
4939 /* get element n from linked list */
4940 for(i=0; pImpl && i<index; i++)
4942 pImpl = pImpl->next;
4945 if (pImpl)
4946 *pRefType = pImpl->hRef;
4947 else
4948 hr = TYPE_E_ELEMENTNOTFOUND;
4951 if(TRACE_ON(ole))
4953 if(SUCCEEDED(hr))
4954 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4955 else
4956 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4959 return hr;
4962 /* ITypeInfo::GetImplTypeFlags
4964 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4965 * or base interface in a type description.
4967 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4968 UINT index, INT *pImplTypeFlags)
4970 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4971 int i;
4972 TLBImplType *pImpl;
4974 TRACE("(%p) index %d\n", This, index);
4975 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4976 i++, pImpl=pImpl->next)
4978 if(i==index && pImpl){
4979 *pImplTypeFlags=pImpl->implflags;
4980 return S_OK;
4982 *pImplTypeFlags=0;
4983 return TYPE_E_ELEMENTNOTFOUND;
4986 /* GetIDsOfNames
4987 * Maps between member names and member IDs, and parameter names and
4988 * parameter IDs.
4990 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4991 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4993 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4994 const TLBFuncDesc *pFDesc;
4995 const TLBVarDesc *pVDesc;
4996 HRESULT ret=S_OK;
4997 int i;
4999 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5000 cNames);
5002 /* init out parameters in case of failure */
5003 for (i = 0; i < cNames; i++)
5004 pMemId[i] = MEMBERID_NIL;
5006 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5007 int j;
5008 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5009 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5010 for(i=1; i < cNames; i++){
5011 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5012 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5013 break;
5014 if( j<pFDesc->funcdesc.cParams)
5015 pMemId[i]=j;
5016 else
5017 ret=DISP_E_UNKNOWNNAME;
5019 TRACE("-- 0x%08x\n", ret);
5020 return ret;
5023 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5024 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5025 if(cNames) *pMemId=pVDesc->vardesc.memid;
5026 return ret;
5029 /* not found, see if it can be found in an inherited interface */
5030 if(This->TypeAttr.cImplTypes) {
5031 /* recursive search */
5032 ITypeInfo *pTInfo;
5033 ret=ITypeInfo_GetRefTypeInfo(iface,
5034 This->impltypelist->hRef, &pTInfo);
5035 if(SUCCEEDED(ret)){
5036 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5037 ITypeInfo_Release(pTInfo);
5038 return ret;
5040 WARN("Could not search inherited interface!\n");
5041 } else
5042 WARN("no names found\n");
5043 return DISP_E_UNKNOWNNAME;
5046 /* ITypeInfo::Invoke
5048 * Invokes a method, or accesses a property of an object, that implements the
5049 * interface described by the type description.
5051 DWORD
5052 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5053 DWORD res;
5055 if (TRACE_ON(ole)) {
5056 int i;
5057 TRACE("Calling %p(",func);
5058 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5059 TRACE(")\n");
5062 switch (callconv) {
5063 case CC_STDCALL:
5065 switch (nrargs) {
5066 case 0:
5067 res = func();
5068 break;
5069 case 1:
5070 res = func(args[0]);
5071 break;
5072 case 2:
5073 res = func(args[0],args[1]);
5074 break;
5075 case 3:
5076 res = func(args[0],args[1],args[2]);
5077 break;
5078 case 4:
5079 res = func(args[0],args[1],args[2],args[3]);
5080 break;
5081 case 5:
5082 res = func(args[0],args[1],args[2],args[3],args[4]);
5083 break;
5084 case 6:
5085 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5086 break;
5087 case 7:
5088 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5089 break;
5090 case 8:
5091 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5092 break;
5093 case 9:
5094 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5095 break;
5096 case 10:
5097 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5098 break;
5099 case 11:
5100 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5101 break;
5102 case 12:
5103 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]);
5104 break;
5105 case 13:
5106 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]);
5107 break;
5108 case 14:
5109 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]);
5110 break;
5111 case 15:
5112 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]);
5113 break;
5114 case 16:
5115 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]);
5116 break;
5117 case 17:
5118 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]);
5119 break;
5120 case 18:
5121 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]);
5122 break;
5123 case 19:
5124 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]);
5125 break;
5126 case 20:
5127 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]);
5128 break;
5129 case 21:
5130 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]);
5131 break;
5132 case 22:
5133 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]);
5134 break;
5135 case 23:
5136 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]);
5137 break;
5138 default:
5139 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5140 res = -1;
5141 break;
5143 break;
5144 default:
5145 FIXME("unsupported calling convention %d\n",callconv);
5146 res = -1;
5147 break;
5149 TRACE("returns %08x\n",res);
5150 return res;
5153 extern int _argsize(DWORD vt);
5155 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5157 HRESULT hr = S_OK;
5158 ITypeInfo *tinfo2 = NULL;
5159 TYPEATTR *tattr = NULL;
5161 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5162 if (hr)
5164 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5165 "hr = 0x%08x\n",
5166 tdesc->u.hreftype, hr);
5167 return hr;
5169 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5170 if (hr)
5172 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5173 ITypeInfo_Release(tinfo2);
5174 return hr;
5177 switch (tattr->typekind)
5179 case TKIND_ENUM:
5180 *vt |= VT_I4;
5181 break;
5183 case TKIND_ALIAS:
5184 tdesc = &tattr->tdescAlias;
5185 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5186 break;
5188 case TKIND_INTERFACE:
5189 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5190 *vt |= VT_DISPATCH;
5191 else
5192 *vt |= VT_UNKNOWN;
5193 break;
5195 case TKIND_DISPATCH:
5196 *vt |= VT_DISPATCH;
5197 break;
5199 case TKIND_COCLASS:
5200 *vt |= VT_UNKNOWN;
5201 break;
5203 case TKIND_RECORD:
5204 FIXME("TKIND_RECORD unhandled.\n");
5205 hr = E_NOTIMPL;
5206 break;
5208 case TKIND_UNION:
5209 FIXME("TKIND_UNION unhandled.\n");
5210 hr = E_NOTIMPL;
5211 break;
5213 default:
5214 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5215 hr = E_NOTIMPL;
5216 break;
5218 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5219 ITypeInfo_Release(tinfo2);
5220 return hr;
5223 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5225 HRESULT hr = S_OK;
5227 /* enforce only one level of pointer indirection */
5228 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5230 tdesc = tdesc->u.lptdesc;
5232 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5233 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5234 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5235 if ((tdesc->vt == VT_USERDEFINED) ||
5236 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5238 VARTYPE vt_userdefined = 0;
5239 const TYPEDESC *tdesc_userdefined = tdesc;
5240 if (tdesc->vt == VT_PTR)
5242 vt_userdefined = VT_BYREF;
5243 tdesc_userdefined = tdesc->u.lptdesc;
5245 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5246 if ((hr == S_OK) &&
5247 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5248 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5250 *vt |= vt_userdefined;
5251 return S_OK;
5254 *vt = VT_BYREF;
5257 switch (tdesc->vt)
5259 case VT_HRESULT:
5260 *vt |= VT_ERROR;
5261 break;
5262 case VT_USERDEFINED:
5263 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5264 break;
5265 case VT_VOID:
5266 case VT_CARRAY:
5267 case VT_PTR:
5268 case VT_LPSTR:
5269 case VT_LPWSTR:
5270 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5271 hr = DISP_E_BADVARTYPE;
5272 break;
5273 case VT_SAFEARRAY:
5274 *vt |= VT_ARRAY;
5275 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5276 break;
5277 default:
5278 *vt |= tdesc->vt;
5279 break;
5281 return hr;
5284 /***********************************************************************
5285 * DispCallFunc (OLEAUT32.@)
5287 * Invokes a function of the specifed calling convention, passing the
5288 * specified arguments and returns the result.
5290 * PARAMS
5291 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5292 * oVft [I] The offset in the vtable. See notes.
5293 * cc [I] Calling convention of the function to call.
5294 * vtReturn [I] The return type of the function.
5295 * cActuals [I] Number of parameters.
5296 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5297 * prgpvarg [I] The arguments to pass.
5298 * pvargResult [O] The return value of the function. Can be NULL.
5300 * RETURNS
5301 * Success: S_OK.
5302 * Failure: HRESULT code.
5304 * NOTES
5305 * The HRESULT return value of this function is not affected by the return
5306 * value of the user supplied function, which is returned in pvargResult.
5308 * If pvInstance is NULL then a non-object function is to be called and oVft
5309 * is the address of the function to call.
5311 * The cc parameter can be one of the following values:
5312 *|CC_FASTCALL
5313 *|CC_CDECL
5314 *|CC_PASCAL
5315 *|CC_STDCALL
5316 *|CC_FPFASTCALL
5317 *|CC_SYSCALL
5318 *|CC_MPWCDECL
5319 *|CC_MPWPASCAL
5322 HRESULT WINAPI
5323 DispCallFunc(
5324 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5325 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5327 int i, argsize, argspos;
5328 DWORD *args;
5329 HRESULT hres;
5331 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5332 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5333 pvargResult, V_VT(pvargResult));
5335 argsize = 0;
5336 if (pvInstance)
5337 argsize++; /* for This pointer */
5339 for (i=0;i<cActuals;i++)
5341 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5342 dump_Variant(prgpvarg[i]);
5343 argsize += _argsize(prgvt[i]);
5345 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5347 argspos = 0;
5348 if (pvInstance)
5350 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5351 argspos++;
5354 for (i=0;i<cActuals;i++)
5356 VARIANT *arg = prgpvarg[i];
5357 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5358 if (prgvt[i] == VT_VARIANT)
5359 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5360 else
5361 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5362 argspos += _argsize(prgvt[i]);
5365 if (pvInstance)
5367 FARPROC *vtable = *(FARPROC**)pvInstance;
5368 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5370 else
5371 /* if we aren't invoking an object then the function pointer is stored
5372 * in oVft */
5373 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5375 if (pvargResult && (vtReturn != VT_EMPTY))
5377 TRACE("Method returned 0x%08x\n",hres);
5378 V_VT(pvargResult) = vtReturn;
5379 V_UI4(pvargResult) = hres;
5382 HeapFree(GetProcessHeap(),0,args);
5383 return S_OK;
5386 #define INVBUF_ELEMENT_SIZE \
5387 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5388 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5389 ((VARIANTARG *)(buffer))
5390 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5391 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5392 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5393 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5394 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5395 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5397 static HRESULT WINAPI ITypeInfo_fnInvoke(
5398 ITypeInfo2 *iface,
5399 VOID *pIUnk,
5400 MEMBERID memid,
5401 UINT16 wFlags,
5402 DISPPARAMS *pDispParams,
5403 VARIANT *pVarResult,
5404 EXCEPINFO *pExcepInfo,
5405 UINT *pArgErr)
5407 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5408 int i;
5409 unsigned int var_index;
5410 TYPEKIND type_kind;
5411 HRESULT hres;
5412 const TLBFuncDesc *pFuncInfo;
5414 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5415 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5418 if (!pDispParams)
5420 ERR("NULL pDispParams not allowed\n");
5421 return E_INVALIDARG;
5424 dump_DispParms(pDispParams);
5426 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5428 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5429 pDispParams->cNamedArgs, pDispParams->cArgs);
5430 return E_INVALIDARG;
5433 /* we do this instead of using GetFuncDesc since it will return a fake
5434 * FUNCDESC for dispinterfaces and we want the real function description */
5435 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5436 if ((memid == pFuncInfo->funcdesc.memid) &&
5437 (wFlags & pFuncInfo->funcdesc.invkind))
5438 break;
5440 if (pFuncInfo) {
5441 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5443 if (TRACE_ON(ole))
5445 TRACE("invoking:\n");
5446 dump_TLBFuncDescOne(pFuncInfo);
5449 switch (func_desc->funckind) {
5450 case FUNC_PUREVIRTUAL:
5451 case FUNC_VIRTUAL: {
5452 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5453 VARIANT varresult;
5454 VARIANT retval; /* pointer for storing byref retvals in */
5455 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5456 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5457 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5459 hres = S_OK;
5460 for (i = 0; i < func_desc->cParams; i++)
5462 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5463 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5464 if (FAILED(hres))
5465 goto func_fail;
5468 TRACE("changing args\n");
5469 for (i = 0; i < func_desc->cParams; i++)
5471 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5473 if (wParamFlags & PARAMFLAG_FRETVAL)
5475 /* note: this check is placed so that if the caller passes
5476 * in a VARIANTARG for the retval we just ignore it, like
5477 * native does */
5478 if (i == func_desc->cParams - 1)
5480 VARIANTARG *arg;
5481 arg = prgpvarg[i] = &rgvarg[i];
5482 memset(arg, 0, sizeof(*arg));
5483 V_VT(arg) = rgvt[i];
5484 memset(&retval, 0, sizeof(retval));
5485 V_BYREF(arg) = &retval;
5487 else
5489 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5490 hres = E_UNEXPECTED;
5491 break;
5494 else if (i < pDispParams->cArgs)
5496 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5497 dump_Variant(src_arg);
5499 if (rgvt[i] == VT_VARIANT)
5500 hres = VariantCopy(&rgvarg[i], src_arg);
5501 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5503 if (rgvt[i] == V_VT(src_arg))
5504 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5505 else
5507 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5508 hres = VariantCopy(&missing_arg[i], src_arg);
5509 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5511 V_VT(&rgvarg[i]) = rgvt[i];
5513 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5515 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5516 V_VT(&missing_arg[i]) = V_VT(src_arg);
5517 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5518 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5519 V_VT(&rgvarg[i]) = rgvt[i];
5521 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5523 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5524 V_VT(&rgvarg[i]) = rgvt[i];
5526 else
5528 /* FIXME: this doesn't work for VT_BYREF arguments if
5529 * they are not the same type as in the paramdesc */
5530 V_VT(&rgvarg[i]) = V_VT(src_arg);
5531 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5532 V_VT(&rgvarg[i]) = rgvt[i];
5535 if (FAILED(hres))
5537 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5538 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5539 debugstr_VT(src_arg), debugstr_VF(src_arg));
5540 break;
5542 prgpvarg[i] = &rgvarg[i];
5544 else if (wParamFlags & PARAMFLAG_FOPT)
5546 VARIANTARG *arg;
5547 arg = prgpvarg[i] = &rgvarg[i];
5548 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5550 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5551 if (FAILED(hres))
5552 break;
5554 else
5556 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5557 V_VT(arg) = VT_VARIANT | VT_BYREF;
5558 V_VARIANTREF(arg) = &missing_arg[i];
5559 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5560 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5563 else
5565 hres = DISP_E_BADPARAMCOUNT;
5566 break;
5569 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5570 if (func_desc->cParamsOpt < 0)
5572 FIXME("Does not support safearray optional parameters\n");
5573 hres = DISP_E_BADPARAMCOUNT;
5574 goto func_fail; /* FIXME: we don't free changed types here */
5577 /* VT_VOID is a special case for return types, so it is not
5578 * handled in the general function */
5579 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5580 V_VT(&varresult) = VT_EMPTY;
5581 else
5583 V_VT(&varresult) = 0;
5584 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5585 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5588 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5589 V_VT(&varresult), func_desc->cParams, rgvt,
5590 prgpvarg, &varresult);
5592 for (i = 0; i < func_desc->cParams; i++)
5594 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5595 if (wParamFlags & PARAMFLAG_FRETVAL)
5597 if (TRACE_ON(ole))
5599 TRACE("[retval] value: ");
5600 dump_Variant(prgpvarg[i]);
5603 if (pVarResult)
5605 VariantInit(pVarResult);
5606 /* deref return value */
5607 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5610 /* free data stored in varresult. Note that
5611 * VariantClear doesn't do what we want because we are
5612 * working with byref types. */
5613 /* FIXME: clear safearrays, bstrs, records and
5614 * variants here too */
5615 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5616 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5618 if(*V_UNKNOWNREF(prgpvarg[i]))
5619 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5621 break;
5623 else if (i < pDispParams->cArgs)
5625 if (wParamFlags & PARAMFLAG_FOUT)
5627 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5629 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5630 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5632 if (FAILED(hres))
5634 ERR("failed to convert param %d to vt %d\n", i,
5635 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5636 break;
5639 VariantClear(&rgvarg[i]);
5641 else if (wParamFlags & PARAMFLAG_FOPT)
5643 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5644 VariantClear(&rgvarg[i]);
5648 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5650 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5651 hres = DISP_E_EXCEPTION;
5652 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5655 func_fail:
5656 HeapFree(GetProcessHeap(), 0, buffer);
5657 break;
5659 case FUNC_DISPATCH: {
5660 IDispatch *disp;
5662 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5663 if (SUCCEEDED(hres)) {
5664 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5665 hres = IDispatch_Invoke(
5666 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5667 pVarResult,pExcepInfo,pArgErr
5669 if (FAILED(hres))
5670 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5671 IDispatch_Release(disp);
5672 } else
5673 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5674 break;
5676 default:
5677 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5678 hres = E_FAIL;
5679 break;
5682 TRACE("-- 0x%08x\n", hres);
5683 return hres;
5685 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5686 VARDESC *var_desc;
5688 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5689 if(FAILED(hres)) return hres;
5691 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5692 dump_VARDESC(var_desc);
5693 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5694 return E_NOTIMPL;
5697 /* not found, look for it in inherited interfaces */
5698 ITypeInfo2_GetTypeKind(iface, &type_kind);
5699 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5700 HREFTYPE ref_type;
5701 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5702 /* recursive search */
5703 ITypeInfo *pTInfo;
5704 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5705 if(SUCCEEDED(hres)){
5706 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5707 ITypeInfo_Release(pTInfo);
5708 return hres;
5710 WARN("Could not search inherited interface!\n");
5713 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5714 return DISP_E_MEMBERNOTFOUND;
5717 /* ITypeInfo::GetDocumentation
5719 * Retrieves the documentation string, the complete Help file name and path,
5720 * and the context ID for the Help topic for a specified type description.
5722 * (Can be tested by the Visual Basic Editor in Word for instance.)
5724 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5725 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5726 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5728 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5729 const TLBFuncDesc *pFDesc;
5730 const TLBVarDesc *pVDesc;
5731 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5732 " HelpContext(%p) HelpFile(%p)\n",
5733 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5734 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5735 if(pBstrName)
5736 *pBstrName=SysAllocString(This->Name);
5737 if(pBstrDocString)
5738 *pBstrDocString=SysAllocString(This->DocString);
5739 if(pdwHelpContext)
5740 *pdwHelpContext=This->dwHelpContext;
5741 if(pBstrHelpFile)
5742 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5743 return S_OK;
5744 }else {/* for a member */
5745 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5746 if(pFDesc->funcdesc.memid==memid){
5747 if(pBstrName)
5748 *pBstrName = SysAllocString(pFDesc->Name);
5749 if(pBstrDocString)
5750 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5751 if(pdwHelpContext)
5752 *pdwHelpContext=pFDesc->helpcontext;
5753 return S_OK;
5755 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5756 if(pVDesc->vardesc.memid==memid){
5757 if(pBstrName)
5758 *pBstrName = SysAllocString(pVDesc->Name);
5759 if(pBstrDocString)
5760 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5761 if(pdwHelpContext)
5762 *pdwHelpContext=pVDesc->HelpContext;
5763 return S_OK;
5767 if(This->TypeAttr.cImplTypes &&
5768 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5769 /* recursive search */
5770 ITypeInfo *pTInfo;
5771 HRESULT result;
5772 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5773 &pTInfo);
5774 if(SUCCEEDED(result)) {
5775 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5776 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5777 ITypeInfo_Release(pTInfo);
5778 return result;
5780 WARN("Could not search inherited interface!\n");
5783 WARN("member %d not found\n", memid);
5784 return TYPE_E_ELEMENTNOTFOUND;
5787 /* ITypeInfo::GetDllEntry
5789 * Retrieves a description or specification of an entry point for a function
5790 * in a DLL.
5792 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5793 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5794 WORD *pwOrdinal)
5796 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5797 const TLBFuncDesc *pFDesc;
5799 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5801 if (pBstrDllName) *pBstrDllName = NULL;
5802 if (pBstrName) *pBstrName = NULL;
5803 if (pwOrdinal) *pwOrdinal = 0;
5805 if (This->TypeAttr.typekind != TKIND_MODULE)
5806 return TYPE_E_BADMODULEKIND;
5808 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5809 if(pFDesc->funcdesc.memid==memid){
5810 dump_TypeInfo(This);
5811 if (TRACE_ON(ole))
5812 dump_TLBFuncDescOne(pFDesc);
5814 if (pBstrDllName)
5815 *pBstrDllName = SysAllocString(This->DllName);
5817 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5818 if (pBstrName)
5819 *pBstrName = SysAllocString(pFDesc->Entry);
5820 if (pwOrdinal)
5821 *pwOrdinal = -1;
5822 return S_OK;
5824 if (pBstrName)
5825 *pBstrName = NULL;
5826 if (pwOrdinal)
5827 *pwOrdinal = (DWORD)pFDesc->Entry;
5828 return S_OK;
5830 return TYPE_E_ELEMENTNOTFOUND;
5833 /* ITypeInfo::GetRefTypeInfo
5835 * If a type description references other type descriptions, it retrieves
5836 * the referenced type descriptions.
5838 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5839 ITypeInfo2 *iface,
5840 HREFTYPE hRefType,
5841 ITypeInfo **ppTInfo)
5843 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5844 HRESULT result = E_FAIL;
5846 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5848 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5849 ITypeInfo_AddRef(*ppTInfo);
5850 result = S_OK;
5852 else if (hRefType == -1 &&
5853 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5854 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5856 /* when we meet a DUAL dispinterface, we must create the interface
5857 * version of it.
5859 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5862 /* the interface version contains the same information as the dispinterface
5863 * copy the contents of the structs.
5865 *pTypeInfoImpl = *This;
5866 pTypeInfoImpl->ref = 0;
5868 /* change the type to interface */
5869 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5871 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5873 /* we use data structures from This, so we need to keep a reference
5874 * to it to stop it being destroyed and signal to the new instance to
5875 * not free its data structures when it is destroyed */
5876 pTypeInfoImpl->no_free_data = TRUE;
5877 pTypeInfoImpl->next = This;
5878 ITypeInfo_AddRef((ITypeInfo*) This);
5880 ITypeInfo_AddRef(*ppTInfo);
5882 result = S_OK;
5884 } else {
5885 TLBRefType *pRefType;
5886 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5887 if(pRefType->reference == hRefType)
5888 break;
5890 if(!pRefType)
5891 FIXME("Can't find pRefType for ref %x\n", hRefType);
5892 if(pRefType && hRefType != -1) {
5893 ITypeLib *pTLib = NULL;
5895 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5896 UINT Index;
5897 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5898 } else {
5899 if(pRefType->pImpTLInfo->pImpTypeLib) {
5900 TRACE("typeinfo in imported typelib that is already loaded\n");
5901 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5902 ITypeLib2_AddRef((ITypeLib*) pTLib);
5903 result = S_OK;
5904 } else {
5905 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5906 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5907 pRefType->pImpTLInfo->wVersionMajor,
5908 pRefType->pImpTLInfo->wVersionMinor,
5909 pRefType->pImpTLInfo->lcid,
5910 &pTLib);
5912 if(!SUCCEEDED(result)) {
5913 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5914 result=LoadTypeLib(libnam, &pTLib);
5915 SysFreeString(libnam);
5917 if(SUCCEEDED(result)) {
5918 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5919 ITypeLib2_AddRef(pTLib);
5923 if(SUCCEEDED(result)) {
5924 if(pRefType->index == TLB_REF_USE_GUID)
5925 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5926 &pRefType->guid,
5927 ppTInfo);
5928 else
5929 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5930 ppTInfo);
5932 if (pTLib != NULL)
5933 ITypeLib2_Release(pTLib);
5937 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
5938 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5939 return result;
5942 /* ITypeInfo::AddressOfMember
5944 * Retrieves the addresses of static functions or variables, such as those
5945 * defined in a DLL.
5947 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5948 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5950 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5951 HRESULT hr;
5952 BSTR dll, entry;
5953 WORD ordinal;
5954 HMODULE module;
5956 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
5958 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5959 if (FAILED(hr))
5960 return hr;
5962 module = LoadLibraryW(dll);
5963 if (!module)
5965 ERR("couldn't load %s\n", debugstr_w(dll));
5966 SysFreeString(dll);
5967 if (entry) SysFreeString(entry);
5968 return STG_E_FILENOTFOUND;
5970 /* FIXME: store library somewhere where we can free it */
5972 if (entry)
5974 LPSTR entryA;
5975 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5976 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5977 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5979 *ppv = GetProcAddress(module, entryA);
5980 if (!*ppv)
5981 ERR("function not found %s\n", debugstr_a(entryA));
5983 HeapFree(GetProcessHeap(), 0, entryA);
5985 else
5987 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5988 if (!*ppv)
5989 ERR("function not found %d\n", ordinal);
5992 SysFreeString(dll);
5993 if (entry) SysFreeString(entry);
5995 if (!*ppv)
5996 return TYPE_E_DLLFUNCTIONNOTFOUND;
5998 return S_OK;
6001 /* ITypeInfo::CreateInstance
6003 * Creates a new instance of a type that describes a component object class
6004 * (coclass).
6006 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6007 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6009 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6010 HRESULT hr;
6011 TYPEATTR *pTA;
6013 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6015 *ppvObj = NULL;
6017 if(pOuterUnk)
6019 WARN("Not able to aggregate\n");
6020 return CLASS_E_NOAGGREGATION;
6023 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6024 if(FAILED(hr)) return hr;
6026 if(pTA->typekind != TKIND_COCLASS)
6028 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6029 hr = E_INVALIDARG;
6030 goto end;
6033 hr = S_FALSE;
6034 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6036 IUnknown *pUnk;
6037 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6038 TRACE("GetActiveObject rets %08x\n", hr);
6039 if(hr == S_OK)
6041 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6042 IUnknown_Release(pUnk);
6046 if(hr != S_OK)
6047 hr = CoCreateInstance(&pTA->guid, NULL,
6048 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6049 riid, ppvObj);
6051 end:
6052 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6053 return hr;
6056 /* ITypeInfo::GetMops
6058 * Retrieves marshalling information.
6060 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6061 BSTR *pBstrMops)
6063 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6064 FIXME("(%p) stub!\n", This);
6065 return S_OK;
6068 /* ITypeInfo::GetContainingTypeLib
6070 * Retrieves the containing type library and the index of the type description
6071 * within that type library.
6073 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6074 ITypeLib * *ppTLib, UINT *pIndex)
6076 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6078 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6079 if (pIndex) {
6080 *pIndex=This->index;
6081 TRACE("returning pIndex=%d\n", *pIndex);
6084 if (ppTLib) {
6085 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6086 ITypeLib2_AddRef(*ppTLib);
6087 TRACE("returning ppTLib=%p\n", *ppTLib);
6090 return S_OK;
6093 /* ITypeInfo::ReleaseTypeAttr
6095 * Releases a TYPEATTR previously returned by GetTypeAttr.
6098 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6099 TYPEATTR* pTypeAttr)
6101 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6102 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6103 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6106 /* ITypeInfo::ReleaseFuncDesc
6108 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6110 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6111 ITypeInfo2 *iface,
6112 FUNCDESC *pFuncDesc)
6114 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6115 SHORT i;
6117 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6119 for (i = 0; i < pFuncDesc->cParams; i++)
6120 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6121 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6123 SysFreeString((BSTR)pFuncDesc);
6126 /* ITypeInfo::ReleaseVarDesc
6128 * Releases a VARDESC previously returned by GetVarDesc.
6130 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6131 VARDESC *pVarDesc)
6133 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6134 TRACE("(%p)->(%p)\n", This, pVarDesc);
6136 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6137 if (pVarDesc->varkind == VAR_CONST)
6138 VariantClear(pVarDesc->u.lpvarValue);
6139 SysFreeString((BSTR)pVarDesc);
6142 /* ITypeInfo2::GetTypeKind
6144 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6147 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6148 TYPEKIND *pTypeKind)
6150 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6151 *pTypeKind=This->TypeAttr.typekind;
6152 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6153 return S_OK;
6156 /* ITypeInfo2::GetTypeFlags
6158 * Returns the type flags without any allocations. This returns a DWORD type
6159 * flag, which expands the type flags without growing the TYPEATTR (type
6160 * attribute).
6163 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6166 *pTypeFlags=This->TypeAttr.wTypeFlags;
6167 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6168 return S_OK;
6171 /* ITypeInfo2::GetFuncIndexOfMemId
6172 * Binds to a specific member based on a known DISPID, where the member name
6173 * is not known (for example, when binding to a default member).
6176 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6177 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6179 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6180 const TLBFuncDesc *pFuncInfo;
6181 int i;
6182 HRESULT result;
6184 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6185 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6186 break;
6187 if(pFuncInfo) {
6188 *pFuncIndex = i;
6189 result = S_OK;
6190 } else
6191 result = TYPE_E_ELEMENTNOTFOUND;
6193 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6194 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6195 return result;
6198 /* TypeInfo2::GetVarIndexOfMemId
6200 * Binds to a specific member based on a known DISPID, where the member name
6201 * is not known (for example, when binding to a default member).
6204 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6205 MEMBERID memid, UINT *pVarIndex)
6207 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6208 TLBVarDesc *pVarInfo;
6209 int i;
6210 HRESULT result;
6211 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6212 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6214 if(pVarInfo) {
6215 *pVarIndex = i;
6216 result = S_OK;
6217 } else
6218 result = TYPE_E_ELEMENTNOTFOUND;
6220 TRACE("(%p) memid 0x%08x -> %s\n", This,
6221 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6222 return result;
6225 /* ITypeInfo2::GetCustData
6227 * Gets the custom data
6229 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6230 ITypeInfo2 * iface,
6231 REFGUID guid,
6232 VARIANT *pVarVal)
6234 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6235 TLBCustData *pCData;
6237 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6238 if( IsEqualIID(guid, &pCData->guid)) break;
6240 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6242 if(pCData)
6244 VariantInit( pVarVal);
6245 VariantCopy( pVarVal, &pCData->data);
6246 return S_OK;
6248 return E_INVALIDARG; /* FIXME: correct? */
6251 /* ITypeInfo2::GetFuncCustData
6253 * Gets the custom data
6255 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6256 ITypeInfo2 * iface,
6257 UINT index,
6258 REFGUID guid,
6259 VARIANT *pVarVal)
6261 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6262 TLBCustData *pCData=NULL;
6263 TLBFuncDesc * pFDesc;
6264 int i;
6265 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6266 pFDesc=pFDesc->next);
6268 if(pFDesc)
6269 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6270 if( IsEqualIID(guid, &pCData->guid)) break;
6272 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6274 if(pCData){
6275 VariantInit( pVarVal);
6276 VariantCopy( pVarVal, &pCData->data);
6277 return S_OK;
6279 return E_INVALIDARG; /* FIXME: correct? */
6282 /* ITypeInfo2::GetParamCustData
6284 * Gets the custom data
6286 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6287 ITypeInfo2 * iface,
6288 UINT indexFunc,
6289 UINT indexParam,
6290 REFGUID guid,
6291 VARIANT *pVarVal)
6293 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6294 TLBCustData *pCData=NULL;
6295 TLBFuncDesc * pFDesc;
6296 int i;
6298 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6300 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6301 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6302 pCData = pCData->next)
6303 if( IsEqualIID(guid, &pCData->guid)) break;
6305 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6307 if(pCData)
6309 VariantInit( pVarVal);
6310 VariantCopy( pVarVal, &pCData->data);
6311 return S_OK;
6313 return E_INVALIDARG; /* FIXME: correct? */
6316 /* ITypeInfo2::GetVarCustData
6318 * Gets the custom data
6320 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6321 ITypeInfo2 * iface,
6322 UINT index,
6323 REFGUID guid,
6324 VARIANT *pVarVal)
6326 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6327 TLBCustData *pCData=NULL;
6328 TLBVarDesc * pVDesc;
6329 int i;
6331 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6333 if(pVDesc)
6335 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6337 if( IsEqualIID(guid, &pCData->guid)) break;
6341 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6343 if(pCData)
6345 VariantInit( pVarVal);
6346 VariantCopy( pVarVal, &pCData->data);
6347 return S_OK;
6349 return E_INVALIDARG; /* FIXME: correct? */
6352 /* ITypeInfo2::GetImplCustData
6354 * Gets the custom data
6356 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6357 ITypeInfo2 * iface,
6358 UINT index,
6359 REFGUID guid,
6360 VARIANT *pVarVal)
6362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6363 TLBCustData *pCData=NULL;
6364 TLBImplType * pRDesc;
6365 int i;
6367 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6369 if(pRDesc)
6371 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6373 if( IsEqualIID(guid, &pCData->guid)) break;
6377 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6379 if(pCData)
6381 VariantInit( pVarVal);
6382 VariantCopy( pVarVal, &pCData->data);
6383 return S_OK;
6385 return E_INVALIDARG; /* FIXME: correct? */
6388 /* ITypeInfo2::GetDocumentation2
6390 * Retrieves the documentation string, the complete Help file name and path,
6391 * the localization context to use, and the context ID for the library Help
6392 * topic in the Help file.
6395 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6396 ITypeInfo2 * iface,
6397 MEMBERID memid,
6398 LCID lcid,
6399 BSTR *pbstrHelpString,
6400 DWORD *pdwHelpStringContext,
6401 BSTR *pbstrHelpStringDll)
6403 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6404 const TLBFuncDesc *pFDesc;
6405 const TLBVarDesc *pVDesc;
6406 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6407 "HelpStringContext(%p) HelpStringDll(%p)\n",
6408 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6409 pbstrHelpStringDll );
6410 /* the help string should be obtained from the helpstringdll,
6411 * using the _DLLGetDocumentation function, based on the supplied
6412 * lcid. Nice to do sometime...
6414 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6415 if(pbstrHelpString)
6416 *pbstrHelpString=SysAllocString(This->Name);
6417 if(pdwHelpStringContext)
6418 *pdwHelpStringContext=This->dwHelpStringContext;
6419 if(pbstrHelpStringDll)
6420 *pbstrHelpStringDll=
6421 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6422 return S_OK;
6423 }else {/* for a member */
6424 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6425 if(pFDesc->funcdesc.memid==memid){
6426 if(pbstrHelpString)
6427 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6428 if(pdwHelpStringContext)
6429 *pdwHelpStringContext=pFDesc->HelpStringContext;
6430 if(pbstrHelpStringDll)
6431 *pbstrHelpStringDll=
6432 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6433 return S_OK;
6435 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6436 if(pVDesc->vardesc.memid==memid){
6437 if(pbstrHelpString)
6438 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6439 if(pdwHelpStringContext)
6440 *pdwHelpStringContext=pVDesc->HelpStringContext;
6441 if(pbstrHelpStringDll)
6442 *pbstrHelpStringDll=
6443 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6444 return S_OK;
6447 return TYPE_E_ELEMENTNOTFOUND;
6450 /* ITypeInfo2::GetAllCustData
6452 * Gets all custom data items for the Type info.
6455 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6456 ITypeInfo2 * iface,
6457 CUSTDATA *pCustData)
6459 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6460 TLBCustData *pCData;
6461 int i;
6463 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6465 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6466 if(pCustData->prgCustData ){
6467 pCustData->cCustData=This->ctCustData;
6468 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6469 pCustData->prgCustData[i].guid=pCData->guid;
6470 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6472 }else{
6473 ERR(" OUT OF MEMORY!\n");
6474 return E_OUTOFMEMORY;
6476 return S_OK;
6479 /* ITypeInfo2::GetAllFuncCustData
6481 * Gets all custom data items for the specified Function
6484 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6485 ITypeInfo2 * iface,
6486 UINT index,
6487 CUSTDATA *pCustData)
6489 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6490 TLBCustData *pCData;
6491 TLBFuncDesc * pFDesc;
6492 int i;
6493 TRACE("(%p) index %d\n", This, index);
6494 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6495 pFDesc=pFDesc->next)
6497 if(pFDesc){
6498 pCustData->prgCustData =
6499 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6500 if(pCustData->prgCustData ){
6501 pCustData->cCustData=pFDesc->ctCustData;
6502 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6503 pCData = pCData->next){
6504 pCustData->prgCustData[i].guid=pCData->guid;
6505 VariantCopy(& pCustData->prgCustData[i].varValue,
6506 & pCData->data);
6508 }else{
6509 ERR(" OUT OF MEMORY!\n");
6510 return E_OUTOFMEMORY;
6512 return S_OK;
6514 return TYPE_E_ELEMENTNOTFOUND;
6517 /* ITypeInfo2::GetAllParamCustData
6519 * Gets all custom data items for the Functions
6522 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6523 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6525 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6526 TLBCustData *pCData=NULL;
6527 TLBFuncDesc * pFDesc;
6528 int i;
6529 TRACE("(%p) index %d\n", This, indexFunc);
6530 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6531 pFDesc=pFDesc->next)
6533 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6534 pCustData->prgCustData =
6535 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6536 sizeof(CUSTDATAITEM));
6537 if(pCustData->prgCustData ){
6538 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6539 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6540 pCData; i++, pCData = pCData->next){
6541 pCustData->prgCustData[i].guid=pCData->guid;
6542 VariantCopy(& pCustData->prgCustData[i].varValue,
6543 & pCData->data);
6545 }else{
6546 ERR(" OUT OF MEMORY!\n");
6547 return E_OUTOFMEMORY;
6549 return S_OK;
6551 return TYPE_E_ELEMENTNOTFOUND;
6554 /* ITypeInfo2::GetAllVarCustData
6556 * Gets all custom data items for the specified Variable
6559 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6560 UINT index, CUSTDATA *pCustData)
6562 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6563 TLBCustData *pCData;
6564 TLBVarDesc * pVDesc;
6565 int i;
6566 TRACE("(%p) index %d\n", This, index);
6567 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6568 pVDesc=pVDesc->next)
6570 if(pVDesc){
6571 pCustData->prgCustData =
6572 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6573 if(pCustData->prgCustData ){
6574 pCustData->cCustData=pVDesc->ctCustData;
6575 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6576 pCData = pCData->next){
6577 pCustData->prgCustData[i].guid=pCData->guid;
6578 VariantCopy(& pCustData->prgCustData[i].varValue,
6579 & pCData->data);
6581 }else{
6582 ERR(" OUT OF MEMORY!\n");
6583 return E_OUTOFMEMORY;
6585 return S_OK;
6587 return TYPE_E_ELEMENTNOTFOUND;
6590 /* ITypeInfo2::GetAllImplCustData
6592 * Gets all custom data items for the specified implementation type
6595 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6596 ITypeInfo2 * iface,
6597 UINT index,
6598 CUSTDATA *pCustData)
6600 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6601 TLBCustData *pCData;
6602 TLBImplType * pRDesc;
6603 int i;
6604 TRACE("(%p) index %d\n", This, index);
6605 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6606 pRDesc=pRDesc->next)
6608 if(pRDesc){
6609 pCustData->prgCustData =
6610 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6611 if(pCustData->prgCustData ){
6612 pCustData->cCustData=pRDesc->ctCustData;
6613 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6614 pCData = pCData->next){
6615 pCustData->prgCustData[i].guid=pCData->guid;
6616 VariantCopy(& pCustData->prgCustData[i].varValue,
6617 & pCData->data);
6619 }else{
6620 ERR(" OUT OF MEMORY!\n");
6621 return E_OUTOFMEMORY;
6623 return S_OK;
6625 return TYPE_E_ELEMENTNOTFOUND;
6628 static const ITypeInfo2Vtbl tinfvt =
6631 ITypeInfo_fnQueryInterface,
6632 ITypeInfo_fnAddRef,
6633 ITypeInfo_fnRelease,
6635 ITypeInfo_fnGetTypeAttr,
6636 ITypeInfo_fnGetTypeComp,
6637 ITypeInfo_fnGetFuncDesc,
6638 ITypeInfo_fnGetVarDesc,
6639 ITypeInfo_fnGetNames,
6640 ITypeInfo_fnGetRefTypeOfImplType,
6641 ITypeInfo_fnGetImplTypeFlags,
6642 ITypeInfo_fnGetIDsOfNames,
6643 ITypeInfo_fnInvoke,
6644 ITypeInfo_fnGetDocumentation,
6645 ITypeInfo_fnGetDllEntry,
6646 ITypeInfo_fnGetRefTypeInfo,
6647 ITypeInfo_fnAddressOfMember,
6648 ITypeInfo_fnCreateInstance,
6649 ITypeInfo_fnGetMops,
6650 ITypeInfo_fnGetContainingTypeLib,
6651 ITypeInfo_fnReleaseTypeAttr,
6652 ITypeInfo_fnReleaseFuncDesc,
6653 ITypeInfo_fnReleaseVarDesc,
6655 ITypeInfo2_fnGetTypeKind,
6656 ITypeInfo2_fnGetTypeFlags,
6657 ITypeInfo2_fnGetFuncIndexOfMemId,
6658 ITypeInfo2_fnGetVarIndexOfMemId,
6659 ITypeInfo2_fnGetCustData,
6660 ITypeInfo2_fnGetFuncCustData,
6661 ITypeInfo2_fnGetParamCustData,
6662 ITypeInfo2_fnGetVarCustData,
6663 ITypeInfo2_fnGetImplTypeCustData,
6664 ITypeInfo2_fnGetDocumentation2,
6665 ITypeInfo2_fnGetAllCustData,
6666 ITypeInfo2_fnGetAllFuncCustData,
6667 ITypeInfo2_fnGetAllParamCustData,
6668 ITypeInfo2_fnGetAllVarCustData,
6669 ITypeInfo2_fnGetAllImplTypeCustData,
6672 /******************************************************************************
6673 * CreateDispTypeInfo [OLEAUT32.31]
6675 * Build type information for an object so it can be called through an
6676 * IDispatch interface.
6678 * RETURNS
6679 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6680 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6682 * NOTES
6683 * This call allows an objects methods to be accessed through IDispatch, by
6684 * building an ITypeInfo object that IDispatch can use to call through.
6686 HRESULT WINAPI CreateDispTypeInfo(
6687 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6688 LCID lcid, /* [I] Locale Id */
6689 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6691 ITypeInfoImpl *pTIClass, *pTIIface;
6692 ITypeLibImpl *pTypeLibImpl;
6693 int param, func;
6694 TLBFuncDesc **ppFuncDesc;
6696 TRACE("\n");
6697 pTypeLibImpl = TypeLibImpl_Constructor();
6698 if (!pTypeLibImpl) return E_FAIL;
6700 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6701 pTIIface->pTypeLib = pTypeLibImpl;
6702 pTIIface->index = 0;
6703 pTIIface->Name = NULL;
6704 pTIIface->dwHelpContext = -1;
6705 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6706 pTIIface->TypeAttr.lcid = lcid;
6707 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6708 pTIIface->TypeAttr.wMajorVerNum = 0;
6709 pTIIface->TypeAttr.wMinorVerNum = 0;
6710 pTIIface->TypeAttr.cbAlignment = 2;
6711 pTIIface->TypeAttr.cbSizeInstance = -1;
6712 pTIIface->TypeAttr.cbSizeVft = -1;
6713 pTIIface->TypeAttr.cFuncs = 0;
6714 pTIIface->TypeAttr.cImplTypes = 0;
6715 pTIIface->TypeAttr.cVars = 0;
6716 pTIIface->TypeAttr.wTypeFlags = 0;
6718 ppFuncDesc = &pTIIface->funclist;
6719 for(func = 0; func < pidata->cMembers; func++) {
6720 METHODDATA *md = pidata->pmethdata + func;
6721 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6722 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6723 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6724 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6725 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6726 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6727 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6728 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6729 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6730 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6731 (*ppFuncDesc)->funcdesc.cScodes = 0;
6732 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6733 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6734 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6735 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6736 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6737 md->cArgs * sizeof(ELEMDESC));
6738 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6739 md->cArgs * sizeof(TLBParDesc));
6740 for(param = 0; param < md->cArgs; param++) {
6741 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6742 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6744 (*ppFuncDesc)->helpcontext = 0;
6745 (*ppFuncDesc)->HelpStringContext = 0;
6746 (*ppFuncDesc)->HelpString = NULL;
6747 (*ppFuncDesc)->Entry = NULL;
6748 (*ppFuncDesc)->ctCustData = 0;
6749 (*ppFuncDesc)->pCustData = NULL;
6750 (*ppFuncDesc)->next = NULL;
6751 ppFuncDesc = &(*ppFuncDesc)->next;
6754 dump_TypeInfo(pTIIface);
6756 pTypeLibImpl->pTypeInfo = pTIIface;
6757 pTypeLibImpl->TypeInfoCount++;
6759 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6760 pTIClass->pTypeLib = pTypeLibImpl;
6761 pTIClass->index = 1;
6762 pTIClass->Name = NULL;
6763 pTIClass->dwHelpContext = -1;
6764 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6765 pTIClass->TypeAttr.lcid = lcid;
6766 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6767 pTIClass->TypeAttr.wMajorVerNum = 0;
6768 pTIClass->TypeAttr.wMinorVerNum = 0;
6769 pTIClass->TypeAttr.cbAlignment = 2;
6770 pTIClass->TypeAttr.cbSizeInstance = -1;
6771 pTIClass->TypeAttr.cbSizeVft = -1;
6772 pTIClass->TypeAttr.cFuncs = 0;
6773 pTIClass->TypeAttr.cImplTypes = 1;
6774 pTIClass->TypeAttr.cVars = 0;
6775 pTIClass->TypeAttr.wTypeFlags = 0;
6777 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6778 pTIClass->impltypelist->hRef = 1;
6780 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6781 pTIClass->reflist->index = 0;
6782 pTIClass->reflist->reference = 1;
6783 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6785 dump_TypeInfo(pTIClass);
6787 pTIIface->next = pTIClass;
6788 pTypeLibImpl->TypeInfoCount++;
6790 *pptinfo = (ITypeInfo*)pTIClass;
6791 return S_OK;
6795 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6797 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6799 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6802 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6804 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6806 return ITypeInfo_AddRef((ITypeInfo *)This);
6809 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6811 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6813 return ITypeInfo_Release((ITypeInfo *)This);
6816 static HRESULT WINAPI ITypeComp_fnBind(
6817 ITypeComp * iface,
6818 OLECHAR * szName,
6819 ULONG lHash,
6820 WORD wFlags,
6821 ITypeInfo ** ppTInfo,
6822 DESCKIND * pDescKind,
6823 BINDPTR * pBindPtr)
6825 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6826 const TLBFuncDesc *pFDesc;
6827 const TLBVarDesc *pVDesc;
6828 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6830 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6832 *pDescKind = DESCKIND_NONE;
6833 pBindPtr->lpfuncdesc = NULL;
6834 *ppTInfo = NULL;
6836 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6837 if (!strcmpiW(pFDesc->Name, szName)) {
6838 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6839 break;
6840 else
6841 /* name found, but wrong flags */
6842 hr = TYPE_E_TYPEMISMATCH;
6845 if (pFDesc)
6847 HRESULT hr = TLB_AllocAndInitFuncDesc(
6848 &pFDesc->funcdesc,
6849 &pBindPtr->lpfuncdesc,
6850 This->TypeAttr.typekind == TKIND_DISPATCH);
6851 if (FAILED(hr))
6852 return hr;
6853 *pDescKind = DESCKIND_FUNCDESC;
6854 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6855 ITypeInfo_AddRef(*ppTInfo);
6856 return S_OK;
6857 } else {
6858 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6859 if (!strcmpiW(pVDesc->Name, szName)) {
6860 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6861 if (FAILED(hr))
6862 return hr;
6863 *pDescKind = DESCKIND_VARDESC;
6864 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6865 ITypeInfo_AddRef(*ppTInfo);
6866 return S_OK;
6870 /* FIXME: search each inherited interface, not just the first */
6871 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6872 /* recursive search */
6873 ITypeInfo *pTInfo;
6874 ITypeComp *pTComp;
6875 HRESULT hr;
6876 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6877 if (SUCCEEDED(hr))
6879 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6880 ITypeInfo_Release(pTInfo);
6882 if (SUCCEEDED(hr))
6884 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6885 ITypeComp_Release(pTComp);
6886 return hr;
6888 WARN("Could not search inherited interface!\n");
6890 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6891 return hr;
6894 static HRESULT WINAPI ITypeComp_fnBindType(
6895 ITypeComp * iface,
6896 OLECHAR * szName,
6897 ULONG lHash,
6898 ITypeInfo ** ppTInfo,
6899 ITypeComp ** ppTComp)
6901 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6903 /* strange behaviour (does nothing) but like the
6904 * original */
6906 if (!ppTInfo || !ppTComp)
6907 return E_POINTER;
6909 *ppTInfo = NULL;
6910 *ppTComp = NULL;
6912 return S_OK;
6915 static const ITypeCompVtbl tcompvt =
6918 ITypeComp_fnQueryInterface,
6919 ITypeComp_fnAddRef,
6920 ITypeComp_fnRelease,
6922 ITypeComp_fnBind,
6923 ITypeComp_fnBindType