ole: Improve typelib traces.
[wine/wine64.git] / dlls / oleaut32 / typelib.c
blob965342c1efaf970a144ad34acf1bb0f830479110
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 int TLB_ReadTypeLib(LPCWSTR file, INT index, 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], szFileCopy[MAX_PATH+1];
337 WCHAR *pIndexStr;
338 HRESULT res;
339 INT index = 1;
341 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
343 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
344 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
346 *pptLib = NULL;
347 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
348 NULL)) {
350 /* Look for a trailing '\\' followed by an index */
351 pIndexStr = strrchrW(szFile, '\\');
352 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
353 index = atoiW(pIndexStr);
354 memcpy(szFileCopy, szFile,
355 (pIndexStr - szFile - 1) * sizeof(WCHAR));
356 szFileCopy[pIndexStr - szFile - 1] = '\0';
357 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
358 szPath,NULL))
359 return TYPE_E_CANTLOADLIBRARY;
360 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
361 return TYPE_E_CANTLOADLIBRARY;
365 TRACE("File %s index %d\n", debugstr_w(szPath), index);
367 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
369 if (SUCCEEDED(res))
370 switch(regkind)
372 case REGKIND_DEFAULT:
373 /* don't register typelibs supplied with full path. Experimentation confirms the following */
374 if ((!szFile) ||
375 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
376 (szFile[0] && (szFile[1] == ':'))) break;
377 /* else fall-through */
379 case REGKIND_REGISTER:
380 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
382 IUnknown_Release(*pptLib);
383 *pptLib = 0;
385 break;
386 case REGKIND_NONE:
387 break;
390 TRACE(" returns %08lx\n",res);
391 return res;
394 /******************************************************************************
395 * LoadRegTypeLib [OLEAUT32.162]
397 * Loads a registered type library.
399 * PARAMS
400 * rguid [I] GUID of the registered type library.
401 * wVerMajor [I] major version.
402 * wVerMinor [I] minor version.
403 * lcid [I] locale ID.
404 * ppTLib [O] pointer that receives an ITypeLib object on success.
406 * RETURNS
407 * Success: S_OK.
408 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
409 * LoadTypeLib.
411 HRESULT WINAPI LoadRegTypeLib(
412 REFGUID rguid,
413 WORD wVerMajor,
414 WORD wVerMinor,
415 LCID lcid,
416 ITypeLib **ppTLib)
418 BSTR bstr=NULL;
419 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
421 if(SUCCEEDED(res))
423 res= LoadTypeLib(bstr, ppTLib);
424 SysFreeString(bstr);
427 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
429 return res;
433 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
434 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
435 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
436 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
437 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
438 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
440 /******************************************************************************
441 * RegisterTypeLib [OLEAUT32.163]
442 * Adds information about a type library to the System Registry
443 * NOTES
444 * Docs: ITypeLib FAR * ptlib
445 * Docs: OLECHAR FAR* szFullPath
446 * Docs: OLECHAR FAR* szHelpDir
448 * RETURNS
449 * Success: S_OK
450 * Failure: Status
452 HRESULT WINAPI RegisterTypeLib(
453 ITypeLib * ptlib, /* [in] Pointer to the library*/
454 OLECHAR * szFullPath, /* [in] full Path of the library*/
455 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
456 may be NULL*/
458 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
459 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
460 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
461 HRESULT res;
462 TLIBATTR *attr;
463 WCHAR keyName[60];
464 WCHAR tmp[16];
465 HKEY key, subKey;
466 UINT types, tidx;
467 TYPEKIND kind;
468 DWORD disposition;
470 if (ptlib == NULL || szFullPath == NULL)
471 return E_INVALIDARG;
473 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
474 return E_FAIL;
476 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
478 res = S_OK;
479 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
480 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
482 LPOLESTR doc;
484 /* Set the human-readable name of the typelib */
485 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
487 if (RegSetValueExW(key, NULL, 0, REG_SZ,
488 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
489 res = E_FAIL;
491 SysFreeString(doc);
493 else
494 res = E_FAIL;
496 /* Make up the name of the typelib path subkey */
497 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
499 /* Create the typelib path subkey */
500 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
501 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
503 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
504 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
505 res = E_FAIL;
507 RegCloseKey(subKey);
509 else
510 res = E_FAIL;
512 /* Create the flags subkey */
513 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
514 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
516 /* FIXME: is %u correct? */
517 static const WCHAR formatW[] = {'%','u',0};
518 WCHAR buf[20];
519 sprintfW(buf, formatW, attr->wLibFlags);
520 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
521 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
522 res = E_FAIL;
524 RegCloseKey(subKey);
526 else
527 res = E_FAIL;
529 /* create the helpdir subkey */
530 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
531 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
533 BOOL freeHelpDir = FALSE;
534 OLECHAR* pIndexStr;
536 /* if we created a new key, and helpDir was null, set the helpdir
537 to the directory which contains the typelib. However,
538 if we just opened an existing key, we leave the helpdir alone */
539 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
540 szHelpDir = SysAllocString(szFullPath);
541 pIndexStr = strrchrW(szHelpDir, '\\');
542 if (pIndexStr) {
543 *pIndexStr = 0;
545 freeHelpDir = TRUE;
548 /* if we have an szHelpDir, set it! */
549 if (szHelpDir != NULL) {
550 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
551 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
552 res = E_FAIL;
556 /* tidy up */
557 if (freeHelpDir) SysFreeString(szHelpDir);
558 RegCloseKey(subKey);
560 } else {
561 res = E_FAIL;
564 RegCloseKey(key);
566 else
567 res = E_FAIL;
569 /* register OLE Automation-compatible interfaces for this typelib */
570 types = ITypeLib_GetTypeInfoCount(ptlib);
571 for (tidx=0; tidx<types; tidx++) {
572 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
573 LPOLESTR name = NULL;
574 ITypeInfo *tinfo = NULL;
576 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
578 switch (kind) {
579 case TKIND_INTERFACE:
580 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
581 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
582 break;
584 case TKIND_DISPATCH:
585 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
586 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
587 break;
589 default:
590 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
591 break;
594 if (tinfo) {
595 TYPEATTR *tattr = NULL;
596 ITypeInfo_GetTypeAttr(tinfo, &tattr);
598 if (tattr) {
599 TRACE_(typelib)("guid=%s, flags=%04x (",
600 debugstr_guid(&tattr->guid),
601 tattr->wTypeFlags);
603 if (TRACE_ON(typelib)) {
604 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
605 XX(FAPPOBJECT);
606 XX(FCANCREATE);
607 XX(FLICENSED);
608 XX(FPREDECLID);
609 XX(FHIDDEN);
610 XX(FCONTROL);
611 XX(FDUAL);
612 XX(FNONEXTENSIBLE);
613 XX(FOLEAUTOMATION);
614 XX(FRESTRICTED);
615 XX(FAGGREGATABLE);
616 XX(FREPLACEABLE);
617 XX(FDISPATCHABLE);
618 XX(FREVERSEBIND);
619 XX(FPROXY);
620 #undef XX
621 MESSAGE("\n");
624 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
626 /* register interface<->typelib coupling */
627 get_interface_key( &tattr->guid, keyName );
628 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
629 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
631 if (name)
632 RegSetValueExW(key, NULL, 0, REG_SZ,
633 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
635 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
636 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
637 RegSetValueExW(subKey, NULL, 0, REG_SZ,
638 (BYTE*)PSOA, sizeof PSOA);
639 RegCloseKey(subKey);
642 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
643 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
644 RegSetValueExW(subKey, NULL, 0, REG_SZ,
645 (BYTE*)PSOA, sizeof PSOA);
646 RegCloseKey(subKey);
649 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
650 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
652 WCHAR buffer[40];
653 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
654 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
656 StringFromGUID2(&attr->guid, buffer, 40);
657 RegSetValueExW(subKey, NULL, 0, REG_SZ,
658 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
659 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
660 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
661 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
662 RegCloseKey(subKey);
665 RegCloseKey(key);
669 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
672 ITypeInfo_Release(tinfo);
675 SysFreeString(name);
679 ITypeLib_ReleaseTLibAttr(ptlib, attr);
681 return res;
685 /******************************************************************************
686 * UnRegisterTypeLib [OLEAUT32.186]
687 * Removes information about a type library from the System Registry
688 * NOTES
690 * RETURNS
691 * Success: S_OK
692 * Failure: Status
694 HRESULT WINAPI UnRegisterTypeLib(
695 REFGUID libid, /* [in] Guid of the library */
696 WORD wVerMajor, /* [in] major version */
697 WORD wVerMinor, /* [in] minor version */
698 LCID lcid, /* [in] locale id */
699 SYSKIND syskind)
701 BSTR tlibPath = NULL;
702 DWORD tmpLength;
703 WCHAR keyName[60];
704 WCHAR subKeyName[50];
705 int result = S_OK;
706 DWORD i = 0;
707 BOOL deleteOtherStuff;
708 HKEY key = NULL;
709 HKEY subKey = NULL;
710 TYPEATTR* typeAttr = NULL;
711 TYPEKIND kind;
712 ITypeInfo* typeInfo = NULL;
713 ITypeLib* typeLib = NULL;
714 int numTypes;
716 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
718 /* Create the path to the key */
719 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
721 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
723 TRACE("Unsupported syskind %i\n", syskind);
724 result = E_INVALIDARG;
725 goto end;
728 /* get the path to the typelib on disk */
729 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
730 result = E_INVALIDARG;
731 goto end;
734 /* Try and open the key to the type library. */
735 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
736 result = E_INVALIDARG;
737 goto end;
740 /* Try and load the type library */
741 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
742 result = TYPE_E_INVALIDSTATE;
743 goto end;
746 /* remove any types registered with this typelib */
747 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
748 for (i=0; i<numTypes; i++) {
749 /* get the kind of type */
750 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
751 goto enddeleteloop;
754 /* skip non-interfaces, and get type info for the type */
755 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
756 goto enddeleteloop;
758 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
759 goto enddeleteloop;
761 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
762 goto enddeleteloop;
765 /* the path to the type */
766 get_interface_key( &typeAttr->guid, subKeyName );
768 /* Delete its bits */
769 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
770 goto enddeleteloop;
772 RegDeleteKeyW(subKey, ProxyStubClsidW);
773 RegDeleteKeyW(subKey, ProxyStubClsid32W);
774 RegDeleteKeyW(subKey, TypeLibW);
775 RegCloseKey(subKey);
776 subKey = NULL;
777 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
779 enddeleteloop:
780 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
781 typeAttr = NULL;
782 if (typeInfo) ITypeInfo_Release(typeInfo);
783 typeInfo = NULL;
786 /* Now, delete the type library path subkey */
787 get_lcid_subkey( lcid, syskind, subKeyName );
788 RegDeleteKeyW(key, subKeyName);
789 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
790 RegDeleteKeyW(key, subKeyName);
792 /* check if there is anything besides the FLAGS/HELPDIR keys.
793 If there is, we don't delete them */
794 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
795 deleteOtherStuff = TRUE;
796 i = 0;
797 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
798 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
800 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
801 if (!strcmpW(subKeyName, FLAGSW)) continue;
802 if (!strcmpW(subKeyName, HELPDIRW)) continue;
803 deleteOtherStuff = FALSE;
804 break;
807 /* only delete the other parts of the key if we're absolutely sure */
808 if (deleteOtherStuff) {
809 RegDeleteKeyW(key, FLAGSW);
810 RegDeleteKeyW(key, HELPDIRW);
811 RegCloseKey(key);
812 key = NULL;
814 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
815 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
816 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
819 end:
820 if (tlibPath) SysFreeString(tlibPath);
821 if (typeLib) ITypeLib_Release(typeLib);
822 if (subKey) RegCloseKey(subKey);
823 if (key) RegCloseKey(key);
824 return result;
827 /*======================= ITypeLib implementation =======================*/
829 typedef struct tagTLBCustData
831 GUID guid;
832 VARIANT data;
833 struct tagTLBCustData* next;
834 } TLBCustData;
836 /* data structure for import typelibs */
837 typedef struct tagTLBImpLib
839 int offset; /* offset in the file (MSFT)
840 offset in nametable (SLTG)
841 just used to identify library while reading
842 data from file */
843 GUID guid; /* libid */
844 BSTR name; /* name */
846 LCID lcid; /* lcid of imported typelib */
848 WORD wVersionMajor; /* major version number */
849 WORD wVersionMinor; /* minor version number */
851 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
852 NULL if not yet loaded */
853 struct tagTLBImpLib * next;
854 } TLBImpLib;
856 /* internal ITypeLib data */
857 typedef struct tagITypeLibImpl
859 const ITypeLib2Vtbl *lpVtbl;
860 const ITypeCompVtbl *lpVtblTypeComp;
861 LONG ref;
862 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
864 /* strings can be stored in tlb as multibyte strings BUT they are *always*
865 * exported to the application as a UNICODE string.
867 BSTR Name;
868 BSTR DocString;
869 BSTR HelpFile;
870 BSTR HelpStringDll;
871 unsigned long dwHelpContext;
872 int TypeInfoCount; /* nr of typeinfo's in librarry */
873 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
874 int ctCustData; /* number of items in cust data list */
875 TLBCustData * pCustData; /* linked list to cust data */
876 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
877 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
878 libary. Only used while read MSFT
879 typelibs */
881 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
882 struct tagITypeLibImpl *next, *prev;
883 WCHAR *path;
884 INT index;
885 } ITypeLibImpl;
887 static const ITypeLib2Vtbl tlbvt;
888 static const ITypeCompVtbl tlbtcvt;
890 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
892 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
895 /* ITypeLib methods */
896 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
897 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
899 /*======================= ITypeInfo implementation =======================*/
901 /* data for referenced types */
902 typedef struct tagTLBRefType
904 INT index; /* Type index for internal ref or for external ref
905 it the format is SLTG. -2 indicates to
906 use guid */
908 GUID guid; /* guid of the referenced type */
909 /* if index == TLB_REF_USE_GUID */
911 HREFTYPE reference; /* The href of this ref */
912 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
913 TLB_REF_INTERNAL for internal refs
914 TLB_REF_NOT_FOUND for broken refs */
916 struct tagTLBRefType * next;
917 } TLBRefType;
919 #define TLB_REF_USE_GUID -2
921 #define TLB_REF_INTERNAL (void*)-2
922 #define TLB_REF_NOT_FOUND (void*)-1
924 /* internal Parameter data */
925 typedef struct tagTLBParDesc
927 BSTR Name;
928 int ctCustData;
929 TLBCustData * pCustData; /* linked list to cust data */
930 } TLBParDesc;
932 /* internal Function data */
933 typedef struct tagTLBFuncDesc
935 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
936 BSTR Name; /* the name of this function */
937 TLBParDesc *pParamDesc; /* array with param names and custom data */
938 int helpcontext;
939 int HelpStringContext;
940 BSTR HelpString;
941 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
942 int ctCustData;
943 TLBCustData * pCustData; /* linked list to cust data; */
944 struct tagTLBFuncDesc * next;
945 } TLBFuncDesc;
947 /* internal Variable data */
948 typedef struct tagTLBVarDesc
950 VARDESC vardesc; /* lots of info on the variable and its attributes. */
951 BSTR Name; /* the name of this variable */
952 int HelpContext;
953 int HelpStringContext; /* FIXME: where? */
954 BSTR HelpString;
955 int ctCustData;
956 TLBCustData * pCustData;/* linked list to cust data; */
957 struct tagTLBVarDesc * next;
958 } TLBVarDesc;
960 /* internal implemented interface data */
961 typedef struct tagTLBImplType
963 HREFTYPE hRef; /* hRef of interface */
964 int implflags; /* IMPLFLAG_*s */
965 int ctCustData;
966 TLBCustData * pCustData;/* linked list to custom data; */
967 struct tagTLBImplType *next;
968 } TLBImplType;
970 /* internal TypeInfo data */
971 typedef struct tagITypeInfoImpl
973 const ITypeInfo2Vtbl *lpVtbl;
974 const ITypeCompVtbl *lpVtblTypeComp;
975 LONG ref;
976 TYPEATTR TypeAttr ; /* _lots_ of type information. */
977 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
978 int index; /* index in this typelib; */
979 HREFTYPE hreftype; /* hreftype for app object binding */
980 /* type libs seem to store the doc strings in ascii
981 * so why should we do it in unicode?
983 BSTR Name;
984 BSTR DocString;
985 BSTR DllName;
986 unsigned long dwHelpContext;
987 unsigned long dwHelpStringContext;
989 /* functions */
990 TLBFuncDesc * funclist; /* linked list with function descriptions */
992 /* variables */
993 TLBVarDesc * varlist; /* linked list with variable descriptions */
995 /* Implemented Interfaces */
996 TLBImplType * impltypelist;
998 TLBRefType * reflist;
999 int ctCustData;
1000 TLBCustData * pCustData; /* linked list to cust data; */
1001 struct tagITypeInfoImpl * next;
1002 } ITypeInfoImpl;
1004 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1006 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1009 static const ITypeInfo2Vtbl tinfvt;
1010 static const ITypeCompVtbl tcompvt;
1012 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1014 typedef struct tagTLBContext
1016 unsigned int oStart; /* start of TLB in file */
1017 unsigned int pos; /* current pos */
1018 unsigned int length; /* total length */
1019 void *mapping; /* memory mapping */
1020 MSFT_SegDir * pTblDir;
1021 ITypeLibImpl* pLibInfo;
1022 } TLBContext;
1025 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1028 debug
1030 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1031 if (pTD->vt & VT_RESERVED)
1032 szVarType += strlen(strcpy(szVarType, "reserved | "));
1033 if (pTD->vt & VT_BYREF)
1034 szVarType += strlen(strcpy(szVarType, "ref to "));
1035 if (pTD->vt & VT_ARRAY)
1036 szVarType += strlen(strcpy(szVarType, "array of "));
1037 if (pTD->vt & VT_VECTOR)
1038 szVarType += strlen(strcpy(szVarType, "vector of "));
1039 switch(pTD->vt & VT_TYPEMASK) {
1040 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1041 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1042 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1043 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1044 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1045 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1046 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1047 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1048 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1049 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1050 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1051 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1052 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1053 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1054 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1055 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1056 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1057 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1058 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1059 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1060 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1061 pTD->u.hreftype); break;
1062 case VT_PTR: sprintf(szVarType, "ptr to ");
1063 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1064 break;
1065 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1066 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1067 break;
1068 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1069 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1070 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1071 break;
1073 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1077 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1078 char buf[200];
1079 USHORT flags = edesc->u.paramdesc.wParamFlags;
1080 dump_TypeDesc(&edesc->tdesc,buf);
1081 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1082 MESSAGE("\t\tu.paramdesc.wParamFlags");
1083 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1084 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1085 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1086 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1087 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1088 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1089 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1090 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1091 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1093 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1094 int i;
1095 MESSAGE("memid is %08lx\n",funcdesc->memid);
1096 for (i=0;i<funcdesc->cParams;i++) {
1097 MESSAGE("Param %d:\n",i);
1098 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1100 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1101 switch (funcdesc->funckind) {
1102 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1103 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1104 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1105 case FUNC_STATIC: MESSAGE("static");break;
1106 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1107 default: MESSAGE("unknown");break;
1109 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1110 switch (funcdesc->invkind) {
1111 case INVOKE_FUNC: MESSAGE("func");break;
1112 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1113 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1114 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1116 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1117 switch (funcdesc->callconv) {
1118 case CC_CDECL: MESSAGE("cdecl");break;
1119 case CC_PASCAL: MESSAGE("pascal");break;
1120 case CC_STDCALL: MESSAGE("stdcall");break;
1121 case CC_SYSCALL: MESSAGE("syscall");break;
1122 default:break;
1124 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1125 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1126 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1128 MESSAGE("\telemdescFunc (return value type):\n");
1129 dump_ELEMDESC(&funcdesc->elemdescFunc);
1132 static const char * typekind_desc[] =
1134 "TKIND_ENUM",
1135 "TKIND_RECORD",
1136 "TKIND_MODULE",
1137 "TKIND_INTERFACE",
1138 "TKIND_DISPATCH",
1139 "TKIND_COCLASS",
1140 "TKIND_ALIAS",
1141 "TKIND_UNION",
1142 "TKIND_MAX"
1145 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1147 int i;
1148 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1149 for (i=0;i<pfd->funcdesc.cParams;i++)
1150 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1153 dump_FUNCDESC(&(pfd->funcdesc));
1155 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1156 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1158 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1160 while (pfd)
1162 dump_TLBFuncDescOne(pfd);
1163 pfd = pfd->next;
1166 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1168 while (pvd)
1170 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1171 pvd = pvd->next;
1175 static void dump_TLBImpLib(const TLBImpLib *import)
1177 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1178 debugstr_w(import->name));
1179 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1180 import->wVersionMinor, import->lcid, import->offset);
1183 static void dump_TLBRefType(const TLBRefType * prt)
1185 while (prt)
1187 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1188 if(prt->index == -1)
1189 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1190 else
1191 TRACE_(typelib)("type no: %d\n", prt->index);
1193 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1194 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1195 TRACE_(typelib)("in lib\n");
1196 dump_TLBImpLib(prt->pImpTLInfo);
1198 prt = prt->next;
1202 static void dump_TLBImplType(const TLBImplType * impl)
1204 while (impl) {
1205 TRACE_(typelib)(
1206 "implementing/inheriting interface hRef = %lx implflags %x\n",
1207 impl->hRef, impl->implflags);
1208 impl = impl->next;
1212 void dump_Variant(const VARIANT * pvar)
1214 SYSTEMTIME st;
1216 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1218 if (pvar)
1220 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1221 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1223 TRACE(",%p", V_BYREF(pvar));
1225 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1227 TRACE(",FIXME");
1229 else switch (V_TYPE(pvar))
1231 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1232 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1233 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1234 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1235 case VT_INT:
1236 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1237 case VT_UINT:
1238 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1239 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1240 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1241 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1242 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1243 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1244 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1245 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1246 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1247 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1248 V_CY(pvar).s.Lo); break;
1249 case VT_DATE:
1250 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1251 TRACE(",<invalid>");
1252 else
1253 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1254 st.wHour, st.wMinute, st.wSecond);
1255 break;
1256 case VT_ERROR:
1257 case VT_VOID:
1258 case VT_USERDEFINED:
1259 case VT_EMPTY:
1260 case VT_NULL: break;
1261 default: TRACE(",?"); break;
1264 TRACE("}\n");
1267 static void dump_DispParms(const DISPPARAMS * pdp)
1269 int index = 0;
1271 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1273 while (index < pdp->cArgs)
1275 dump_Variant( &pdp->rgvarg[index] );
1276 ++index;
1280 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1282 TRACE("%p ref=%lu\n", pty, pty->ref);
1283 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1284 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1285 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1286 TRACE("fct:%u var:%u impl:%u\n",
1287 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1288 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1289 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1290 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1291 if (TRACE_ON(ole))
1292 dump_TLBFuncDesc(pty->funclist);
1293 dump_TLBVarDesc(pty->varlist);
1294 dump_TLBImplType(pty->impltypelist);
1297 static void dump_VARDESC(const VARDESC *v)
1299 MESSAGE("memid %ld\n",v->memid);
1300 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1301 MESSAGE("oInst %ld\n",v->u.oInst);
1302 dump_ELEMDESC(&(v->elemdescVar));
1303 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1304 MESSAGE("varkind %d\n",v->varkind);
1307 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1309 /* VT_LPWSTR is largest type that */
1310 /* may appear in type description*/
1311 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1312 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1313 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1314 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1315 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1316 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1317 {{0},30},{{0},31}
1320 static void TLB_abort(void)
1322 DebugBreak();
1324 static void * TLB_Alloc(unsigned size)
1326 void * ret;
1327 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1328 /* FIXME */
1329 ERR("cannot allocate memory\n");
1331 return ret;
1334 static void TLB_Free(void * ptr)
1336 HeapFree(GetProcessHeap(), 0, ptr);
1339 /* returns the size required for a deep copy of a typedesc into a
1340 * flat buffer */
1341 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1343 SIZE_T size = 0;
1345 if (alloc_initial_space)
1346 size += sizeof(TYPEDESC);
1348 switch (tdesc->vt)
1350 case VT_PTR:
1351 case VT_SAFEARRAY:
1352 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1353 break;
1354 case VT_CARRAY:
1355 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1356 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1357 break;
1359 return size;
1362 /* deep copy a typedesc into a flat buffer */
1363 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1365 if (!dest)
1367 dest = buffer;
1368 buffer = (char *)buffer + sizeof(TYPEDESC);
1371 *dest = *src;
1373 switch (src->vt)
1375 case VT_PTR:
1376 case VT_SAFEARRAY:
1377 dest->u.lptdesc = buffer;
1378 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1379 break;
1380 case VT_CARRAY:
1381 dest->u.lpadesc = buffer;
1382 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1383 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1384 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1385 break;
1387 return buffer;
1390 /**********************************************************************
1392 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1394 /* read function */
1395 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1397 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1398 pcx->pos, count, pcx->oStart, pcx->length, where);
1400 if (where != DO_NOT_SEEK)
1402 where += pcx->oStart;
1403 if (where > pcx->length)
1405 /* FIXME */
1406 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1407 TLB_abort();
1409 pcx->pos = where;
1411 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1412 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1413 pcx->pos += count;
1414 return count;
1417 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1418 long where )
1420 DWORD ret;
1422 ret = MSFT_Read(buffer, count, pcx, where);
1423 FromLEDWords(buffer, ret);
1425 return ret;
1428 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1429 long where )
1431 DWORD ret;
1433 ret = MSFT_Read(buffer, count, pcx, where);
1434 FromLEWords(buffer, ret);
1436 return ret;
1439 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1441 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1442 memset(pGuid,0, sizeof(GUID));
1443 return;
1445 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1446 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1447 pGuid->Data2 = FromLEWord(pGuid->Data2);
1448 pGuid->Data3 = FromLEWord(pGuid->Data3);
1449 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1452 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1454 MSFT_NameIntro niName;
1456 if (offset < 0)
1458 ERR_(typelib)("bad offset %d\n", offset);
1459 return -1;
1462 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1463 pcx->pTblDir->pNametab.offset+offset);
1465 return niName.hreftype;
1468 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1470 char * name;
1471 MSFT_NameIntro niName;
1472 int lengthInChars;
1473 WCHAR* pwstring = NULL;
1474 BSTR bstrName = NULL;
1476 if (offset < 0)
1478 ERR_(typelib)("bad offset %d\n", offset);
1479 return NULL;
1481 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1482 pcx->pTblDir->pNametab.offset+offset);
1483 niName.namelen &= 0xFF; /* FIXME: correct ? */
1484 name=TLB_Alloc((niName.namelen & 0xff) +1);
1485 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1486 name[niName.namelen & 0xff]='\0';
1488 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1489 name, -1, NULL, 0);
1491 /* no invalid characters in string */
1492 if (lengthInChars)
1494 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1496 /* don't check for invalid character since this has been done previously */
1497 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1499 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1500 lengthInChars = SysStringLen(bstrName);
1501 HeapFree(GetProcessHeap(), 0, pwstring);
1504 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1505 return bstrName;
1508 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1510 char * string;
1511 INT16 length;
1512 int lengthInChars;
1513 BSTR bstr = NULL;
1515 if(offset<0) return NULL;
1516 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1517 if(length <= 0) return 0;
1518 string=TLB_Alloc(length +1);
1519 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1520 string[length]='\0';
1522 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1523 string, -1, NULL, 0);
1525 /* no invalid characters in string */
1526 if (lengthInChars)
1528 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1530 /* don't check for invalid character since this has been done previously */
1531 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1533 bstr = SysAllocStringLen(pwstring, lengthInChars);
1534 lengthInChars = SysStringLen(bstr);
1535 HeapFree(GetProcessHeap(), 0, pwstring);
1538 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1539 return bstr;
1542 * read a value and fill a VARIANT structure
1544 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1546 int size;
1548 TRACE_(typelib)("\n");
1550 if(offset <0) { /* data are packed in here */
1551 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1552 V_I4(pVar) = offset & 0x3ffffff;
1553 return;
1555 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1556 pcx->pTblDir->pCustData.offset + offset );
1557 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1558 switch (V_VT(pVar)){
1559 case VT_EMPTY: /* FIXME: is this right? */
1560 case VT_NULL: /* FIXME: is this right? */
1561 case VT_I2 : /* this should not happen */
1562 case VT_I4 :
1563 case VT_R4 :
1564 case VT_ERROR :
1565 case VT_BOOL :
1566 case VT_I1 :
1567 case VT_UI1 :
1568 case VT_UI2 :
1569 case VT_UI4 :
1570 case VT_INT :
1571 case VT_UINT :
1572 case VT_VOID : /* FIXME: is this right? */
1573 case VT_HRESULT :
1574 size=4; break;
1575 case VT_R8 :
1576 case VT_CY :
1577 case VT_DATE :
1578 case VT_I8 :
1579 case VT_UI8 :
1580 case VT_DECIMAL : /* FIXME: is this right? */
1581 case VT_FILETIME :
1582 size=8;break;
1583 /* pointer types with known behaviour */
1584 case VT_BSTR :{
1585 char * ptr;
1586 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1587 if(size < 0) {
1588 FIXME("BSTR length = %d?\n", size);
1589 } else {
1590 ptr=TLB_Alloc(size);/* allocate temp buffer */
1591 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1592 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1593 /* FIXME: do we need a AtoW conversion here? */
1594 V_UNION(pVar, bstrVal[size])=L'\0';
1595 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1596 TLB_Free(ptr);
1599 size=-4; break;
1600 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1601 case VT_DISPATCH :
1602 case VT_VARIANT :
1603 case VT_UNKNOWN :
1604 case VT_PTR :
1605 case VT_SAFEARRAY :
1606 case VT_CARRAY :
1607 case VT_USERDEFINED :
1608 case VT_LPSTR :
1609 case VT_LPWSTR :
1610 case VT_BLOB :
1611 case VT_STREAM :
1612 case VT_STORAGE :
1613 case VT_STREAMED_OBJECT :
1614 case VT_STORED_OBJECT :
1615 case VT_BLOB_OBJECT :
1616 case VT_CF :
1617 case VT_CLSID :
1618 default:
1619 size=0;
1620 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1621 V_VT(pVar));
1624 if(size>0) /* (big|small) endian correct? */
1625 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1626 return;
1629 * create a linked list with custom data
1631 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1633 MSFT_CDGuid entry;
1634 TLBCustData* pNew;
1635 int count=0;
1637 TRACE_(typelib)("\n");
1639 while(offset >=0){
1640 count++;
1641 pNew=TLB_Alloc(sizeof(TLBCustData));
1642 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1643 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1644 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1645 /* add new custom data at head of the list */
1646 pNew->next=*ppCustData;
1647 *ppCustData=pNew;
1648 offset = entry.next;
1650 return count;
1653 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1654 ITypeInfoImpl *pTI)
1656 if(type <0)
1657 pTd->vt=type & VT_TYPEMASK;
1658 else
1659 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1661 if(pTd->vt == VT_USERDEFINED)
1662 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1664 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1667 static void
1668 MSFT_DoFuncs(TLBContext* pcx,
1669 ITypeInfoImpl* pTI,
1670 int cFuncs,
1671 int cVars,
1672 int offset,
1673 TLBFuncDesc** pptfd)
1676 * member information is stored in a data structure at offset
1677 * indicated by the memoffset field of the typeinfo structure
1678 * There are several distinctive parts.
1679 * The first part starts with a field that holds the total length
1680 * of this (first) part excluding this field. Then follow the records,
1681 * for each member there is one record.
1683 * The first entry is always the length of the record (including this
1684 * length word).
1685 * The rest of the record depends on the type of the member. If there is
1686 * a field indicating the member type (function, variable, interface, etc)
1687 * I have not found it yet. At this time we depend on the information
1688 * in the type info and the usual order how things are stored.
1690 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1691 * for each member;
1693 * Third is an equal sized array with file offsets to the name entry
1694 * of each member.
1696 * The fourth and last (?) part is an array with offsets to the records
1697 * in the first part of this file segment.
1700 int infolen, nameoffset, reclength, nrattributes, i;
1701 int recoffset = offset + sizeof(INT);
1703 char recbuf[512];
1704 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1705 TLBFuncDesc *ptfd_prev = NULL;
1707 TRACE_(typelib)("\n");
1709 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1711 for ( i = 0; i < cFuncs ; i++ )
1713 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1715 /* name, eventually add to a hash table */
1716 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1717 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1719 /* nameoffset is sometimes -1 on the second half of a propget/propput
1720 * pair of functions */
1721 if ((nameoffset == -1) && (i > 0))
1722 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1723 else
1724 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1726 /* read the function information record */
1727 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1729 reclength &= 0x1ff;
1731 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1733 /* do the attributes */
1734 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1735 / sizeof(int);
1737 if ( nrattributes > 0 )
1739 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1741 if ( nrattributes > 1 )
1743 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1744 pFuncRec->OptAttr[1]) ;
1746 if ( nrattributes > 2 )
1748 if ( pFuncRec->FKCCIC & 0x2000 )
1750 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1752 else
1754 (*pptfd)->Entry = MSFT_ReadString(pcx,
1755 pFuncRec->OptAttr[2]);
1757 if( nrattributes > 5 )
1759 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1761 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1763 MSFT_CustData(pcx,
1764 pFuncRec->OptAttr[6],
1765 &(*pptfd)->pCustData);
1772 /* fill the FuncDesc Structure */
1773 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1774 offset + infolen + ( i + 1) * sizeof(INT));
1776 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1777 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1778 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1779 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1780 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1781 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1782 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1784 MSFT_GetTdesc(pcx,
1785 pFuncRec->DataType,
1786 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1787 pTI);
1789 /* do the parameters/arguments */
1790 if(pFuncRec->nrargs)
1792 int j = 0;
1793 MSFT_ParameterInfo paraminfo;
1795 (*pptfd)->funcdesc.lprgelemdescParam =
1796 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1798 (*pptfd)->pParamDesc =
1799 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1801 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1802 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1804 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1806 TYPEDESC *lpArgTypeDesc;
1807 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1809 MSFT_GetTdesc(pcx,
1810 paraminfo.DataType,
1811 &elemdesc->tdesc,
1812 pTI);
1814 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1816 /* name */
1817 if (paraminfo.oName == -1)
1818 /* this occurs for [propput] or [propget] methods, so
1819 * we should just set the name of the parameter to the
1820 * name of the method. */
1821 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1822 else
1823 (*pptfd)->pParamDesc[j].Name =
1824 MSFT_ReadName( pcx, paraminfo.oName );
1825 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1827 lpArgTypeDesc = &elemdesc->tdesc;
1829 /* resolve referenced type if any */
1830 while ( lpArgTypeDesc != NULL )
1832 switch ( lpArgTypeDesc->vt )
1834 case VT_PTR:
1835 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1836 break;
1838 case VT_CARRAY:
1839 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1840 break;
1842 case VT_USERDEFINED:
1843 MSFT_DoRefType(pcx, pTI,
1844 lpArgTypeDesc->u.hreftype);
1846 lpArgTypeDesc = NULL;
1847 break;
1849 default:
1850 lpArgTypeDesc = NULL;
1854 /* default value */
1855 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1856 (pFuncRec->FKCCIC & 0x1000) )
1858 INT* pInt = (INT *)((char *)pFuncRec +
1859 reclength -
1860 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1862 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1864 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1865 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1867 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1868 pInt[j], pcx);
1870 else
1871 elemdesc->u.paramdesc.pparamdescex = NULL;
1872 /* custom info */
1873 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1875 MSFT_CustData(pcx,
1876 pFuncRec->OptAttr[7+j],
1877 &(*pptfd)->pParamDesc[j].pCustData);
1880 /* SEEK value = jump to offset,
1881 * from there jump to the end of record,
1882 * go back by (j-1) arguments
1884 MSFT_ReadLEDWords( &paraminfo ,
1885 sizeof(MSFT_ParameterInfo), pcx,
1886 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1887 * sizeof(MSFT_ParameterInfo)));
1891 /* scode is not used: archaic win16 stuff FIXME: right? */
1892 (*pptfd)->funcdesc.cScodes = 0 ;
1893 (*pptfd)->funcdesc.lprgscode = NULL ;
1895 ptfd_prev = *pptfd;
1896 pptfd = & ((*pptfd)->next);
1897 recoffset += reclength;
1901 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1902 int cVars, int offset, TLBVarDesc ** pptvd)
1904 int infolen, nameoffset, reclength;
1905 char recbuf[256];
1906 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1907 int i;
1908 int recoffset;
1910 TRACE_(typelib)("\n");
1912 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1913 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1914 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1915 recoffset += offset+sizeof(INT);
1916 for(i=0;i<cVars;i++){
1917 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1918 /* name, eventually add to a hash table */
1919 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1920 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1921 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1922 /* read the variable information record */
1923 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1924 reclength &=0xff;
1925 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1926 /* Optional data */
1927 if(reclength >(6*sizeof(INT)) )
1928 (*pptvd)->HelpContext=pVarRec->HelpContext;
1929 if(reclength >(7*sizeof(INT)) )
1930 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1931 if(reclength >(8*sizeof(INT)) )
1932 if(reclength >(9*sizeof(INT)) )
1933 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1934 /* fill the VarDesc Structure */
1935 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1936 offset + infolen + ( i + 1) * sizeof(INT));
1937 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1938 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1939 MSFT_GetTdesc(pcx, pVarRec->DataType,
1940 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1941 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1942 if(pVarRec->VarKind == VAR_CONST ){
1943 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1944 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1945 pVarRec->OffsValue, pcx);
1946 } else
1947 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1948 pptvd=&((*pptvd)->next);
1949 recoffset += reclength;
1952 /* fill in data for a hreftype (offset). When the referenced type is contained
1953 * in the typelib, it's just an (file) offset in the type info base dir.
1954 * If comes from import, it's an offset+1 in the ImpInfo table
1955 * */
1956 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1957 int offset)
1959 int j;
1960 TLBRefType **ppRefType = &pTI->reflist;
1962 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1964 while(*ppRefType) {
1965 if((*ppRefType)->reference == offset)
1966 return;
1967 ppRefType = &(*ppRefType)->next;
1970 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1971 sizeof(**ppRefType));
1973 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1974 /* external typelib */
1975 MSFT_ImpInfo impinfo;
1976 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1978 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1980 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1981 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1982 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1983 if(pImpLib->offset==impinfo.oImpFile) break;
1984 pImpLib=pImpLib->next;
1986 if(pImpLib){
1987 (*ppRefType)->reference=offset;
1988 (*ppRefType)->pImpTLInfo = pImpLib;
1989 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1990 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1991 (*ppRefType)->index = TLB_REF_USE_GUID;
1992 } else
1993 (*ppRefType)->index = impinfo.oGuid;
1994 }else{
1995 ERR("Cannot find a reference\n");
1996 (*ppRefType)->reference=-1;
1997 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1999 }else{
2000 /* in this typelib */
2001 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2002 (*ppRefType)->reference=offset;
2003 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2007 /* process Implemented Interfaces of a com class */
2008 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2009 int offset)
2011 int i;
2012 MSFT_RefRecord refrec;
2013 TLBImplType **ppImpl = &pTI->impltypelist;
2015 TRACE_(typelib)("\n");
2017 for(i=0;i<count;i++){
2018 if(offset<0) break; /* paranoia */
2019 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2020 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2021 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2022 (*ppImpl)->hRef = refrec.reftype;
2023 (*ppImpl)->implflags=refrec.flags;
2024 (*ppImpl)->ctCustData=
2025 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2026 offset=refrec.onext;
2027 ppImpl=&((*ppImpl)->next);
2031 * process a typeinfo record
2033 static ITypeInfoImpl * MSFT_DoTypeInfo(
2034 TLBContext *pcx,
2035 int count,
2036 ITypeLibImpl * pLibInfo)
2038 MSFT_TypeInfoBase tiBase;
2039 ITypeInfoImpl *ptiRet;
2041 TRACE_(typelib)("count=%u\n", count);
2043 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2044 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2045 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2047 /* this is where we are coming from */
2048 ptiRet->pTypeLib = pLibInfo;
2049 ptiRet->index=count;
2050 /* fill in the typeattr fields */
2051 WARN("Assign constructor/destructor memid\n");
2053 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2054 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2055 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2056 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2057 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2058 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2059 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2060 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2061 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2062 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2063 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2064 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2065 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2066 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2067 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2068 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2069 MSFT_GetTdesc(pcx, tiBase.datatype1,
2070 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2072 /* FIXME: */
2073 /* IDLDESC idldescType; *//* never saw this one != zero */
2075 /* name, eventually add to a hash table */
2076 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2077 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2078 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2079 /* help info */
2080 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2081 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2082 ptiRet->dwHelpContext=tiBase.helpcontext;
2084 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2085 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2087 /* note: InfoType's Help file and HelpStringDll come from the containing
2088 * library. Further HelpString and Docstring appear to be the same thing :(
2090 /* functions */
2091 if(ptiRet->TypeAttr.cFuncs >0 )
2092 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2093 ptiRet->TypeAttr.cVars,
2094 tiBase.memoffset, & ptiRet->funclist);
2095 /* variables */
2096 if(ptiRet->TypeAttr.cVars >0 )
2097 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2098 ptiRet->TypeAttr.cVars,
2099 tiBase.memoffset, & ptiRet->varlist);
2100 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2101 switch(ptiRet->TypeAttr.typekind)
2103 case TKIND_COCLASS:
2104 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2105 tiBase.datatype1);
2106 break;
2107 case TKIND_DISPATCH:
2108 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2110 if (tiBase.datatype1 != -1)
2112 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2113 ptiRet->impltypelist->hRef = tiBase.datatype1;
2115 else
2116 { /* FIXME: This is a really bad hack to add IDispatch */
2117 const char* szStdOle = "stdole2.tlb\0";
2118 int nStdOleLen = strlen(szStdOle);
2119 TLBRefType **ppRef = &ptiRet->reflist;
2121 while(*ppRef) {
2122 if((*ppRef)->reference == -1)
2123 break;
2124 ppRef = &(*ppRef)->next;
2126 if(!*ppRef) {
2127 *ppRef = TLB_Alloc(sizeof(**ppRef));
2128 (*ppRef)->guid = IID_IDispatch;
2129 (*ppRef)->reference = -1;
2130 (*ppRef)->index = TLB_REF_USE_GUID;
2131 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2132 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2133 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2134 nStdOleLen + 1);
2136 MultiByteToWideChar(CP_ACP,
2137 MB_PRECOMPOSED,
2138 szStdOle,
2140 (*ppRef)->pImpTLInfo->name,
2141 SysStringLen((*ppRef)->pImpTLInfo->name));
2143 (*ppRef)->pImpTLInfo->lcid = 0;
2144 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2145 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2148 break;
2149 default:
2150 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2151 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2152 ptiRet->impltypelist->hRef = tiBase.datatype1;
2153 break;
2156 ptiRet->ctCustData=
2157 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2159 TRACE_(typelib)("%s guid: %s kind:%s\n",
2160 debugstr_w(ptiRet->Name),
2161 debugstr_guid(&ptiRet->TypeAttr.guid),
2162 typekind_desc[ptiRet->TypeAttr.typekind]);
2164 return ptiRet;
2167 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2168 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2169 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2170 * tradeoff here.
2172 static ITypeLibImpl *tlb_cache_first;
2173 static CRITICAL_SECTION cache_section;
2174 static CRITICAL_SECTION_DEBUG cache_section_debug =
2176 0, 0, &cache_section,
2177 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2178 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2180 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2183 /****************************************************************************
2184 * TLB_ReadTypeLib
2186 * find the type of the typelib file and map the typelib resource into
2187 * the memory
2189 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2190 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2191 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2193 ITypeLibImpl *entry;
2194 int ret = TYPE_E_CANTLOADLIBRARY;
2195 DWORD dwSignature = 0;
2196 HANDLE hFile;
2198 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2200 *ppTypeLib = NULL;
2202 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2203 EnterCriticalSection(&cache_section);
2204 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2206 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2208 TRACE("cache hit\n");
2209 *ppTypeLib = (ITypeLib2*)entry;
2210 ITypeLib_AddRef(*ppTypeLib);
2211 LeaveCriticalSection(&cache_section);
2212 return S_OK;
2215 LeaveCriticalSection(&cache_section);
2217 /* check the signature of the file */
2218 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2219 if (INVALID_HANDLE_VALUE != hFile)
2221 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2222 if (hMapping)
2224 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2225 if(pBase)
2227 /* retrieve file size */
2228 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2230 /* first try to load as *.tlb */
2231 dwSignature = FromLEDWord(*((DWORD*) pBase));
2232 if ( dwSignature == MSFT_SIGNATURE)
2234 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2236 else if ( dwSignature == SLTG_SIGNATURE)
2238 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2240 UnmapViewOfFile(pBase);
2242 CloseHandle(hMapping);
2244 CloseHandle(hFile);
2246 else
2248 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2251 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2252 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2254 /* find the typelibrary resource*/
2255 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2256 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2257 if (hinstDLL)
2259 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2260 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2261 if (hrsrc)
2263 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2264 if (hGlobal)
2266 LPVOID pBase = LockResource(hGlobal);
2267 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2269 if (pBase)
2271 /* try to load as incore resource */
2272 dwSignature = FromLEDWord(*((DWORD*) pBase));
2273 if ( dwSignature == MSFT_SIGNATURE)
2275 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2277 else if ( dwSignature == SLTG_SIGNATURE)
2279 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2281 else
2283 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2286 FreeResource( hGlobal );
2289 FreeLibrary(hinstDLL);
2293 if(*ppTypeLib) {
2294 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2296 TRACE("adding to cache\n");
2297 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2298 lstrcpyW(impl->path, pszFileName);
2299 /* We should really canonicalise the path here. */
2300 impl->index = index;
2302 /* FIXME: check if it has added already in the meantime */
2303 EnterCriticalSection(&cache_section);
2304 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2305 impl->prev = NULL;
2306 tlb_cache_first = impl;
2307 LeaveCriticalSection(&cache_section);
2308 ret = S_OK;
2309 } else
2310 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2312 return ret;
2315 /*================== ITypeLib(2) Methods ===================================*/
2317 /****************************************************************************
2318 * ITypeLib2_Constructor_MSFT
2320 * loading an MSFT typelib from an in-memory image
2322 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2324 TLBContext cx;
2325 long lPSegDir;
2326 MSFT_Header tlbHeader;
2327 MSFT_SegDir tlbSegDir;
2328 ITypeLibImpl * pTypeLibImpl;
2330 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2332 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2333 if (!pTypeLibImpl) return NULL;
2335 pTypeLibImpl->lpVtbl = &tlbvt;
2336 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2337 pTypeLibImpl->ref = 1;
2339 /* get pointer to beginning of typelib data */
2340 cx.pos = 0;
2341 cx.oStart=0;
2342 cx.mapping = pLib;
2343 cx.pLibInfo = pTypeLibImpl;
2344 cx.length = dwTLBLength;
2346 /* read header */
2347 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2348 TRACE("header:\n");
2349 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2350 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2351 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2352 return NULL;
2354 /* there is a small amount of information here until the next important
2355 * part:
2356 * the segment directory . Try to calculate the amount of data */
2357 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2359 /* now read the segment directory */
2360 TRACE("read segment directory (at %ld)\n",lPSegDir);
2361 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2362 cx.pTblDir = &tlbSegDir;
2364 /* just check two entries */
2365 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2367 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2368 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2369 return NULL;
2372 /* now fill our internal data */
2373 /* TLIBATTR fields */
2374 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2376 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2377 /* Windows seems to have zero here, is this correct? */
2378 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2379 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2380 else
2381 pTypeLibImpl->LibAttr.lcid = 0;
2383 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2384 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2385 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2386 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2388 /* name, eventually add to a hash table */
2389 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2391 /* help info */
2392 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2393 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2395 if( tlbHeader.varflags & HELPDLLFLAG)
2397 int offset;
2398 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2399 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2402 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2404 /* custom data */
2405 if(tlbHeader.CustomDataOffset >= 0)
2407 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2410 /* fill in typedescriptions */
2411 if(tlbSegDir.pTypdescTab.length > 0)
2413 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2414 INT16 td[4];
2415 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2416 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2417 for(i=0; i<cTD; )
2419 /* FIXME: add several sanity checks here */
2420 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2421 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2423 /* FIXME: check safearray */
2424 if(td[3] < 0)
2425 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2426 else
2427 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2429 else if(td[0] == VT_CARRAY)
2431 /* array descr table here */
2432 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2434 else if(td[0] == VT_USERDEFINED)
2436 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2438 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2441 /* second time around to fill the array subscript info */
2442 for(i=0;i<cTD;i++)
2444 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2445 if(tlbSegDir.pArrayDescriptions.offset>0)
2447 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2448 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2450 if(td[1]<0)
2451 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2452 else
2453 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2455 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2457 for(j = 0; j<td[2]; j++)
2459 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2460 sizeof(INT), &cx, DO_NOT_SEEK);
2461 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2462 sizeof(INT), &cx, DO_NOT_SEEK);
2465 else
2467 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2468 ERR("didn't find array description data\n");
2473 /* imported type libs */
2474 if(tlbSegDir.pImpFiles.offset>0)
2476 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2477 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2478 UINT16 size;
2480 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2482 char *name;
2483 DWORD len;
2485 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2486 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2487 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2489 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2490 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2491 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2492 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2494 size >>= 2;
2495 name = TLB_Alloc(size+1);
2496 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2497 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2498 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2499 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2500 TLB_Free(name);
2502 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2503 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2505 ppImpLib = &(*ppImpLib)->next;
2509 /* type info's */
2510 if(tlbHeader.nrtypeinfos >= 0 )
2512 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2513 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2514 int i;
2516 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2518 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2520 ppTI = &((*ppTI)->next);
2521 (pTypeLibImpl->TypeInfoCount)++;
2525 TRACE("(%p)\n", pTypeLibImpl);
2526 return (ITypeLib2*) pTypeLibImpl;
2530 static BSTR TLB_MultiByteToBSTR(char *ptr)
2532 DWORD len;
2533 WCHAR *nameW;
2534 BSTR ret;
2536 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2537 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2538 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2539 ret = SysAllocString(nameW);
2540 HeapFree(GetProcessHeap(), 0, nameW);
2541 return ret;
2544 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2546 char b[3];
2547 int i;
2548 short s;
2550 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2551 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2552 return FALSE;
2555 guid->Data4[0] = s >> 8;
2556 guid->Data4[1] = s & 0xff;
2558 b[2] = '\0';
2559 for(i = 0; i < 6; i++) {
2560 memcpy(b, str + 24 + 2 * i, 2);
2561 guid->Data4[i + 2] = strtol(b, NULL, 16);
2563 return TRUE;
2566 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2568 WORD bytelen;
2569 DWORD len;
2570 WCHAR *nameW;
2572 *pBstr = NULL;
2573 bytelen = *(WORD*)ptr;
2574 if(bytelen == 0xffff) return 2;
2575 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2576 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2577 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2578 *pBstr = SysAllocStringLen(nameW, len);
2579 HeapFree(GetProcessHeap(), 0, nameW);
2580 return bytelen + 2;
2583 static WORD SLTG_ReadStringA(char *ptr, char **str)
2585 WORD bytelen;
2587 *str = NULL;
2588 bytelen = *(WORD*)ptr;
2589 if(bytelen == 0xffff) return 2;
2590 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2591 memcpy(*str, ptr + 2, bytelen);
2592 (*str)[bytelen] = '\0';
2593 return bytelen + 2;
2596 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2598 char *ptr = pLibBlk;
2599 WORD w;
2601 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2602 FIXME("libblk magic = %04x\n", w);
2603 return 0;
2606 ptr += 6;
2607 if((w = *(WORD*)ptr) != 0xffff) {
2608 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2609 ptr += w;
2611 ptr += 2;
2613 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2615 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2617 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2618 ptr += 4;
2620 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2621 ptr += 2;
2623 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2624 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2625 else
2626 pTypeLibImpl->LibAttr.lcid = 0;
2627 ptr += 2;
2629 ptr += 4; /* skip res12 */
2631 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2632 ptr += 2;
2634 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2635 ptr += 2;
2637 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2638 ptr += 2;
2640 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2641 ptr += sizeof(GUID);
2643 return ptr - (char*)pLibBlk;
2646 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2648 BOOL done = FALSE;
2649 TYPEDESC *pTD = &pElem->tdesc;
2651 /* Handle [in/out] first */
2652 if((*pType & 0xc000) == 0xc000)
2653 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2654 else if(*pType & 0x8000)
2655 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2656 else if(*pType & 0x4000)
2657 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2658 else
2659 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2661 if(*pType & 0x2000)
2662 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2664 if(*pType & 0x80)
2665 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2667 while(!done) {
2668 if((*pType & 0xe00) == 0xe00) {
2669 pTD->vt = VT_PTR;
2670 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2671 sizeof(TYPEDESC));
2672 pTD = pTD->u.lptdesc;
2674 switch(*pType & 0x7f) {
2675 case VT_PTR:
2676 pTD->vt = VT_PTR;
2677 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2678 sizeof(TYPEDESC));
2679 pTD = pTD->u.lptdesc;
2680 break;
2682 case VT_USERDEFINED:
2683 pTD->vt = VT_USERDEFINED;
2684 pTD->u.hreftype = *(++pType) / 4;
2685 done = TRUE;
2686 break;
2688 case VT_CARRAY:
2690 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2691 array */
2693 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2695 pTD->vt = VT_CARRAY;
2696 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2697 sizeof(ARRAYDESC) +
2698 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2699 pTD->u.lpadesc->cDims = pSA->cDims;
2700 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2701 pSA->cDims * sizeof(SAFEARRAYBOUND));
2703 pTD = &pTD->u.lpadesc->tdescElem;
2704 break;
2707 case VT_SAFEARRAY:
2709 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2710 useful? */
2712 pType++;
2713 pTD->vt = VT_SAFEARRAY;
2714 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2715 sizeof(TYPEDESC));
2716 pTD = pTD->u.lptdesc;
2717 break;
2719 default:
2720 pTD->vt = *pType & 0x7f;
2721 done = TRUE;
2722 break;
2724 pType++;
2726 return pType;
2730 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2731 char *pNameTable)
2733 int ref;
2734 char *name;
2735 TLBRefType **ppRefType;
2737 if(pRef->magic != SLTG_REF_MAGIC) {
2738 FIXME("Ref magic = %x\n", pRef->magic);
2739 return;
2741 name = ( (char*)(&pRef->names) + pRef->number);
2743 ppRefType = &pTI->reflist;
2744 for(ref = 0; ref < pRef->number >> 3; ref++) {
2745 char *refname;
2746 unsigned int lib_offs, type_num;
2748 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2749 sizeof(**ppRefType));
2751 name += SLTG_ReadStringA(name, &refname);
2752 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2753 FIXME("Can't sscanf ref\n");
2754 if(lib_offs != 0xffff) {
2755 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2757 while(*import) {
2758 if((*import)->offset == lib_offs)
2759 break;
2760 import = &(*import)->next;
2762 if(!*import) {
2763 char fname[MAX_PATH+1];
2764 int len;
2766 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2767 sizeof(**import));
2768 (*import)->offset = lib_offs;
2769 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2770 &(*import)->guid);
2771 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2772 &(*import)->wVersionMajor,
2773 &(*import)->wVersionMinor,
2774 &(*import)->lcid, fname) != 4) {
2775 FIXME("can't sscanf ref %s\n",
2776 pNameTable + lib_offs + 40);
2778 len = strlen(fname);
2779 if(fname[len-1] != '#')
2780 FIXME("fname = %s\n", fname);
2781 fname[len-1] = '\0';
2782 (*import)->name = TLB_MultiByteToBSTR(fname);
2784 (*ppRefType)->pImpTLInfo = *import;
2785 } else { /* internal ref */
2786 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2788 (*ppRefType)->reference = ref;
2789 (*ppRefType)->index = type_num;
2791 HeapFree(GetProcessHeap(), 0, refname);
2792 ppRefType = &(*ppRefType)->next;
2794 if((BYTE)*name != SLTG_REF_MAGIC)
2795 FIXME("End of ref block magic = %x\n", *name);
2796 dump_TLBRefType(pTI->reflist);
2799 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2800 BOOL OneOnly)
2802 SLTG_ImplInfo *info;
2803 TLBImplType **ppImplType = &pTI->impltypelist;
2804 /* I don't really get this structure, usually it's 0x16 bytes
2805 long, but iuser.tlb contains some that are 0x18 bytes long.
2806 That's ok because we can use the next ptr to jump to the next
2807 one. But how do we know the length of the last one? The WORD
2808 at offs 0x8 might be the clue. For now I'm just assuming that
2809 the last one is the regular 0x16 bytes. */
2811 info = (SLTG_ImplInfo*)pBlk;
2812 while(1) {
2813 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2814 sizeof(**ppImplType));
2815 (*ppImplType)->hRef = info->ref;
2816 (*ppImplType)->implflags = info->impltypeflags;
2817 pTI->TypeAttr.cImplTypes++;
2818 ppImplType = &(*ppImplType)->next;
2820 if(info->next == 0xffff)
2821 break;
2822 if(OneOnly)
2823 FIXME("Interface inheriting more than one interface\n");
2824 info = (SLTG_ImplInfo*)(pBlk + info->next);
2826 info++; /* see comment at top of function */
2827 return (char*)info;
2830 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2831 char *pNameTable)
2833 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2834 SLTG_MemberHeader *pMemHeader;
2835 char *pFirstItem, *pNextItem;
2837 if(pTIHeader->href_table != 0xffffffff) {
2838 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2839 pNameTable);
2843 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2845 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2847 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2848 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2851 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2855 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2856 char *pNameTable)
2858 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2859 SLTG_MemberHeader *pMemHeader;
2860 SLTG_Function *pFunc;
2861 char *pFirstItem, *pNextItem;
2862 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2863 int num = 0;
2865 if(pTIHeader->href_table != 0xffffffff) {
2866 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2867 pNameTable);
2870 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2872 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2874 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2875 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2878 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2879 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2881 int param;
2882 WORD *pType, *pArg;
2884 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2885 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2886 FIXME("func magic = %02x\n", pFunc->magic);
2887 return NULL;
2889 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2890 sizeof(**ppFuncDesc));
2891 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2893 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2894 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2895 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2896 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2897 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2898 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2900 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2901 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2903 if(pFunc->retnextopt & 0x80)
2904 pType = &pFunc->rettype;
2905 else
2906 pType = (WORD*)(pFirstItem + pFunc->rettype);
2909 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2911 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2912 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2913 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2914 (*ppFuncDesc)->pParamDesc =
2915 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2916 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2918 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2920 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2921 char *paramName = pNameTable + *pArg;
2922 BOOL HaveOffs;
2923 /* If arg type follows then paramName points to the 2nd
2924 letter of the name, else the next WORD is an offset to
2925 the arg type and paramName points to the first letter.
2926 So let's take one char off paramName and see if we're
2927 pointing at an alpha-numeric char. However if *pArg is
2928 0xffff or 0xfffe then the param has no name, the former
2929 meaning that the next WORD is the type, the latter
2930 meaning the the next WORD is an offset to the type. */
2932 HaveOffs = FALSE;
2933 if(*pArg == 0xffff)
2934 paramName = NULL;
2935 else if(*pArg == 0xfffe) {
2936 paramName = NULL;
2937 HaveOffs = TRUE;
2939 else if(paramName[-1] && !isalnum(paramName[-1]))
2940 HaveOffs = TRUE;
2942 pArg++;
2944 if(HaveOffs) { /* the next word is an offset to type */
2945 pType = (WORD*)(pFirstItem + *pArg);
2946 SLTG_DoType(pType, pFirstItem,
2947 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2948 pArg++;
2949 } else {
2950 if(paramName)
2951 paramName--;
2952 pArg = SLTG_DoType(pArg, pFirstItem,
2953 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2956 /* Are we an optional param ? */
2957 if((*ppFuncDesc)->funcdesc.cParams - param <=
2958 (*ppFuncDesc)->funcdesc.cParamsOpt)
2959 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2961 if(paramName) {
2962 (*ppFuncDesc)->pParamDesc[param].Name =
2963 TLB_MultiByteToBSTR(paramName);
2967 ppFuncDesc = &((*ppFuncDesc)->next);
2968 if(pFunc->next == 0xffff) break;
2970 pTI->TypeAttr.cFuncs = num;
2971 if (TRACE_ON(typelib))
2972 dump_TLBFuncDesc(pTI->funclist);
2973 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2976 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2977 char *pNameTable)
2979 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2980 SLTG_MemberHeader *pMemHeader;
2981 SLTG_RecordItem *pItem;
2982 char *pFirstItem;
2983 TLBVarDesc **ppVarDesc = &pTI->varlist;
2984 int num = 0;
2985 WORD *pType;
2986 char buf[300];
2988 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2990 pFirstItem = (char*)(pMemHeader + 1);
2991 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2992 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2993 if(pItem->magic != SLTG_RECORD_MAGIC) {
2994 FIXME("record magic = %02x\n", pItem->magic);
2995 return NULL;
2997 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2998 sizeof(**ppVarDesc));
2999 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3000 (*ppVarDesc)->vardesc.memid = pItem->memid;
3001 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3002 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3004 if(pItem->typepos == 0x02)
3005 pType = &pItem->type;
3006 else if(pItem->typepos == 0x00)
3007 pType = (WORD*)(pFirstItem + pItem->type);
3008 else {
3009 FIXME("typepos = %02x\n", pItem->typepos);
3010 break;
3013 SLTG_DoType(pType, pFirstItem,
3014 &(*ppVarDesc)->vardesc.elemdescVar);
3016 /* FIXME("helpcontext, helpstring\n"); */
3018 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3020 ppVarDesc = &((*ppVarDesc)->next);
3021 if(pItem->next == 0xffff) break;
3023 pTI->TypeAttr.cVars = num;
3024 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3027 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3028 char *pNameTable)
3030 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3031 SLTG_MemberHeader *pMemHeader;
3032 SLTG_AliasItem *pItem;
3033 int i, mustbelast;
3035 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3036 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3038 mustbelast = 0;
3039 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3040 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3041 if (pItem->vt == 0xffff) {
3042 if (i<(pMemHeader->cbExtra/4-1))
3043 FIXME("Endmarker too early in process alias data!\n");
3044 break;
3046 if (mustbelast) {
3047 FIXME("Chain extends over last entry?\n");
3048 break;
3050 if (pItem->vt == VT_USERDEFINED) {
3051 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3052 /* guessing here ... */
3053 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3054 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3055 mustbelast = 1;
3056 } else {
3057 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3058 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3060 pItem++;
3062 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3065 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3066 char *pNameTable)
3068 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3069 SLTG_MemberHeader *pMemHeader;
3070 SLTG_AliasItem *pItem;
3072 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3073 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3074 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3075 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3076 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3079 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3080 char *pNameTable)
3082 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3083 SLTG_MemberHeader *pMemHeader;
3084 SLTG_EnumItem *pItem;
3085 char *pFirstItem;
3086 TLBVarDesc **ppVarDesc = &pTI->varlist;
3087 int num = 0;
3089 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3091 pFirstItem = (char*)(pMemHeader + 1);
3092 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3093 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3094 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3095 FIXME("enumitem magic = %04x\n", pItem->magic);
3096 return NULL;
3098 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3099 sizeof(**ppVarDesc));
3100 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3101 (*ppVarDesc)->vardesc.memid = pItem->memid;
3102 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3103 sizeof(VARIANT));
3104 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3105 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3106 *(INT*)(pItem->value + pFirstItem);
3107 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3108 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3109 /* FIXME("helpcontext, helpstring\n"); */
3111 ppVarDesc = &((*ppVarDesc)->next);
3112 if(pItem->next == 0xffff) break;
3114 pTI->TypeAttr.cVars = num;
3115 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3118 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3119 managable copy of it into this */
3120 typedef struct {
3121 WORD small_no;
3122 char *index_name;
3123 char *other_name;
3124 WORD res1a;
3125 WORD name_offs;
3126 WORD more_bytes;
3127 char *extra;
3128 WORD res20;
3129 DWORD helpcontext;
3130 WORD res26;
3131 GUID uuid;
3132 } SLTG_InternalOtherTypeInfo;
3134 /****************************************************************************
3135 * ITypeLib2_Constructor_SLTG
3137 * loading a SLTG typelib from an in-memory image
3139 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3141 ITypeLibImpl *pTypeLibImpl;
3142 SLTG_Header *pHeader;
3143 SLTG_BlkEntry *pBlkEntry;
3144 SLTG_Magic *pMagic;
3145 SLTG_Index *pIndex;
3146 SLTG_Pad9 *pPad9;
3147 LPVOID pBlk, pFirstBlk;
3148 SLTG_LibBlk *pLibBlk;
3149 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3150 char *pAfterOTIBlks = NULL;
3151 char *pNameTable, *ptr;
3152 int i;
3153 DWORD len, order;
3154 ITypeInfoImpl **ppTypeInfoImpl;
3156 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3158 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3159 if (!pTypeLibImpl) return NULL;
3161 pTypeLibImpl->lpVtbl = &tlbvt;
3162 pTypeLibImpl->ref = 1;
3164 pHeader = pLib;
3166 TRACE_(typelib)("header:\n");
3167 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3168 pHeader->nrOfFileBlks );
3169 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3170 FIXME("Header type magic 0x%08lx not supported.\n",
3171 pHeader->SLTG_magic);
3172 return NULL;
3175 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3176 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3178 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3179 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3181 /* Next we have a magic block */
3182 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3184 /* Let's see if we're still in sync */
3185 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3186 sizeof(SLTG_COMPOBJ_MAGIC))) {
3187 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3188 return NULL;
3190 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3191 sizeof(SLTG_DIR_MAGIC))) {
3192 FIXME("dir magic = %s\n", pMagic->dir_magic);
3193 return NULL;
3196 pIndex = (SLTG_Index*)(pMagic+1);
3198 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3200 pFirstBlk = (LPVOID)(pPad9 + 1);
3202 /* We'll set up a ptr to the main library block, which is the last one. */
3204 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3205 pBlkEntry[order].next != 0;
3206 order = pBlkEntry[order].next - 1, i++) {
3207 pBlk = (char*)pBlk + pBlkEntry[order].len;
3209 pLibBlk = pBlk;
3211 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3213 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3214 interspersed */
3216 len += 0x40;
3218 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3220 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3221 sizeof(*pOtherTypeInfoBlks) *
3222 pTypeLibImpl->TypeInfoCount);
3225 ptr = (char*)pLibBlk + len;
3227 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3228 WORD w, extra;
3229 len = 0;
3231 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3233 w = *(WORD*)(ptr + 2);
3234 if(w != 0xffff) {
3235 len += w;
3236 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3237 w+1);
3238 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3239 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3241 w = *(WORD*)(ptr + 4 + len);
3242 if(w != 0xffff) {
3243 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3244 len += w;
3245 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3246 w+1);
3247 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3248 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3250 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3251 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3252 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3253 if(extra) {
3254 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3255 extra);
3256 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3257 len += extra;
3259 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3260 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3261 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3262 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3263 len += sizeof(SLTG_OtherTypeInfo);
3264 ptr += len;
3267 pAfterOTIBlks = ptr;
3269 /* Skip this WORD and get the next DWORD */
3270 len = *(DWORD*)(pAfterOTIBlks + 2);
3272 /* Now add this to pLibBLk look at what we're pointing at and
3273 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3274 dust and we should be pointing at the beginning of the name
3275 table */
3277 pNameTable = (char*)pLibBlk + len;
3279 switch(*(WORD*)pNameTable) {
3280 case 0xffff:
3281 break;
3282 case 0x0200:
3283 pNameTable += 0x20;
3284 break;
3285 default:
3286 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3287 break;
3290 pNameTable += 0x216;
3292 pNameTable += 2;
3294 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3296 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3299 /* Hopefully we now have enough ptrs set up to actually read in
3300 some TypeInfos. It's not clear which order to do them in, so
3301 I'll just follow the links along the BlkEntry chain and read
3302 them in in the order in which they're in the file */
3304 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3306 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3307 pBlkEntry[order].next != 0;
3308 order = pBlkEntry[order].next - 1, i++) {
3310 SLTG_TypeInfoHeader *pTIHeader;
3311 SLTG_TypeInfoTail *pTITail;
3313 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3314 pOtherTypeInfoBlks[i].index_name)) {
3315 FIXME("Index strings don't match\n");
3316 return NULL;
3319 pTIHeader = pBlk;
3320 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3321 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3322 return NULL;
3324 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3325 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3326 (*ppTypeInfoImpl)->index = i;
3327 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3328 pOtherTypeInfoBlks[i].name_offs +
3329 pNameTable);
3330 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3331 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3332 sizeof(GUID));
3333 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3334 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3335 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3336 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3337 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3339 if((pTIHeader->typeflags1 & 7) != 2)
3340 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3341 if(pTIHeader->typeflags3 != 2)
3342 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3344 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3345 debugstr_w((*ppTypeInfoImpl)->Name),
3346 typekind_desc[pTIHeader->typekind],
3347 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3348 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3350 switch(pTIHeader->typekind) {
3351 case TKIND_ENUM:
3352 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3353 break;
3355 case TKIND_RECORD:
3356 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3357 break;
3359 case TKIND_INTERFACE:
3360 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3361 break;
3363 case TKIND_COCLASS:
3364 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3365 break;
3367 case TKIND_ALIAS:
3368 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3369 if (pTITail->tdescalias_vt)
3370 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3371 break;
3373 case TKIND_DISPATCH:
3374 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3375 break;
3377 default:
3378 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3379 pTITail = NULL;
3380 break;
3384 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3385 but we've already set those */
3386 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3387 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3388 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3390 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3391 X(06);
3392 X(08);
3393 X(0a);
3394 X(0c);
3395 X(0e);
3396 X(10);
3397 X(12);
3398 X(16);
3399 X(18);
3400 X(1a);
3401 X(1c);
3402 X(1e);
3403 X(24);
3404 X(26);
3405 X(2a);
3406 X(2c);
3407 X(2e);
3408 X(30);
3409 X(32);
3410 X(34);
3412 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3413 pBlk = (char*)pBlk + pBlkEntry[order].len;
3416 if(i != pTypeLibImpl->TypeInfoCount) {
3417 FIXME("Somehow processed %d TypeInfos\n", i);
3418 return NULL;
3421 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3422 return (ITypeLib2*)pTypeLibImpl;
3425 /* ITypeLib::QueryInterface
3427 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3428 ITypeLib2 * iface,
3429 REFIID riid,
3430 VOID **ppvObject)
3432 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3434 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3436 *ppvObject=NULL;
3437 if(IsEqualIID(riid, &IID_IUnknown) ||
3438 IsEqualIID(riid,&IID_ITypeLib)||
3439 IsEqualIID(riid,&IID_ITypeLib2))
3441 *ppvObject = This;
3444 if(*ppvObject)
3446 ITypeLib2_AddRef(iface);
3447 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3448 return S_OK;
3450 TRACE("-- Interface: E_NOINTERFACE\n");
3451 return E_NOINTERFACE;
3454 /* ITypeLib::AddRef
3456 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3458 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3459 ULONG ref = InterlockedIncrement(&This->ref);
3461 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3463 return ref;
3466 /* ITypeLib::Release
3468 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3470 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3471 ULONG ref = InterlockedDecrement(&This->ref);
3473 TRACE("(%p)->(%lu)\n",This, ref);
3475 if (!ref)
3477 /* remove cache entry */
3478 TRACE("removing from cache list\n");
3479 EnterCriticalSection(&cache_section);
3480 if (This->next) This->next->prev = This->prev;
3481 if (This->prev) This->prev->next = This->next;
3482 else tlb_cache_first = This->next;
3483 LeaveCriticalSection(&cache_section);
3485 /* FIXME destroy child objects */
3486 TRACE(" destroying ITypeLib(%p)\n",This);
3488 if (This->Name)
3490 SysFreeString(This->Name);
3491 This->Name = NULL;
3494 if (This->DocString)
3496 SysFreeString(This->DocString);
3497 This->DocString = NULL;
3500 if (This->HelpFile)
3502 SysFreeString(This->HelpFile);
3503 This->HelpFile = NULL;
3506 if (This->HelpStringDll)
3508 SysFreeString(This->HelpStringDll);
3509 This->HelpStringDll = NULL;
3512 if (This->pTypeInfo) /* can be NULL */
3513 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3514 HeapFree(GetProcessHeap(),0,This);
3515 return 0;
3518 return ref;
3521 /* ITypeLib::GetTypeInfoCount
3523 * Returns the number of type descriptions in the type library
3525 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3527 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3528 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3529 return This->TypeInfoCount;
3532 /* ITypeLib::GetTypeInfo
3534 * retrieves the specified type description in the library.
3536 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3537 ITypeLib2 *iface,
3538 UINT index,
3539 ITypeInfo **ppTInfo)
3541 int i;
3543 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3544 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3546 TRACE("(%p)->(index=%d)\n", This, index);
3548 if (!ppTInfo) return E_INVALIDARG;
3550 /* search element n in list */
3551 for(i=0; i < index; i++)
3553 pTypeInfo = pTypeInfo->next;
3554 if (!pTypeInfo)
3556 TRACE("-- element not found\n");
3557 return TYPE_E_ELEMENTNOTFOUND;
3561 *ppTInfo = (ITypeInfo *) pTypeInfo;
3563 ITypeInfo_AddRef(*ppTInfo);
3564 TRACE("-- found (%p)\n",*ppTInfo);
3565 return S_OK;
3569 /* ITypeLibs::GetTypeInfoType
3571 * Retrieves the type of a type description.
3573 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3574 ITypeLib2 *iface,
3575 UINT index,
3576 TYPEKIND *pTKind)
3578 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3579 int i;
3580 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3582 TRACE("(%p) index %d\n", This, index);
3584 if(!pTKind) return E_INVALIDARG;
3586 /* search element n in list */
3587 for(i=0; i < index; i++)
3589 if(!pTInfo)
3591 TRACE("-- element not found\n");
3592 return TYPE_E_ELEMENTNOTFOUND;
3594 pTInfo = pTInfo->next;
3597 *pTKind = pTInfo->TypeAttr.typekind;
3598 TRACE("-- found Type (%d)\n", *pTKind);
3599 return S_OK;
3602 /* ITypeLib::GetTypeInfoOfGuid
3604 * Retrieves the type description that corresponds to the specified GUID.
3607 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3608 ITypeLib2 *iface,
3609 REFGUID guid,
3610 ITypeInfo **ppTInfo)
3612 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3613 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3615 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3617 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3619 /* search linked list for guid */
3620 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3622 pTypeInfo = pTypeInfo->next;
3624 if (!pTypeInfo)
3626 /* end of list reached */
3627 TRACE("-- element not found\n");
3628 return TYPE_E_ELEMENTNOTFOUND;
3632 TRACE("-- found (%p, %s)\n",
3633 pTypeInfo,
3634 debugstr_w(pTypeInfo->Name));
3636 *ppTInfo = (ITypeInfo*)pTypeInfo;
3637 ITypeInfo_AddRef(*ppTInfo);
3638 return S_OK;
3641 /* ITypeLib::GetLibAttr
3643 * Retrieves the structure that contains the library's attributes.
3646 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3647 ITypeLib2 *iface,
3648 LPTLIBATTR *ppTLibAttr)
3650 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3651 TRACE("(%p)\n",This);
3652 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3653 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3654 return S_OK;
3657 /* ITypeLib::GetTypeComp
3659 * Enables a client compiler to bind to a library's types, variables,
3660 * constants, and global functions.
3663 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3664 ITypeLib2 *iface,
3665 ITypeComp **ppTComp)
3667 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3669 TRACE("(%p)->(%p)\n",This,ppTComp);
3670 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3671 ITypeComp_AddRef(*ppTComp);
3673 return S_OK;
3676 /* ITypeLib::GetDocumentation
3678 * Retrieves the library's documentation string, the complete Help file name
3679 * and path, and the context identifier for the library Help topic in the Help
3680 * file.
3682 * On a successful return all non-null BSTR pointers will have been set,
3683 * possibly to NULL.
3685 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3686 ITypeLib2 *iface,
3687 INT index,
3688 BSTR *pBstrName,
3689 BSTR *pBstrDocString,
3690 DWORD *pdwHelpContext,
3691 BSTR *pBstrHelpFile)
3693 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3695 HRESULT result = E_INVALIDARG;
3697 ITypeInfo *pTInfo;
3700 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3701 This, index,
3702 pBstrName, pBstrDocString,
3703 pdwHelpContext, pBstrHelpFile);
3705 if(index<0)
3707 /* documentation for the typelib */
3708 if(pBstrName)
3710 if (This->Name)
3712 if(!(*pBstrName = SysAllocString(This->Name)))
3713 goto memerr1;
3715 else
3716 *pBstrName = NULL;
3718 if(pBstrDocString)
3720 if (This->DocString)
3722 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3723 goto memerr2;
3725 else if (This->Name)
3727 if(!(*pBstrDocString = SysAllocString(This->Name)))
3728 goto memerr2;
3730 else
3731 *pBstrDocString = NULL;
3733 if(pdwHelpContext)
3735 *pdwHelpContext = This->dwHelpContext;
3737 if(pBstrHelpFile)
3739 if (This->HelpFile)
3741 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3742 goto memerr3;
3744 else
3745 *pBstrHelpFile = NULL;
3748 result = S_OK;
3750 else
3752 /* for a typeinfo */
3753 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3755 if(SUCCEEDED(result))
3757 result = ITypeInfo_GetDocumentation(pTInfo,
3758 MEMBERID_NIL,
3759 pBstrName,
3760 pBstrDocString,
3761 pdwHelpContext, pBstrHelpFile);
3763 ITypeInfo_Release(pTInfo);
3766 return result;
3767 memerr3:
3768 if (pBstrDocString) SysFreeString (*pBstrDocString);
3769 memerr2:
3770 if (pBstrName) SysFreeString (*pBstrName);
3771 memerr1:
3772 return STG_E_INSUFFICIENTMEMORY;
3775 /* ITypeLib::IsName
3777 * Indicates whether a passed-in string contains the name of a type or member
3778 * described in the library.
3781 static HRESULT WINAPI ITypeLib2_fnIsName(
3782 ITypeLib2 *iface,
3783 LPOLESTR szNameBuf,
3784 ULONG lHashVal,
3785 BOOL *pfName)
3787 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3788 ITypeInfoImpl *pTInfo;
3789 TLBFuncDesc *pFInfo;
3790 TLBVarDesc *pVInfo;
3791 int i;
3792 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3794 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3795 pfName);
3797 *pfName=TRUE;
3798 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3799 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3800 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3801 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3802 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3803 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3804 goto ITypeLib2_fnIsName_exit;
3806 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3807 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3810 *pfName=FALSE;
3812 ITypeLib2_fnIsName_exit:
3813 TRACE("(%p)slow! search for %s: %s found!\n", This,
3814 debugstr_w(szNameBuf), *pfName?"NOT":"");
3816 return S_OK;
3819 /* ITypeLib::FindName
3821 * Finds occurrences of a type description in a type library. This may be used
3822 * to quickly verify that a name exists in a type library.
3825 static HRESULT WINAPI ITypeLib2_fnFindName(
3826 ITypeLib2 *iface,
3827 LPOLESTR szNameBuf,
3828 ULONG lHashVal,
3829 ITypeInfo **ppTInfo,
3830 MEMBERID *rgMemId,
3831 UINT16 *pcFound)
3833 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3834 ITypeInfoImpl *pTInfo;
3835 TLBFuncDesc *pFInfo;
3836 TLBVarDesc *pVInfo;
3837 int i,j = 0;
3838 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3840 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3841 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3842 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3843 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3844 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3845 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3846 goto ITypeLib2_fnFindName_exit;
3849 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3850 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3851 continue;
3852 ITypeLib2_fnFindName_exit:
3853 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3854 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3855 j++;
3857 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3858 This, *pcFound, debugstr_w(szNameBuf), j);
3860 *pcFound=j;
3862 return S_OK;
3865 /* ITypeLib::ReleaseTLibAttr
3867 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3870 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3871 ITypeLib2 *iface,
3872 TLIBATTR *pTLibAttr)
3874 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3875 TRACE("freeing (%p)\n",This);
3876 HeapFree(GetProcessHeap(),0,pTLibAttr);
3880 /* ITypeLib2::GetCustData
3882 * gets the custom data
3884 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3885 ITypeLib2 * iface,
3886 REFGUID guid,
3887 VARIANT *pVarVal)
3889 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3890 TLBCustData *pCData;
3892 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3894 if( IsEqualIID(guid, &pCData->guid)) break;
3897 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3899 if(pCData)
3901 VariantInit( pVarVal);
3902 VariantCopy( pVarVal, &pCData->data);
3903 return S_OK;
3905 return E_INVALIDARG; /* FIXME: correct? */
3908 /* ITypeLib2::GetLibStatistics
3910 * Returns statistics about a type library that are required for efficient
3911 * sizing of hash tables.
3914 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3915 ITypeLib2 * iface,
3916 ULONG *pcUniqueNames,
3917 ULONG *pcchUniqueNames)
3919 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3921 FIXME("(%p): stub!\n", This);
3923 if(pcUniqueNames) *pcUniqueNames=1;
3924 if(pcchUniqueNames) *pcchUniqueNames=1;
3925 return S_OK;
3928 /* ITypeLib2::GetDocumentation2
3930 * Retrieves the library's documentation string, the complete Help file name
3931 * and path, the localization context to use, and the context ID for the
3932 * library Help topic in the Help file.
3935 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3936 ITypeLib2 * iface,
3937 INT index,
3938 LCID lcid,
3939 BSTR *pbstrHelpString,
3940 DWORD *pdwHelpStringContext,
3941 BSTR *pbstrHelpStringDll)
3943 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3944 HRESULT result;
3945 ITypeInfo *pTInfo;
3947 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3949 /* the help string should be obtained from the helpstringdll,
3950 * using the _DLLGetDocumentation function, based on the supplied
3951 * lcid. Nice to do sometime...
3953 if(index<0)
3955 /* documentation for the typelib */
3956 if(pbstrHelpString)
3957 *pbstrHelpString=SysAllocString(This->DocString);
3958 if(pdwHelpStringContext)
3959 *pdwHelpStringContext=This->dwHelpContext;
3960 if(pbstrHelpStringDll)
3961 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3963 result = S_OK;
3965 else
3967 /* for a typeinfo */
3968 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3970 if(SUCCEEDED(result))
3972 ITypeInfo2 * pTInfo2;
3973 result = ITypeInfo_QueryInterface(pTInfo,
3974 &IID_ITypeInfo2,
3975 (LPVOID*) &pTInfo2);
3977 if(SUCCEEDED(result))
3979 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3980 MEMBERID_NIL,
3981 lcid,
3982 pbstrHelpString,
3983 pdwHelpStringContext,
3984 pbstrHelpStringDll);
3986 ITypeInfo2_Release(pTInfo2);
3989 ITypeInfo_Release(pTInfo);
3992 return result;
3995 /* ITypeLib2::GetAllCustData
3997 * Gets all custom data items for the library.
4000 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4001 ITypeLib2 * iface,
4002 CUSTDATA *pCustData)
4004 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4005 TLBCustData *pCData;
4006 int i;
4007 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4008 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4009 if(pCustData->prgCustData ){
4010 pCustData->cCustData=This->ctCustData;
4011 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4012 pCustData->prgCustData[i].guid=pCData->guid;
4013 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4015 }else{
4016 ERR(" OUT OF MEMORY!\n");
4017 return E_OUTOFMEMORY;
4019 return S_OK;
4022 static const ITypeLib2Vtbl tlbvt = {
4023 ITypeLib2_fnQueryInterface,
4024 ITypeLib2_fnAddRef,
4025 ITypeLib2_fnRelease,
4026 ITypeLib2_fnGetTypeInfoCount,
4027 ITypeLib2_fnGetTypeInfo,
4028 ITypeLib2_fnGetTypeInfoType,
4029 ITypeLib2_fnGetTypeInfoOfGuid,
4030 ITypeLib2_fnGetLibAttr,
4031 ITypeLib2_fnGetTypeComp,
4032 ITypeLib2_fnGetDocumentation,
4033 ITypeLib2_fnIsName,
4034 ITypeLib2_fnFindName,
4035 ITypeLib2_fnReleaseTLibAttr,
4037 ITypeLib2_fnGetCustData,
4038 ITypeLib2_fnGetLibStatistics,
4039 ITypeLib2_fnGetDocumentation2,
4040 ITypeLib2_fnGetAllCustData
4044 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4046 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4048 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4051 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4053 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4055 return ITypeLib2_AddRef((ITypeLib2 *)This);
4058 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4060 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4062 return ITypeLib2_Release((ITypeLib2 *)This);
4065 static HRESULT WINAPI ITypeLibComp_fnBind(
4066 ITypeComp * iface,
4067 OLECHAR * szName,
4068 ULONG lHash,
4069 WORD wFlags,
4070 ITypeInfo ** ppTInfo,
4071 DESCKIND * pDescKind,
4072 BINDPTR * pBindPtr)
4074 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4075 ITypeInfoImpl *pTypeInfo;
4077 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4079 *pDescKind = DESCKIND_NONE;
4080 pBindPtr->lptcomp = NULL;
4081 *ppTInfo = NULL;
4083 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4085 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4087 /* FIXME: check wFlags here? */
4088 /* FIXME: we should use a hash table to look this info up using lHash
4089 * instead of an O(n) search */
4090 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4091 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4093 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4095 *pDescKind = DESCKIND_TYPECOMP;
4096 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4097 ITypeComp_AddRef(pBindPtr->lptcomp);
4098 TRACE("module or enum: %s\n", debugstr_w(szName));
4099 return S_OK;
4103 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4104 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4106 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4107 HRESULT hr;
4109 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4110 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4112 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4113 return S_OK;
4117 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4118 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4120 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4121 HRESULT hr;
4122 ITypeInfo *subtypeinfo;
4123 BINDPTR subbindptr;
4124 DESCKIND subdesckind;
4126 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4127 &subtypeinfo, &subdesckind, &subbindptr);
4128 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4130 TYPEDESC tdesc_appobject =
4133 (TYPEDESC *)pTypeInfo->hreftype
4135 VT_USERDEFINED
4137 const VARDESC vardesc_appobject =
4139 -2, /* memid */
4140 NULL, /* lpstrSchema */
4142 0 /* oInst */
4145 /* ELEMDESC */
4147 /* TYPEDESC */
4149 &tdesc_appobject
4151 VT_PTR
4154 0, /* wVarFlags */
4155 VAR_STATIC /* varkind */
4158 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4160 /* cleanup things filled in by Bind call so we can put our
4161 * application object data in there instead */
4162 switch (subdesckind)
4164 case DESCKIND_FUNCDESC:
4165 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4166 break;
4167 case DESCKIND_VARDESC:
4168 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4169 break;
4170 default:
4171 break;
4173 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4175 if (pTypeInfo->hreftype == -1)
4176 FIXME("no hreftype for interface %p\n", pTypeInfo);
4178 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4179 if (FAILED(hr))
4180 return hr;
4182 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4183 *ppTInfo = (ITypeInfo *)pTypeInfo;
4184 ITypeInfo_AddRef(*ppTInfo);
4185 return S_OK;
4190 TRACE("name not found %s\n", debugstr_w(szName));
4191 return S_OK;
4194 static HRESULT WINAPI ITypeLibComp_fnBindType(
4195 ITypeComp * iface,
4196 OLECHAR * szName,
4197 ULONG lHash,
4198 ITypeInfo ** ppTInfo,
4199 ITypeComp ** ppTComp)
4201 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4202 return E_NOTIMPL;
4205 static const ITypeCompVtbl tlbtcvt =
4208 ITypeLibComp_fnQueryInterface,
4209 ITypeLibComp_fnAddRef,
4210 ITypeLibComp_fnRelease,
4212 ITypeLibComp_fnBind,
4213 ITypeLibComp_fnBindType
4216 /*================== ITypeInfo(2) Methods ===================================*/
4217 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4219 ITypeInfoImpl * pTypeInfoImpl;
4221 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4222 if (pTypeInfoImpl)
4224 pTypeInfoImpl->lpVtbl = &tinfvt;
4225 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4226 pTypeInfoImpl->ref=1;
4227 pTypeInfoImpl->hreftype = -1;
4229 TRACE("(%p)\n", pTypeInfoImpl);
4230 return (ITypeInfo2*) pTypeInfoImpl;
4233 /* ITypeInfo::QueryInterface
4235 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4236 ITypeInfo2 *iface,
4237 REFIID riid,
4238 VOID **ppvObject)
4240 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4242 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4244 *ppvObject=NULL;
4245 if(IsEqualIID(riid, &IID_IUnknown) ||
4246 IsEqualIID(riid,&IID_ITypeInfo)||
4247 IsEqualIID(riid,&IID_ITypeInfo2))
4248 *ppvObject = This;
4250 if(*ppvObject){
4251 ITypeInfo_AddRef(iface);
4252 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4253 return S_OK;
4255 TRACE("-- Interface: E_NOINTERFACE\n");
4256 return E_NOINTERFACE;
4259 /* ITypeInfo::AddRef
4261 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4263 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4264 ULONG ref = InterlockedIncrement(&This->ref);
4266 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4268 TRACE("(%p)->ref is %lu\n",This, ref);
4269 return ref;
4272 /* ITypeInfo::Release
4274 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4276 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4277 ULONG ref = InterlockedDecrement(&This->ref);
4279 TRACE("(%p)->(%lu)\n",This, ref);
4281 if (ref) {
4282 /* We don't release ITypeLib when ref=0 because
4283 it means that function is called by ITypeLib2_Release */
4284 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4285 } else {
4286 FIXME("destroy child objects\n");
4288 TRACE("destroying ITypeInfo(%p)\n",This);
4289 if (This->Name)
4291 SysFreeString(This->Name);
4292 This->Name = 0;
4295 if (This->DocString)
4297 SysFreeString(This->DocString);
4298 This->DocString = 0;
4301 if (This->DllName)
4303 SysFreeString(This->DllName);
4304 This->DllName = 0;
4307 if (This->next)
4309 ITypeInfo_Release((ITypeInfo*)This->next);
4312 HeapFree(GetProcessHeap(),0,This);
4313 return 0;
4315 return ref;
4318 /* ITypeInfo::GetTypeAttr
4320 * Retrieves a TYPEATTR structure that contains the attributes of the type
4321 * description.
4324 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4325 LPTYPEATTR *ppTypeAttr)
4327 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4328 SIZE_T size;
4330 TRACE("(%p)\n",This);
4332 size = sizeof(**ppTypeAttr);
4333 if (This->TypeAttr.typekind == TKIND_ALIAS)
4334 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4336 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4337 if (!*ppTypeAttr)
4338 return E_OUTOFMEMORY;
4340 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4342 if (This->TypeAttr.typekind == TKIND_ALIAS)
4343 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4344 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4346 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4347 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4348 funcs */
4349 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4350 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4352 return S_OK;
4355 /* ITypeInfo::GetTypeComp
4357 * Retrieves the ITypeComp interface for the type description, which enables a
4358 * client compiler to bind to the type description's members.
4361 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4362 ITypeComp * *ppTComp)
4364 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4366 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4368 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4369 ITypeComp_AddRef(*ppTComp);
4370 return S_OK;
4373 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4375 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4376 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4377 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4378 return size;
4381 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4383 memcpy(dest, src, sizeof(ELEMDESC));
4384 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4385 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4387 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4388 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4389 *buffer += sizeof(PARAMDESCEX);
4390 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4391 VariantInit(&pparamdescex_dest->varDefaultValue);
4392 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4393 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4395 else
4396 dest->u.paramdesc.pparamdescex = NULL;
4397 return S_OK;
4400 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4402 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4403 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4406 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4408 FUNCDESC *dest;
4409 char *buffer;
4410 SIZE_T size = sizeof(*src);
4411 SHORT i;
4412 HRESULT hr;
4414 size += sizeof(*src->lprgscode) * src->cScodes;
4415 size += TLB_SizeElemDesc(&src->elemdescFunc);
4416 for (i = 0; i < src->cParams; i++)
4418 size += sizeof(ELEMDESC);
4419 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4422 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4423 if (!dest) return E_OUTOFMEMORY;
4425 memcpy(dest, src, sizeof(FUNCDESC));
4426 buffer = (char *)(dest + 1);
4428 dest->lprgscode = (SCODE *)buffer;
4429 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4430 buffer += sizeof(*src->lprgscode) * src->cScodes;
4432 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4433 if (FAILED(hr))
4435 SysFreeString((BSTR)dest);
4436 return hr;
4439 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4440 buffer += sizeof(ELEMDESC) * src->cParams;
4441 for (i = 0; i < src->cParams; i++)
4443 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4444 if (FAILED(hr))
4445 break;
4447 if (FAILED(hr))
4449 /* undo the above actions */
4450 for (i = i - 1; i >= 0; i--)
4451 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4452 TLB_FreeElemDesc(&dest->elemdescFunc);
4453 SysFreeString((BSTR)dest);
4454 return hr;
4457 /* special treatment for dispinterfaces: this makes functions appear
4458 * to return their [retval] value when it is really returning an
4459 * HRESULT */
4460 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4462 if (dest->cParams &&
4463 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4465 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4466 if (elemdesc->tdesc.vt != VT_PTR)
4468 ERR("elemdesc should have started with VT_PTR instead of:\n");
4469 if (ERR_ON(ole))
4470 dump_ELEMDESC(elemdesc);
4471 return E_UNEXPECTED;
4474 /* copy last parameter to the return value. we are using a flat
4475 * buffer so there is no danger of leaking memory in
4476 * elemdescFunc */
4477 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4479 /* remove the last parameter */
4480 dest->cParams--;
4482 else
4483 /* otherwise this function is made to appear to have no return
4484 * value */
4485 dest->elemdescFunc.tdesc.vt = VT_VOID;
4489 *dest_ptr = dest;
4490 return S_OK;
4493 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4495 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4496 const TLBFuncDesc *pFDesc;
4497 int i;
4499 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4502 if (pFDesc)
4504 *ppFuncDesc = &pFDesc->funcdesc;
4505 return S_OK;
4508 return E_INVALIDARG;
4511 /* ITypeInfo::GetFuncDesc
4513 * Retrieves the FUNCDESC structure that contains information about a
4514 * specified function.
4517 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4518 LPFUNCDESC *ppFuncDesc)
4520 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4521 const FUNCDESC *internal_funcdesc;
4522 HRESULT hr;
4524 TRACE("(%p) index %d\n", This, index);
4526 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4527 if (FAILED(hr))
4528 return hr;
4530 return TLB_AllocAndInitFuncDesc(
4531 internal_funcdesc,
4532 ppFuncDesc,
4533 This->TypeAttr.typekind == TKIND_DISPATCH);
4536 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4538 VARDESC *dest;
4539 char *buffer;
4540 SIZE_T size = sizeof(*src);
4541 HRESULT hr;
4543 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4544 if (src->varkind == VAR_CONST)
4545 size += sizeof(VARIANT);
4546 size += TLB_SizeElemDesc(&src->elemdescVar);
4548 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4549 if (!dest) return E_OUTOFMEMORY;
4551 *dest = *src;
4552 buffer = (char *)(dest + 1);
4553 if (src->lpstrSchema)
4555 int len;
4556 dest->lpstrSchema = (LPOLESTR)buffer;
4557 len = strlenW(src->lpstrSchema);
4558 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4559 buffer += (len + 1) * sizeof(WCHAR);
4562 if (src->varkind == VAR_CONST)
4564 HRESULT hr;
4566 dest->u.lpvarValue = (VARIANT *)buffer;
4567 *dest->u.lpvarValue = *src->u.lpvarValue;
4568 buffer += sizeof(VARIANT);
4569 VariantInit(dest->u.lpvarValue);
4570 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4571 if (FAILED(hr))
4573 SysFreeString((BSTR)dest_ptr);
4574 return hr;
4577 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4578 if (FAILED(hr))
4580 if (src->varkind == VAR_CONST)
4581 VariantClear(dest->u.lpvarValue);
4582 SysFreeString((BSTR)dest);
4583 return hr;
4585 *dest_ptr = dest;
4586 return S_OK;
4589 /* ITypeInfo::GetVarDesc
4591 * Retrieves a VARDESC structure that describes the specified variable.
4594 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4595 LPVARDESC *ppVarDesc)
4597 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4598 int i;
4599 const TLBVarDesc *pVDesc;
4601 TRACE("(%p) index %d\n", This, index);
4603 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4606 if (pVDesc)
4607 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4609 return E_INVALIDARG;
4612 /* ITypeInfo_GetNames
4614 * Retrieves the variable with the specified member ID (or the name of the
4615 * property or method and its parameters) that correspond to the specified
4616 * function ID.
4618 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4619 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4621 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4622 TLBFuncDesc * pFDesc;
4623 TLBVarDesc * pVDesc;
4624 int i;
4625 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4626 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4627 if(pFDesc)
4629 /* function found, now return function and parameter names */
4630 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4632 if(!i)
4633 *rgBstrNames=SysAllocString(pFDesc->Name);
4634 else
4635 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4637 *pcNames=i;
4639 else
4641 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4642 if(pVDesc)
4644 *rgBstrNames=SysAllocString(pVDesc->Name);
4645 *pcNames=1;
4647 else
4649 if(This->TypeAttr.cImplTypes &&
4650 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4651 /* recursive search */
4652 ITypeInfo *pTInfo;
4653 HRESULT result;
4654 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4655 &pTInfo);
4656 if(SUCCEEDED(result))
4658 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4659 ITypeInfo_Release(pTInfo);
4660 return result;
4662 WARN("Could not search inherited interface!\n");
4664 else
4666 WARN("no names found\n");
4668 *pcNames=0;
4669 return TYPE_E_ELEMENTNOTFOUND;
4672 return S_OK;
4676 /* ITypeInfo::GetRefTypeOfImplType
4678 * If a type description describes a COM class, it retrieves the type
4679 * description of the implemented interface types. For an interface,
4680 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4681 * if any exist.
4684 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4685 ITypeInfo2 *iface,
4686 UINT index,
4687 HREFTYPE *pRefType)
4689 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4690 int i;
4691 HRESULT hr = S_OK;
4692 TLBImplType *pImpl = This->impltypelist;
4694 TRACE("(%p) index %d\n", This, index);
4695 if (TRACE_ON(ole)) dump_TypeInfo(This);
4697 if(index==(UINT)-1)
4699 /* only valid on dual interfaces;
4700 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4702 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4704 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4705 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4707 *pRefType = -1;
4709 else
4711 hr = TYPE_E_ELEMENTNOTFOUND;
4714 else
4716 /* get element n from linked list */
4717 for(i=0; pImpl && i<index; i++)
4719 pImpl = pImpl->next;
4722 if (pImpl)
4723 *pRefType = pImpl->hRef;
4724 else
4725 hr = TYPE_E_ELEMENTNOTFOUND;
4728 if(TRACE_ON(ole))
4730 if(SUCCEEDED(hr))
4731 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4732 else
4733 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4736 return hr;
4739 /* ITypeInfo::GetImplTypeFlags
4741 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4742 * or base interface in a type description.
4744 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4745 UINT index, INT *pImplTypeFlags)
4747 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4748 int i;
4749 TLBImplType *pImpl;
4751 TRACE("(%p) index %d\n", This, index);
4752 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4753 i++, pImpl=pImpl->next)
4755 if(i==index && pImpl){
4756 *pImplTypeFlags=pImpl->implflags;
4757 return S_OK;
4759 *pImplTypeFlags=0;
4760 return TYPE_E_ELEMENTNOTFOUND;
4763 /* GetIDsOfNames
4764 * Maps between member names and member IDs, and parameter names and
4765 * parameter IDs.
4767 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4768 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4770 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4771 TLBFuncDesc * pFDesc;
4772 TLBVarDesc * pVDesc;
4773 HRESULT ret=S_OK;
4775 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4776 cNames);
4777 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4778 int i, j;
4779 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4780 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4781 for(i=1; i < cNames; i++){
4782 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4783 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4784 break;
4785 if( j<pFDesc->funcdesc.cParams)
4786 pMemId[i]=j;
4787 else
4788 ret=DISP_E_UNKNOWNNAME;
4790 return ret;
4793 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4794 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4795 if(cNames) *pMemId=pVDesc->vardesc.memid;
4796 return ret;
4799 /* not found, see if this is and interface with an inheritance */
4800 if(This->TypeAttr.cImplTypes &&
4801 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4802 /* recursive search */
4803 ITypeInfo *pTInfo;
4804 ret=ITypeInfo_GetRefTypeInfo(iface,
4805 This->impltypelist->hRef, &pTInfo);
4806 if(SUCCEEDED(ret)){
4807 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4808 ITypeInfo_Release(pTInfo);
4809 return ret;
4811 WARN("Could not search inherited interface!\n");
4812 } else
4813 WARN("no names found\n");
4814 return DISP_E_UNKNOWNNAME;
4817 /* ITypeInfo::Invoke
4819 * Invokes a method, or accesses a property of an object, that implements the
4820 * interface described by the type description.
4822 DWORD
4823 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4824 DWORD res;
4826 if (TRACE_ON(ole)) {
4827 int i;
4828 TRACE("Calling %p(",func);
4829 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4830 TRACE(")\n");
4833 switch (callconv) {
4834 case CC_STDCALL:
4836 switch (nrargs) {
4837 case 0:
4838 res = func();
4839 break;
4840 case 1:
4841 res = func(args[0]);
4842 break;
4843 case 2:
4844 res = func(args[0],args[1]);
4845 break;
4846 case 3:
4847 res = func(args[0],args[1],args[2]);
4848 break;
4849 case 4:
4850 res = func(args[0],args[1],args[2],args[3]);
4851 break;
4852 case 5:
4853 res = func(args[0],args[1],args[2],args[3],args[4]);
4854 break;
4855 case 6:
4856 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4857 break;
4858 case 7:
4859 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4860 break;
4861 case 8:
4862 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4863 break;
4864 case 9:
4865 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4866 break;
4867 case 10:
4868 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4869 break;
4870 case 11:
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]);
4872 break;
4873 case 12:
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]);
4875 break;
4876 case 13:
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]);
4878 break;
4879 case 14:
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]);
4881 break;
4882 default:
4883 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4884 res = -1;
4885 break;
4887 break;
4888 default:
4889 FIXME("unsupported calling convention %d\n",callconv);
4890 res = -1;
4891 break;
4893 TRACE("returns %08lx\n",res);
4894 return res;
4897 extern int _argsize(DWORD vt);
4899 /****************************************************************************
4900 * Helper functions for Dispcall / Invoke, which copies one variant
4901 * with target type onto the argument stack.
4903 static HRESULT
4904 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4905 DWORD *argpos, VARIANT *arg, VARTYPE vt
4907 UINT arglen = _argsize(vt)*sizeof(DWORD);
4908 VARIANT va;
4910 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4911 memcpy(argpos,&arg,sizeof(void*));
4912 return S_OK;
4915 if (V_VT(arg) == vt) {
4916 memcpy(argpos, &V_I4(arg), arglen);
4917 return S_OK;
4920 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4921 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4922 return S_OK;
4925 if (vt == VT_VARIANT) {
4926 memcpy(argpos, arg, arglen);
4927 return S_OK;
4929 /* Deref BYREF vars if there is need */
4930 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4931 memcpy(argpos,(void*)V_I4(arg), arglen);
4932 return S_OK;
4934 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4935 /* in this context, if the type lib specifies IUnknown*, giving an
4936 IDispatch* is correct; so, don't invoke VariantChangeType */
4937 memcpy(argpos,&V_I4(arg), arglen);
4938 return S_OK;
4940 if ((vt == VT_PTR) && tdesc)
4941 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4943 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4944 ITypeInfo *tinfo2 = NULL;
4945 TYPEATTR *tattr = NULL;
4946 HRESULT hres;
4948 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4949 if (hres) {
4950 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4951 "while coercing from vt 0x%x. Copying 4 byte.\n",
4952 tdesc->u.hreftype,V_VT(arg));
4953 memcpy(argpos, &V_I4(arg), 4);
4954 return S_OK;
4956 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4957 if( hres )
4959 ERR("GetTypeAttr failed\n");
4960 ITypeInfo_Release(tinfo2);
4961 return hres;
4963 switch (tattr->typekind) {
4964 case TKIND_ENUM:
4965 switch ( V_VT( arg ) ) {
4966 case VT_I2:
4967 *argpos = V_I2(arg);
4968 hres = S_OK;
4969 break;
4970 case VT_I4:
4971 memcpy(argpos, &V_I4(arg), 4);
4972 hres = S_OK;
4973 break;
4974 case VT_BYREF|VT_I4:
4975 memcpy(argpos, V_I4REF(arg), 4);
4976 hres = S_OK;
4977 break;
4978 default:
4979 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4980 hres = E_FAIL;
4981 break;
4983 break;
4985 case TKIND_ALIAS:
4986 tdesc = &(tattr->tdescAlias);
4987 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4988 break;
4990 case TKIND_INTERFACE:
4991 if (V_VT(arg) == VT_DISPATCH) {
4992 IDispatch *disp;
4993 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4994 memcpy(argpos, &V_DISPATCH(arg), 4);
4995 hres = S_OK;
4996 break;
4998 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4999 &IID_IDispatch,(LPVOID*)&disp);
5000 if (SUCCEEDED(hres)) {
5001 memcpy(argpos,&disp,4);
5002 IUnknown_Release(V_DISPATCH(arg));
5003 hres = S_OK;
5004 break;
5006 FIXME("Failed to query IDispatch interface from %s while "
5007 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
5008 hres = E_FAIL;
5009 break;
5011 if (V_VT(arg) == VT_UNKNOWN) {
5012 memcpy(argpos, &V_UNKNOWN(arg), 4);
5013 hres = S_OK;
5014 break;
5016 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
5017 V_VT(arg),debugstr_guid(&(tattr->guid)));
5018 hres = E_FAIL;
5019 break;
5021 case TKIND_DISPATCH:
5022 if (V_VT(arg) == VT_DISPATCH) {
5023 memcpy(argpos, &V_DISPATCH(arg), 4);
5024 hres = S_OK;
5026 else {
5027 hres = E_FAIL;
5028 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
5030 break;
5031 case TKIND_RECORD:
5032 FIXME("TKIND_RECORD unhandled.\n");
5033 hres = E_FAIL;
5034 break;
5035 default:
5036 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5037 hres = E_FAIL;
5038 break;
5040 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5041 ITypeInfo_Release(tinfo2);
5042 return hres;
5045 VariantInit(&va);
5046 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
5047 memcpy(argpos,&V_I4(&va), arglen);
5048 FIXME("Should not use VariantChangeType here."
5049 " (conversion from 0x%x -> 0x%x) %08lx\n",
5050 V_VT(arg), vt, *argpos
5052 return S_OK;
5054 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
5055 return E_FAIL;
5058 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5060 HRESULT hr = S_OK;
5061 ITypeInfo *tinfo2 = NULL;
5062 TYPEATTR *tattr = NULL;
5064 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5065 if (hr)
5067 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
5068 "hr = 0x%08lx\n",
5069 tdesc->u.hreftype, hr);
5070 return hr;
5072 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5073 if (hr)
5075 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
5076 ITypeInfo_Release(tinfo2);
5077 return hr;
5080 switch (tattr->typekind)
5082 case TKIND_ENUM:
5083 *vt |= VT_I4;
5084 break;
5086 case TKIND_ALIAS:
5087 tdesc = &tattr->tdescAlias;
5088 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5089 break;
5091 case TKIND_INTERFACE:
5092 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5093 *vt |= VT_DISPATCH;
5094 else
5095 *vt |= VT_UNKNOWN;
5096 break;
5098 case TKIND_DISPATCH:
5099 *vt |= VT_DISPATCH;
5100 break;
5102 case TKIND_RECORD:
5103 FIXME("TKIND_RECORD unhandled.\n");
5104 hr = E_NOTIMPL;
5105 break;
5107 case TKIND_UNION:
5108 FIXME("TKIND_RECORD unhandled.\n");
5109 hr = E_NOTIMPL;
5110 break;
5112 default:
5113 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5114 hr = E_NOTIMPL;
5115 break;
5117 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5118 ITypeInfo_Release(tinfo2);
5119 return hr;
5122 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5124 HRESULT hr = S_OK;
5126 /* enforce only one level of pointer indirection */
5127 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
5129 tdesc = tdesc->u.lptdesc;
5131 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5132 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5133 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5134 if ((tdesc->vt == VT_USERDEFINED) ||
5135 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5137 VARTYPE vt_userdefined = 0;
5138 const TYPEDESC *tdesc_userdefined = tdesc;
5139 if (tdesc->vt == VT_PTR)
5141 vt_userdefined = VT_BYREF;
5142 tdesc_userdefined = tdesc->u.lptdesc;
5144 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5145 if ((hr == S_OK) &&
5146 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5147 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5149 *vt |= vt_userdefined;
5150 return S_OK;
5153 *vt = VT_BYREF;
5156 switch (tdesc->vt)
5158 case VT_HRESULT:
5159 *vt |= VT_ERROR;
5160 break;
5161 case VT_USERDEFINED:
5162 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5163 break;
5164 case VT_PTR:
5165 ERR("cannot convert VT_PTR into variant VT\n");
5166 hr = E_FAIL;
5167 break;
5168 default:
5169 *vt |= tdesc->vt;
5170 break;
5172 return hr;
5175 /***********************************************************************
5176 * DispCallFunc (OLEAUT32.@)
5178 * Invokes a function of the specifed calling convention, passing the
5179 * specified arguments and returns the result.
5181 * PARAMS
5182 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5183 * oVft [I] The offset in the vtable. See notes.
5184 * cc [I] Calling convention of the function to call.
5185 * vtReturn [I] The return type of the function.
5186 * cActuals [I] Number of parameters.
5187 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5188 * prgpvarg [I] The arguments to pass.
5189 * pvargResult [O] The return value of the function. Can be NULL.
5191 * RETURNS
5192 * Success: S_OK.
5193 * Failure: HRESULT code.
5195 * NOTES
5196 * The HRESULT return value of this function is not affected by the return
5197 * value of the user supplied function, which is returned in pvargResult.
5199 * If pvInstance is NULL then a non-object function is to be called and oVft
5200 * is the address of the function to call.
5202 * The cc parameter can be one of the following values:
5203 *|CC_FASTCALL
5204 *|CC_CDECL
5205 *|CC_PASCAL
5206 *|CC_STDCALL
5207 *|CC_FPFASTCALL
5208 *|CC_SYSCALL
5209 *|CC_MPWCDECL
5210 *|CC_MPWPASCAL
5212 * BUGS
5213 * Native accepts arguments in the reverse order. I.e. the first item in the
5214 * prgpvarg array is the last argument in the C/C++ declaration of the
5215 * function to be called.
5217 HRESULT WINAPI
5218 DispCallFunc(
5219 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5220 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5222 int i, argsize, argspos;
5223 DWORD *args;
5224 HRESULT hres;
5226 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5227 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5228 pvargResult, V_VT(pvargResult));
5230 argsize = 0;
5231 if (pvInstance)
5232 argsize++; /* for This pointer */
5234 for (i=0;i<cActuals;i++)
5236 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5237 dump_Variant(prgpvarg[i]);
5238 argsize += _argsize(prgvt[i]);
5240 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5242 argspos = 0;
5243 if (pvInstance)
5245 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5246 argspos++;
5249 for (i=0;i<cActuals;i++)
5251 VARIANT *arg = prgpvarg[i];
5252 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5253 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5254 argspos += _argsize(prgvt[i]);
5257 if (pvInstance)
5259 FARPROC *vtable = *(FARPROC**)pvInstance;
5260 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5262 else
5263 /* if we aren't invoking an object then the function pointer is stored
5264 * in oVft */
5265 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5267 if (pvargResult && (vtReturn != VT_EMPTY))
5269 TRACE("Method returned 0x%08lx\n",hres);
5270 V_VT(pvargResult) = vtReturn;
5271 V_UI4(pvargResult) = hres;
5274 HeapFree(GetProcessHeap(),0,args);
5275 return S_OK;
5278 static HRESULT WINAPI ITypeInfo_fnInvoke(
5279 ITypeInfo2 *iface,
5280 VOID *pIUnk,
5281 MEMBERID memid,
5282 UINT16 wFlags,
5283 DISPPARAMS *pDispParams,
5284 VARIANT *pVarResult,
5285 EXCEPINFO *pExcepInfo,
5286 UINT *pArgErr)
5288 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5289 int i;
5290 unsigned int var_index;
5291 TYPEKIND type_kind;
5292 HRESULT hres;
5293 const TLBFuncDesc *pFuncInfo;
5295 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5296 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5298 dump_DispParms(pDispParams);
5300 /* we do this instead of using GetFuncDesc since it will return a fake
5301 * FUNCDESC for dispinterfaces and we want the real function description */
5302 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5303 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5304 break;
5306 if (pFuncInfo) {
5307 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5309 if (TRACE_ON(ole))
5311 TRACE("invoking:\n");
5312 dump_TLBFuncDesc(pFuncInfo);
5315 switch (func_desc->funckind) {
5316 case FUNC_PUREVIRTUAL:
5317 case FUNC_VIRTUAL: {
5318 DWORD res;
5319 int numargs, numargs2, argspos, args2pos;
5320 DWORD *args , *args2;
5321 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
5322 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
5324 hres = S_OK;
5325 numargs = 1; /* sizeof(thisptr) */
5326 numargs2 = 0;
5327 for (i = 0; i < func_desc->cParams; i++) {
5328 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5330 numargs += _argsize(tdesc->vt);
5331 if (i>=pDispParams->cArgs) { /* arguments to return */
5332 if (tdesc->vt == VT_PTR) {
5333 numargs2 += _argsize(tdesc->u.lptdesc->vt);
5334 } else {
5335 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
5336 numargs2 += _argsize(tdesc->vt);
5341 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
5342 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
5344 args[0] = (DWORD)pIUnk;
5345 argspos = 1; args2pos = 0;
5346 for (i = 0; i < func_desc->cParams; i++) {
5347 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
5348 TYPEDESC *tdesc = &(elemdesc->tdesc);
5349 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
5350 int arglen = _argsize(tdesc->vt);
5352 if (i<pDispParams->cArgs) {
5353 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
5355 if (paramFlags & PARAMFLAG_FOPT) {
5356 if(i < func_desc->cParams - func_desc->cParamsOpt)
5357 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5358 if(V_VT(arg) == VT_EMPTY
5359 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
5360 /* FIXME: Documentation says that we do this when parameter is left unspecified.
5361 How to determine it? */
5363 if(paramFlags & PARAMFLAG_FHASDEFAULT)
5364 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5365 V_VT(arg) = VT_ERROR;
5366 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5367 arglen = _argsize(VT_ERROR);
5370 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5371 if (FAILED(hres)) goto func_fail;
5372 argspos += arglen;
5373 } else if (paramFlags & PARAMFLAG_FOPT) {
5374 VARIANT *arg = &rgvarg[i];
5376 if (i < func_desc->cParams - func_desc->cParamsOpt)
5377 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5378 if (paramFlags & PARAMFLAG_FHASDEFAULT)
5379 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5381 V_VT(arg) = VT_ERROR;
5382 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5383 arglen = _argsize(VT_ERROR);
5384 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5385 if (FAILED(hres)) goto func_fail;
5386 argspos += arglen;
5387 } else {
5388 if (tdesc->vt == VT_PTR)
5389 arglen = _argsize(tdesc->u.lptdesc->vt);
5390 else
5391 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5393 /* Supply pointers for the rest, so propertyget works*/
5394 args[argspos] = (DWORD)&args2[args2pos];
5396 /* If pointer to variant, pass reference it. */
5397 if ((tdesc->vt == VT_PTR) &&
5398 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5399 pVarResult
5401 args[argspos]= (DWORD)pVarResult;
5402 argspos += 1;
5403 args2pos += arglen;
5406 if (func_desc->cParamsOpt < 0)
5407 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5409 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5410 func_desc->callconv,
5411 numargs,
5412 args
5415 if (pVarResult) {
5416 for (i = 0; i < func_desc->cParams; i++) {
5417 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5418 if (wParamFlags & PARAMFLAG_FRETVAL) {
5419 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5420 TYPEDESC *tdesc = &elemdesc->tdesc;
5421 VARIANTARG varresult;
5422 V_VT(&varresult) = 0;
5423 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5424 if (hres)
5425 break;
5426 /* FIXME: this is really messy - we should keep the
5427 * args in VARIANTARGs rather than a DWORD array */
5428 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5429 if (TRACE_ON(ole))
5431 TRACE("varresult: ");
5432 dump_Variant(&varresult);
5434 hres = VariantCopyInd(pVarResult, &varresult);
5435 /* free data stored in varresult. Note that
5436 * VariantClear doesn't do what we want because we are
5437 * working with byref types. */
5438 /* FIXME: clear safearrays, bstrs, records and
5439 * variants here too */
5440 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5441 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5443 if(*V_UNKNOWNREF(&varresult))
5444 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5446 break;
5451 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5452 WARN("invoked function failed with error 0x%08lx\n", res);
5453 hres = DISP_E_EXCEPTION;
5454 if (pExcepInfo) pExcepInfo->scode = res;
5456 func_fail:
5457 HeapFree(GetProcessHeap(), 0, rgvarg);
5458 HeapFree(GetProcessHeap(),0,args2);
5459 HeapFree(GetProcessHeap(),0,args);
5460 break;
5462 case FUNC_DISPATCH: {
5463 IDispatch *disp;
5465 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5466 if (SUCCEEDED(hres)) {
5467 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5468 hres = IDispatch_Invoke(
5469 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5470 pVarResult,pExcepInfo,pArgErr
5472 if (FAILED(hres))
5473 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5474 IDispatch_Release(disp);
5475 } else
5476 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5477 break;
5479 default:
5480 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5481 hres = E_FAIL;
5482 break;
5485 TRACE("-- 0x%08lx\n", hres);
5486 return hres;
5488 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5489 VARDESC *var_desc;
5491 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5492 if(FAILED(hres)) return hres;
5494 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5495 dump_VARDESC(var_desc);
5496 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5497 return E_NOTIMPL;
5500 /* not found, look for it in inherited interfaces */
5501 ITypeInfo2_GetTypeKind(iface, &type_kind);
5502 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5503 HREFTYPE ref_type;
5504 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5505 /* recursive search */
5506 ITypeInfo *pTInfo;
5507 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5508 if(SUCCEEDED(hres)){
5509 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5510 ITypeInfo_Release(pTInfo);
5511 return hres;
5513 WARN("Could not search inherited interface!\n");
5516 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5517 return DISP_E_MEMBERNOTFOUND;
5520 /* ITypeInfo::GetDocumentation
5522 * Retrieves the documentation string, the complete Help file name and path,
5523 * and the context ID for the Help topic for a specified type description.
5525 * (Can be tested by the Visual Basic Editor in Word for instance.)
5527 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5528 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5529 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5531 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5532 TLBFuncDesc * pFDesc;
5533 TLBVarDesc * pVDesc;
5534 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5535 " HelpContext(%p) HelpFile(%p)\n",
5536 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5537 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5538 if(pBstrName)
5539 *pBstrName=SysAllocString(This->Name);
5540 if(pBstrDocString)
5541 *pBstrDocString=SysAllocString(This->DocString);
5542 if(pdwHelpContext)
5543 *pdwHelpContext=This->dwHelpContext;
5544 if(pBstrHelpFile)
5545 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5546 return S_OK;
5547 }else {/* for a member */
5548 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5549 if(pFDesc->funcdesc.memid==memid){
5550 if(pBstrName)
5551 *pBstrName = SysAllocString(pFDesc->Name);
5552 if(pBstrDocString)
5553 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5554 if(pdwHelpContext)
5555 *pdwHelpContext=pFDesc->helpcontext;
5556 return S_OK;
5558 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5559 if(pVDesc->vardesc.memid==memid){
5560 if(pBstrName)
5561 *pBstrName = SysAllocString(pVDesc->Name);
5562 if(pBstrDocString)
5563 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5564 if(pdwHelpContext)
5565 *pdwHelpContext=pVDesc->HelpContext;
5566 return S_OK;
5569 WARN("member %ld not found\n", memid);
5570 return TYPE_E_ELEMENTNOTFOUND;
5573 /* ITypeInfo::GetDllEntry
5575 * Retrieves a description or specification of an entry point for a function
5576 * in a DLL.
5578 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5579 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5580 WORD *pwOrdinal)
5582 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5583 TLBFuncDesc *pFDesc;
5585 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5587 if (pBstrDllName) *pBstrDllName = NULL;
5588 if (pBstrName) *pBstrName = NULL;
5589 if (pwOrdinal) *pwOrdinal = 0;
5591 if (This->TypeAttr.typekind != TKIND_MODULE)
5592 return TYPE_E_BADMODULEKIND;
5594 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5595 if(pFDesc->funcdesc.memid==memid){
5596 dump_TypeInfo(This);
5597 if (TRACE_ON(ole))
5598 dump_TLBFuncDescOne(pFDesc);
5600 if (pBstrDllName)
5601 *pBstrDllName = SysAllocString(This->DllName);
5603 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5604 if (pBstrName)
5605 *pBstrName = SysAllocString(pFDesc->Entry);
5606 if (pwOrdinal)
5607 *pwOrdinal = -1;
5608 return S_OK;
5610 if (pBstrName)
5611 *pBstrName = NULL;
5612 if (pwOrdinal)
5613 *pwOrdinal = (DWORD)pFDesc->Entry;
5614 return S_OK;
5616 return TYPE_E_ELEMENTNOTFOUND;
5619 /* ITypeInfo::GetRefTypeInfo
5621 * If a type description references other type descriptions, it retrieves
5622 * the referenced type descriptions.
5624 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5625 ITypeInfo2 *iface,
5626 HREFTYPE hRefType,
5627 ITypeInfo **ppTInfo)
5629 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5630 HRESULT result = E_FAIL;
5632 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5634 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5635 ITypeInfo_AddRef(*ppTInfo);
5636 result = S_OK;
5638 else if (hRefType == -1 &&
5639 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5640 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5642 /* when we meet a DUAL dispinterface, we must create the interface
5643 * version of it.
5645 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5648 /* the interface version contains the same information as the dispinterface
5649 * copy the contents of the structs.
5651 *pTypeInfoImpl = *This;
5652 pTypeInfoImpl->ref = 1;
5654 /* change the type to interface */
5655 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5657 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5659 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5661 result = S_OK;
5663 } else {
5664 TLBRefType *pRefType;
5665 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5666 if(pRefType->reference == hRefType)
5667 break;
5669 if(!pRefType)
5670 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5671 if(pRefType && hRefType != -1) {
5672 ITypeLib *pTLib = NULL;
5674 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5675 UINT Index;
5676 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5677 } else {
5678 if(pRefType->pImpTLInfo->pImpTypeLib) {
5679 TRACE("typeinfo in imported typelib that is already loaded\n");
5680 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5681 ITypeLib2_AddRef((ITypeLib*) pTLib);
5682 result = S_OK;
5683 } else {
5684 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5685 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5686 pRefType->pImpTLInfo->wVersionMajor,
5687 pRefType->pImpTLInfo->wVersionMinor,
5688 pRefType->pImpTLInfo->lcid,
5689 &pTLib);
5691 if(!SUCCEEDED(result)) {
5692 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5693 result=LoadTypeLib(libnam, &pTLib);
5694 SysFreeString(libnam);
5696 if(SUCCEEDED(result)) {
5697 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5698 ITypeLib2_AddRef(pTLib);
5702 if(SUCCEEDED(result)) {
5703 if(pRefType->index == TLB_REF_USE_GUID)
5704 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5705 &pRefType->guid,
5706 ppTInfo);
5707 else
5708 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5709 ppTInfo);
5711 if (pTLib != NULL)
5712 ITypeLib2_Release(pTLib);
5716 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5717 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5718 return result;
5721 /* ITypeInfo::AddressOfMember
5723 * Retrieves the addresses of static functions or variables, such as those
5724 * defined in a DLL.
5726 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5727 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5729 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5730 HRESULT hr;
5731 BSTR dll, entry;
5732 WORD ordinal;
5733 HMODULE module;
5735 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5737 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5738 if (FAILED(hr))
5739 return hr;
5741 module = LoadLibraryW(dll);
5742 if (!module)
5744 ERR("couldn't load %s\n", debugstr_w(dll));
5745 SysFreeString(dll);
5746 if (entry) SysFreeString(entry);
5747 return STG_E_FILENOTFOUND;
5749 /* FIXME: store library somewhere where we can free it */
5751 if (entry)
5753 LPSTR entryA;
5754 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5755 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5756 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5758 *ppv = GetProcAddress(module, entryA);
5759 if (!*ppv)
5760 ERR("function not found %s\n", debugstr_a(entryA));
5762 HeapFree(GetProcessHeap(), 0, entryA);
5764 else
5766 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5767 if (!*ppv)
5768 ERR("function not found %d\n", ordinal);
5771 SysFreeString(dll);
5772 if (entry) SysFreeString(entry);
5774 if (!*ppv)
5775 return TYPE_E_DLLFUNCTIONNOTFOUND;
5777 return S_OK;
5780 /* ITypeInfo::CreateInstance
5782 * Creates a new instance of a type that describes a component object class
5783 * (coclass).
5785 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5786 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5788 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5789 FIXME("(%p) stub!\n", This);
5790 return S_OK;
5793 /* ITypeInfo::GetMops
5795 * Retrieves marshalling information.
5797 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5798 BSTR *pBstrMops)
5800 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5801 FIXME("(%p) stub!\n", This);
5802 return S_OK;
5805 /* ITypeInfo::GetContainingTypeLib
5807 * Retrieves the containing type library and the index of the type description
5808 * within that type library.
5810 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5811 ITypeLib * *ppTLib, UINT *pIndex)
5813 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5815 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5816 if (pIndex) {
5817 *pIndex=This->index;
5818 TRACE("returning pIndex=%d\n", *pIndex);
5821 if (ppTLib) {
5822 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5823 ITypeLib2_AddRef(*ppTLib);
5824 TRACE("returning ppTLib=%p\n", *ppTLib);
5827 return S_OK;
5830 /* ITypeInfo::ReleaseTypeAttr
5832 * Releases a TYPEATTR previously returned by GetTypeAttr.
5835 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5836 TYPEATTR* pTypeAttr)
5838 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5839 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5840 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5843 /* ITypeInfo::ReleaseFuncDesc
5845 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5847 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5848 ITypeInfo2 *iface,
5849 FUNCDESC *pFuncDesc)
5851 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5852 SHORT i;
5854 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5856 for (i = 0; i < pFuncDesc->cParams; i++)
5857 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5858 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5860 SysFreeString((BSTR)pFuncDesc);
5863 /* ITypeInfo::ReleaseVarDesc
5865 * Releases a VARDESC previously returned by GetVarDesc.
5867 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5868 VARDESC *pVarDesc)
5870 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5871 TRACE("(%p)->(%p)\n", This, pVarDesc);
5873 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5874 if (pVarDesc->varkind == VAR_CONST)
5875 VariantClear(pVarDesc->u.lpvarValue);
5876 SysFreeString((BSTR)pVarDesc);
5879 /* ITypeInfo2::GetTypeKind
5881 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5884 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5885 TYPEKIND *pTypeKind)
5887 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5888 *pTypeKind=This->TypeAttr.typekind;
5889 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5890 return S_OK;
5893 /* ITypeInfo2::GetTypeFlags
5895 * Returns the type flags without any allocations. This returns a DWORD type
5896 * flag, which expands the type flags without growing the TYPEATTR (type
5897 * attribute).
5900 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5902 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5903 *pTypeFlags=This->TypeAttr.wTypeFlags;
5904 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5905 return S_OK;
5908 /* ITypeInfo2::GetFuncIndexOfMemId
5909 * Binds to a specific member based on a known DISPID, where the member name
5910 * is not known (for example, when binding to a default member).
5913 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5914 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5916 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5917 TLBFuncDesc *pFuncInfo;
5918 int i;
5919 HRESULT result;
5921 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5922 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5923 break;
5924 if(pFuncInfo) {
5925 *pFuncIndex = i;
5926 result = S_OK;
5927 } else
5928 result = TYPE_E_ELEMENTNOTFOUND;
5930 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5931 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5932 return result;
5935 /* TypeInfo2::GetVarIndexOfMemId
5937 * Binds to a specific member based on a known DISPID, where the member name
5938 * is not known (for example, when binding to a default member).
5941 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5942 MEMBERID memid, UINT *pVarIndex)
5944 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5945 TLBVarDesc *pVarInfo;
5946 int i;
5947 HRESULT result;
5948 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5949 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5951 if(pVarInfo) {
5952 *pVarIndex = i;
5953 result = S_OK;
5954 } else
5955 result = TYPE_E_ELEMENTNOTFOUND;
5957 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5958 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5959 return result;
5962 /* ITypeInfo2::GetCustData
5964 * Gets the custom data
5966 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5967 ITypeInfo2 * iface,
5968 REFGUID guid,
5969 VARIANT *pVarVal)
5971 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5972 TLBCustData *pCData;
5974 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5975 if( IsEqualIID(guid, &pCData->guid)) break;
5977 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5979 if(pCData)
5981 VariantInit( pVarVal);
5982 VariantCopy( pVarVal, &pCData->data);
5983 return S_OK;
5985 return E_INVALIDARG; /* FIXME: correct? */
5988 /* ITypeInfo2::GetFuncCustData
5990 * Gets the custom data
5992 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5993 ITypeInfo2 * iface,
5994 UINT index,
5995 REFGUID guid,
5996 VARIANT *pVarVal)
5998 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5999 TLBCustData *pCData=NULL;
6000 TLBFuncDesc * pFDesc;
6001 int i;
6002 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6003 pFDesc=pFDesc->next);
6005 if(pFDesc)
6006 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6007 if( IsEqualIID(guid, &pCData->guid)) break;
6009 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6011 if(pCData){
6012 VariantInit( pVarVal);
6013 VariantCopy( pVarVal, &pCData->data);
6014 return S_OK;
6016 return E_INVALIDARG; /* FIXME: correct? */
6019 /* ITypeInfo2::GetParamCustData
6021 * Gets the custom data
6023 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6024 ITypeInfo2 * iface,
6025 UINT indexFunc,
6026 UINT indexParam,
6027 REFGUID guid,
6028 VARIANT *pVarVal)
6030 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6031 TLBCustData *pCData=NULL;
6032 TLBFuncDesc * pFDesc;
6033 int i;
6035 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6037 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6038 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6039 pCData = pCData->next)
6040 if( IsEqualIID(guid, &pCData->guid)) break;
6042 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6044 if(pCData)
6046 VariantInit( pVarVal);
6047 VariantCopy( pVarVal, &pCData->data);
6048 return S_OK;
6050 return E_INVALIDARG; /* FIXME: correct? */
6053 /* ITypeInfo2::GetVarCustData
6055 * Gets the custom data
6057 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6058 ITypeInfo2 * iface,
6059 UINT index,
6060 REFGUID guid,
6061 VARIANT *pVarVal)
6063 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6064 TLBCustData *pCData=NULL;
6065 TLBVarDesc * pVDesc;
6066 int i;
6068 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6070 if(pVDesc)
6072 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6074 if( IsEqualIID(guid, &pCData->guid)) break;
6078 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6080 if(pCData)
6082 VariantInit( pVarVal);
6083 VariantCopy( pVarVal, &pCData->data);
6084 return S_OK;
6086 return E_INVALIDARG; /* FIXME: correct? */
6089 /* ITypeInfo2::GetImplCustData
6091 * Gets the custom data
6093 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6094 ITypeInfo2 * iface,
6095 UINT index,
6096 REFGUID guid,
6097 VARIANT *pVarVal)
6099 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6100 TLBCustData *pCData=NULL;
6101 TLBImplType * pRDesc;
6102 int i;
6104 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6106 if(pRDesc)
6108 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6110 if( IsEqualIID(guid, &pCData->guid)) break;
6114 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6116 if(pCData)
6118 VariantInit( pVarVal);
6119 VariantCopy( pVarVal, &pCData->data);
6120 return S_OK;
6122 return E_INVALIDARG; /* FIXME: correct? */
6125 /* ITypeInfo2::GetDocumentation2
6127 * Retrieves the documentation string, the complete Help file name and path,
6128 * the localization context to use, and the context ID for the library Help
6129 * topic in the Help file.
6132 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6133 ITypeInfo2 * iface,
6134 MEMBERID memid,
6135 LCID lcid,
6136 BSTR *pbstrHelpString,
6137 DWORD *pdwHelpStringContext,
6138 BSTR *pbstrHelpStringDll)
6140 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6141 TLBFuncDesc * pFDesc;
6142 TLBVarDesc * pVDesc;
6143 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6144 "HelpStringContext(%p) HelpStringDll(%p)\n",
6145 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6146 pbstrHelpStringDll );
6147 /* the help string should be obtained from the helpstringdll,
6148 * using the _DLLGetDocumentation function, based on the supplied
6149 * lcid. Nice to do sometime...
6151 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6152 if(pbstrHelpString)
6153 *pbstrHelpString=SysAllocString(This->Name);
6154 if(pdwHelpStringContext)
6155 *pdwHelpStringContext=This->dwHelpStringContext;
6156 if(pbstrHelpStringDll)
6157 *pbstrHelpStringDll=
6158 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6159 return S_OK;
6160 }else {/* for a member */
6161 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6162 if(pFDesc->funcdesc.memid==memid){
6163 if(pbstrHelpString)
6164 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6165 if(pdwHelpStringContext)
6166 *pdwHelpStringContext=pFDesc->HelpStringContext;
6167 if(pbstrHelpStringDll)
6168 *pbstrHelpStringDll=
6169 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6170 return S_OK;
6172 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6173 if(pVDesc->vardesc.memid==memid){
6174 if(pbstrHelpString)
6175 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6176 if(pdwHelpStringContext)
6177 *pdwHelpStringContext=pVDesc->HelpStringContext;
6178 if(pbstrHelpStringDll)
6179 *pbstrHelpStringDll=
6180 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6181 return S_OK;
6184 return TYPE_E_ELEMENTNOTFOUND;
6187 /* ITypeInfo2::GetAllCustData
6189 * Gets all custom data items for the Type info.
6192 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6193 ITypeInfo2 * iface,
6194 CUSTDATA *pCustData)
6196 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6197 TLBCustData *pCData;
6198 int i;
6200 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6202 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6203 if(pCustData->prgCustData ){
6204 pCustData->cCustData=This->ctCustData;
6205 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6206 pCustData->prgCustData[i].guid=pCData->guid;
6207 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6209 }else{
6210 ERR(" OUT OF MEMORY!\n");
6211 return E_OUTOFMEMORY;
6213 return S_OK;
6216 /* ITypeInfo2::GetAllFuncCustData
6218 * Gets all custom data items for the specified Function
6221 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6222 ITypeInfo2 * iface,
6223 UINT index,
6224 CUSTDATA *pCustData)
6226 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6227 TLBCustData *pCData;
6228 TLBFuncDesc * pFDesc;
6229 int i;
6230 TRACE("(%p) index %d\n", This, index);
6231 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6232 pFDesc=pFDesc->next)
6234 if(pFDesc){
6235 pCustData->prgCustData =
6236 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6237 if(pCustData->prgCustData ){
6238 pCustData->cCustData=pFDesc->ctCustData;
6239 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6240 pCData = pCData->next){
6241 pCustData->prgCustData[i].guid=pCData->guid;
6242 VariantCopy(& pCustData->prgCustData[i].varValue,
6243 & pCData->data);
6245 }else{
6246 ERR(" OUT OF MEMORY!\n");
6247 return E_OUTOFMEMORY;
6249 return S_OK;
6251 return TYPE_E_ELEMENTNOTFOUND;
6254 /* ITypeInfo2::GetAllParamCustData
6256 * Gets all custom data items for the Functions
6259 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6260 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6262 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6263 TLBCustData *pCData=NULL;
6264 TLBFuncDesc * pFDesc;
6265 int i;
6266 TRACE("(%p) index %d\n", This, indexFunc);
6267 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6268 pFDesc=pFDesc->next)
6270 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6271 pCustData->prgCustData =
6272 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6273 sizeof(CUSTDATAITEM));
6274 if(pCustData->prgCustData ){
6275 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6276 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6277 pCData; i++, pCData = pCData->next){
6278 pCustData->prgCustData[i].guid=pCData->guid;
6279 VariantCopy(& pCustData->prgCustData[i].varValue,
6280 & pCData->data);
6282 }else{
6283 ERR(" OUT OF MEMORY!\n");
6284 return E_OUTOFMEMORY;
6286 return S_OK;
6288 return TYPE_E_ELEMENTNOTFOUND;
6291 /* ITypeInfo2::GetAllVarCustData
6293 * Gets all custom data items for the specified Variable
6296 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6297 UINT index, CUSTDATA *pCustData)
6299 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6300 TLBCustData *pCData;
6301 TLBVarDesc * pVDesc;
6302 int i;
6303 TRACE("(%p) index %d\n", This, index);
6304 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6305 pVDesc=pVDesc->next)
6307 if(pVDesc){
6308 pCustData->prgCustData =
6309 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6310 if(pCustData->prgCustData ){
6311 pCustData->cCustData=pVDesc->ctCustData;
6312 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6313 pCData = pCData->next){
6314 pCustData->prgCustData[i].guid=pCData->guid;
6315 VariantCopy(& pCustData->prgCustData[i].varValue,
6316 & pCData->data);
6318 }else{
6319 ERR(" OUT OF MEMORY!\n");
6320 return E_OUTOFMEMORY;
6322 return S_OK;
6324 return TYPE_E_ELEMENTNOTFOUND;
6327 /* ITypeInfo2::GetAllImplCustData
6329 * Gets all custom data items for the specified implementation type
6332 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6333 ITypeInfo2 * iface,
6334 UINT index,
6335 CUSTDATA *pCustData)
6337 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6338 TLBCustData *pCData;
6339 TLBImplType * pRDesc;
6340 int i;
6341 TRACE("(%p) index %d\n", This, index);
6342 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6343 pRDesc=pRDesc->next)
6345 if(pRDesc){
6346 pCustData->prgCustData =
6347 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6348 if(pCustData->prgCustData ){
6349 pCustData->cCustData=pRDesc->ctCustData;
6350 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6351 pCData = pCData->next){
6352 pCustData->prgCustData[i].guid=pCData->guid;
6353 VariantCopy(& pCustData->prgCustData[i].varValue,
6354 & pCData->data);
6356 }else{
6357 ERR(" OUT OF MEMORY!\n");
6358 return E_OUTOFMEMORY;
6360 return S_OK;
6362 return TYPE_E_ELEMENTNOTFOUND;
6365 static const ITypeInfo2Vtbl tinfvt =
6368 ITypeInfo_fnQueryInterface,
6369 ITypeInfo_fnAddRef,
6370 ITypeInfo_fnRelease,
6372 ITypeInfo_fnGetTypeAttr,
6373 ITypeInfo_fnGetTypeComp,
6374 ITypeInfo_fnGetFuncDesc,
6375 ITypeInfo_fnGetVarDesc,
6376 ITypeInfo_fnGetNames,
6377 ITypeInfo_fnGetRefTypeOfImplType,
6378 ITypeInfo_fnGetImplTypeFlags,
6379 ITypeInfo_fnGetIDsOfNames,
6380 ITypeInfo_fnInvoke,
6381 ITypeInfo_fnGetDocumentation,
6382 ITypeInfo_fnGetDllEntry,
6383 ITypeInfo_fnGetRefTypeInfo,
6384 ITypeInfo_fnAddressOfMember,
6385 ITypeInfo_fnCreateInstance,
6386 ITypeInfo_fnGetMops,
6387 ITypeInfo_fnGetContainingTypeLib,
6388 ITypeInfo_fnReleaseTypeAttr,
6389 ITypeInfo_fnReleaseFuncDesc,
6390 ITypeInfo_fnReleaseVarDesc,
6392 ITypeInfo2_fnGetTypeKind,
6393 ITypeInfo2_fnGetTypeFlags,
6394 ITypeInfo2_fnGetFuncIndexOfMemId,
6395 ITypeInfo2_fnGetVarIndexOfMemId,
6396 ITypeInfo2_fnGetCustData,
6397 ITypeInfo2_fnGetFuncCustData,
6398 ITypeInfo2_fnGetParamCustData,
6399 ITypeInfo2_fnGetVarCustData,
6400 ITypeInfo2_fnGetImplTypeCustData,
6401 ITypeInfo2_fnGetDocumentation2,
6402 ITypeInfo2_fnGetAllCustData,
6403 ITypeInfo2_fnGetAllFuncCustData,
6404 ITypeInfo2_fnGetAllParamCustData,
6405 ITypeInfo2_fnGetAllVarCustData,
6406 ITypeInfo2_fnGetAllImplTypeCustData,
6409 /******************************************************************************
6410 * CreateDispTypeInfo [OLEAUT32.31]
6412 * Build type information for an object so it can be called through an
6413 * IDispatch interface.
6415 * RETURNS
6416 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6417 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6419 * NOTES
6420 * This call allows an objects methods to be accessed through IDispatch, by
6421 * building an ITypeInfo object that IDispatch can use to call through.
6423 HRESULT WINAPI CreateDispTypeInfo(
6424 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6425 LCID lcid, /* [I] Locale Id */
6426 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6428 ITypeInfoImpl *pTIImpl;
6429 int param, func;
6430 TLBFuncDesc **ppFuncDesc;
6432 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
6433 pTIImpl->pTypeLib = NULL;
6434 pTIImpl->index = 0;
6435 pTIImpl->Name = NULL;
6436 pTIImpl->dwHelpContext = -1;
6437 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
6438 pTIImpl->TypeAttr.lcid = lcid;
6439 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
6440 pTIImpl->TypeAttr.wMajorVerNum = 0;
6441 pTIImpl->TypeAttr.wMinorVerNum = 0;
6442 pTIImpl->TypeAttr.cbAlignment = 2;
6443 pTIImpl->TypeAttr.cbSizeInstance = -1;
6444 pTIImpl->TypeAttr.cbSizeVft = -1;
6445 pTIImpl->TypeAttr.cFuncs = 0;
6446 pTIImpl->TypeAttr.cImplTypes = 1;
6447 pTIImpl->TypeAttr.cVars = 0;
6448 pTIImpl->TypeAttr.wTypeFlags = 0;
6450 ppFuncDesc = &pTIImpl->funclist;
6451 for(func = 0; func < pidata->cMembers; func++) {
6452 METHODDATA *md = pidata->pmethdata + func;
6453 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6454 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6455 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6456 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6457 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6458 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6459 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6460 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6461 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6462 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6463 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6464 md->cArgs * sizeof(ELEMDESC));
6465 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6466 md->cArgs * sizeof(TLBParDesc));
6467 for(param = 0; param < md->cArgs; param++) {
6468 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6469 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6471 ppFuncDesc = &(*ppFuncDesc)->next;
6473 *pptinfo = (ITypeInfo*)pTIImpl;
6474 return S_OK;
6478 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6480 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6482 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6485 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6487 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6489 return ITypeInfo_AddRef((ITypeInfo *)This);
6492 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6494 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6496 return ITypeInfo_Release((ITypeInfo *)This);
6499 static HRESULT WINAPI ITypeComp_fnBind(
6500 ITypeComp * iface,
6501 OLECHAR * szName,
6502 ULONG lHash,
6503 WORD wFlags,
6504 ITypeInfo ** ppTInfo,
6505 DESCKIND * pDescKind,
6506 BINDPTR * pBindPtr)
6508 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6509 TLBFuncDesc * pFDesc;
6510 TLBVarDesc * pVDesc;
6512 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6514 *pDescKind = DESCKIND_NONE;
6515 pBindPtr->lpfuncdesc = NULL;
6516 *ppTInfo = NULL;
6518 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6519 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6520 if (!strcmpW(pFDesc->Name, szName)) {
6521 break;
6524 if (pFDesc)
6526 HRESULT hr = TLB_AllocAndInitFuncDesc(
6527 &pFDesc->funcdesc,
6528 &pBindPtr->lpfuncdesc,
6529 This->TypeAttr.typekind == TKIND_DISPATCH);
6530 if (FAILED(hr))
6531 return hr;
6532 *pDescKind = DESCKIND_FUNCDESC;
6533 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6534 ITypeInfo_AddRef(*ppTInfo);
6535 return S_OK;
6536 } else {
6537 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6538 if (!strcmpW(pVDesc->Name, szName)) {
6539 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6540 if (FAILED(hr))
6541 return hr;
6542 *pDescKind = DESCKIND_VARDESC;
6543 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6544 ITypeInfo_AddRef(*ppTInfo);
6545 return S_OK;
6549 /* FIXME: search each inherited interface, not just the first */
6550 if (This->TypeAttr.cImplTypes) {
6551 /* recursive search */
6552 ITypeInfo *pTInfo;
6553 ITypeComp *pTComp;
6554 HRESULT hr;
6555 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6556 if (SUCCEEDED(hr))
6558 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6559 ITypeInfo_Release(pTInfo);
6561 if (SUCCEEDED(hr))
6563 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6564 ITypeComp_Release(pTComp);
6565 return hr;
6567 WARN("Could not search inherited interface!\n");
6569 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6570 return DISP_E_MEMBERNOTFOUND;
6573 static HRESULT WINAPI ITypeComp_fnBindType(
6574 ITypeComp * iface,
6575 OLECHAR * szName,
6576 ULONG lHash,
6577 ITypeInfo ** ppTInfo,
6578 ITypeComp ** ppTComp)
6580 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6582 /* strange behaviour (does nothing) but like the
6583 * original */
6585 if (!ppTInfo || !ppTComp)
6586 return E_POINTER;
6588 *ppTInfo = NULL;
6589 *ppTComp = NULL;
6591 return S_OK;
6594 static const ITypeCompVtbl tcompvt =
6597 ITypeComp_fnQueryInterface,
6598 ITypeComp_fnAddRef,
6599 ITypeComp_fnRelease,
6601 ITypeComp_fnBind,
6602 ITypeComp_fnBindType