rpcrt4: Initialise pStubMsg->MemorySize to zero before calling ComplexStructMemorySiz...
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob21c69a9abb1a3411efc8b5048ef19bc9f998d59f
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 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
86 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
88 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
89 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
91 /****************************************************************************
92 * FromLExxx
94 * Takes p_iVal (which is in little endian) and returns it
95 * in the host machine's byte order.
97 #ifdef WORDS_BIGENDIAN
98 static WORD FromLEWord(WORD p_iVal)
100 return (((p_iVal & 0x00FF) << 8) |
101 ((p_iVal & 0xFF00) >> 8));
105 static DWORD FromLEDWord(DWORD p_iVal)
107 return (((p_iVal & 0x000000FF) << 24) |
108 ((p_iVal & 0x0000FF00) << 8) |
109 ((p_iVal & 0x00FF0000) >> 8) |
110 ((p_iVal & 0xFF000000) >> 24));
112 #else
113 #define FromLEWord(X) (X)
114 #define FromLEDWord(X) (X)
115 #endif
118 /****************************************************************************
119 * FromLExxx
121 * Fix byte order in any structure if necessary
123 #ifdef WORDS_BIGENDIAN
124 static void FromLEWords(void *p_Val, int p_iSize)
126 WORD *Val = p_Val;
128 p_iSize /= sizeof(WORD);
130 while (p_iSize) {
131 *Val = FromLEWord(*Val);
132 Val++;
133 p_iSize--;
138 static void FromLEDWords(void *p_Val, int p_iSize)
140 DWORD *Val = p_Val;
142 p_iSize /= sizeof(DWORD);
144 while (p_iSize) {
145 *Val = FromLEDWord(*Val);
146 Val++;
147 p_iSize--;
150 #else
151 #define FromLEWords(X,Y) /*nothing*/
152 #define FromLEDWords(X,Y) /*nothing*/
153 #endif
155 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
156 /* buffer must be at least 60 characters long */
157 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
159 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
160 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
162 memcpy( buffer, TypelibW, sizeof(TypelibW) );
163 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
165 return buffer;
168 /* get the path of an interface key, in the form "Interface\\<guid>" */
169 /* buffer must be at least 50 characters long */
170 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
172 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
174 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
175 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
176 return buffer;
179 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
180 /* buffer must be at least 16 characters long */
181 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
183 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
184 static const WCHAR win16W[] = {'w','i','n','1','6',0};
185 static const WCHAR win32W[] = {'w','i','n','3','2',0};
187 sprintfW( buffer, LcidFormatW, lcid );
188 switch(syskind)
190 case SYS_WIN16: strcatW( buffer, win16W ); break;
191 case SYS_WIN32: strcatW( buffer, win32W ); break;
192 default:
193 TRACE("Typelib is for unsupported syskind %i\n", syskind);
194 return NULL;
196 return buffer;
199 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
202 /****************************************************************************
203 * QueryPathOfRegTypeLib [OLEAUT32.164]
205 * Gets the path to a registered type library.
207 * PARAMS
208 * guid [I] referenced guid
209 * wMaj [I] major version
210 * wMin [I] minor version
211 * lcid [I] locale id
212 * path [O] path of typelib
214 * RETURNS
215 * Success: S_OK.
216 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
217 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
218 * opened.
220 HRESULT WINAPI QueryPathOfRegTypeLib(
221 REFGUID guid,
222 WORD wMaj,
223 WORD wMin,
224 LCID lcid,
225 LPBSTR path )
227 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
228 LCID myLCID = lcid;
229 HKEY hkey;
230 WCHAR buffer[60];
231 WCHAR Path[MAX_PATH];
232 LONG res;
234 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
236 get_typelib_key( guid, wMaj, wMin, buffer );
238 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
239 if (res == ERROR_FILE_NOT_FOUND)
241 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
242 return TYPE_E_LIBNOTREGISTERED;
244 else if (res != ERROR_SUCCESS)
246 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
247 return TYPE_E_REGISTRYACCESS;
250 while (hr != S_OK)
252 LONG dwPathLen = sizeof(Path);
254 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
256 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
258 if (!lcid)
259 break;
260 else if (myLCID == lcid)
262 /* try with sub-langid */
263 myLCID = SUBLANGID(lcid);
265 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
267 /* try with system langid */
268 myLCID = 0;
270 else
272 break;
275 else
277 *path = SysAllocString( Path );
278 hr = S_OK;
281 RegCloseKey( hkey );
282 TRACE_(typelib)("-- 0x%08lx\n", hr);
283 return hr;
286 /******************************************************************************
287 * CreateTypeLib [OLEAUT32.160] creates a typelib
289 * RETURNS
290 * Success: S_OK
291 * Failure: Status
293 HRESULT WINAPI CreateTypeLib(
294 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
296 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
297 return E_FAIL;
300 /******************************************************************************
301 * LoadTypeLib [OLEAUT32.161]
303 * Loads a type library
305 * PARAMS
306 * szFile [I] Name of file to load from.
307 * pptLib [O] Pointer that receives ITypeLib object on success.
309 * RETURNS
310 * Success: S_OK
311 * Failure: Status
313 * SEE
314 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
316 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
318 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
319 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
322 /******************************************************************************
323 * LoadTypeLibEx [OLEAUT32.183]
325 * Loads and optionally registers a type library
327 * RETURNS
328 * Success: S_OK
329 * Failure: Status
331 HRESULT WINAPI LoadTypeLibEx(
332 LPCOLESTR szFile, /* [in] Name of file to load from */
333 REGKIND regkind, /* [in] Specify kind of registration */
334 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
336 WCHAR szPath[MAX_PATH+1];
337 HRESULT res;
339 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
341 *pptLib = NULL;
343 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
345 if (SUCCEEDED(res))
346 switch(regkind)
348 case REGKIND_DEFAULT:
349 /* don't register typelibs supplied with full path. Experimentation confirms the following */
350 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
351 (szFile[0] && (szFile[1] == ':'))) break;
352 /* else fall-through */
354 case REGKIND_REGISTER:
355 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
357 IUnknown_Release(*pptLib);
358 *pptLib = 0;
360 break;
361 case REGKIND_NONE:
362 break;
365 TRACE(" returns %08lx\n",res);
366 return res;
369 /******************************************************************************
370 * LoadRegTypeLib [OLEAUT32.162]
372 * Loads a registered type library.
374 * PARAMS
375 * rguid [I] GUID of the registered type library.
376 * wVerMajor [I] major version.
377 * wVerMinor [I] minor version.
378 * lcid [I] locale ID.
379 * ppTLib [O] pointer that receives an ITypeLib object on success.
381 * RETURNS
382 * Success: S_OK.
383 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
384 * LoadTypeLib.
386 HRESULT WINAPI LoadRegTypeLib(
387 REFGUID rguid,
388 WORD wVerMajor,
389 WORD wVerMinor,
390 LCID lcid,
391 ITypeLib **ppTLib)
393 BSTR bstr=NULL;
394 HRESULT res;
396 *ppTLib = NULL;
398 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
400 if(SUCCEEDED(res))
402 res= LoadTypeLib(bstr, ppTLib);
403 SysFreeString(bstr);
406 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
408 return res;
412 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
413 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
414 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
415 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
416 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
417 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
419 /******************************************************************************
420 * RegisterTypeLib [OLEAUT32.163]
421 * Adds information about a type library to the System Registry
422 * NOTES
423 * Docs: ITypeLib FAR * ptlib
424 * Docs: OLECHAR FAR* szFullPath
425 * Docs: OLECHAR FAR* szHelpDir
427 * RETURNS
428 * Success: S_OK
429 * Failure: Status
431 HRESULT WINAPI RegisterTypeLib(
432 ITypeLib * ptlib, /* [in] Pointer to the library*/
433 OLECHAR * szFullPath, /* [in] full Path of the library*/
434 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
435 may be NULL*/
437 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
438 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
439 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
440 HRESULT res;
441 TLIBATTR *attr;
442 WCHAR keyName[60];
443 WCHAR tmp[16];
444 HKEY key, subKey;
445 UINT types, tidx;
446 TYPEKIND kind;
447 DWORD disposition;
449 if (ptlib == NULL || szFullPath == NULL)
450 return E_INVALIDARG;
452 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
453 return E_FAIL;
455 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
457 res = S_OK;
458 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
459 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
461 LPOLESTR doc;
463 /* Set the human-readable name of the typelib */
464 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
466 if (RegSetValueExW(key, NULL, 0, REG_SZ,
467 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
468 res = E_FAIL;
470 SysFreeString(doc);
472 else
473 res = E_FAIL;
475 /* Make up the name of the typelib path subkey */
476 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
478 /* Create the typelib path subkey */
479 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
480 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
482 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
483 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
484 res = E_FAIL;
486 RegCloseKey(subKey);
488 else
489 res = E_FAIL;
491 /* Create the flags subkey */
492 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
493 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
495 /* FIXME: is %u correct? */
496 static const WCHAR formatW[] = {'%','u',0};
497 WCHAR buf[20];
498 sprintfW(buf, formatW, attr->wLibFlags);
499 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
500 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
501 res = E_FAIL;
503 RegCloseKey(subKey);
505 else
506 res = E_FAIL;
508 /* create the helpdir subkey */
509 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
510 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
512 BOOL freeHelpDir = FALSE;
513 OLECHAR* pIndexStr;
515 /* if we created a new key, and helpDir was null, set the helpdir
516 to the directory which contains the typelib. However,
517 if we just opened an existing key, we leave the helpdir alone */
518 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
519 szHelpDir = SysAllocString(szFullPath);
520 pIndexStr = strrchrW(szHelpDir, '\\');
521 if (pIndexStr) {
522 *pIndexStr = 0;
524 freeHelpDir = TRUE;
527 /* if we have an szHelpDir, set it! */
528 if (szHelpDir != NULL) {
529 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
530 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
531 res = E_FAIL;
535 /* tidy up */
536 if (freeHelpDir) SysFreeString(szHelpDir);
537 RegCloseKey(subKey);
539 } else {
540 res = E_FAIL;
543 RegCloseKey(key);
545 else
546 res = E_FAIL;
548 /* register OLE Automation-compatible interfaces for this typelib */
549 types = ITypeLib_GetTypeInfoCount(ptlib);
550 for (tidx=0; tidx<types; tidx++) {
551 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
552 LPOLESTR name = NULL;
553 ITypeInfo *tinfo = NULL;
555 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
557 switch (kind) {
558 case TKIND_INTERFACE:
559 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
560 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
561 break;
563 case TKIND_DISPATCH:
564 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
565 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
566 break;
568 default:
569 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
570 break;
573 if (tinfo) {
574 TYPEATTR *tattr = NULL;
575 ITypeInfo_GetTypeAttr(tinfo, &tattr);
577 if (tattr) {
578 TRACE_(typelib)("guid=%s, flags=%04x (",
579 debugstr_guid(&tattr->guid),
580 tattr->wTypeFlags);
582 if (TRACE_ON(typelib)) {
583 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
584 XX(FAPPOBJECT);
585 XX(FCANCREATE);
586 XX(FLICENSED);
587 XX(FPREDECLID);
588 XX(FHIDDEN);
589 XX(FCONTROL);
590 XX(FDUAL);
591 XX(FNONEXTENSIBLE);
592 XX(FOLEAUTOMATION);
593 XX(FRESTRICTED);
594 XX(FAGGREGATABLE);
595 XX(FREPLACEABLE);
596 XX(FDISPATCHABLE);
597 XX(FREVERSEBIND);
598 XX(FPROXY);
599 #undef XX
600 MESSAGE("\n");
603 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
605 /* register interface<->typelib coupling */
606 get_interface_key( &tattr->guid, keyName );
607 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
608 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
610 if (name)
611 RegSetValueExW(key, NULL, 0, REG_SZ,
612 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
614 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
615 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
616 RegSetValueExW(subKey, NULL, 0, REG_SZ,
617 (BYTE*)PSOA, sizeof PSOA);
618 RegCloseKey(subKey);
621 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
622 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
623 RegSetValueExW(subKey, NULL, 0, REG_SZ,
624 (BYTE*)PSOA, sizeof PSOA);
625 RegCloseKey(subKey);
628 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
629 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
631 WCHAR buffer[40];
632 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
633 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
635 StringFromGUID2(&attr->guid, buffer, 40);
636 RegSetValueExW(subKey, NULL, 0, REG_SZ,
637 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
638 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
639 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
640 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
641 RegCloseKey(subKey);
644 RegCloseKey(key);
648 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
651 ITypeInfo_Release(tinfo);
654 SysFreeString(name);
658 ITypeLib_ReleaseTLibAttr(ptlib, attr);
660 return res;
664 /******************************************************************************
665 * UnRegisterTypeLib [OLEAUT32.186]
666 * Removes information about a type library from the System Registry
667 * NOTES
669 * RETURNS
670 * Success: S_OK
671 * Failure: Status
673 HRESULT WINAPI UnRegisterTypeLib(
674 REFGUID libid, /* [in] Guid of the library */
675 WORD wVerMajor, /* [in] major version */
676 WORD wVerMinor, /* [in] minor version */
677 LCID lcid, /* [in] locale id */
678 SYSKIND syskind)
680 BSTR tlibPath = NULL;
681 DWORD tmpLength;
682 WCHAR keyName[60];
683 WCHAR subKeyName[50];
684 int result = S_OK;
685 DWORD i = 0;
686 BOOL deleteOtherStuff;
687 HKEY key = NULL;
688 HKEY subKey = NULL;
689 TYPEATTR* typeAttr = NULL;
690 TYPEKIND kind;
691 ITypeInfo* typeInfo = NULL;
692 ITypeLib* typeLib = NULL;
693 int numTypes;
695 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
697 /* Create the path to the key */
698 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
700 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
702 TRACE("Unsupported syskind %i\n", syskind);
703 result = E_INVALIDARG;
704 goto end;
707 /* get the path to the typelib on disk */
708 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
709 result = E_INVALIDARG;
710 goto end;
713 /* Try and open the key to the type library. */
714 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
715 result = E_INVALIDARG;
716 goto end;
719 /* Try and load the type library */
720 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
721 result = TYPE_E_INVALIDSTATE;
722 goto end;
725 /* remove any types registered with this typelib */
726 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
727 for (i=0; i<numTypes; i++) {
728 /* get the kind of type */
729 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
730 goto enddeleteloop;
733 /* skip non-interfaces, and get type info for the type */
734 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
735 goto enddeleteloop;
737 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
738 goto enddeleteloop;
740 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
741 goto enddeleteloop;
744 /* the path to the type */
745 get_interface_key( &typeAttr->guid, subKeyName );
747 /* Delete its bits */
748 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
749 goto enddeleteloop;
751 RegDeleteKeyW(subKey, ProxyStubClsidW);
752 RegDeleteKeyW(subKey, ProxyStubClsid32W);
753 RegDeleteKeyW(subKey, TypeLibW);
754 RegCloseKey(subKey);
755 subKey = NULL;
756 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
758 enddeleteloop:
759 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
760 typeAttr = NULL;
761 if (typeInfo) ITypeInfo_Release(typeInfo);
762 typeInfo = NULL;
765 /* Now, delete the type library path subkey */
766 get_lcid_subkey( lcid, syskind, subKeyName );
767 RegDeleteKeyW(key, subKeyName);
768 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
769 RegDeleteKeyW(key, subKeyName);
771 /* check if there is anything besides the FLAGS/HELPDIR keys.
772 If there is, we don't delete them */
773 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
774 deleteOtherStuff = TRUE;
775 i = 0;
776 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
777 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
779 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
780 if (!strcmpW(subKeyName, FLAGSW)) continue;
781 if (!strcmpW(subKeyName, HELPDIRW)) continue;
782 deleteOtherStuff = FALSE;
783 break;
786 /* only delete the other parts of the key if we're absolutely sure */
787 if (deleteOtherStuff) {
788 RegDeleteKeyW(key, FLAGSW);
789 RegDeleteKeyW(key, HELPDIRW);
790 RegCloseKey(key);
791 key = NULL;
793 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
794 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
795 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
798 end:
799 if (tlibPath) SysFreeString(tlibPath);
800 if (typeLib) ITypeLib_Release(typeLib);
801 if (subKey) RegCloseKey(subKey);
802 if (key) RegCloseKey(key);
803 return result;
806 /*======================= ITypeLib implementation =======================*/
808 typedef struct tagTLBCustData
810 GUID guid;
811 VARIANT data;
812 struct tagTLBCustData* next;
813 } TLBCustData;
815 /* data structure for import typelibs */
816 typedef struct tagTLBImpLib
818 int offset; /* offset in the file (MSFT)
819 offset in nametable (SLTG)
820 just used to identify library while reading
821 data from file */
822 GUID guid; /* libid */
823 BSTR name; /* name */
825 LCID lcid; /* lcid of imported typelib */
827 WORD wVersionMajor; /* major version number */
828 WORD wVersionMinor; /* minor version number */
830 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
831 NULL if not yet loaded */
832 struct tagTLBImpLib * next;
833 } TLBImpLib;
835 /* internal ITypeLib data */
836 typedef struct tagITypeLibImpl
838 const ITypeLib2Vtbl *lpVtbl;
839 const ITypeCompVtbl *lpVtblTypeComp;
840 LONG ref;
841 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
843 /* strings can be stored in tlb as multibyte strings BUT they are *always*
844 * exported to the application as a UNICODE string.
846 BSTR Name;
847 BSTR DocString;
848 BSTR HelpFile;
849 BSTR HelpStringDll;
850 unsigned long dwHelpContext;
851 int TypeInfoCount; /* nr of typeinfo's in librarry */
852 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
853 int ctCustData; /* number of items in cust data list */
854 TLBCustData * pCustData; /* linked list to cust data */
855 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
856 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
857 libary. Only used while read MSFT
858 typelibs */
860 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
861 struct tagITypeLibImpl *next, *prev;
862 WCHAR *path;
863 INT index;
864 } ITypeLibImpl;
866 static const ITypeLib2Vtbl tlbvt;
867 static const ITypeCompVtbl tlbtcvt;
869 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
871 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
874 /* ITypeLib methods */
875 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
876 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
878 /*======================= ITypeInfo implementation =======================*/
880 /* data for referenced types */
881 typedef struct tagTLBRefType
883 INT index; /* Type index for internal ref or for external ref
884 it the format is SLTG. -2 indicates to
885 use guid */
887 GUID guid; /* guid of the referenced type */
888 /* if index == TLB_REF_USE_GUID */
890 HREFTYPE reference; /* The href of this ref */
891 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
892 TLB_REF_INTERNAL for internal refs
893 TLB_REF_NOT_FOUND for broken refs */
895 struct tagTLBRefType * next;
896 } TLBRefType;
898 #define TLB_REF_USE_GUID -2
900 #define TLB_REF_INTERNAL (void*)-2
901 #define TLB_REF_NOT_FOUND (void*)-1
903 /* internal Parameter data */
904 typedef struct tagTLBParDesc
906 BSTR Name;
907 int ctCustData;
908 TLBCustData * pCustData; /* linked list to cust data */
909 } TLBParDesc;
911 /* internal Function data */
912 typedef struct tagTLBFuncDesc
914 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
915 BSTR Name; /* the name of this function */
916 TLBParDesc *pParamDesc; /* array with param names and custom data */
917 int helpcontext;
918 int HelpStringContext;
919 BSTR HelpString;
920 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
921 int ctCustData;
922 TLBCustData * pCustData; /* linked list to cust data; */
923 struct tagTLBFuncDesc * next;
924 } TLBFuncDesc;
926 /* internal Variable data */
927 typedef struct tagTLBVarDesc
929 VARDESC vardesc; /* lots of info on the variable and its attributes. */
930 BSTR Name; /* the name of this variable */
931 int HelpContext;
932 int HelpStringContext; /* FIXME: where? */
933 BSTR HelpString;
934 int ctCustData;
935 TLBCustData * pCustData;/* linked list to cust data; */
936 struct tagTLBVarDesc * next;
937 } TLBVarDesc;
939 /* internal implemented interface data */
940 typedef struct tagTLBImplType
942 HREFTYPE hRef; /* hRef of interface */
943 int implflags; /* IMPLFLAG_*s */
944 int ctCustData;
945 TLBCustData * pCustData;/* linked list to custom data; */
946 struct tagTLBImplType *next;
947 } TLBImplType;
949 /* internal TypeInfo data */
950 typedef struct tagITypeInfoImpl
952 const ITypeInfo2Vtbl *lpVtbl;
953 const ITypeCompVtbl *lpVtblTypeComp;
954 LONG ref;
955 TYPEATTR TypeAttr ; /* _lots_ of type information. */
956 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
957 int index; /* index in this typelib; */
958 HREFTYPE hreftype; /* hreftype for app object binding */
959 /* type libs seem to store the doc strings in ascii
960 * so why should we do it in unicode?
962 BSTR Name;
963 BSTR DocString;
964 BSTR DllName;
965 unsigned long dwHelpContext;
966 unsigned long dwHelpStringContext;
968 /* functions */
969 TLBFuncDesc * funclist; /* linked list with function descriptions */
971 /* variables */
972 TLBVarDesc * varlist; /* linked list with variable descriptions */
974 /* Implemented Interfaces */
975 TLBImplType * impltypelist;
977 TLBRefType * reflist;
978 int ctCustData;
979 TLBCustData * pCustData; /* linked list to cust data; */
980 struct tagITypeInfoImpl * next;
981 } ITypeInfoImpl;
983 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
985 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
988 static const ITypeInfo2Vtbl tinfvt;
989 static const ITypeCompVtbl tcompvt;
991 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
993 typedef struct tagTLBContext
995 unsigned int oStart; /* start of TLB in file */
996 unsigned int pos; /* current pos */
997 unsigned int length; /* total length */
998 void *mapping; /* memory mapping */
999 MSFT_SegDir * pTblDir;
1000 ITypeLibImpl* pLibInfo;
1001 } TLBContext;
1004 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1007 debug
1009 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1010 if (pTD->vt & VT_RESERVED)
1011 szVarType += strlen(strcpy(szVarType, "reserved | "));
1012 if (pTD->vt & VT_BYREF)
1013 szVarType += strlen(strcpy(szVarType, "ref to "));
1014 if (pTD->vt & VT_ARRAY)
1015 szVarType += strlen(strcpy(szVarType, "array of "));
1016 if (pTD->vt & VT_VECTOR)
1017 szVarType += strlen(strcpy(szVarType, "vector of "));
1018 switch(pTD->vt & VT_TYPEMASK) {
1019 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1020 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1021 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1022 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1023 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1024 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1025 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1026 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1027 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1028 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1029 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1030 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1031 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1032 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1033 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1034 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1035 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1036 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1037 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1038 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1039 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1040 pTD->u.hreftype); break;
1041 case VT_PTR: sprintf(szVarType, "ptr to ");
1042 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1043 break;
1044 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1045 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1046 break;
1047 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1048 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1049 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1050 break;
1052 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1056 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1057 char buf[200];
1058 USHORT flags = edesc->u.paramdesc.wParamFlags;
1059 dump_TypeDesc(&edesc->tdesc,buf);
1060 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1061 MESSAGE("\t\tu.paramdesc.wParamFlags");
1062 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1063 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1064 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1065 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1066 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1067 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1068 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1069 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1070 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1072 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1073 int i;
1074 MESSAGE("memid is %08lx\n",funcdesc->memid);
1075 for (i=0;i<funcdesc->cParams;i++) {
1076 MESSAGE("Param %d:\n",i);
1077 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1079 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1080 switch (funcdesc->funckind) {
1081 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1082 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1083 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1084 case FUNC_STATIC: MESSAGE("static");break;
1085 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1086 default: MESSAGE("unknown");break;
1088 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1089 switch (funcdesc->invkind) {
1090 case INVOKE_FUNC: MESSAGE("func");break;
1091 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1092 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1093 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1095 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1096 switch (funcdesc->callconv) {
1097 case CC_CDECL: MESSAGE("cdecl");break;
1098 case CC_PASCAL: MESSAGE("pascal");break;
1099 case CC_STDCALL: MESSAGE("stdcall");break;
1100 case CC_SYSCALL: MESSAGE("syscall");break;
1101 default:break;
1103 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1104 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1105 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1107 MESSAGE("\telemdescFunc (return value type):\n");
1108 dump_ELEMDESC(&funcdesc->elemdescFunc);
1111 static const char * typekind_desc[] =
1113 "TKIND_ENUM",
1114 "TKIND_RECORD",
1115 "TKIND_MODULE",
1116 "TKIND_INTERFACE",
1117 "TKIND_DISPATCH",
1118 "TKIND_COCLASS",
1119 "TKIND_ALIAS",
1120 "TKIND_UNION",
1121 "TKIND_MAX"
1124 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1126 int i;
1127 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1128 for (i=0;i<pfd->funcdesc.cParams;i++)
1129 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1132 dump_FUNCDESC(&(pfd->funcdesc));
1134 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1135 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1137 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1139 while (pfd)
1141 dump_TLBFuncDescOne(pfd);
1142 pfd = pfd->next;
1145 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1147 while (pvd)
1149 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1150 pvd = pvd->next;
1154 static void dump_TLBImpLib(const TLBImpLib *import)
1156 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1157 debugstr_w(import->name));
1158 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1159 import->wVersionMinor, import->lcid, import->offset);
1162 static void dump_TLBRefType(const TLBRefType * prt)
1164 while (prt)
1166 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1167 if(prt->index == -1)
1168 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1169 else
1170 TRACE_(typelib)("type no: %d\n", prt->index);
1172 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1173 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1174 TRACE_(typelib)("in lib\n");
1175 dump_TLBImpLib(prt->pImpTLInfo);
1177 prt = prt->next;
1181 static void dump_TLBImplType(const TLBImplType * impl)
1183 while (impl) {
1184 TRACE_(typelib)(
1185 "implementing/inheriting interface hRef = %lx implflags %x\n",
1186 impl->hRef, impl->implflags);
1187 impl = impl->next;
1191 void dump_Variant(const VARIANT * pvar)
1193 SYSTEMTIME st;
1195 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1197 if (pvar)
1199 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1200 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1202 TRACE(",%p", V_BYREF(pvar));
1204 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1206 TRACE(",%p", V_ARRAY(pvar));
1208 else switch (V_TYPE(pvar))
1210 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1211 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1212 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1213 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1214 case VT_INT:
1215 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1216 case VT_UINT:
1217 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1218 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1219 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1220 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1221 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1222 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1223 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1224 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1225 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1226 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1227 V_CY(pvar).s.Lo); break;
1228 case VT_DATE:
1229 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1230 TRACE(",<invalid>");
1231 else
1232 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1233 st.wHour, st.wMinute, st.wSecond);
1234 break;
1235 case VT_ERROR:
1236 case VT_VOID:
1237 case VT_USERDEFINED:
1238 case VT_EMPTY:
1239 case VT_NULL: break;
1240 default: TRACE(",?"); break;
1243 TRACE("}\n");
1246 static void dump_DispParms(const DISPPARAMS * pdp)
1248 int index = 0;
1250 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1252 while (index < pdp->cArgs)
1254 dump_Variant( &pdp->rgvarg[index] );
1255 ++index;
1259 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1261 TRACE("%p ref=%lu\n", pty, pty->ref);
1262 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1263 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1264 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1265 TRACE("fct:%u var:%u impl:%u\n",
1266 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1267 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1268 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1269 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1270 if (TRACE_ON(ole))
1271 dump_TLBFuncDesc(pty->funclist);
1272 dump_TLBVarDesc(pty->varlist);
1273 dump_TLBImplType(pty->impltypelist);
1276 static void dump_VARDESC(const VARDESC *v)
1278 MESSAGE("memid %ld\n",v->memid);
1279 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1280 MESSAGE("oInst %ld\n",v->u.oInst);
1281 dump_ELEMDESC(&(v->elemdescVar));
1282 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1283 MESSAGE("varkind %d\n",v->varkind);
1286 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1288 /* VT_LPWSTR is largest type that */
1289 /* may appear in type description*/
1290 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1291 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1292 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1293 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1294 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1295 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1296 {{0},30},{{0},31}
1299 static void TLB_abort(void)
1301 DebugBreak();
1303 static void * TLB_Alloc(unsigned size)
1305 void * ret;
1306 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1307 /* FIXME */
1308 ERR("cannot allocate memory\n");
1310 return ret;
1313 static void TLB_Free(void * ptr)
1315 HeapFree(GetProcessHeap(), 0, ptr);
1318 /* returns the size required for a deep copy of a typedesc into a
1319 * flat buffer */
1320 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1322 SIZE_T size = 0;
1324 if (alloc_initial_space)
1325 size += sizeof(TYPEDESC);
1327 switch (tdesc->vt)
1329 case VT_PTR:
1330 case VT_SAFEARRAY:
1331 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1332 break;
1333 case VT_CARRAY:
1334 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1335 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1336 break;
1338 return size;
1341 /* deep copy a typedesc into a flat buffer */
1342 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1344 if (!dest)
1346 dest = buffer;
1347 buffer = (char *)buffer + sizeof(TYPEDESC);
1350 *dest = *src;
1352 switch (src->vt)
1354 case VT_PTR:
1355 case VT_SAFEARRAY:
1356 dest->u.lptdesc = buffer;
1357 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1358 break;
1359 case VT_CARRAY:
1360 dest->u.lpadesc = buffer;
1361 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1362 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1363 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1364 break;
1366 return buffer;
1369 /**********************************************************************
1371 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1373 /* read function */
1374 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1376 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1377 pcx->pos, count, pcx->oStart, pcx->length, where);
1379 if (where != DO_NOT_SEEK)
1381 where += pcx->oStart;
1382 if (where > pcx->length)
1384 /* FIXME */
1385 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1386 TLB_abort();
1388 pcx->pos = where;
1390 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1391 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1392 pcx->pos += count;
1393 return count;
1396 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1397 long where )
1399 DWORD ret;
1401 ret = MSFT_Read(buffer, count, pcx, where);
1402 FromLEDWords(buffer, ret);
1404 return ret;
1407 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1408 long where )
1410 DWORD ret;
1412 ret = MSFT_Read(buffer, count, pcx, where);
1413 FromLEWords(buffer, ret);
1415 return ret;
1418 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1420 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1421 memset(pGuid,0, sizeof(GUID));
1422 return;
1424 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1425 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1426 pGuid->Data2 = FromLEWord(pGuid->Data2);
1427 pGuid->Data3 = FromLEWord(pGuid->Data3);
1428 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1431 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1433 MSFT_NameIntro niName;
1435 if (offset < 0)
1437 ERR_(typelib)("bad offset %d\n", offset);
1438 return -1;
1441 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1442 pcx->pTblDir->pNametab.offset+offset);
1444 return niName.hreftype;
1447 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1449 char * name;
1450 MSFT_NameIntro niName;
1451 int lengthInChars;
1452 WCHAR* pwstring = NULL;
1453 BSTR bstrName = NULL;
1455 if (offset < 0)
1457 ERR_(typelib)("bad offset %d\n", offset);
1458 return NULL;
1460 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1461 pcx->pTblDir->pNametab.offset+offset);
1462 niName.namelen &= 0xFF; /* FIXME: correct ? */
1463 name=TLB_Alloc((niName.namelen & 0xff) +1);
1464 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1465 name[niName.namelen & 0xff]='\0';
1467 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1468 name, -1, NULL, 0);
1470 /* no invalid characters in string */
1471 if (lengthInChars)
1473 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1475 /* don't check for invalid character since this has been done previously */
1476 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1478 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1479 lengthInChars = SysStringLen(bstrName);
1480 HeapFree(GetProcessHeap(), 0, pwstring);
1483 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1484 return bstrName;
1487 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1489 char * string;
1490 INT16 length;
1491 int lengthInChars;
1492 BSTR bstr = NULL;
1494 if(offset<0) return NULL;
1495 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1496 if(length <= 0) return 0;
1497 string=TLB_Alloc(length +1);
1498 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1499 string[length]='\0';
1501 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1502 string, -1, NULL, 0);
1504 /* no invalid characters in string */
1505 if (lengthInChars)
1507 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1509 /* don't check for invalid character since this has been done previously */
1510 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1512 bstr = SysAllocStringLen(pwstring, lengthInChars);
1513 lengthInChars = SysStringLen(bstr);
1514 HeapFree(GetProcessHeap(), 0, pwstring);
1517 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1518 return bstr;
1521 * read a value and fill a VARIANT structure
1523 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1525 int size;
1527 TRACE_(typelib)("\n");
1529 if(offset <0) { /* data are packed in here */
1530 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1531 V_I4(pVar) = offset & 0x3ffffff;
1532 return;
1534 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1535 pcx->pTblDir->pCustData.offset + offset );
1536 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1537 switch (V_VT(pVar)){
1538 case VT_EMPTY: /* FIXME: is this right? */
1539 case VT_NULL: /* FIXME: is this right? */
1540 case VT_I2 : /* this should not happen */
1541 case VT_I4 :
1542 case VT_R4 :
1543 case VT_ERROR :
1544 case VT_BOOL :
1545 case VT_I1 :
1546 case VT_UI1 :
1547 case VT_UI2 :
1548 case VT_UI4 :
1549 case VT_INT :
1550 case VT_UINT :
1551 case VT_VOID : /* FIXME: is this right? */
1552 case VT_HRESULT :
1553 size=4; break;
1554 case VT_R8 :
1555 case VT_CY :
1556 case VT_DATE :
1557 case VT_I8 :
1558 case VT_UI8 :
1559 case VT_DECIMAL : /* FIXME: is this right? */
1560 case VT_FILETIME :
1561 size=8;break;
1562 /* pointer types with known behaviour */
1563 case VT_BSTR :{
1564 char * ptr;
1565 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1566 if(size < 0) {
1567 FIXME("BSTR length = %d?\n", size);
1568 } else {
1569 ptr=TLB_Alloc(size);/* allocate temp buffer */
1570 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1571 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1572 /* FIXME: do we need a AtoW conversion here? */
1573 V_UNION(pVar, bstrVal[size])=L'\0';
1574 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1575 TLB_Free(ptr);
1578 size=-4; break;
1579 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1580 case VT_DISPATCH :
1581 case VT_VARIANT :
1582 case VT_UNKNOWN :
1583 case VT_PTR :
1584 case VT_SAFEARRAY :
1585 case VT_CARRAY :
1586 case VT_USERDEFINED :
1587 case VT_LPSTR :
1588 case VT_LPWSTR :
1589 case VT_BLOB :
1590 case VT_STREAM :
1591 case VT_STORAGE :
1592 case VT_STREAMED_OBJECT :
1593 case VT_STORED_OBJECT :
1594 case VT_BLOB_OBJECT :
1595 case VT_CF :
1596 case VT_CLSID :
1597 default:
1598 size=0;
1599 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1600 V_VT(pVar));
1603 if(size>0) /* (big|small) endian correct? */
1604 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1605 return;
1608 * create a linked list with custom data
1610 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1612 MSFT_CDGuid entry;
1613 TLBCustData* pNew;
1614 int count=0;
1616 TRACE_(typelib)("\n");
1618 while(offset >=0){
1619 count++;
1620 pNew=TLB_Alloc(sizeof(TLBCustData));
1621 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1622 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1623 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1624 /* add new custom data at head of the list */
1625 pNew->next=*ppCustData;
1626 *ppCustData=pNew;
1627 offset = entry.next;
1629 return count;
1632 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1633 ITypeInfoImpl *pTI)
1635 if(type <0)
1636 pTd->vt=type & VT_TYPEMASK;
1637 else
1638 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1640 if(pTd->vt == VT_USERDEFINED)
1641 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1643 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1646 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1648 /* resolve referenced type if any */
1649 while (lpTypeDesc)
1651 switch (lpTypeDesc->vt)
1653 case VT_PTR:
1654 lpTypeDesc = lpTypeDesc->u.lptdesc;
1655 break;
1657 case VT_CARRAY:
1658 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1659 break;
1661 case VT_USERDEFINED:
1662 MSFT_DoRefType(pcx, pTI,
1663 lpTypeDesc->u.hreftype);
1665 lpTypeDesc = NULL;
1666 break;
1668 default:
1669 lpTypeDesc = NULL;
1674 static void
1675 MSFT_DoFuncs(TLBContext* pcx,
1676 ITypeInfoImpl* pTI,
1677 int cFuncs,
1678 int cVars,
1679 int offset,
1680 TLBFuncDesc** pptfd)
1683 * member information is stored in a data structure at offset
1684 * indicated by the memoffset field of the typeinfo structure
1685 * There are several distinctive parts.
1686 * The first part starts with a field that holds the total length
1687 * of this (first) part excluding this field. Then follow the records,
1688 * for each member there is one record.
1690 * The first entry is always the length of the record (including this
1691 * length word).
1692 * The rest of the record depends on the type of the member. If there is
1693 * a field indicating the member type (function, variable, interface, etc)
1694 * I have not found it yet. At this time we depend on the information
1695 * in the type info and the usual order how things are stored.
1697 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1698 * for each member;
1700 * Third is an equal sized array with file offsets to the name entry
1701 * of each member.
1703 * The fourth and last (?) part is an array with offsets to the records
1704 * in the first part of this file segment.
1707 int infolen, nameoffset, reclength, nrattributes, i;
1708 int recoffset = offset + sizeof(INT);
1710 char recbuf[512];
1711 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1712 TLBFuncDesc *ptfd_prev = NULL;
1714 TRACE_(typelib)("\n");
1716 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1718 for ( i = 0; i < cFuncs ; i++ )
1720 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1722 /* name, eventually add to a hash table */
1723 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1724 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1726 /* nameoffset is sometimes -1 on the second half of a propget/propput
1727 * pair of functions */
1728 if ((nameoffset == -1) && (i > 0))
1729 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1730 else
1731 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1733 /* read the function information record */
1734 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1736 reclength &= 0x1ff;
1738 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1740 /* do the attributes */
1741 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1742 / sizeof(int);
1744 if ( nrattributes > 0 )
1746 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1748 if ( nrattributes > 1 )
1750 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1751 pFuncRec->OptAttr[1]) ;
1753 if ( nrattributes > 2 )
1755 if ( pFuncRec->FKCCIC & 0x2000 )
1757 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1759 else
1761 (*pptfd)->Entry = MSFT_ReadString(pcx,
1762 pFuncRec->OptAttr[2]);
1764 if( nrattributes > 5 )
1766 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1768 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1770 MSFT_CustData(pcx,
1771 pFuncRec->OptAttr[6],
1772 &(*pptfd)->pCustData);
1779 /* fill the FuncDesc Structure */
1780 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1781 offset + infolen + ( i + 1) * sizeof(INT));
1783 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1784 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1785 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1786 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1787 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1788 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1789 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1791 MSFT_GetTdesc(pcx,
1792 pFuncRec->DataType,
1793 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1794 pTI);
1795 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1797 /* do the parameters/arguments */
1798 if(pFuncRec->nrargs)
1800 int j = 0;
1801 MSFT_ParameterInfo paraminfo;
1803 (*pptfd)->funcdesc.lprgelemdescParam =
1804 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1806 (*pptfd)->pParamDesc =
1807 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1809 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1810 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1812 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1814 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1816 MSFT_GetTdesc(pcx,
1817 paraminfo.DataType,
1818 &elemdesc->tdesc,
1819 pTI);
1821 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1823 /* name */
1824 if (paraminfo.oName == -1)
1825 /* this occurs for [propput] or [propget] methods, so
1826 * we should just set the name of the parameter to the
1827 * name of the method. */
1828 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1829 else
1830 (*pptfd)->pParamDesc[j].Name =
1831 MSFT_ReadName( pcx, paraminfo.oName );
1832 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1834 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1836 /* default value */
1837 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1838 (pFuncRec->FKCCIC & 0x1000) )
1840 INT* pInt = (INT *)((char *)pFuncRec +
1841 reclength -
1842 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1844 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1846 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1847 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1849 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1850 pInt[j], pcx);
1852 else
1853 elemdesc->u.paramdesc.pparamdescex = NULL;
1854 /* custom info */
1855 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1857 MSFT_CustData(pcx,
1858 pFuncRec->OptAttr[7+j],
1859 &(*pptfd)->pParamDesc[j].pCustData);
1862 /* SEEK value = jump to offset,
1863 * from there jump to the end of record,
1864 * go back by (j-1) arguments
1866 MSFT_ReadLEDWords( &paraminfo ,
1867 sizeof(MSFT_ParameterInfo), pcx,
1868 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1869 * sizeof(MSFT_ParameterInfo)));
1873 /* scode is not used: archaic win16 stuff FIXME: right? */
1874 (*pptfd)->funcdesc.cScodes = 0 ;
1875 (*pptfd)->funcdesc.lprgscode = NULL ;
1877 ptfd_prev = *pptfd;
1878 pptfd = & ((*pptfd)->next);
1879 recoffset += reclength;
1883 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1884 int cVars, int offset, TLBVarDesc ** pptvd)
1886 int infolen, nameoffset, reclength;
1887 char recbuf[256];
1888 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1889 int i;
1890 int recoffset;
1892 TRACE_(typelib)("\n");
1894 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1895 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1896 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1897 recoffset += offset+sizeof(INT);
1898 for(i=0;i<cVars;i++){
1899 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1900 /* name, eventually add to a hash table */
1901 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1902 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1903 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1904 /* read the variable information record */
1905 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1906 reclength &=0xff;
1907 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1908 /* Optional data */
1909 if(reclength >(6*sizeof(INT)) )
1910 (*pptvd)->HelpContext=pVarRec->HelpContext;
1911 if(reclength >(7*sizeof(INT)) )
1912 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1913 if(reclength >(8*sizeof(INT)) )
1914 if(reclength >(9*sizeof(INT)) )
1915 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1916 /* fill the VarDesc Structure */
1917 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1918 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1919 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1920 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1921 MSFT_GetTdesc(pcx, pVarRec->DataType,
1922 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1923 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1924 if(pVarRec->VarKind == VAR_CONST ){
1925 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1926 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1927 pVarRec->OffsValue, pcx);
1928 } else
1929 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1930 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1931 pptvd=&((*pptvd)->next);
1932 recoffset += reclength;
1935 /* fill in data for a hreftype (offset). When the referenced type is contained
1936 * in the typelib, it's just an (file) offset in the type info base dir.
1937 * If comes from import, it's an offset+1 in the ImpInfo table
1938 * */
1939 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1940 int offset)
1942 int j;
1943 TLBRefType **ppRefType = &pTI->reflist;
1945 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1947 while(*ppRefType) {
1948 if((*ppRefType)->reference == offset)
1949 return;
1950 ppRefType = &(*ppRefType)->next;
1953 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1954 sizeof(**ppRefType));
1956 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1957 /* external typelib */
1958 MSFT_ImpInfo impinfo;
1959 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1961 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1963 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1964 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1965 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1966 if(pImpLib->offset==impinfo.oImpFile) break;
1967 pImpLib=pImpLib->next;
1969 if(pImpLib){
1970 (*ppRefType)->reference=offset;
1971 (*ppRefType)->pImpTLInfo = pImpLib;
1972 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1973 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1974 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1975 (*ppRefType)->index = TLB_REF_USE_GUID;
1976 } else
1977 (*ppRefType)->index = impinfo.oGuid;
1978 }else{
1979 ERR("Cannot find a reference\n");
1980 (*ppRefType)->reference=-1;
1981 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1983 }else{
1984 /* in this typelib */
1985 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1986 (*ppRefType)->reference=offset;
1987 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1991 /* process Implemented Interfaces of a com class */
1992 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1993 int offset)
1995 int i;
1996 MSFT_RefRecord refrec;
1997 TLBImplType **ppImpl = &pTI->impltypelist;
1999 TRACE_(typelib)("\n");
2001 for(i=0;i<count;i++){
2002 if(offset<0) break; /* paranoia */
2003 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2004 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2005 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2006 (*ppImpl)->hRef = refrec.reftype;
2007 (*ppImpl)->implflags=refrec.flags;
2008 (*ppImpl)->ctCustData=
2009 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2010 offset=refrec.onext;
2011 ppImpl=&((*ppImpl)->next);
2015 * process a typeinfo record
2017 static ITypeInfoImpl * MSFT_DoTypeInfo(
2018 TLBContext *pcx,
2019 int count,
2020 INT dispatch_href,
2021 ITypeLibImpl * pLibInfo)
2023 MSFT_TypeInfoBase tiBase;
2024 ITypeInfoImpl *ptiRet;
2026 TRACE_(typelib)("count=%u\n", count);
2028 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2029 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2030 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2032 /* this is where we are coming from */
2033 ptiRet->pTypeLib = pLibInfo;
2034 ptiRet->index=count;
2035 /* fill in the typeattr fields */
2036 WARN("Assign constructor/destructor memid\n");
2038 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2039 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2040 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2041 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2042 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2043 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2044 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2045 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2046 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2047 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2048 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2049 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2050 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2051 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2052 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2053 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2054 MSFT_GetTdesc(pcx, tiBase.datatype1,
2055 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2057 /* FIXME: */
2058 /* IDLDESC idldescType; *//* never saw this one != zero */
2060 /* name, eventually add to a hash table */
2061 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2062 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2063 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2064 /* help info */
2065 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2066 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2067 ptiRet->dwHelpContext=tiBase.helpcontext;
2069 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2070 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2072 /* note: InfoType's Help file and HelpStringDll come from the containing
2073 * library. Further HelpString and Docstring appear to be the same thing :(
2075 /* functions */
2076 if(ptiRet->TypeAttr.cFuncs >0 )
2077 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2078 ptiRet->TypeAttr.cVars,
2079 tiBase.memoffset, & ptiRet->funclist);
2080 /* variables */
2081 if(ptiRet->TypeAttr.cVars >0 )
2082 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2083 ptiRet->TypeAttr.cVars,
2084 tiBase.memoffset, & ptiRet->varlist);
2085 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2086 switch(ptiRet->TypeAttr.typekind)
2088 case TKIND_COCLASS:
2089 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2090 tiBase.datatype1);
2091 break;
2092 case TKIND_DISPATCH:
2093 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2095 if (tiBase.datatype1 != -1)
2097 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2098 ptiRet->impltypelist->hRef = tiBase.datatype1;
2100 else
2102 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2103 ptiRet->impltypelist->hRef = dispatch_href;
2105 break;
2106 default:
2107 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2108 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2109 ptiRet->impltypelist->hRef = tiBase.datatype1;
2110 break;
2113 ptiRet->ctCustData=
2114 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2116 TRACE_(typelib)("%s guid: %s kind:%s\n",
2117 debugstr_w(ptiRet->Name),
2118 debugstr_guid(&ptiRet->TypeAttr.guid),
2119 typekind_desc[ptiRet->TypeAttr.typekind]);
2121 return ptiRet;
2124 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2125 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2126 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2127 * tradeoff here.
2129 static ITypeLibImpl *tlb_cache_first;
2130 static CRITICAL_SECTION cache_section;
2131 static CRITICAL_SECTION_DEBUG cache_section_debug =
2133 0, 0, &cache_section,
2134 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2135 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2137 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2140 /****************************************************************************
2141 * TLB_ReadTypeLib
2143 * find the type of the typelib file and map the typelib resource into
2144 * the memory
2146 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2147 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2148 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2150 ITypeLibImpl *entry;
2151 int ret = TYPE_E_CANTLOADLIBRARY;
2152 INT index = 1;
2153 HINSTANCE hinstDLL;
2155 *ppTypeLib = NULL;
2157 lstrcpynW(pszPath, pszFileName, cchPath);
2159 /* first try loading as a dll and access the typelib as a resource */
2160 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2161 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2162 if (!hinstDLL)
2164 /* it may have been specified with resource index appended to the
2165 * path, so remove it and try again */
2166 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2167 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2169 index = atoiW(pIndexStr);
2170 pszPath[pIndexStr - pszFileName - 1] = '\0';
2172 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2173 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2177 /* get the path to the specified typelib file */
2178 if (!hinstDLL)
2180 /* otherwise, try loading as a regular file */
2181 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2182 return TYPE_E_CANTLOADLIBRARY;
2185 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2187 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2188 EnterCriticalSection(&cache_section);
2189 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2191 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2193 TRACE("cache hit\n");
2194 *ppTypeLib = (ITypeLib2*)entry;
2195 ITypeLib_AddRef(*ppTypeLib);
2196 LeaveCriticalSection(&cache_section);
2197 return S_OK;
2200 LeaveCriticalSection(&cache_section);
2202 /* now actually load and parse the typelib */
2203 if (hinstDLL)
2205 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2206 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2207 if (hrsrc)
2209 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2210 if (hGlobal)
2212 LPVOID pBase = LockResource(hGlobal);
2213 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2215 if (pBase)
2217 /* try to load as incore resource */
2218 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2219 if (dwSignature == MSFT_SIGNATURE)
2220 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2221 else if (dwSignature == SLTG_SIGNATURE)
2222 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2223 else
2224 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2226 FreeResource( hGlobal );
2229 FreeLibrary(hinstDLL);
2231 else
2233 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2234 if (INVALID_HANDLE_VALUE != hFile)
2236 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2237 if (hMapping)
2239 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2240 if(pBase)
2242 /* retrieve file size */
2243 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2244 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2246 if (dwSignature == MSFT_SIGNATURE)
2247 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2248 else if (dwSignature == SLTG_SIGNATURE)
2249 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2251 UnmapViewOfFile(pBase);
2253 CloseHandle(hMapping);
2255 CloseHandle(hFile);
2259 if(*ppTypeLib) {
2260 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2262 TRACE("adding to cache\n");
2263 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2264 lstrcpyW(impl->path, pszPath);
2265 /* We should really canonicalise the path here. */
2266 impl->index = index;
2268 /* FIXME: check if it has added already in the meantime */
2269 EnterCriticalSection(&cache_section);
2270 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2271 impl->prev = NULL;
2272 tlb_cache_first = impl;
2273 LeaveCriticalSection(&cache_section);
2274 ret = S_OK;
2275 } else
2276 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2278 return ret;
2281 /*================== ITypeLib(2) Methods ===================================*/
2283 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2285 ITypeLibImpl* pTypeLibImpl;
2287 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2288 if (!pTypeLibImpl) return NULL;
2290 pTypeLibImpl->lpVtbl = &tlbvt;
2291 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2292 pTypeLibImpl->ref = 1;
2294 return pTypeLibImpl;
2297 /****************************************************************************
2298 * ITypeLib2_Constructor_MSFT
2300 * loading an MSFT typelib from an in-memory image
2302 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2304 TLBContext cx;
2305 long lPSegDir;
2306 MSFT_Header tlbHeader;
2307 MSFT_SegDir tlbSegDir;
2308 ITypeLibImpl * pTypeLibImpl;
2310 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2312 pTypeLibImpl = TypeLibImpl_Constructor();
2313 if (!pTypeLibImpl) return NULL;
2315 /* get pointer to beginning of typelib data */
2316 cx.pos = 0;
2317 cx.oStart=0;
2318 cx.mapping = pLib;
2319 cx.pLibInfo = pTypeLibImpl;
2320 cx.length = dwTLBLength;
2322 /* read header */
2323 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2324 TRACE_(typelib)("header:\n");
2325 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2326 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2327 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2328 return NULL;
2330 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2332 /* there is a small amount of information here until the next important
2333 * part:
2334 * the segment directory . Try to calculate the amount of data */
2335 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2337 /* now read the segment directory */
2338 TRACE("read segment directory (at %ld)\n",lPSegDir);
2339 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2340 cx.pTblDir = &tlbSegDir;
2342 /* just check two entries */
2343 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2345 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2346 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2347 return NULL;
2350 /* now fill our internal data */
2351 /* TLIBATTR fields */
2352 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2354 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2355 /* Windows seems to have zero here, is this correct? */
2356 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2357 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2358 else
2359 pTypeLibImpl->LibAttr.lcid = 0;
2361 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2362 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2363 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2364 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2366 /* name, eventually add to a hash table */
2367 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2369 /* help info */
2370 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2371 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2373 if( tlbHeader.varflags & HELPDLLFLAG)
2375 int offset;
2376 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2377 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2380 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2382 /* custom data */
2383 if(tlbHeader.CustomDataOffset >= 0)
2385 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2388 /* fill in typedescriptions */
2389 if(tlbSegDir.pTypdescTab.length > 0)
2391 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2392 INT16 td[4];
2393 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2394 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2395 for(i=0; i<cTD; )
2397 /* FIXME: add several sanity checks here */
2398 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2399 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2401 /* FIXME: check safearray */
2402 if(td[3] < 0)
2403 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2404 else
2405 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2407 else if(td[0] == VT_CARRAY)
2409 /* array descr table here */
2410 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2412 else if(td[0] == VT_USERDEFINED)
2414 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2416 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2419 /* second time around to fill the array subscript info */
2420 for(i=0;i<cTD;i++)
2422 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2423 if(tlbSegDir.pArrayDescriptions.offset>0)
2425 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2426 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2428 if(td[1]<0)
2429 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2430 else
2431 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2433 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2435 for(j = 0; j<td[2]; j++)
2437 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2438 sizeof(INT), &cx, DO_NOT_SEEK);
2439 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2440 sizeof(INT), &cx, DO_NOT_SEEK);
2443 else
2445 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2446 ERR("didn't find array description data\n");
2451 /* imported type libs */
2452 if(tlbSegDir.pImpFiles.offset>0)
2454 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2455 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2456 UINT16 size;
2458 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2460 char *name;
2461 DWORD len;
2463 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2464 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2465 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2467 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2468 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2469 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2470 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2472 size >>= 2;
2473 name = TLB_Alloc(size+1);
2474 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2475 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2476 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2477 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2478 TLB_Free(name);
2480 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2481 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2483 ppImpLib = &(*ppImpLib)->next;
2487 /* type info's */
2488 if(tlbHeader.nrtypeinfos >= 0 )
2490 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2491 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2492 int i;
2494 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2496 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2498 ppTI = &((*ppTI)->next);
2499 (pTypeLibImpl->TypeInfoCount)++;
2503 TRACE("(%p)\n", pTypeLibImpl);
2504 return (ITypeLib2*) pTypeLibImpl;
2508 static BSTR TLB_MultiByteToBSTR(char *ptr)
2510 DWORD len;
2511 WCHAR *nameW;
2512 BSTR ret;
2514 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2515 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2516 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2517 ret = SysAllocString(nameW);
2518 HeapFree(GetProcessHeap(), 0, nameW);
2519 return ret;
2522 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2524 char b[3];
2525 int i;
2526 short s;
2528 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2529 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2530 return FALSE;
2533 guid->Data4[0] = s >> 8;
2534 guid->Data4[1] = s & 0xff;
2536 b[2] = '\0';
2537 for(i = 0; i < 6; i++) {
2538 memcpy(b, str + 24 + 2 * i, 2);
2539 guid->Data4[i + 2] = strtol(b, NULL, 16);
2541 return TRUE;
2544 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2546 WORD bytelen;
2547 DWORD len;
2548 WCHAR *nameW;
2550 *pBstr = NULL;
2551 bytelen = *(WORD*)ptr;
2552 if(bytelen == 0xffff) return 2;
2553 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2554 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2555 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2556 *pBstr = SysAllocStringLen(nameW, len);
2557 HeapFree(GetProcessHeap(), 0, nameW);
2558 return bytelen + 2;
2561 static WORD SLTG_ReadStringA(char *ptr, char **str)
2563 WORD bytelen;
2565 *str = NULL;
2566 bytelen = *(WORD*)ptr;
2567 if(bytelen == 0xffff) return 2;
2568 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2569 memcpy(*str, ptr + 2, bytelen);
2570 (*str)[bytelen] = '\0';
2571 return bytelen + 2;
2574 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2576 char *ptr = pLibBlk;
2577 WORD w;
2579 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2580 FIXME("libblk magic = %04x\n", w);
2581 return 0;
2584 ptr += 6;
2585 if((w = *(WORD*)ptr) != 0xffff) {
2586 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2587 ptr += w;
2589 ptr += 2;
2591 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2593 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2595 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2596 ptr += 4;
2598 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2599 ptr += 2;
2601 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2602 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2603 else
2604 pTypeLibImpl->LibAttr.lcid = 0;
2605 ptr += 2;
2607 ptr += 4; /* skip res12 */
2609 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2610 ptr += 2;
2612 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2613 ptr += 2;
2615 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2616 ptr += 2;
2618 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2619 ptr += sizeof(GUID);
2621 return ptr - (char*)pLibBlk;
2624 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2626 BOOL done = FALSE;
2627 TYPEDESC *pTD = &pElem->tdesc;
2629 /* Handle [in/out] first */
2630 if((*pType & 0xc000) == 0xc000)
2631 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2632 else if(*pType & 0x8000)
2633 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2634 else if(*pType & 0x4000)
2635 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2636 else
2637 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2639 if(*pType & 0x2000)
2640 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2642 if(*pType & 0x80)
2643 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2645 while(!done) {
2646 if((*pType & 0xe00) == 0xe00) {
2647 pTD->vt = VT_PTR;
2648 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2649 sizeof(TYPEDESC));
2650 pTD = pTD->u.lptdesc;
2652 switch(*pType & 0x7f) {
2653 case VT_PTR:
2654 pTD->vt = VT_PTR;
2655 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2656 sizeof(TYPEDESC));
2657 pTD = pTD->u.lptdesc;
2658 break;
2660 case VT_USERDEFINED:
2661 pTD->vt = VT_USERDEFINED;
2662 pTD->u.hreftype = *(++pType) / 4;
2663 done = TRUE;
2664 break;
2666 case VT_CARRAY:
2668 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2669 array */
2671 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2673 pTD->vt = VT_CARRAY;
2674 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2675 sizeof(ARRAYDESC) +
2676 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2677 pTD->u.lpadesc->cDims = pSA->cDims;
2678 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2679 pSA->cDims * sizeof(SAFEARRAYBOUND));
2681 pTD = &pTD->u.lpadesc->tdescElem;
2682 break;
2685 case VT_SAFEARRAY:
2687 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2688 useful? */
2690 pType++;
2691 pTD->vt = VT_SAFEARRAY;
2692 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2693 sizeof(TYPEDESC));
2694 pTD = pTD->u.lptdesc;
2695 break;
2697 default:
2698 pTD->vt = *pType & 0x7f;
2699 done = TRUE;
2700 break;
2702 pType++;
2704 return pType;
2708 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2709 char *pNameTable)
2711 int ref;
2712 char *name;
2713 TLBRefType **ppRefType;
2715 if(pRef->magic != SLTG_REF_MAGIC) {
2716 FIXME("Ref magic = %x\n", pRef->magic);
2717 return;
2719 name = ( (char*)(&pRef->names) + pRef->number);
2721 ppRefType = &pTI->reflist;
2722 for(ref = 0; ref < pRef->number >> 3; ref++) {
2723 char *refname;
2724 unsigned int lib_offs, type_num;
2726 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2727 sizeof(**ppRefType));
2729 name += SLTG_ReadStringA(name, &refname);
2730 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2731 FIXME("Can't sscanf ref\n");
2732 if(lib_offs != 0xffff) {
2733 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2735 while(*import) {
2736 if((*import)->offset == lib_offs)
2737 break;
2738 import = &(*import)->next;
2740 if(!*import) {
2741 char fname[MAX_PATH+1];
2742 int len;
2744 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2745 sizeof(**import));
2746 (*import)->offset = lib_offs;
2747 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2748 &(*import)->guid);
2749 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2750 &(*import)->wVersionMajor,
2751 &(*import)->wVersionMinor,
2752 &(*import)->lcid, fname) != 4) {
2753 FIXME("can't sscanf ref %s\n",
2754 pNameTable + lib_offs + 40);
2756 len = strlen(fname);
2757 if(fname[len-1] != '#')
2758 FIXME("fname = %s\n", fname);
2759 fname[len-1] = '\0';
2760 (*import)->name = TLB_MultiByteToBSTR(fname);
2762 (*ppRefType)->pImpTLInfo = *import;
2763 } else { /* internal ref */
2764 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2766 (*ppRefType)->reference = ref;
2767 (*ppRefType)->index = type_num;
2769 HeapFree(GetProcessHeap(), 0, refname);
2770 ppRefType = &(*ppRefType)->next;
2772 if((BYTE)*name != SLTG_REF_MAGIC)
2773 FIXME("End of ref block magic = %x\n", *name);
2774 dump_TLBRefType(pTI->reflist);
2777 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2778 BOOL OneOnly)
2780 SLTG_ImplInfo *info;
2781 TLBImplType **ppImplType = &pTI->impltypelist;
2782 /* I don't really get this structure, usually it's 0x16 bytes
2783 long, but iuser.tlb contains some that are 0x18 bytes long.
2784 That's ok because we can use the next ptr to jump to the next
2785 one. But how do we know the length of the last one? The WORD
2786 at offs 0x8 might be the clue. For now I'm just assuming that
2787 the last one is the regular 0x16 bytes. */
2789 info = (SLTG_ImplInfo*)pBlk;
2790 while(1) {
2791 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2792 sizeof(**ppImplType));
2793 (*ppImplType)->hRef = info->ref;
2794 (*ppImplType)->implflags = info->impltypeflags;
2795 pTI->TypeAttr.cImplTypes++;
2796 ppImplType = &(*ppImplType)->next;
2798 if(info->next == 0xffff)
2799 break;
2800 if(OneOnly)
2801 FIXME("Interface inheriting more than one interface\n");
2802 info = (SLTG_ImplInfo*)(pBlk + info->next);
2804 info++; /* see comment at top of function */
2805 return (char*)info;
2808 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2809 char *pNameTable)
2811 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2812 SLTG_MemberHeader *pMemHeader;
2813 char *pFirstItem, *pNextItem;
2815 if(pTIHeader->href_table != 0xffffffff) {
2816 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2817 pNameTable);
2821 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2823 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2825 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2826 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2829 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2833 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2834 char *pNameTable)
2836 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2837 SLTG_MemberHeader *pMemHeader;
2838 SLTG_Function *pFunc;
2839 char *pFirstItem, *pNextItem;
2840 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2841 int num = 0;
2843 if(pTIHeader->href_table != 0xffffffff) {
2844 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2845 pNameTable);
2848 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2850 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2852 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2853 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2856 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2857 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2859 int param;
2860 WORD *pType, *pArg;
2862 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2863 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2864 FIXME("func magic = %02x\n", pFunc->magic);
2865 return NULL;
2867 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2868 sizeof(**ppFuncDesc));
2869 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2871 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2872 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2873 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2874 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2875 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2876 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2878 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2879 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2881 if(pFunc->retnextopt & 0x80)
2882 pType = &pFunc->rettype;
2883 else
2884 pType = (WORD*)(pFirstItem + pFunc->rettype);
2887 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2889 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2890 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2891 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2892 (*ppFuncDesc)->pParamDesc =
2893 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2894 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2896 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2898 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2899 char *paramName = pNameTable + *pArg;
2900 BOOL HaveOffs;
2901 /* If arg type follows then paramName points to the 2nd
2902 letter of the name, else the next WORD is an offset to
2903 the arg type and paramName points to the first letter.
2904 So let's take one char off paramName and see if we're
2905 pointing at an alpha-numeric char. However if *pArg is
2906 0xffff or 0xfffe then the param has no name, the former
2907 meaning that the next WORD is the type, the latter
2908 meaning the the next WORD is an offset to the type. */
2910 HaveOffs = FALSE;
2911 if(*pArg == 0xffff)
2912 paramName = NULL;
2913 else if(*pArg == 0xfffe) {
2914 paramName = NULL;
2915 HaveOffs = TRUE;
2917 else if(paramName[-1] && !isalnum(paramName[-1]))
2918 HaveOffs = TRUE;
2920 pArg++;
2922 if(HaveOffs) { /* the next word is an offset to type */
2923 pType = (WORD*)(pFirstItem + *pArg);
2924 SLTG_DoType(pType, pFirstItem,
2925 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2926 pArg++;
2927 } else {
2928 if(paramName)
2929 paramName--;
2930 pArg = SLTG_DoType(pArg, pFirstItem,
2931 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2934 /* Are we an optional param ? */
2935 if((*ppFuncDesc)->funcdesc.cParams - param <=
2936 (*ppFuncDesc)->funcdesc.cParamsOpt)
2937 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2939 if(paramName) {
2940 (*ppFuncDesc)->pParamDesc[param].Name =
2941 TLB_MultiByteToBSTR(paramName);
2945 ppFuncDesc = &((*ppFuncDesc)->next);
2946 if(pFunc->next == 0xffff) break;
2948 pTI->TypeAttr.cFuncs = num;
2949 if (TRACE_ON(typelib))
2950 dump_TLBFuncDesc(pTI->funclist);
2951 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2954 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2955 char *pNameTable)
2957 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2958 SLTG_MemberHeader *pMemHeader;
2959 SLTG_RecordItem *pItem;
2960 char *pFirstItem;
2961 TLBVarDesc **ppVarDesc = &pTI->varlist;
2962 int num = 0;
2963 WORD *pType;
2964 char buf[300];
2966 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2968 pFirstItem = (char*)(pMemHeader + 1);
2969 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2970 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2971 if(pItem->magic != SLTG_RECORD_MAGIC) {
2972 FIXME("record magic = %02x\n", pItem->magic);
2973 return NULL;
2975 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2976 sizeof(**ppVarDesc));
2977 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2978 (*ppVarDesc)->vardesc.memid = pItem->memid;
2979 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2980 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2982 if(pItem->typepos == 0x02)
2983 pType = &pItem->type;
2984 else if(pItem->typepos == 0x00)
2985 pType = (WORD*)(pFirstItem + pItem->type);
2986 else {
2987 FIXME("typepos = %02x\n", pItem->typepos);
2988 break;
2991 SLTG_DoType(pType, pFirstItem,
2992 &(*ppVarDesc)->vardesc.elemdescVar);
2994 /* FIXME("helpcontext, helpstring\n"); */
2996 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2998 ppVarDesc = &((*ppVarDesc)->next);
2999 if(pItem->next == 0xffff) break;
3001 pTI->TypeAttr.cVars = num;
3002 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3005 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3006 char *pNameTable)
3008 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3009 SLTG_MemberHeader *pMemHeader;
3010 SLTG_AliasItem *pItem;
3011 int i, mustbelast;
3013 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3014 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3016 mustbelast = 0;
3017 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3018 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3019 if (pItem->vt == 0xffff) {
3020 if (i<(pMemHeader->cbExtra/4-1))
3021 FIXME("Endmarker too early in process alias data!\n");
3022 break;
3024 if (mustbelast) {
3025 FIXME("Chain extends over last entry?\n");
3026 break;
3028 if (pItem->vt == VT_USERDEFINED) {
3029 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3030 /* guessing here ... */
3031 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3032 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3033 mustbelast = 1;
3034 } else {
3035 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3036 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3038 pItem++;
3040 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3043 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3044 char *pNameTable)
3046 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3047 SLTG_MemberHeader *pMemHeader;
3048 SLTG_AliasItem *pItem;
3050 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3051 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3052 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3053 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3054 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3057 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3058 char *pNameTable)
3060 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3061 SLTG_MemberHeader *pMemHeader;
3062 SLTG_EnumItem *pItem;
3063 char *pFirstItem;
3064 TLBVarDesc **ppVarDesc = &pTI->varlist;
3065 int num = 0;
3067 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3069 pFirstItem = (char*)(pMemHeader + 1);
3070 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3071 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3072 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3073 FIXME("enumitem magic = %04x\n", pItem->magic);
3074 return NULL;
3076 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3077 sizeof(**ppVarDesc));
3078 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3079 (*ppVarDesc)->vardesc.memid = pItem->memid;
3080 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3081 sizeof(VARIANT));
3082 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3083 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3084 *(INT*)(pItem->value + pFirstItem);
3085 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3086 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3087 /* FIXME("helpcontext, helpstring\n"); */
3089 ppVarDesc = &((*ppVarDesc)->next);
3090 if(pItem->next == 0xffff) break;
3092 pTI->TypeAttr.cVars = num;
3093 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3096 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3097 managable copy of it into this */
3098 typedef struct {
3099 WORD small_no;
3100 char *index_name;
3101 char *other_name;
3102 WORD res1a;
3103 WORD name_offs;
3104 WORD more_bytes;
3105 char *extra;
3106 WORD res20;
3107 DWORD helpcontext;
3108 WORD res26;
3109 GUID uuid;
3110 } SLTG_InternalOtherTypeInfo;
3112 /****************************************************************************
3113 * ITypeLib2_Constructor_SLTG
3115 * loading a SLTG typelib from an in-memory image
3117 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3119 ITypeLibImpl *pTypeLibImpl;
3120 SLTG_Header *pHeader;
3121 SLTG_BlkEntry *pBlkEntry;
3122 SLTG_Magic *pMagic;
3123 SLTG_Index *pIndex;
3124 SLTG_Pad9 *pPad9;
3125 LPVOID pBlk, pFirstBlk;
3126 SLTG_LibBlk *pLibBlk;
3127 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3128 char *pAfterOTIBlks = NULL;
3129 char *pNameTable, *ptr;
3130 int i;
3131 DWORD len, order;
3132 ITypeInfoImpl **ppTypeInfoImpl;
3134 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3137 pTypeLibImpl = TypeLibImpl_Constructor();
3138 if (!pTypeLibImpl) return NULL;
3140 pHeader = pLib;
3142 TRACE_(typelib)("header:\n");
3143 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3144 pHeader->nrOfFileBlks );
3145 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3146 FIXME("Header type magic 0x%08lx not supported.\n",
3147 pHeader->SLTG_magic);
3148 return NULL;
3151 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3152 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3154 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3155 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3157 /* Next we have a magic block */
3158 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3160 /* Let's see if we're still in sync */
3161 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3162 sizeof(SLTG_COMPOBJ_MAGIC))) {
3163 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3164 return NULL;
3166 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3167 sizeof(SLTG_DIR_MAGIC))) {
3168 FIXME("dir magic = %s\n", pMagic->dir_magic);
3169 return NULL;
3172 pIndex = (SLTG_Index*)(pMagic+1);
3174 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3176 pFirstBlk = (LPVOID)(pPad9 + 1);
3178 /* We'll set up a ptr to the main library block, which is the last one. */
3180 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3181 pBlkEntry[order].next != 0;
3182 order = pBlkEntry[order].next - 1, i++) {
3183 pBlk = (char*)pBlk + pBlkEntry[order].len;
3185 pLibBlk = pBlk;
3187 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3189 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3190 interspersed */
3192 len += 0x40;
3194 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3196 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3197 sizeof(*pOtherTypeInfoBlks) *
3198 pTypeLibImpl->TypeInfoCount);
3201 ptr = (char*)pLibBlk + len;
3203 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3204 WORD w, extra;
3205 len = 0;
3207 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3209 w = *(WORD*)(ptr + 2);
3210 if(w != 0xffff) {
3211 len += w;
3212 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3213 w+1);
3214 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3215 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3217 w = *(WORD*)(ptr + 4 + len);
3218 if(w != 0xffff) {
3219 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3220 len += w;
3221 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3222 w+1);
3223 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3224 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3226 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3227 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3228 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3229 if(extra) {
3230 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3231 extra);
3232 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3233 len += extra;
3235 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3236 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3237 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3238 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3239 len += sizeof(SLTG_OtherTypeInfo);
3240 ptr += len;
3243 pAfterOTIBlks = ptr;
3245 /* Skip this WORD and get the next DWORD */
3246 len = *(DWORD*)(pAfterOTIBlks + 2);
3248 /* Now add this to pLibBLk look at what we're pointing at and
3249 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3250 dust and we should be pointing at the beginning of the name
3251 table */
3253 pNameTable = (char*)pLibBlk + len;
3255 switch(*(WORD*)pNameTable) {
3256 case 0xffff:
3257 break;
3258 case 0x0200:
3259 pNameTable += 0x20;
3260 break;
3261 default:
3262 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3263 break;
3266 pNameTable += 0x216;
3268 pNameTable += 2;
3270 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3272 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3275 /* Hopefully we now have enough ptrs set up to actually read in
3276 some TypeInfos. It's not clear which order to do them in, so
3277 I'll just follow the links along the BlkEntry chain and read
3278 them in in the order in which they're in the file */
3280 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3282 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3283 pBlkEntry[order].next != 0;
3284 order = pBlkEntry[order].next - 1, i++) {
3286 SLTG_TypeInfoHeader *pTIHeader;
3287 SLTG_TypeInfoTail *pTITail;
3289 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3290 pOtherTypeInfoBlks[i].index_name)) {
3291 FIXME("Index strings don't match\n");
3292 return NULL;
3295 pTIHeader = pBlk;
3296 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3297 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3298 return NULL;
3300 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3301 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3302 (*ppTypeInfoImpl)->index = i;
3303 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3304 pOtherTypeInfoBlks[i].name_offs +
3305 pNameTable);
3306 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3307 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3308 sizeof(GUID));
3309 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3310 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3311 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3312 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3313 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3315 if((pTIHeader->typeflags1 & 7) != 2)
3316 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3317 if(pTIHeader->typeflags3 != 2)
3318 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3320 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3321 debugstr_w((*ppTypeInfoImpl)->Name),
3322 typekind_desc[pTIHeader->typekind],
3323 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3324 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3326 switch(pTIHeader->typekind) {
3327 case TKIND_ENUM:
3328 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3329 break;
3331 case TKIND_RECORD:
3332 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3333 break;
3335 case TKIND_INTERFACE:
3336 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3337 break;
3339 case TKIND_COCLASS:
3340 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3341 break;
3343 case TKIND_ALIAS:
3344 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3345 if (pTITail->tdescalias_vt)
3346 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3347 break;
3349 case TKIND_DISPATCH:
3350 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3351 break;
3353 default:
3354 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3355 pTITail = NULL;
3356 break;
3360 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3361 but we've already set those */
3362 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3363 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3364 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3366 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3367 X(06);
3368 X(08);
3369 X(0a);
3370 X(0c);
3371 X(0e);
3372 X(10);
3373 X(12);
3374 X(16);
3375 X(18);
3376 X(1a);
3377 X(1c);
3378 X(1e);
3379 X(24);
3380 X(26);
3381 X(2a);
3382 X(2c);
3383 X(2e);
3384 X(30);
3385 X(32);
3386 X(34);
3388 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3389 pBlk = (char*)pBlk + pBlkEntry[order].len;
3392 if(i != pTypeLibImpl->TypeInfoCount) {
3393 FIXME("Somehow processed %d TypeInfos\n", i);
3394 return NULL;
3397 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3398 return (ITypeLib2*)pTypeLibImpl;
3401 /* ITypeLib::QueryInterface
3403 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3404 ITypeLib2 * iface,
3405 REFIID riid,
3406 VOID **ppvObject)
3408 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3410 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3412 *ppvObject=NULL;
3413 if(IsEqualIID(riid, &IID_IUnknown) ||
3414 IsEqualIID(riid,&IID_ITypeLib)||
3415 IsEqualIID(riid,&IID_ITypeLib2))
3417 *ppvObject = This;
3420 if(*ppvObject)
3422 ITypeLib2_AddRef(iface);
3423 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3424 return S_OK;
3426 TRACE("-- Interface: E_NOINTERFACE\n");
3427 return E_NOINTERFACE;
3430 /* ITypeLib::AddRef
3432 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3434 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3435 ULONG ref = InterlockedIncrement(&This->ref);
3437 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3439 return ref;
3442 /* ITypeLib::Release
3444 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3446 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3447 ULONG ref = InterlockedDecrement(&This->ref);
3449 TRACE("(%p)->(%lu)\n",This, ref);
3451 if (!ref)
3453 /* remove cache entry */
3454 if(This->path)
3456 TRACE("removing from cache list\n");
3457 EnterCriticalSection(&cache_section);
3458 if (This->next) This->next->prev = This->prev;
3459 if (This->prev) This->prev->next = This->next;
3460 else tlb_cache_first = This->next;
3461 LeaveCriticalSection(&cache_section);
3462 HeapFree(GetProcessHeap(), 0, This->path);
3464 /* FIXME destroy child objects */
3465 TRACE(" destroying ITypeLib(%p)\n",This);
3467 if (This->Name)
3469 SysFreeString(This->Name);
3470 This->Name = NULL;
3473 if (This->DocString)
3475 SysFreeString(This->DocString);
3476 This->DocString = NULL;
3479 if (This->HelpFile)
3481 SysFreeString(This->HelpFile);
3482 This->HelpFile = NULL;
3485 if (This->HelpStringDll)
3487 SysFreeString(This->HelpStringDll);
3488 This->HelpStringDll = NULL;
3491 if (This->pTypeInfo) /* can be NULL */
3492 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3493 HeapFree(GetProcessHeap(),0,This);
3494 return 0;
3497 return ref;
3500 /* ITypeLib::GetTypeInfoCount
3502 * Returns the number of type descriptions in the type library
3504 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3506 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3507 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3508 return This->TypeInfoCount;
3511 /* ITypeLib::GetTypeInfo
3513 * retrieves the specified type description in the library.
3515 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3516 ITypeLib2 *iface,
3517 UINT index,
3518 ITypeInfo **ppTInfo)
3520 int i;
3522 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3523 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3525 TRACE("(%p)->(index=%d)\n", This, index);
3527 if (!ppTInfo) return E_INVALIDARG;
3529 /* search element n in list */
3530 for(i=0; i < index; i++)
3532 pTypeInfo = pTypeInfo->next;
3533 if (!pTypeInfo)
3535 TRACE("-- element not found\n");
3536 return TYPE_E_ELEMENTNOTFOUND;
3540 *ppTInfo = (ITypeInfo *) pTypeInfo;
3542 ITypeInfo_AddRef(*ppTInfo);
3543 TRACE("-- found (%p)\n",*ppTInfo);
3544 return S_OK;
3548 /* ITypeLibs::GetTypeInfoType
3550 * Retrieves the type of a type description.
3552 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3553 ITypeLib2 *iface,
3554 UINT index,
3555 TYPEKIND *pTKind)
3557 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3558 int i;
3559 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3561 TRACE("(%p) index %d\n", This, index);
3563 if(!pTKind) return E_INVALIDARG;
3565 /* search element n in list */
3566 for(i=0; i < index; i++)
3568 if(!pTInfo)
3570 TRACE("-- element not found\n");
3571 return TYPE_E_ELEMENTNOTFOUND;
3573 pTInfo = pTInfo->next;
3576 *pTKind = pTInfo->TypeAttr.typekind;
3577 TRACE("-- found Type (%d)\n", *pTKind);
3578 return S_OK;
3581 /* ITypeLib::GetTypeInfoOfGuid
3583 * Retrieves the type description that corresponds to the specified GUID.
3586 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3587 ITypeLib2 *iface,
3588 REFGUID guid,
3589 ITypeInfo **ppTInfo)
3591 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3592 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3594 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3596 if (!pTypeInfo)
3598 WARN("-- element not found\n");
3599 return TYPE_E_ELEMENTNOTFOUND;
3602 /* search linked list for guid */
3603 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3605 pTypeInfo = pTypeInfo->next;
3607 if (!pTypeInfo)
3609 /* end of list reached */
3610 WARN("-- element not found\n");
3611 return TYPE_E_ELEMENTNOTFOUND;
3615 TRACE("-- found (%p, %s)\n",
3616 pTypeInfo,
3617 debugstr_w(pTypeInfo->Name));
3619 *ppTInfo = (ITypeInfo*)pTypeInfo;
3620 ITypeInfo_AddRef(*ppTInfo);
3621 return S_OK;
3624 /* ITypeLib::GetLibAttr
3626 * Retrieves the structure that contains the library's attributes.
3629 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3630 ITypeLib2 *iface,
3631 LPTLIBATTR *ppTLibAttr)
3633 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3634 TRACE("(%p)\n",This);
3635 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3636 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3637 return S_OK;
3640 /* ITypeLib::GetTypeComp
3642 * Enables a client compiler to bind to a library's types, variables,
3643 * constants, and global functions.
3646 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3647 ITypeLib2 *iface,
3648 ITypeComp **ppTComp)
3650 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3652 TRACE("(%p)->(%p)\n",This,ppTComp);
3653 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3654 ITypeComp_AddRef(*ppTComp);
3656 return S_OK;
3659 /* ITypeLib::GetDocumentation
3661 * Retrieves the library's documentation string, the complete Help file name
3662 * and path, and the context identifier for the library Help topic in the Help
3663 * file.
3665 * On a successful return all non-null BSTR pointers will have been set,
3666 * possibly to NULL.
3668 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3669 ITypeLib2 *iface,
3670 INT index,
3671 BSTR *pBstrName,
3672 BSTR *pBstrDocString,
3673 DWORD *pdwHelpContext,
3674 BSTR *pBstrHelpFile)
3676 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3678 HRESULT result = E_INVALIDARG;
3680 ITypeInfo *pTInfo;
3683 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3684 This, index,
3685 pBstrName, pBstrDocString,
3686 pdwHelpContext, pBstrHelpFile);
3688 if(index<0)
3690 /* documentation for the typelib */
3691 if(pBstrName)
3693 if (This->Name)
3695 if(!(*pBstrName = SysAllocString(This->Name)))
3696 goto memerr1;
3698 else
3699 *pBstrName = NULL;
3701 if(pBstrDocString)
3703 if (This->DocString)
3705 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3706 goto memerr2;
3708 else if (This->Name)
3710 if(!(*pBstrDocString = SysAllocString(This->Name)))
3711 goto memerr2;
3713 else
3714 *pBstrDocString = NULL;
3716 if(pdwHelpContext)
3718 *pdwHelpContext = This->dwHelpContext;
3720 if(pBstrHelpFile)
3722 if (This->HelpFile)
3724 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3725 goto memerr3;
3727 else
3728 *pBstrHelpFile = NULL;
3731 result = S_OK;
3733 else
3735 /* for a typeinfo */
3736 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3738 if(SUCCEEDED(result))
3740 result = ITypeInfo_GetDocumentation(pTInfo,
3741 MEMBERID_NIL,
3742 pBstrName,
3743 pBstrDocString,
3744 pdwHelpContext, pBstrHelpFile);
3746 ITypeInfo_Release(pTInfo);
3749 return result;
3750 memerr3:
3751 if (pBstrDocString) SysFreeString (*pBstrDocString);
3752 memerr2:
3753 if (pBstrName) SysFreeString (*pBstrName);
3754 memerr1:
3755 return STG_E_INSUFFICIENTMEMORY;
3758 /* ITypeLib::IsName
3760 * Indicates whether a passed-in string contains the name of a type or member
3761 * described in the library.
3764 static HRESULT WINAPI ITypeLib2_fnIsName(
3765 ITypeLib2 *iface,
3766 LPOLESTR szNameBuf,
3767 ULONG lHashVal,
3768 BOOL *pfName)
3770 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3771 ITypeInfoImpl *pTInfo;
3772 TLBFuncDesc *pFInfo;
3773 TLBVarDesc *pVInfo;
3774 int i;
3775 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3777 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3778 pfName);
3780 *pfName=TRUE;
3781 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3782 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3783 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3784 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3785 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3786 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3787 goto ITypeLib2_fnIsName_exit;
3789 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3790 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3793 *pfName=FALSE;
3795 ITypeLib2_fnIsName_exit:
3796 TRACE("(%p)slow! search for %s: %s found!\n", This,
3797 debugstr_w(szNameBuf), *pfName?"NOT":"");
3799 return S_OK;
3802 /* ITypeLib::FindName
3804 * Finds occurrences of a type description in a type library. This may be used
3805 * to quickly verify that a name exists in a type library.
3808 static HRESULT WINAPI ITypeLib2_fnFindName(
3809 ITypeLib2 *iface,
3810 LPOLESTR szNameBuf,
3811 ULONG lHashVal,
3812 ITypeInfo **ppTInfo,
3813 MEMBERID *rgMemId,
3814 UINT16 *pcFound)
3816 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3817 ITypeInfoImpl *pTInfo;
3818 TLBFuncDesc *pFInfo;
3819 TLBVarDesc *pVInfo;
3820 int i,j = 0;
3821 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3823 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3824 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3825 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3826 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3827 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3828 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3829 goto ITypeLib2_fnFindName_exit;
3832 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3833 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3834 continue;
3835 ITypeLib2_fnFindName_exit:
3836 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3837 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3838 j++;
3840 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3841 This, *pcFound, debugstr_w(szNameBuf), j);
3843 *pcFound=j;
3845 return S_OK;
3848 /* ITypeLib::ReleaseTLibAttr
3850 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3853 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3854 ITypeLib2 *iface,
3855 TLIBATTR *pTLibAttr)
3857 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3858 TRACE("freeing (%p)\n",This);
3859 HeapFree(GetProcessHeap(),0,pTLibAttr);
3863 /* ITypeLib2::GetCustData
3865 * gets the custom data
3867 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3868 ITypeLib2 * iface,
3869 REFGUID guid,
3870 VARIANT *pVarVal)
3872 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3873 TLBCustData *pCData;
3875 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3877 if( IsEqualIID(guid, &pCData->guid)) break;
3880 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3882 if(pCData)
3884 VariantInit( pVarVal);
3885 VariantCopy( pVarVal, &pCData->data);
3886 return S_OK;
3888 return E_INVALIDARG; /* FIXME: correct? */
3891 /* ITypeLib2::GetLibStatistics
3893 * Returns statistics about a type library that are required for efficient
3894 * sizing of hash tables.
3897 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3898 ITypeLib2 * iface,
3899 ULONG *pcUniqueNames,
3900 ULONG *pcchUniqueNames)
3902 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3904 FIXME("(%p): stub!\n", This);
3906 if(pcUniqueNames) *pcUniqueNames=1;
3907 if(pcchUniqueNames) *pcchUniqueNames=1;
3908 return S_OK;
3911 /* ITypeLib2::GetDocumentation2
3913 * Retrieves the library's documentation string, the complete Help file name
3914 * and path, the localization context to use, and the context ID for the
3915 * library Help topic in the Help file.
3918 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3919 ITypeLib2 * iface,
3920 INT index,
3921 LCID lcid,
3922 BSTR *pbstrHelpString,
3923 DWORD *pdwHelpStringContext,
3924 BSTR *pbstrHelpStringDll)
3926 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3927 HRESULT result;
3928 ITypeInfo *pTInfo;
3930 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3932 /* the help string should be obtained from the helpstringdll,
3933 * using the _DLLGetDocumentation function, based on the supplied
3934 * lcid. Nice to do sometime...
3936 if(index<0)
3938 /* documentation for the typelib */
3939 if(pbstrHelpString)
3940 *pbstrHelpString=SysAllocString(This->DocString);
3941 if(pdwHelpStringContext)
3942 *pdwHelpStringContext=This->dwHelpContext;
3943 if(pbstrHelpStringDll)
3944 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3946 result = S_OK;
3948 else
3950 /* for a typeinfo */
3951 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3953 if(SUCCEEDED(result))
3955 ITypeInfo2 * pTInfo2;
3956 result = ITypeInfo_QueryInterface(pTInfo,
3957 &IID_ITypeInfo2,
3958 (LPVOID*) &pTInfo2);
3960 if(SUCCEEDED(result))
3962 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3963 MEMBERID_NIL,
3964 lcid,
3965 pbstrHelpString,
3966 pdwHelpStringContext,
3967 pbstrHelpStringDll);
3969 ITypeInfo2_Release(pTInfo2);
3972 ITypeInfo_Release(pTInfo);
3975 return result;
3978 /* ITypeLib2::GetAllCustData
3980 * Gets all custom data items for the library.
3983 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3984 ITypeLib2 * iface,
3985 CUSTDATA *pCustData)
3987 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3988 TLBCustData *pCData;
3989 int i;
3990 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3991 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3992 if(pCustData->prgCustData ){
3993 pCustData->cCustData=This->ctCustData;
3994 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3995 pCustData->prgCustData[i].guid=pCData->guid;
3996 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3998 }else{
3999 ERR(" OUT OF MEMORY!\n");
4000 return E_OUTOFMEMORY;
4002 return S_OK;
4005 static const ITypeLib2Vtbl tlbvt = {
4006 ITypeLib2_fnQueryInterface,
4007 ITypeLib2_fnAddRef,
4008 ITypeLib2_fnRelease,
4009 ITypeLib2_fnGetTypeInfoCount,
4010 ITypeLib2_fnGetTypeInfo,
4011 ITypeLib2_fnGetTypeInfoType,
4012 ITypeLib2_fnGetTypeInfoOfGuid,
4013 ITypeLib2_fnGetLibAttr,
4014 ITypeLib2_fnGetTypeComp,
4015 ITypeLib2_fnGetDocumentation,
4016 ITypeLib2_fnIsName,
4017 ITypeLib2_fnFindName,
4018 ITypeLib2_fnReleaseTLibAttr,
4020 ITypeLib2_fnGetCustData,
4021 ITypeLib2_fnGetLibStatistics,
4022 ITypeLib2_fnGetDocumentation2,
4023 ITypeLib2_fnGetAllCustData
4027 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4029 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4031 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4034 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4036 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4038 return ITypeLib2_AddRef((ITypeLib2 *)This);
4041 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4043 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4045 return ITypeLib2_Release((ITypeLib2 *)This);
4048 static HRESULT WINAPI ITypeLibComp_fnBind(
4049 ITypeComp * iface,
4050 OLECHAR * szName,
4051 ULONG lHash,
4052 WORD wFlags,
4053 ITypeInfo ** ppTInfo,
4054 DESCKIND * pDescKind,
4055 BINDPTR * pBindPtr)
4057 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4058 ITypeInfoImpl *pTypeInfo;
4060 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4062 *pDescKind = DESCKIND_NONE;
4063 pBindPtr->lptcomp = NULL;
4064 *ppTInfo = NULL;
4066 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4068 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4070 /* FIXME: check wFlags here? */
4071 /* FIXME: we should use a hash table to look this info up using lHash
4072 * instead of an O(n) search */
4073 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4074 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4076 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4078 *pDescKind = DESCKIND_TYPECOMP;
4079 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4080 ITypeComp_AddRef(pBindPtr->lptcomp);
4081 TRACE("module or enum: %s\n", debugstr_w(szName));
4082 return S_OK;
4086 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4087 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4089 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4090 HRESULT hr;
4092 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4093 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4095 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4096 return S_OK;
4100 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4101 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4103 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4104 HRESULT hr;
4105 ITypeInfo *subtypeinfo;
4106 BINDPTR subbindptr;
4107 DESCKIND subdesckind;
4109 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4110 &subtypeinfo, &subdesckind, &subbindptr);
4111 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4113 TYPEDESC tdesc_appobject =
4116 (TYPEDESC *)pTypeInfo->hreftype
4118 VT_USERDEFINED
4120 const VARDESC vardesc_appobject =
4122 -2, /* memid */
4123 NULL, /* lpstrSchema */
4125 0 /* oInst */
4128 /* ELEMDESC */
4130 /* TYPEDESC */
4132 &tdesc_appobject
4134 VT_PTR
4137 0, /* wVarFlags */
4138 VAR_STATIC /* varkind */
4141 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4143 /* cleanup things filled in by Bind call so we can put our
4144 * application object data in there instead */
4145 switch (subdesckind)
4147 case DESCKIND_FUNCDESC:
4148 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4149 break;
4150 case DESCKIND_VARDESC:
4151 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4152 break;
4153 default:
4154 break;
4156 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4158 if (pTypeInfo->hreftype == -1)
4159 FIXME("no hreftype for interface %p\n", pTypeInfo);
4161 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4162 if (FAILED(hr))
4163 return hr;
4165 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4166 *ppTInfo = (ITypeInfo *)pTypeInfo;
4167 ITypeInfo_AddRef(*ppTInfo);
4168 return S_OK;
4173 TRACE("name not found %s\n", debugstr_w(szName));
4174 return S_OK;
4177 static HRESULT WINAPI ITypeLibComp_fnBindType(
4178 ITypeComp * iface,
4179 OLECHAR * szName,
4180 ULONG lHash,
4181 ITypeInfo ** ppTInfo,
4182 ITypeComp ** ppTComp)
4184 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4185 return E_NOTIMPL;
4188 static const ITypeCompVtbl tlbtcvt =
4191 ITypeLibComp_fnQueryInterface,
4192 ITypeLibComp_fnAddRef,
4193 ITypeLibComp_fnRelease,
4195 ITypeLibComp_fnBind,
4196 ITypeLibComp_fnBindType
4199 /*================== ITypeInfo(2) Methods ===================================*/
4200 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4202 ITypeInfoImpl * pTypeInfoImpl;
4204 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4205 if (pTypeInfoImpl)
4207 pTypeInfoImpl->lpVtbl = &tinfvt;
4208 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4209 pTypeInfoImpl->ref=1;
4210 pTypeInfoImpl->hreftype = -1;
4212 TRACE("(%p)\n", pTypeInfoImpl);
4213 return (ITypeInfo2*) pTypeInfoImpl;
4216 /* ITypeInfo::QueryInterface
4218 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4219 ITypeInfo2 *iface,
4220 REFIID riid,
4221 VOID **ppvObject)
4223 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4225 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4227 *ppvObject=NULL;
4228 if(IsEqualIID(riid, &IID_IUnknown) ||
4229 IsEqualIID(riid,&IID_ITypeInfo)||
4230 IsEqualIID(riid,&IID_ITypeInfo2))
4231 *ppvObject = This;
4233 if(*ppvObject){
4234 ITypeInfo_AddRef(iface);
4235 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4236 return S_OK;
4238 TRACE("-- Interface: E_NOINTERFACE\n");
4239 return E_NOINTERFACE;
4242 /* ITypeInfo::AddRef
4244 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4246 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4247 ULONG ref = InterlockedIncrement(&This->ref);
4249 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4251 TRACE("(%p)->ref is %lu\n",This, ref);
4252 return ref;
4255 /* ITypeInfo::Release
4257 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4259 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4260 ULONG ref = InterlockedDecrement(&This->ref);
4262 TRACE("(%p)->(%lu)\n",This, ref);
4264 if (ref) {
4265 /* We don't release ITypeLib when ref=0 because
4266 it means that function is called by ITypeLib2_Release */
4267 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4268 } else {
4269 static int once = 0;
4270 if (!once)
4272 once = 1;
4273 FIXME("destroy child objects\n");
4276 TRACE("destroying ITypeInfo(%p)\n",This);
4277 if (This->Name)
4279 SysFreeString(This->Name);
4280 This->Name = 0;
4283 if (This->DocString)
4285 SysFreeString(This->DocString);
4286 This->DocString = 0;
4289 if (This->DllName)
4291 SysFreeString(This->DllName);
4292 This->DllName = 0;
4295 if (This->next)
4297 ITypeInfo_Release((ITypeInfo*)This->next);
4300 HeapFree(GetProcessHeap(),0,This);
4301 return 0;
4303 return ref;
4306 /* ITypeInfo::GetTypeAttr
4308 * Retrieves a TYPEATTR structure that contains the attributes of the type
4309 * description.
4312 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4313 LPTYPEATTR *ppTypeAttr)
4315 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4316 SIZE_T size;
4318 TRACE("(%p)\n",This);
4320 size = sizeof(**ppTypeAttr);
4321 if (This->TypeAttr.typekind == TKIND_ALIAS)
4322 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4324 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4325 if (!*ppTypeAttr)
4326 return E_OUTOFMEMORY;
4328 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4330 if (This->TypeAttr.typekind == TKIND_ALIAS)
4331 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4332 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4334 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4335 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4336 funcs */
4337 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4338 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4340 return S_OK;
4343 /* ITypeInfo::GetTypeComp
4345 * Retrieves the ITypeComp interface for the type description, which enables a
4346 * client compiler to bind to the type description's members.
4349 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4350 ITypeComp * *ppTComp)
4352 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4354 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4356 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4357 ITypeComp_AddRef(*ppTComp);
4358 return S_OK;
4361 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4363 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4364 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4365 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4366 return size;
4369 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4371 memcpy(dest, src, sizeof(ELEMDESC));
4372 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4373 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4375 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4376 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4377 *buffer += sizeof(PARAMDESCEX);
4378 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4379 VariantInit(&pparamdescex_dest->varDefaultValue);
4380 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4381 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4383 else
4384 dest->u.paramdesc.pparamdescex = NULL;
4385 return S_OK;
4388 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4390 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4391 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4394 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4396 FUNCDESC *dest;
4397 char *buffer;
4398 SIZE_T size = sizeof(*src);
4399 SHORT i;
4400 HRESULT hr;
4402 size += sizeof(*src->lprgscode) * src->cScodes;
4403 size += TLB_SizeElemDesc(&src->elemdescFunc);
4404 for (i = 0; i < src->cParams; i++)
4406 size += sizeof(ELEMDESC);
4407 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4410 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4411 if (!dest) return E_OUTOFMEMORY;
4413 memcpy(dest, src, sizeof(FUNCDESC));
4414 buffer = (char *)(dest + 1);
4416 dest->lprgscode = (SCODE *)buffer;
4417 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4418 buffer += sizeof(*src->lprgscode) * src->cScodes;
4420 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4421 if (FAILED(hr))
4423 SysFreeString((BSTR)dest);
4424 return hr;
4427 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4428 buffer += sizeof(ELEMDESC) * src->cParams;
4429 for (i = 0; i < src->cParams; i++)
4431 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4432 if (FAILED(hr))
4433 break;
4435 if (FAILED(hr))
4437 /* undo the above actions */
4438 for (i = i - 1; i >= 0; i--)
4439 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4440 TLB_FreeElemDesc(&dest->elemdescFunc);
4441 SysFreeString((BSTR)dest);
4442 return hr;
4445 /* special treatment for dispinterfaces: this makes functions appear
4446 * to return their [retval] value when it is really returning an
4447 * HRESULT */
4448 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4450 if (dest->cParams &&
4451 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4453 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4454 if (elemdesc->tdesc.vt != VT_PTR)
4456 ERR("elemdesc should have started with VT_PTR instead of:\n");
4457 if (ERR_ON(ole))
4458 dump_ELEMDESC(elemdesc);
4459 return E_UNEXPECTED;
4462 /* copy last parameter to the return value. we are using a flat
4463 * buffer so there is no danger of leaking memory in
4464 * elemdescFunc */
4465 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4467 /* remove the last parameter */
4468 dest->cParams--;
4470 else
4471 /* otherwise this function is made to appear to have no return
4472 * value */
4473 dest->elemdescFunc.tdesc.vt = VT_VOID;
4477 *dest_ptr = dest;
4478 return S_OK;
4481 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4483 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4484 const TLBFuncDesc *pFDesc;
4485 int i;
4487 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4490 if (pFDesc)
4492 *ppFuncDesc = &pFDesc->funcdesc;
4493 return S_OK;
4496 return E_INVALIDARG;
4499 /* ITypeInfo::GetFuncDesc
4501 * Retrieves the FUNCDESC structure that contains information about a
4502 * specified function.
4505 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4506 LPFUNCDESC *ppFuncDesc)
4508 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4509 const FUNCDESC *internal_funcdesc;
4510 HRESULT hr;
4512 TRACE("(%p) index %d\n", This, index);
4514 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4515 if (FAILED(hr))
4516 return hr;
4518 return TLB_AllocAndInitFuncDesc(
4519 internal_funcdesc,
4520 ppFuncDesc,
4521 This->TypeAttr.typekind == TKIND_DISPATCH);
4524 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4526 VARDESC *dest;
4527 char *buffer;
4528 SIZE_T size = sizeof(*src);
4529 HRESULT hr;
4531 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4532 if (src->varkind == VAR_CONST)
4533 size += sizeof(VARIANT);
4534 size += TLB_SizeElemDesc(&src->elemdescVar);
4536 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4537 if (!dest) return E_OUTOFMEMORY;
4539 *dest = *src;
4540 buffer = (char *)(dest + 1);
4541 if (src->lpstrSchema)
4543 int len;
4544 dest->lpstrSchema = (LPOLESTR)buffer;
4545 len = strlenW(src->lpstrSchema);
4546 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4547 buffer += (len + 1) * sizeof(WCHAR);
4550 if (src->varkind == VAR_CONST)
4552 HRESULT hr;
4554 dest->u.lpvarValue = (VARIANT *)buffer;
4555 *dest->u.lpvarValue = *src->u.lpvarValue;
4556 buffer += sizeof(VARIANT);
4557 VariantInit(dest->u.lpvarValue);
4558 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4559 if (FAILED(hr))
4561 SysFreeString((BSTR)dest_ptr);
4562 return hr;
4565 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4566 if (FAILED(hr))
4568 if (src->varkind == VAR_CONST)
4569 VariantClear(dest->u.lpvarValue);
4570 SysFreeString((BSTR)dest);
4571 return hr;
4573 *dest_ptr = dest;
4574 return S_OK;
4577 /* ITypeInfo::GetVarDesc
4579 * Retrieves a VARDESC structure that describes the specified variable.
4582 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4583 LPVARDESC *ppVarDesc)
4585 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4586 int i;
4587 const TLBVarDesc *pVDesc;
4589 TRACE("(%p) index %d\n", This, index);
4591 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4594 if (pVDesc)
4595 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4597 return E_INVALIDARG;
4600 /* ITypeInfo_GetNames
4602 * Retrieves the variable with the specified member ID (or the name of the
4603 * property or method and its parameters) that correspond to the specified
4604 * function ID.
4606 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4607 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4609 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4610 const TLBFuncDesc *pFDesc;
4611 const TLBVarDesc *pVDesc;
4612 int i;
4613 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4614 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4615 if(pFDesc)
4617 /* function found, now return function and parameter names */
4618 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4620 if(!i)
4621 *rgBstrNames=SysAllocString(pFDesc->Name);
4622 else
4623 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4625 *pcNames=i;
4627 else
4629 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4630 if(pVDesc)
4632 *rgBstrNames=SysAllocString(pVDesc->Name);
4633 *pcNames=1;
4635 else
4637 if(This->TypeAttr.cImplTypes &&
4638 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4639 /* recursive search */
4640 ITypeInfo *pTInfo;
4641 HRESULT result;
4642 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4643 &pTInfo);
4644 if(SUCCEEDED(result))
4646 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4647 ITypeInfo_Release(pTInfo);
4648 return result;
4650 WARN("Could not search inherited interface!\n");
4652 else
4654 WARN("no names found\n");
4656 *pcNames=0;
4657 return TYPE_E_ELEMENTNOTFOUND;
4660 return S_OK;
4664 /* ITypeInfo::GetRefTypeOfImplType
4666 * If a type description describes a COM class, it retrieves the type
4667 * description of the implemented interface types. For an interface,
4668 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4669 * if any exist.
4672 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4673 ITypeInfo2 *iface,
4674 UINT index,
4675 HREFTYPE *pRefType)
4677 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4678 int i;
4679 HRESULT hr = S_OK;
4680 const TLBImplType *pImpl = This->impltypelist;
4682 TRACE("(%p) index %d\n", This, index);
4683 if (TRACE_ON(ole)) dump_TypeInfo(This);
4685 if(index==(UINT)-1)
4687 /* only valid on dual interfaces;
4688 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4690 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4692 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4693 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4695 *pRefType = -1;
4697 else
4699 hr = TYPE_E_ELEMENTNOTFOUND;
4702 else
4704 /* get element n from linked list */
4705 for(i=0; pImpl && i<index; i++)
4707 pImpl = pImpl->next;
4710 if (pImpl)
4711 *pRefType = pImpl->hRef;
4712 else
4713 hr = TYPE_E_ELEMENTNOTFOUND;
4716 if(TRACE_ON(ole))
4718 if(SUCCEEDED(hr))
4719 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4720 else
4721 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4724 return hr;
4727 /* ITypeInfo::GetImplTypeFlags
4729 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4730 * or base interface in a type description.
4732 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4733 UINT index, INT *pImplTypeFlags)
4735 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4736 int i;
4737 TLBImplType *pImpl;
4739 TRACE("(%p) index %d\n", This, index);
4740 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4741 i++, pImpl=pImpl->next)
4743 if(i==index && pImpl){
4744 *pImplTypeFlags=pImpl->implflags;
4745 return S_OK;
4747 *pImplTypeFlags=0;
4748 return TYPE_E_ELEMENTNOTFOUND;
4751 /* GetIDsOfNames
4752 * Maps between member names and member IDs, and parameter names and
4753 * parameter IDs.
4755 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4756 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4758 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4759 const TLBFuncDesc *pFDesc;
4760 const TLBVarDesc *pVDesc;
4761 HRESULT ret=S_OK;
4762 int i;
4764 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4765 cNames);
4767 /* init out parameters in case of failure */
4768 for (i = 0; i < cNames; i++)
4769 pMemId[i] = MEMBERID_NIL;
4771 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4772 int j;
4773 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4774 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4775 for(i=1; i < cNames; i++){
4776 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4777 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4778 break;
4779 if( j<pFDesc->funcdesc.cParams)
4780 pMemId[i]=j;
4781 else
4782 ret=DISP_E_UNKNOWNNAME;
4784 TRACE("-- 0x%08lx\n", ret);
4785 return ret;
4788 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4789 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4790 if(cNames) *pMemId=pVDesc->vardesc.memid;
4791 return ret;
4794 /* not found, see if it can be found in an inherited interface */
4795 if(This->TypeAttr.cImplTypes) {
4796 /* recursive search */
4797 ITypeInfo *pTInfo;
4798 ret=ITypeInfo_GetRefTypeInfo(iface,
4799 This->impltypelist->hRef, &pTInfo);
4800 if(SUCCEEDED(ret)){
4801 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4802 ITypeInfo_Release(pTInfo);
4803 return ret;
4805 WARN("Could not search inherited interface!\n");
4806 } else
4807 WARN("no names found\n");
4808 return DISP_E_UNKNOWNNAME;
4811 /* ITypeInfo::Invoke
4813 * Invokes a method, or accesses a property of an object, that implements the
4814 * interface described by the type description.
4816 DWORD
4817 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4818 DWORD res;
4820 if (TRACE_ON(ole)) {
4821 int i;
4822 TRACE("Calling %p(",func);
4823 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4824 TRACE(")\n");
4827 switch (callconv) {
4828 case CC_STDCALL:
4830 switch (nrargs) {
4831 case 0:
4832 res = func();
4833 break;
4834 case 1:
4835 res = func(args[0]);
4836 break;
4837 case 2:
4838 res = func(args[0],args[1]);
4839 break;
4840 case 3:
4841 res = func(args[0],args[1],args[2]);
4842 break;
4843 case 4:
4844 res = func(args[0],args[1],args[2],args[3]);
4845 break;
4846 case 5:
4847 res = func(args[0],args[1],args[2],args[3],args[4]);
4848 break;
4849 case 6:
4850 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4851 break;
4852 case 7:
4853 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4854 break;
4855 case 8:
4856 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4857 break;
4858 case 9:
4859 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4860 break;
4861 case 10:
4862 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4863 break;
4864 case 11:
4865 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4866 break;
4867 case 12:
4868 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]);
4869 break;
4870 case 13:
4871 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]);
4872 break;
4873 case 14:
4874 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]);
4875 break;
4876 case 15:
4877 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]);
4878 break;
4879 case 16:
4880 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]);
4881 break;
4882 case 17:
4883 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]);
4884 break;
4885 case 18:
4886 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]);
4887 break;
4888 case 19:
4889 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]);
4890 break;
4891 case 20:
4892 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]);
4893 break;
4894 case 21:
4895 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]);
4896 break;
4897 case 22:
4898 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]);
4899 break;
4900 case 23:
4901 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]);
4902 break;
4903 default:
4904 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4905 res = -1;
4906 break;
4908 break;
4909 default:
4910 FIXME("unsupported calling convention %d\n",callconv);
4911 res = -1;
4912 break;
4914 TRACE("returns %08lx\n",res);
4915 return res;
4918 extern int _argsize(DWORD vt);
4920 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4922 HRESULT hr = S_OK;
4923 ITypeInfo *tinfo2 = NULL;
4924 TYPEATTR *tattr = NULL;
4926 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4927 if (hr)
4929 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4930 "hr = 0x%08lx\n",
4931 tdesc->u.hreftype, hr);
4932 return hr;
4934 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4935 if (hr)
4937 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4938 ITypeInfo_Release(tinfo2);
4939 return hr;
4942 switch (tattr->typekind)
4944 case TKIND_ENUM:
4945 *vt |= VT_I4;
4946 break;
4948 case TKIND_ALIAS:
4949 tdesc = &tattr->tdescAlias;
4950 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4951 break;
4953 case TKIND_INTERFACE:
4954 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4955 *vt |= VT_DISPATCH;
4956 else
4957 *vt |= VT_UNKNOWN;
4958 break;
4960 case TKIND_DISPATCH:
4961 *vt |= VT_DISPATCH;
4962 break;
4964 case TKIND_RECORD:
4965 FIXME("TKIND_RECORD unhandled.\n");
4966 hr = E_NOTIMPL;
4967 break;
4969 case TKIND_UNION:
4970 FIXME("TKIND_RECORD unhandled.\n");
4971 hr = E_NOTIMPL;
4972 break;
4974 default:
4975 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4976 hr = E_NOTIMPL;
4977 break;
4979 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4980 ITypeInfo_Release(tinfo2);
4981 return hr;
4984 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4986 HRESULT hr = S_OK;
4988 /* enforce only one level of pointer indirection */
4989 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
4991 tdesc = tdesc->u.lptdesc;
4993 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4994 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4995 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4996 if ((tdesc->vt == VT_USERDEFINED) ||
4997 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4999 VARTYPE vt_userdefined = 0;
5000 const TYPEDESC *tdesc_userdefined = tdesc;
5001 if (tdesc->vt == VT_PTR)
5003 vt_userdefined = VT_BYREF;
5004 tdesc_userdefined = tdesc->u.lptdesc;
5006 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5007 if ((hr == S_OK) &&
5008 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5009 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5011 *vt |= vt_userdefined;
5012 return S_OK;
5015 *vt = VT_BYREF;
5018 switch (tdesc->vt)
5020 case VT_HRESULT:
5021 *vt |= VT_ERROR;
5022 break;
5023 case VT_USERDEFINED:
5024 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5025 break;
5026 case VT_VOID:
5027 case VT_CARRAY:
5028 case VT_PTR:
5029 case VT_LPSTR:
5030 case VT_LPWSTR:
5031 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5032 hr = DISP_E_BADVARTYPE;
5033 break;
5034 case VT_SAFEARRAY:
5035 *vt |= VT_ARRAY;
5036 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5037 break;
5038 default:
5039 *vt |= tdesc->vt;
5040 break;
5042 return hr;
5045 /***********************************************************************
5046 * DispCallFunc (OLEAUT32.@)
5048 * Invokes a function of the specifed calling convention, passing the
5049 * specified arguments and returns the result.
5051 * PARAMS
5052 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5053 * oVft [I] The offset in the vtable. See notes.
5054 * cc [I] Calling convention of the function to call.
5055 * vtReturn [I] The return type of the function.
5056 * cActuals [I] Number of parameters.
5057 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5058 * prgpvarg [I] The arguments to pass.
5059 * pvargResult [O] The return value of the function. Can be NULL.
5061 * RETURNS
5062 * Success: S_OK.
5063 * Failure: HRESULT code.
5065 * NOTES
5066 * The HRESULT return value of this function is not affected by the return
5067 * value of the user supplied function, which is returned in pvargResult.
5069 * If pvInstance is NULL then a non-object function is to be called and oVft
5070 * is the address of the function to call.
5072 * The cc parameter can be one of the following values:
5073 *|CC_FASTCALL
5074 *|CC_CDECL
5075 *|CC_PASCAL
5076 *|CC_STDCALL
5077 *|CC_FPFASTCALL
5078 *|CC_SYSCALL
5079 *|CC_MPWCDECL
5080 *|CC_MPWPASCAL
5083 HRESULT WINAPI
5084 DispCallFunc(
5085 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5086 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5088 int i, argsize, argspos;
5089 DWORD *args;
5090 HRESULT hres;
5092 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5093 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5094 pvargResult, V_VT(pvargResult));
5096 argsize = 0;
5097 if (pvInstance)
5098 argsize++; /* for This pointer */
5100 for (i=0;i<cActuals;i++)
5102 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5103 dump_Variant(prgpvarg[i]);
5104 argsize += _argsize(prgvt[i]);
5106 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5108 argspos = 0;
5109 if (pvInstance)
5111 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5112 argspos++;
5115 for (i=0;i<cActuals;i++)
5117 VARIANT *arg = prgpvarg[i];
5118 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5119 if (prgvt[i] == VT_VARIANT)
5120 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5121 else
5122 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5123 argspos += _argsize(prgvt[i]);
5126 if (pvInstance)
5128 FARPROC *vtable = *(FARPROC**)pvInstance;
5129 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5131 else
5132 /* if we aren't invoking an object then the function pointer is stored
5133 * in oVft */
5134 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5136 if (pvargResult && (vtReturn != VT_EMPTY))
5138 TRACE("Method returned 0x%08lx\n",hres);
5139 V_VT(pvargResult) = vtReturn;
5140 V_UI4(pvargResult) = hres;
5143 HeapFree(GetProcessHeap(),0,args);
5144 return S_OK;
5147 #define INVBUF_ELEMENT_SIZE \
5148 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5149 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5150 ((VARIANTARG *)(buffer))
5151 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5152 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5153 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5154 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5155 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5156 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5158 static HRESULT WINAPI ITypeInfo_fnInvoke(
5159 ITypeInfo2 *iface,
5160 VOID *pIUnk,
5161 MEMBERID memid,
5162 UINT16 wFlags,
5163 DISPPARAMS *pDispParams,
5164 VARIANT *pVarResult,
5165 EXCEPINFO *pExcepInfo,
5166 UINT *pArgErr)
5168 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5169 int i;
5170 unsigned int var_index;
5171 TYPEKIND type_kind;
5172 HRESULT hres;
5173 const TLBFuncDesc *pFuncInfo;
5175 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5176 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5178 dump_DispParms(pDispParams);
5180 /* we do this instead of using GetFuncDesc since it will return a fake
5181 * FUNCDESC for dispinterfaces and we want the real function description */
5182 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5183 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5184 break;
5186 if (pFuncInfo) {
5187 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5189 if (TRACE_ON(ole))
5191 TRACE("invoking:\n");
5192 dump_TLBFuncDescOne(pFuncInfo);
5195 switch (func_desc->funckind) {
5196 case FUNC_PUREVIRTUAL:
5197 case FUNC_VIRTUAL: {
5198 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5199 VARIANT varresult;
5200 VARIANT retval; /* pointer for storing byref retvals in */
5201 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5202 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5203 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5205 hres = S_OK;
5206 for (i = 0; i < func_desc->cParams; i++)
5208 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5209 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5210 if (FAILED(hres))
5211 goto func_fail;
5214 TRACE("changing args\n");
5215 for (i = 0; i < func_desc->cParams; i++)
5217 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5219 if (wParamFlags & PARAMFLAG_FRETVAL)
5221 /* note: this check is placed so that if the caller passes
5222 * in a VARIANTARG for the retval we just ignore it, like
5223 * native does */
5224 if (i == func_desc->cParams - 1)
5226 VARIANTARG *arg;
5227 arg = prgpvarg[i] = &rgvarg[i];
5228 memset(arg, 0, sizeof(*arg));
5229 V_VT(arg) = rgvt[i];
5230 memset(&retval, 0, sizeof(retval));
5231 V_BYREF(arg) = &retval;
5233 else
5235 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5236 hres = E_UNEXPECTED;
5237 break;
5240 else if (i < pDispParams->cArgs)
5242 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5243 dump_Variant(src_arg);
5245 if (rgvt[i] == VT_VARIANT)
5246 hres = VariantCopy(&rgvarg[i], src_arg);
5247 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5249 if (rgvt[i] == V_VT(src_arg))
5250 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5251 else
5253 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5254 hres = VariantCopy(&missing_arg[i], src_arg);
5255 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5257 V_VT(&rgvarg[i]) = rgvt[i];
5259 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5261 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5262 V_VT(&missing_arg[i]) = V_VT(src_arg);
5263 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5264 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5265 V_VT(&rgvarg[i]) = rgvt[i];
5267 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5269 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5270 V_VT(&rgvarg[i]) = rgvt[i];
5272 else
5274 /* FIXME: this doesn't work for VT_BYREF arguments if
5275 * they are not the same type as in the paramdesc */
5276 V_VT(&rgvarg[i]) = V_VT(src_arg);
5277 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5278 V_VT(&rgvarg[i]) = rgvt[i];
5281 if (FAILED(hres))
5283 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5284 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5285 debugstr_VT(src_arg), debugstr_VF(src_arg));
5286 break;
5288 prgpvarg[i] = &rgvarg[i];
5290 else if (wParamFlags & PARAMFLAG_FOPT)
5292 VARIANTARG *arg;
5293 arg = prgpvarg[i] = &rgvarg[i];
5294 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5296 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5297 if (FAILED(hres))
5298 break;
5300 else
5302 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5303 V_VT(arg) = VT_VARIANT | VT_BYREF;
5304 V_VARIANTREF(arg) = &missing_arg[i];
5305 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5306 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5309 else
5311 hres = DISP_E_BADPARAMCOUNT;
5312 break;
5315 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5316 if (func_desc->cParamsOpt < 0)
5318 FIXME("Does not support safearray optional parameters\n");
5319 hres = DISP_E_BADPARAMCOUNT;
5320 goto func_fail; /* FIXME: we don't free changed types here */
5323 V_VT(&varresult) = 0;
5324 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5325 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5327 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5328 V_VT(&varresult), func_desc->cParams, rgvt,
5329 prgpvarg, &varresult);
5331 for (i = 0; i < func_desc->cParams; i++)
5333 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5334 if (wParamFlags & PARAMFLAG_FRETVAL)
5336 if (TRACE_ON(ole))
5338 TRACE("[retval] value: ");
5339 dump_Variant(prgpvarg[i]);
5342 if (pVarResult)
5343 /* deref return value */
5344 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5346 /* free data stored in varresult. Note that
5347 * VariantClear doesn't do what we want because we are
5348 * working with byref types. */
5349 /* FIXME: clear safearrays, bstrs, records and
5350 * variants here too */
5351 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5352 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5354 if(*V_UNKNOWNREF(prgpvarg[i]))
5355 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5357 break;
5359 else if (i < pDispParams->cArgs)
5361 if (wParamFlags & PARAMFLAG_FOUT)
5363 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5365 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5366 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5368 if (FAILED(hres))
5370 ERR("failed to convert param %d to vt %d\n", i,
5371 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5372 break;
5375 VariantClear(&rgvarg[i]);
5377 else if (wParamFlags & PARAMFLAG_FOPT)
5379 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5380 VariantClear(&rgvarg[i]);
5384 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5386 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5387 hres = DISP_E_EXCEPTION;
5388 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5391 func_fail:
5392 HeapFree(GetProcessHeap(), 0, buffer);
5393 break;
5395 case FUNC_DISPATCH: {
5396 IDispatch *disp;
5398 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5399 if (SUCCEEDED(hres)) {
5400 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5401 hres = IDispatch_Invoke(
5402 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5403 pVarResult,pExcepInfo,pArgErr
5405 if (FAILED(hres))
5406 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5407 IDispatch_Release(disp);
5408 } else
5409 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5410 break;
5412 default:
5413 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5414 hres = E_FAIL;
5415 break;
5418 TRACE("-- 0x%08lx\n", hres);
5419 return hres;
5421 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5422 VARDESC *var_desc;
5424 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5425 if(FAILED(hres)) return hres;
5427 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5428 dump_VARDESC(var_desc);
5429 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5430 return E_NOTIMPL;
5433 /* not found, look for it in inherited interfaces */
5434 ITypeInfo2_GetTypeKind(iface, &type_kind);
5435 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5436 HREFTYPE ref_type;
5437 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5438 /* recursive search */
5439 ITypeInfo *pTInfo;
5440 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5441 if(SUCCEEDED(hres)){
5442 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5443 ITypeInfo_Release(pTInfo);
5444 return hres;
5446 WARN("Could not search inherited interface!\n");
5449 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5450 return DISP_E_MEMBERNOTFOUND;
5453 /* ITypeInfo::GetDocumentation
5455 * Retrieves the documentation string, the complete Help file name and path,
5456 * and the context ID for the Help topic for a specified type description.
5458 * (Can be tested by the Visual Basic Editor in Word for instance.)
5460 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5461 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5462 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5465 const TLBFuncDesc *pFDesc;
5466 const TLBVarDesc *pVDesc;
5467 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5468 " HelpContext(%p) HelpFile(%p)\n",
5469 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5470 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5471 if(pBstrName)
5472 *pBstrName=SysAllocString(This->Name);
5473 if(pBstrDocString)
5474 *pBstrDocString=SysAllocString(This->DocString);
5475 if(pdwHelpContext)
5476 *pdwHelpContext=This->dwHelpContext;
5477 if(pBstrHelpFile)
5478 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5479 return S_OK;
5480 }else {/* for a member */
5481 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5482 if(pFDesc->funcdesc.memid==memid){
5483 if(pBstrName)
5484 *pBstrName = SysAllocString(pFDesc->Name);
5485 if(pBstrDocString)
5486 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5487 if(pdwHelpContext)
5488 *pdwHelpContext=pFDesc->helpcontext;
5489 return S_OK;
5491 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5492 if(pVDesc->vardesc.memid==memid){
5493 if(pBstrName)
5494 *pBstrName = SysAllocString(pVDesc->Name);
5495 if(pBstrDocString)
5496 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5497 if(pdwHelpContext)
5498 *pdwHelpContext=pVDesc->HelpContext;
5499 return S_OK;
5502 WARN("member %ld not found\n", memid);
5503 return TYPE_E_ELEMENTNOTFOUND;
5506 /* ITypeInfo::GetDllEntry
5508 * Retrieves a description or specification of an entry point for a function
5509 * in a DLL.
5511 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5512 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5513 WORD *pwOrdinal)
5515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5516 const TLBFuncDesc *pFDesc;
5518 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5520 if (pBstrDllName) *pBstrDllName = NULL;
5521 if (pBstrName) *pBstrName = NULL;
5522 if (pwOrdinal) *pwOrdinal = 0;
5524 if (This->TypeAttr.typekind != TKIND_MODULE)
5525 return TYPE_E_BADMODULEKIND;
5527 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5528 if(pFDesc->funcdesc.memid==memid){
5529 dump_TypeInfo(This);
5530 if (TRACE_ON(ole))
5531 dump_TLBFuncDescOne(pFDesc);
5533 if (pBstrDllName)
5534 *pBstrDllName = SysAllocString(This->DllName);
5536 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5537 if (pBstrName)
5538 *pBstrName = SysAllocString(pFDesc->Entry);
5539 if (pwOrdinal)
5540 *pwOrdinal = -1;
5541 return S_OK;
5543 if (pBstrName)
5544 *pBstrName = NULL;
5545 if (pwOrdinal)
5546 *pwOrdinal = (DWORD)pFDesc->Entry;
5547 return S_OK;
5549 return TYPE_E_ELEMENTNOTFOUND;
5552 /* ITypeInfo::GetRefTypeInfo
5554 * If a type description references other type descriptions, it retrieves
5555 * the referenced type descriptions.
5557 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5558 ITypeInfo2 *iface,
5559 HREFTYPE hRefType,
5560 ITypeInfo **ppTInfo)
5562 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5563 HRESULT result = E_FAIL;
5565 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5567 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5568 ITypeInfo_AddRef(*ppTInfo);
5569 result = S_OK;
5571 else if (hRefType == -1 &&
5572 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5573 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5575 /* when we meet a DUAL dispinterface, we must create the interface
5576 * version of it.
5578 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5581 /* the interface version contains the same information as the dispinterface
5582 * copy the contents of the structs.
5584 *pTypeInfoImpl = *This;
5585 pTypeInfoImpl->ref = 1;
5587 /* change the type to interface */
5588 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5590 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5592 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5594 result = S_OK;
5596 } else {
5597 TLBRefType *pRefType;
5598 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5599 if(pRefType->reference == hRefType)
5600 break;
5602 if(!pRefType)
5603 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5604 if(pRefType && hRefType != -1) {
5605 ITypeLib *pTLib = NULL;
5607 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5608 UINT Index;
5609 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5610 } else {
5611 if(pRefType->pImpTLInfo->pImpTypeLib) {
5612 TRACE("typeinfo in imported typelib that is already loaded\n");
5613 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5614 ITypeLib2_AddRef((ITypeLib*) pTLib);
5615 result = S_OK;
5616 } else {
5617 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5618 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5619 pRefType->pImpTLInfo->wVersionMajor,
5620 pRefType->pImpTLInfo->wVersionMinor,
5621 pRefType->pImpTLInfo->lcid,
5622 &pTLib);
5624 if(!SUCCEEDED(result)) {
5625 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5626 result=LoadTypeLib(libnam, &pTLib);
5627 SysFreeString(libnam);
5629 if(SUCCEEDED(result)) {
5630 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5631 ITypeLib2_AddRef(pTLib);
5635 if(SUCCEEDED(result)) {
5636 if(pRefType->index == TLB_REF_USE_GUID)
5637 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5638 &pRefType->guid,
5639 ppTInfo);
5640 else
5641 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5642 ppTInfo);
5644 if (pTLib != NULL)
5645 ITypeLib2_Release(pTLib);
5649 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5650 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5651 return result;
5654 /* ITypeInfo::AddressOfMember
5656 * Retrieves the addresses of static functions or variables, such as those
5657 * defined in a DLL.
5659 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5660 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5662 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5663 HRESULT hr;
5664 BSTR dll, entry;
5665 WORD ordinal;
5666 HMODULE module;
5668 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5670 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5671 if (FAILED(hr))
5672 return hr;
5674 module = LoadLibraryW(dll);
5675 if (!module)
5677 ERR("couldn't load %s\n", debugstr_w(dll));
5678 SysFreeString(dll);
5679 if (entry) SysFreeString(entry);
5680 return STG_E_FILENOTFOUND;
5682 /* FIXME: store library somewhere where we can free it */
5684 if (entry)
5686 LPSTR entryA;
5687 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5688 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5689 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5691 *ppv = GetProcAddress(module, entryA);
5692 if (!*ppv)
5693 ERR("function not found %s\n", debugstr_a(entryA));
5695 HeapFree(GetProcessHeap(), 0, entryA);
5697 else
5699 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5700 if (!*ppv)
5701 ERR("function not found %d\n", ordinal);
5704 SysFreeString(dll);
5705 if (entry) SysFreeString(entry);
5707 if (!*ppv)
5708 return TYPE_E_DLLFUNCTIONNOTFOUND;
5710 return S_OK;
5713 /* ITypeInfo::CreateInstance
5715 * Creates a new instance of a type that describes a component object class
5716 * (coclass).
5718 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5719 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5721 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5722 FIXME("(%p) stub!\n", This);
5723 return S_OK;
5726 /* ITypeInfo::GetMops
5728 * Retrieves marshalling information.
5730 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5731 BSTR *pBstrMops)
5733 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5734 FIXME("(%p) stub!\n", This);
5735 return S_OK;
5738 /* ITypeInfo::GetContainingTypeLib
5740 * Retrieves the containing type library and the index of the type description
5741 * within that type library.
5743 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5744 ITypeLib * *ppTLib, UINT *pIndex)
5746 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5748 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5749 if (pIndex) {
5750 *pIndex=This->index;
5751 TRACE("returning pIndex=%d\n", *pIndex);
5754 if (ppTLib) {
5755 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5756 ITypeLib2_AddRef(*ppTLib);
5757 TRACE("returning ppTLib=%p\n", *ppTLib);
5760 return S_OK;
5763 /* ITypeInfo::ReleaseTypeAttr
5765 * Releases a TYPEATTR previously returned by GetTypeAttr.
5768 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5769 TYPEATTR* pTypeAttr)
5771 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5772 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5773 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5776 /* ITypeInfo::ReleaseFuncDesc
5778 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5780 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5781 ITypeInfo2 *iface,
5782 FUNCDESC *pFuncDesc)
5784 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5785 SHORT i;
5787 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5789 for (i = 0; i < pFuncDesc->cParams; i++)
5790 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5791 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5793 SysFreeString((BSTR)pFuncDesc);
5796 /* ITypeInfo::ReleaseVarDesc
5798 * Releases a VARDESC previously returned by GetVarDesc.
5800 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5801 VARDESC *pVarDesc)
5803 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5804 TRACE("(%p)->(%p)\n", This, pVarDesc);
5806 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5807 if (pVarDesc->varkind == VAR_CONST)
5808 VariantClear(pVarDesc->u.lpvarValue);
5809 SysFreeString((BSTR)pVarDesc);
5812 /* ITypeInfo2::GetTypeKind
5814 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5817 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5818 TYPEKIND *pTypeKind)
5820 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5821 *pTypeKind=This->TypeAttr.typekind;
5822 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5823 return S_OK;
5826 /* ITypeInfo2::GetTypeFlags
5828 * Returns the type flags without any allocations. This returns a DWORD type
5829 * flag, which expands the type flags without growing the TYPEATTR (type
5830 * attribute).
5833 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5835 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5836 *pTypeFlags=This->TypeAttr.wTypeFlags;
5837 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5838 return S_OK;
5841 /* ITypeInfo2::GetFuncIndexOfMemId
5842 * Binds to a specific member based on a known DISPID, where the member name
5843 * is not known (for example, when binding to a default member).
5846 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5847 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5849 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5850 const TLBFuncDesc *pFuncInfo;
5851 int i;
5852 HRESULT result;
5854 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5855 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5856 break;
5857 if(pFuncInfo) {
5858 *pFuncIndex = i;
5859 result = S_OK;
5860 } else
5861 result = TYPE_E_ELEMENTNOTFOUND;
5863 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5864 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5865 return result;
5868 /* TypeInfo2::GetVarIndexOfMemId
5870 * Binds to a specific member based on a known DISPID, where the member name
5871 * is not known (for example, when binding to a default member).
5874 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5875 MEMBERID memid, UINT *pVarIndex)
5877 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5878 TLBVarDesc *pVarInfo;
5879 int i;
5880 HRESULT result;
5881 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5882 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5884 if(pVarInfo) {
5885 *pVarIndex = i;
5886 result = S_OK;
5887 } else
5888 result = TYPE_E_ELEMENTNOTFOUND;
5890 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5891 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5892 return result;
5895 /* ITypeInfo2::GetCustData
5897 * Gets the custom data
5899 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5900 ITypeInfo2 * iface,
5901 REFGUID guid,
5902 VARIANT *pVarVal)
5904 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5905 TLBCustData *pCData;
5907 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5908 if( IsEqualIID(guid, &pCData->guid)) break;
5910 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5912 if(pCData)
5914 VariantInit( pVarVal);
5915 VariantCopy( pVarVal, &pCData->data);
5916 return S_OK;
5918 return E_INVALIDARG; /* FIXME: correct? */
5921 /* ITypeInfo2::GetFuncCustData
5923 * Gets the custom data
5925 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5926 ITypeInfo2 * iface,
5927 UINT index,
5928 REFGUID guid,
5929 VARIANT *pVarVal)
5931 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5932 TLBCustData *pCData=NULL;
5933 TLBFuncDesc * pFDesc;
5934 int i;
5935 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5936 pFDesc=pFDesc->next);
5938 if(pFDesc)
5939 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5940 if( IsEqualIID(guid, &pCData->guid)) break;
5942 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5944 if(pCData){
5945 VariantInit( pVarVal);
5946 VariantCopy( pVarVal, &pCData->data);
5947 return S_OK;
5949 return E_INVALIDARG; /* FIXME: correct? */
5952 /* ITypeInfo2::GetParamCustData
5954 * Gets the custom data
5956 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5957 ITypeInfo2 * iface,
5958 UINT indexFunc,
5959 UINT indexParam,
5960 REFGUID guid,
5961 VARIANT *pVarVal)
5963 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5964 TLBCustData *pCData=NULL;
5965 TLBFuncDesc * pFDesc;
5966 int i;
5968 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5970 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5971 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5972 pCData = pCData->next)
5973 if( IsEqualIID(guid, &pCData->guid)) break;
5975 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5977 if(pCData)
5979 VariantInit( pVarVal);
5980 VariantCopy( pVarVal, &pCData->data);
5981 return S_OK;
5983 return E_INVALIDARG; /* FIXME: correct? */
5986 /* ITypeInfo2::GetVarCustData
5988 * Gets the custom data
5990 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5991 ITypeInfo2 * iface,
5992 UINT index,
5993 REFGUID guid,
5994 VARIANT *pVarVal)
5996 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5997 TLBCustData *pCData=NULL;
5998 TLBVarDesc * pVDesc;
5999 int i;
6001 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6003 if(pVDesc)
6005 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6007 if( IsEqualIID(guid, &pCData->guid)) break;
6011 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6013 if(pCData)
6015 VariantInit( pVarVal);
6016 VariantCopy( pVarVal, &pCData->data);
6017 return S_OK;
6019 return E_INVALIDARG; /* FIXME: correct? */
6022 /* ITypeInfo2::GetImplCustData
6024 * Gets the custom data
6026 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6027 ITypeInfo2 * iface,
6028 UINT index,
6029 REFGUID guid,
6030 VARIANT *pVarVal)
6032 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6033 TLBCustData *pCData=NULL;
6034 TLBImplType * pRDesc;
6035 int i;
6037 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6039 if(pRDesc)
6041 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6043 if( IsEqualIID(guid, &pCData->guid)) break;
6047 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6049 if(pCData)
6051 VariantInit( pVarVal);
6052 VariantCopy( pVarVal, &pCData->data);
6053 return S_OK;
6055 return E_INVALIDARG; /* FIXME: correct? */
6058 /* ITypeInfo2::GetDocumentation2
6060 * Retrieves the documentation string, the complete Help file name and path,
6061 * the localization context to use, and the context ID for the library Help
6062 * topic in the Help file.
6065 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6066 ITypeInfo2 * iface,
6067 MEMBERID memid,
6068 LCID lcid,
6069 BSTR *pbstrHelpString,
6070 DWORD *pdwHelpStringContext,
6071 BSTR *pbstrHelpStringDll)
6073 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6074 const TLBFuncDesc *pFDesc;
6075 const TLBVarDesc *pVDesc;
6076 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6077 "HelpStringContext(%p) HelpStringDll(%p)\n",
6078 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6079 pbstrHelpStringDll );
6080 /* the help string should be obtained from the helpstringdll,
6081 * using the _DLLGetDocumentation function, based on the supplied
6082 * lcid. Nice to do sometime...
6084 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6085 if(pbstrHelpString)
6086 *pbstrHelpString=SysAllocString(This->Name);
6087 if(pdwHelpStringContext)
6088 *pdwHelpStringContext=This->dwHelpStringContext;
6089 if(pbstrHelpStringDll)
6090 *pbstrHelpStringDll=
6091 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6092 return S_OK;
6093 }else {/* for a member */
6094 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6095 if(pFDesc->funcdesc.memid==memid){
6096 if(pbstrHelpString)
6097 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6098 if(pdwHelpStringContext)
6099 *pdwHelpStringContext=pFDesc->HelpStringContext;
6100 if(pbstrHelpStringDll)
6101 *pbstrHelpStringDll=
6102 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6103 return S_OK;
6105 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6106 if(pVDesc->vardesc.memid==memid){
6107 if(pbstrHelpString)
6108 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6109 if(pdwHelpStringContext)
6110 *pdwHelpStringContext=pVDesc->HelpStringContext;
6111 if(pbstrHelpStringDll)
6112 *pbstrHelpStringDll=
6113 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6114 return S_OK;
6117 return TYPE_E_ELEMENTNOTFOUND;
6120 /* ITypeInfo2::GetAllCustData
6122 * Gets all custom data items for the Type info.
6125 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6126 ITypeInfo2 * iface,
6127 CUSTDATA *pCustData)
6129 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6130 TLBCustData *pCData;
6131 int i;
6133 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6135 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6136 if(pCustData->prgCustData ){
6137 pCustData->cCustData=This->ctCustData;
6138 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6139 pCustData->prgCustData[i].guid=pCData->guid;
6140 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6142 }else{
6143 ERR(" OUT OF MEMORY!\n");
6144 return E_OUTOFMEMORY;
6146 return S_OK;
6149 /* ITypeInfo2::GetAllFuncCustData
6151 * Gets all custom data items for the specified Function
6154 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6155 ITypeInfo2 * iface,
6156 UINT index,
6157 CUSTDATA *pCustData)
6159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6160 TLBCustData *pCData;
6161 TLBFuncDesc * pFDesc;
6162 int i;
6163 TRACE("(%p) index %d\n", This, index);
6164 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6165 pFDesc=pFDesc->next)
6167 if(pFDesc){
6168 pCustData->prgCustData =
6169 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6170 if(pCustData->prgCustData ){
6171 pCustData->cCustData=pFDesc->ctCustData;
6172 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6173 pCData = pCData->next){
6174 pCustData->prgCustData[i].guid=pCData->guid;
6175 VariantCopy(& pCustData->prgCustData[i].varValue,
6176 & pCData->data);
6178 }else{
6179 ERR(" OUT OF MEMORY!\n");
6180 return E_OUTOFMEMORY;
6182 return S_OK;
6184 return TYPE_E_ELEMENTNOTFOUND;
6187 /* ITypeInfo2::GetAllParamCustData
6189 * Gets all custom data items for the Functions
6192 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6193 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6195 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6196 TLBCustData *pCData=NULL;
6197 TLBFuncDesc * pFDesc;
6198 int i;
6199 TRACE("(%p) index %d\n", This, indexFunc);
6200 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6201 pFDesc=pFDesc->next)
6203 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6204 pCustData->prgCustData =
6205 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6206 sizeof(CUSTDATAITEM));
6207 if(pCustData->prgCustData ){
6208 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6209 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6210 pCData; i++, pCData = pCData->next){
6211 pCustData->prgCustData[i].guid=pCData->guid;
6212 VariantCopy(& pCustData->prgCustData[i].varValue,
6213 & pCData->data);
6215 }else{
6216 ERR(" OUT OF MEMORY!\n");
6217 return E_OUTOFMEMORY;
6219 return S_OK;
6221 return TYPE_E_ELEMENTNOTFOUND;
6224 /* ITypeInfo2::GetAllVarCustData
6226 * Gets all custom data items for the specified Variable
6229 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6230 UINT index, CUSTDATA *pCustData)
6232 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6233 TLBCustData *pCData;
6234 TLBVarDesc * pVDesc;
6235 int i;
6236 TRACE("(%p) index %d\n", This, index);
6237 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6238 pVDesc=pVDesc->next)
6240 if(pVDesc){
6241 pCustData->prgCustData =
6242 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6243 if(pCustData->prgCustData ){
6244 pCustData->cCustData=pVDesc->ctCustData;
6245 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6246 pCData = pCData->next){
6247 pCustData->prgCustData[i].guid=pCData->guid;
6248 VariantCopy(& pCustData->prgCustData[i].varValue,
6249 & pCData->data);
6251 }else{
6252 ERR(" OUT OF MEMORY!\n");
6253 return E_OUTOFMEMORY;
6255 return S_OK;
6257 return TYPE_E_ELEMENTNOTFOUND;
6260 /* ITypeInfo2::GetAllImplCustData
6262 * Gets all custom data items for the specified implementation type
6265 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6266 ITypeInfo2 * iface,
6267 UINT index,
6268 CUSTDATA *pCustData)
6270 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6271 TLBCustData *pCData;
6272 TLBImplType * pRDesc;
6273 int i;
6274 TRACE("(%p) index %d\n", This, index);
6275 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6276 pRDesc=pRDesc->next)
6278 if(pRDesc){
6279 pCustData->prgCustData =
6280 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6281 if(pCustData->prgCustData ){
6282 pCustData->cCustData=pRDesc->ctCustData;
6283 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6284 pCData = pCData->next){
6285 pCustData->prgCustData[i].guid=pCData->guid;
6286 VariantCopy(& pCustData->prgCustData[i].varValue,
6287 & pCData->data);
6289 }else{
6290 ERR(" OUT OF MEMORY!\n");
6291 return E_OUTOFMEMORY;
6293 return S_OK;
6295 return TYPE_E_ELEMENTNOTFOUND;
6298 static const ITypeInfo2Vtbl tinfvt =
6301 ITypeInfo_fnQueryInterface,
6302 ITypeInfo_fnAddRef,
6303 ITypeInfo_fnRelease,
6305 ITypeInfo_fnGetTypeAttr,
6306 ITypeInfo_fnGetTypeComp,
6307 ITypeInfo_fnGetFuncDesc,
6308 ITypeInfo_fnGetVarDesc,
6309 ITypeInfo_fnGetNames,
6310 ITypeInfo_fnGetRefTypeOfImplType,
6311 ITypeInfo_fnGetImplTypeFlags,
6312 ITypeInfo_fnGetIDsOfNames,
6313 ITypeInfo_fnInvoke,
6314 ITypeInfo_fnGetDocumentation,
6315 ITypeInfo_fnGetDllEntry,
6316 ITypeInfo_fnGetRefTypeInfo,
6317 ITypeInfo_fnAddressOfMember,
6318 ITypeInfo_fnCreateInstance,
6319 ITypeInfo_fnGetMops,
6320 ITypeInfo_fnGetContainingTypeLib,
6321 ITypeInfo_fnReleaseTypeAttr,
6322 ITypeInfo_fnReleaseFuncDesc,
6323 ITypeInfo_fnReleaseVarDesc,
6325 ITypeInfo2_fnGetTypeKind,
6326 ITypeInfo2_fnGetTypeFlags,
6327 ITypeInfo2_fnGetFuncIndexOfMemId,
6328 ITypeInfo2_fnGetVarIndexOfMemId,
6329 ITypeInfo2_fnGetCustData,
6330 ITypeInfo2_fnGetFuncCustData,
6331 ITypeInfo2_fnGetParamCustData,
6332 ITypeInfo2_fnGetVarCustData,
6333 ITypeInfo2_fnGetImplTypeCustData,
6334 ITypeInfo2_fnGetDocumentation2,
6335 ITypeInfo2_fnGetAllCustData,
6336 ITypeInfo2_fnGetAllFuncCustData,
6337 ITypeInfo2_fnGetAllParamCustData,
6338 ITypeInfo2_fnGetAllVarCustData,
6339 ITypeInfo2_fnGetAllImplTypeCustData,
6342 /******************************************************************************
6343 * CreateDispTypeInfo [OLEAUT32.31]
6345 * Build type information for an object so it can be called through an
6346 * IDispatch interface.
6348 * RETURNS
6349 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6350 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6352 * NOTES
6353 * This call allows an objects methods to be accessed through IDispatch, by
6354 * building an ITypeInfo object that IDispatch can use to call through.
6356 HRESULT WINAPI CreateDispTypeInfo(
6357 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6358 LCID lcid, /* [I] Locale Id */
6359 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6361 ITypeInfoImpl *pTIClass, *pTIIface;
6362 ITypeLibImpl *pTypeLibImpl;
6363 int param, func;
6364 TLBFuncDesc **ppFuncDesc;
6366 TRACE("\n");
6367 pTypeLibImpl = TypeLibImpl_Constructor();
6368 if (!pTypeLibImpl) return E_FAIL;
6370 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6371 pTIIface->pTypeLib = pTypeLibImpl;
6372 pTIIface->index = 0;
6373 pTIIface->Name = NULL;
6374 pTIIface->dwHelpContext = -1;
6375 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6376 pTIIface->TypeAttr.lcid = lcid;
6377 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6378 pTIIface->TypeAttr.wMajorVerNum = 0;
6379 pTIIface->TypeAttr.wMinorVerNum = 0;
6380 pTIIface->TypeAttr.cbAlignment = 2;
6381 pTIIface->TypeAttr.cbSizeInstance = -1;
6382 pTIIface->TypeAttr.cbSizeVft = -1;
6383 pTIIface->TypeAttr.cFuncs = 0;
6384 pTIIface->TypeAttr.cImplTypes = 0;
6385 pTIIface->TypeAttr.cVars = 0;
6386 pTIIface->TypeAttr.wTypeFlags = 0;
6388 ppFuncDesc = &pTIIface->funclist;
6389 for(func = 0; func < pidata->cMembers; func++) {
6390 METHODDATA *md = pidata->pmethdata + func;
6391 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6392 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6393 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6394 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6395 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6396 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6397 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6398 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6399 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6400 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6401 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6402 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6403 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6404 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6405 md->cArgs * sizeof(ELEMDESC));
6406 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6407 md->cArgs * sizeof(TLBParDesc));
6408 for(param = 0; param < md->cArgs; param++) {
6409 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6410 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6412 (*ppFuncDesc)->helpcontext = 0;
6413 (*ppFuncDesc)->HelpStringContext = 0;
6414 (*ppFuncDesc)->HelpString = NULL;
6415 (*ppFuncDesc)->Entry = NULL;
6416 (*ppFuncDesc)->ctCustData = 0;
6417 (*ppFuncDesc)->pCustData = NULL;
6418 (*ppFuncDesc)->next = NULL;
6419 ppFuncDesc = &(*ppFuncDesc)->next;
6422 dump_TypeInfo(pTIIface);
6424 pTypeLibImpl->pTypeInfo = pTIIface;
6425 pTypeLibImpl->TypeInfoCount++;
6427 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6428 pTIClass->pTypeLib = pTypeLibImpl;
6429 pTIClass->index = 1;
6430 pTIClass->Name = NULL;
6431 pTIClass->dwHelpContext = -1;
6432 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6433 pTIClass->TypeAttr.lcid = lcid;
6434 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6435 pTIClass->TypeAttr.wMajorVerNum = 0;
6436 pTIClass->TypeAttr.wMinorVerNum = 0;
6437 pTIClass->TypeAttr.cbAlignment = 2;
6438 pTIClass->TypeAttr.cbSizeInstance = -1;
6439 pTIClass->TypeAttr.cbSizeVft = -1;
6440 pTIClass->TypeAttr.cFuncs = 0;
6441 pTIClass->TypeAttr.cImplTypes = 1;
6442 pTIClass->TypeAttr.cVars = 0;
6443 pTIClass->TypeAttr.wTypeFlags = 0;
6445 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6446 pTIClass->impltypelist->hRef = 1;
6448 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6449 pTIClass->reflist->index = 0;
6450 pTIClass->reflist->reference = 1;
6451 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6453 dump_TypeInfo(pTIClass);
6455 pTIIface->next = pTIClass;
6456 pTypeLibImpl->TypeInfoCount++;
6458 *pptinfo = (ITypeInfo*)pTIClass;
6459 return S_OK;
6463 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6465 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6467 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6470 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6472 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6474 return ITypeInfo_AddRef((ITypeInfo *)This);
6477 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6479 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6481 return ITypeInfo_Release((ITypeInfo *)This);
6484 static HRESULT WINAPI ITypeComp_fnBind(
6485 ITypeComp * iface,
6486 OLECHAR * szName,
6487 ULONG lHash,
6488 WORD wFlags,
6489 ITypeInfo ** ppTInfo,
6490 DESCKIND * pDescKind,
6491 BINDPTR * pBindPtr)
6493 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6494 const TLBFuncDesc *pFDesc;
6495 const TLBVarDesc *pVDesc;
6497 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6499 *pDescKind = DESCKIND_NONE;
6500 pBindPtr->lpfuncdesc = NULL;
6501 *ppTInfo = NULL;
6503 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6504 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6505 if (!strcmpW(pFDesc->Name, szName)) {
6506 break;
6509 if (pFDesc)
6511 HRESULT hr = TLB_AllocAndInitFuncDesc(
6512 &pFDesc->funcdesc,
6513 &pBindPtr->lpfuncdesc,
6514 This->TypeAttr.typekind == TKIND_DISPATCH);
6515 if (FAILED(hr))
6516 return hr;
6517 *pDescKind = DESCKIND_FUNCDESC;
6518 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6519 ITypeInfo_AddRef(*ppTInfo);
6520 return S_OK;
6521 } else {
6522 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6523 if (!strcmpW(pVDesc->Name, szName)) {
6524 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6525 if (FAILED(hr))
6526 return hr;
6527 *pDescKind = DESCKIND_VARDESC;
6528 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6529 ITypeInfo_AddRef(*ppTInfo);
6530 return S_OK;
6534 /* FIXME: search each inherited interface, not just the first */
6535 if (This->TypeAttr.cImplTypes) {
6536 /* recursive search */
6537 ITypeInfo *pTInfo;
6538 ITypeComp *pTComp;
6539 HRESULT hr;
6540 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6541 if (SUCCEEDED(hr))
6543 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6544 ITypeInfo_Release(pTInfo);
6546 if (SUCCEEDED(hr))
6548 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6549 ITypeComp_Release(pTComp);
6550 return hr;
6552 WARN("Could not search inherited interface!\n");
6554 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6555 return DISP_E_MEMBERNOTFOUND;
6558 static HRESULT WINAPI ITypeComp_fnBindType(
6559 ITypeComp * iface,
6560 OLECHAR * szName,
6561 ULONG lHash,
6562 ITypeInfo ** ppTInfo,
6563 ITypeComp ** ppTComp)
6565 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6567 /* strange behaviour (does nothing) but like the
6568 * original */
6570 if (!ppTInfo || !ppTComp)
6571 return E_POINTER;
6573 *ppTInfo = NULL;
6574 *ppTComp = NULL;
6576 return S_OK;
6579 static const ITypeCompVtbl tcompvt =
6582 ITypeComp_fnQueryInterface,
6583 ITypeComp_fnAddRef,
6584 ITypeComp_fnRelease,
6586 ITypeComp_fnBind,
6587 ITypeComp_fnBindType