Add functions for doing a deep copy of a TYPEDESC into a flat buffer.
[wine/testsucceed.git] / dlls / oleaut32 / typelib.c
blob21187ab5c345ca0dab7f343632d2584590bde712
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, 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 /* type libs seem to store the doc strings in ascii
980 * so why should we do it in unicode?
982 BSTR Name;
983 BSTR DocString;
984 BSTR DllName;
985 unsigned long dwHelpContext;
986 unsigned long dwHelpStringContext;
988 /* functions */
989 TLBFuncDesc * funclist; /* linked list with function descriptions */
991 /* variables */
992 TLBVarDesc * varlist; /* linked list with variable descriptions */
994 /* Implemented Interfaces */
995 TLBImplType * impltypelist;
997 TLBRefType * reflist;
998 int ctCustData;
999 TLBCustData * pCustData; /* linked list to cust data; */
1000 struct tagITypeInfoImpl * next;
1001 } ITypeInfoImpl;
1003 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1005 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1008 static const ITypeInfo2Vtbl tinfvt;
1009 static const ITypeCompVtbl tcompvt;
1011 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1013 typedef struct tagTLBContext
1015 unsigned int oStart; /* start of TLB in file */
1016 unsigned int pos; /* current pos */
1017 unsigned int length; /* total length */
1018 void *mapping; /* memory mapping */
1019 MSFT_SegDir * pTblDir;
1020 ITypeLibImpl* pLibInfo;
1021 } TLBContext;
1024 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1027 debug
1029 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1030 if (pTD->vt & VT_RESERVED)
1031 szVarType += strlen(strcpy(szVarType, "reserved | "));
1032 if (pTD->vt & VT_BYREF)
1033 szVarType += strlen(strcpy(szVarType, "ref to "));
1034 if (pTD->vt & VT_ARRAY)
1035 szVarType += strlen(strcpy(szVarType, "array of "));
1036 if (pTD->vt & VT_VECTOR)
1037 szVarType += strlen(strcpy(szVarType, "vector of "));
1038 switch(pTD->vt & VT_TYPEMASK) {
1039 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1040 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1041 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1042 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1043 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1044 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1045 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1046 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1047 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1048 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1049 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1050 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1051 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1052 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1053 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1054 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1055 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1056 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1057 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1058 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1059 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1060 pTD->u.hreftype); break;
1061 case VT_PTR: sprintf(szVarType, "ptr to ");
1062 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1063 break;
1064 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1065 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1066 break;
1067 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1068 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1069 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1070 break;
1072 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1076 static void dump_ELEMDESC(ELEMDESC *edesc) {
1077 char buf[200];
1078 USHORT flags = edesc->u.paramdesc.wParamFlags;
1079 dump_TypeDesc(&edesc->tdesc,buf);
1080 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1081 MESSAGE("\t\tu.paramdesc.wParamFlags");
1082 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1083 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1084 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1085 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1086 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1087 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1088 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1089 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1090 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1092 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
1093 int i;
1094 MESSAGE("memid is %08lx\n",funcdesc->memid);
1095 for (i=0;i<funcdesc->cParams;i++) {
1096 MESSAGE("Param %d:\n",i);
1097 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1099 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1100 switch (funcdesc->funckind) {
1101 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1102 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1103 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1104 case FUNC_STATIC: MESSAGE("static");break;
1105 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1106 default: MESSAGE("unknown");break;
1108 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1109 switch (funcdesc->invkind) {
1110 case INVOKE_FUNC: MESSAGE("func");break;
1111 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1112 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1113 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1115 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1116 switch (funcdesc->callconv) {
1117 case CC_CDECL: MESSAGE("cdecl");break;
1118 case CC_PASCAL: MESSAGE("pascal");break;
1119 case CC_STDCALL: MESSAGE("stdcall");break;
1120 case CC_SYSCALL: MESSAGE("syscall");break;
1121 default:break;
1123 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1124 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1125 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1127 MESSAGE("\telemdescFunc (return value type):\n");
1128 dump_ELEMDESC(&funcdesc->elemdescFunc);
1131 static const char * typekind_desc[] =
1133 "TKIND_ENUM",
1134 "TKIND_RECORD",
1135 "TKIND_MODULE",
1136 "TKIND_INTERFACE",
1137 "TKIND_DISPATCH",
1138 "TKIND_COCLASS",
1139 "TKIND_ALIAS",
1140 "TKIND_UNION",
1141 "TKIND_MAX"
1144 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1146 int i;
1147 if (!TRACE_ON(typelib))
1148 return;
1149 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1150 for (i=0;i<pfd->funcdesc.cParams;i++)
1151 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1154 dump_FUNCDESC(&(pfd->funcdesc));
1156 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1157 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1159 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1161 while (pfd)
1163 dump_TLBFuncDescOne(pfd);
1164 pfd = pfd->next;
1167 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1169 while (pvd)
1171 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1172 pvd = pvd->next;
1176 static void dump_TLBImpLib(TLBImpLib *import)
1178 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1179 debugstr_w(import->name));
1180 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1181 import->wVersionMinor, import->lcid, import->offset);
1184 static void dump_TLBRefType(TLBRefType * prt)
1186 while (prt)
1188 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1189 if(prt->index == -1)
1190 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1191 else
1192 TRACE_(typelib)("type no: %d\n", prt->index);
1194 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1195 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1196 TRACE_(typelib)("in lib\n");
1197 dump_TLBImpLib(prt->pImpTLInfo);
1199 prt = prt->next;
1203 static void dump_TLBImplType(TLBImplType * impl)
1205 while (impl) {
1206 TRACE_(typelib)(
1207 "implementing/inheriting interface hRef = %lx implflags %x\n",
1208 impl->hRef, impl->implflags);
1209 impl = impl->next;
1213 void dump_Variant(VARIANT * pvar)
1215 SYSTEMTIME st;
1217 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1219 if (pvar)
1221 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1222 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1224 TRACE(",%p", V_BYREF(pvar));
1226 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1228 TRACE(",FIXME");
1230 else switch (V_TYPE(pvar))
1232 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1233 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1234 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1235 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1236 case VT_INT:
1237 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1238 case VT_UINT:
1239 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1240 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1241 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1242 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1243 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1244 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1245 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1246 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1247 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1248 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1249 V_CY(pvar).s.Lo); break;
1250 case VT_DATE:
1251 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1252 TRACE(",<invalid>");
1253 else
1254 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1255 st.wHour, st.wMinute, st.wSecond);
1256 break;
1257 case VT_ERROR:
1258 case VT_VOID:
1259 case VT_USERDEFINED:
1260 case VT_EMPTY:
1261 case VT_NULL: break;
1262 default: TRACE(",?"); break;
1265 TRACE("}\n");
1268 static void dump_DispParms(DISPPARAMS * pdp)
1270 int index = 0;
1272 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1274 while (index < pdp->cArgs)
1276 dump_Variant( &pdp->rgvarg[index] );
1277 ++index;
1281 static void dump_TypeInfo(ITypeInfoImpl * pty)
1283 TRACE("%p ref=%lu\n", pty, pty->ref);
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("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1289 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1290 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1291 dump_TLBFuncDesc(pty->funclist);
1292 dump_TLBVarDesc(pty->varlist);
1293 dump_TLBImplType(pty->impltypelist);
1296 static void dump_VARDESC(VARDESC *v)
1298 MESSAGE("memid %ld\n",v->memid);
1299 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1300 MESSAGE("oInst %ld\n",v->u.oInst);
1301 dump_ELEMDESC(&(v->elemdescVar));
1302 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1303 MESSAGE("varkind %d\n",v->varkind);
1306 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1308 /* VT_LPWSTR is largest type that */
1309 /* may appear in type description*/
1310 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1311 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1312 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1313 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1314 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1315 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1316 {{0},30},{{0},31}
1319 static void TLB_abort(void)
1321 DebugBreak();
1323 static void * TLB_Alloc(unsigned size)
1325 void * ret;
1326 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1327 /* FIXME */
1328 ERR("cannot allocate memory\n");
1330 return ret;
1333 static void TLB_Free(void * ptr)
1335 HeapFree(GetProcessHeap(), 0, ptr);
1338 /* returns the size required for a deep copy of a typedesc into a
1339 * flat buffer */
1340 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1342 SIZE_T size = 0;
1344 if (alloc_initial_space)
1345 size += sizeof(TYPEDESC);
1347 switch (tdesc->vt)
1349 case VT_PTR:
1350 case VT_SAFEARRAY:
1351 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1352 break;
1353 case VT_CARRAY:
1354 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1355 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1356 break;
1358 return size;
1361 /* deep copy a typedesc into a flat buffer */
1362 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1364 if (!dest)
1366 dest = buffer;
1367 buffer = (char *)buffer + sizeof(TYPEDESC);
1370 *dest = *src;
1372 switch (src->vt)
1374 case VT_PTR:
1375 case VT_SAFEARRAY:
1376 dest->u.lptdesc = buffer;
1377 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1378 break;
1379 case VT_CARRAY:
1380 dest->u.lpadesc = buffer;
1381 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1382 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1383 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1384 break;
1386 return buffer;
1389 /**********************************************************************
1391 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1393 /* read function */
1394 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1396 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1397 pcx->pos, count, pcx->oStart, pcx->length, where);
1399 if (where != DO_NOT_SEEK)
1401 where += pcx->oStart;
1402 if (where > pcx->length)
1404 /* FIXME */
1405 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1406 TLB_abort();
1408 pcx->pos = where;
1410 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1411 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1412 pcx->pos += count;
1413 return count;
1416 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1417 long where )
1419 DWORD ret;
1421 ret = MSFT_Read(buffer, count, pcx, where);
1422 FromLEDWords(buffer, ret);
1424 return ret;
1427 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1428 long where )
1430 DWORD ret;
1432 ret = MSFT_Read(buffer, count, pcx, where);
1433 FromLEWords(buffer, ret);
1435 return ret;
1438 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1440 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1441 memset(pGuid,0, sizeof(GUID));
1442 return;
1444 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1445 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1446 pGuid->Data2 = FromLEWord(pGuid->Data2);
1447 pGuid->Data3 = FromLEWord(pGuid->Data3);
1448 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1451 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1453 char * name;
1454 MSFT_NameIntro niName;
1455 int lengthInChars;
1456 WCHAR* pwstring = NULL;
1457 BSTR bstrName = NULL;
1459 if (offset < 0)
1461 ERR_(typelib)("bad offset %d\n", offset);
1462 return NULL;
1464 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1465 pcx->pTblDir->pNametab.offset+offset);
1466 niName.namelen &= 0xFF; /* FIXME: correct ? */
1467 name=TLB_Alloc((niName.namelen & 0xff) +1);
1468 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1469 name[niName.namelen & 0xff]='\0';
1471 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1472 name, -1, NULL, 0);
1474 /* no invalid characters in string */
1475 if (lengthInChars)
1477 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1479 /* don't check for invalid character since this has been done previously */
1480 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1482 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1483 lengthInChars = SysStringLen(bstrName);
1484 HeapFree(GetProcessHeap(), 0, pwstring);
1487 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1488 return bstrName;
1491 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1493 char * string;
1494 INT16 length;
1495 int lengthInChars;
1496 BSTR bstr = NULL;
1498 if(offset<0) return NULL;
1499 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1500 if(length <= 0) return 0;
1501 string=TLB_Alloc(length +1);
1502 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1503 string[length]='\0';
1505 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1506 string, -1, NULL, 0);
1508 /* no invalid characters in string */
1509 if (lengthInChars)
1511 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1513 /* don't check for invalid character since this has been done previously */
1514 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1516 bstr = SysAllocStringLen(pwstring, lengthInChars);
1517 lengthInChars = SysStringLen(bstr);
1518 HeapFree(GetProcessHeap(), 0, pwstring);
1521 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1522 return bstr;
1525 * read a value and fill a VARIANT structure
1527 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1529 int size;
1531 TRACE_(typelib)("\n");
1533 if(offset <0) { /* data are packed in here */
1534 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1535 V_I2(pVar) = offset & 0x3ffffff;
1536 return;
1538 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1539 pcx->pTblDir->pCustData.offset + offset );
1540 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1541 switch (V_VT(pVar)){
1542 case VT_EMPTY: /* FIXME: is this right? */
1543 case VT_NULL: /* FIXME: is this right? */
1544 case VT_I2 : /* this should not happen */
1545 case VT_I4 :
1546 case VT_R4 :
1547 case VT_ERROR :
1548 case VT_BOOL :
1549 case VT_I1 :
1550 case VT_UI1 :
1551 case VT_UI2 :
1552 case VT_UI4 :
1553 case VT_INT :
1554 case VT_UINT :
1555 case VT_VOID : /* FIXME: is this right? */
1556 case VT_HRESULT :
1557 size=4; break;
1558 case VT_R8 :
1559 case VT_CY :
1560 case VT_DATE :
1561 case VT_I8 :
1562 case VT_UI8 :
1563 case VT_DECIMAL : /* FIXME: is this right? */
1564 case VT_FILETIME :
1565 size=8;break;
1566 /* pointer types with known behaviour */
1567 case VT_BSTR :{
1568 char * ptr;
1569 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1570 if(size < 0) {
1571 FIXME("BSTR length = %d?\n", size);
1572 } else {
1573 ptr=TLB_Alloc(size);/* allocate temp buffer */
1574 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1575 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1576 /* FIXME: do we need a AtoW conversion here? */
1577 V_UNION(pVar, bstrVal[size])=L'\0';
1578 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1579 TLB_Free(ptr);
1582 size=-4; break;
1583 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1584 case VT_DISPATCH :
1585 case VT_VARIANT :
1586 case VT_UNKNOWN :
1587 case VT_PTR :
1588 case VT_SAFEARRAY :
1589 case VT_CARRAY :
1590 case VT_USERDEFINED :
1591 case VT_LPSTR :
1592 case VT_LPWSTR :
1593 case VT_BLOB :
1594 case VT_STREAM :
1595 case VT_STORAGE :
1596 case VT_STREAMED_OBJECT :
1597 case VT_STORED_OBJECT :
1598 case VT_BLOB_OBJECT :
1599 case VT_CF :
1600 case VT_CLSID :
1601 default:
1602 size=0;
1603 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1604 V_VT(pVar));
1607 if(size>0) /* (big|small) endian correct? */
1608 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1609 return;
1612 * create a linked list with custom data
1614 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1616 MSFT_CDGuid entry;
1617 TLBCustData* pNew;
1618 int count=0;
1620 TRACE_(typelib)("\n");
1622 while(offset >=0){
1623 count++;
1624 pNew=TLB_Alloc(sizeof(TLBCustData));
1625 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1626 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1627 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1628 /* add new custom data at head of the list */
1629 pNew->next=*ppCustData;
1630 *ppCustData=pNew;
1631 offset = entry.next;
1633 return count;
1636 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1637 ITypeInfoImpl *pTI)
1639 if(type <0)
1640 pTd->vt=type & VT_TYPEMASK;
1641 else
1642 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1644 if(pTd->vt == VT_USERDEFINED)
1645 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1647 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1650 static void
1651 MSFT_DoFuncs(TLBContext* pcx,
1652 ITypeInfoImpl* pTI,
1653 int cFuncs,
1654 int cVars,
1655 int offset,
1656 TLBFuncDesc** pptfd)
1659 * member information is stored in a data structure at offset
1660 * indicated by the memoffset field of the typeinfo structure
1661 * There are several distinctive parts.
1662 * The first part starts with a field that holds the total length
1663 * of this (first) part excluding this field. Then follow the records,
1664 * for each member there is one record.
1666 * The first entry is always the length of the record (including this
1667 * length word).
1668 * The rest of the record depends on the type of the member. If there is
1669 * a field indicating the member type (function, variable, interface, etc)
1670 * I have not found it yet. At this time we depend on the information
1671 * in the type info and the usual order how things are stored.
1673 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1674 * for each member;
1676 * Third is an equal sized array with file offsets to the name entry
1677 * of each member.
1679 * The fourth and last (?) part is an array with offsets to the records
1680 * in the first part of this file segment.
1683 int infolen, nameoffset, reclength, nrattributes, i;
1684 int recoffset = offset + sizeof(INT);
1686 char recbuf[512];
1687 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1689 TRACE_(typelib)("\n");
1691 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1693 for ( i = 0; i < cFuncs ; i++ )
1695 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1697 /* name, eventually add to a hash table */
1698 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1699 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1701 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1703 /* read the function information record */
1704 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1706 reclength &= 0x1ff;
1708 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1710 /* do the attributes */
1711 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1712 / sizeof(int);
1714 if ( nrattributes > 0 )
1716 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1718 if ( nrattributes > 1 )
1720 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1721 pFuncRec->OptAttr[1]) ;
1723 if ( nrattributes > 2 )
1725 if ( pFuncRec->FKCCIC & 0x2000 )
1727 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1729 else
1731 (*pptfd)->Entry = MSFT_ReadString(pcx,
1732 pFuncRec->OptAttr[2]);
1734 if( nrattributes > 5 )
1736 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1738 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1740 MSFT_CustData(pcx,
1741 pFuncRec->OptAttr[6],
1742 &(*pptfd)->pCustData);
1749 /* fill the FuncDesc Structure */
1750 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1751 offset + infolen + ( i + 1) * sizeof(INT));
1753 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1754 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1755 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1756 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1757 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1758 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1759 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1761 MSFT_GetTdesc(pcx,
1762 pFuncRec->DataType,
1763 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1764 pTI);
1766 /* do the parameters/arguments */
1767 if(pFuncRec->nrargs)
1769 int j = 0;
1770 MSFT_ParameterInfo paraminfo;
1772 (*pptfd)->funcdesc.lprgelemdescParam =
1773 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1775 (*pptfd)->pParamDesc =
1776 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1778 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1779 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1781 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1783 TYPEDESC* lpArgTypeDesc = 0;
1785 MSFT_GetTdesc(pcx,
1786 paraminfo.DataType,
1787 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1788 pTI);
1790 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1792 /* name */
1793 if (paraminfo.oName == -1)
1794 /* this occurs for [propput] or [propget] methods, so
1795 * we should just set the name of the parameter to the
1796 * name of the method. */
1797 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1798 else
1799 (*pptfd)->pParamDesc[j].Name =
1800 MSFT_ReadName( pcx, paraminfo.oName );
1801 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1803 /* SEEK value = jump to offset,
1804 * from there jump to the end of record,
1805 * go back by (j-1) arguments
1807 MSFT_ReadLEDWords( &paraminfo ,
1808 sizeof(MSFT_ParameterInfo), pcx,
1809 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1810 * sizeof(MSFT_ParameterInfo)));
1811 lpArgTypeDesc =
1812 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1814 while ( lpArgTypeDesc != NULL )
1816 switch ( lpArgTypeDesc->vt )
1818 case VT_PTR:
1819 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1820 break;
1822 case VT_CARRAY:
1823 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1824 break;
1826 case VT_USERDEFINED:
1827 MSFT_DoRefType(pcx, pTI,
1828 lpArgTypeDesc->u.hreftype);
1830 lpArgTypeDesc = NULL;
1831 break;
1833 default:
1834 lpArgTypeDesc = NULL;
1840 /* parameter is the return value! */
1841 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1843 TYPEDESC* lpArgTypeDesc;
1845 (*pptfd)->funcdesc.elemdescFunc =
1846 (*pptfd)->funcdesc.lprgelemdescParam[j];
1848 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1850 while ( lpArgTypeDesc != NULL )
1852 switch ( lpArgTypeDesc->vt )
1854 case VT_PTR:
1855 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1856 break;
1857 case VT_CARRAY:
1858 lpArgTypeDesc =
1859 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1861 break;
1863 case VT_USERDEFINED:
1864 MSFT_DoRefType(pcx,
1865 pTI,
1866 lpArgTypeDesc->u.hreftype);
1868 lpArgTypeDesc = NULL;
1869 break;
1871 default:
1872 lpArgTypeDesc = NULL;
1877 /* second time around */
1878 for(j=0;j<pFuncRec->nrargs;j++)
1880 /* default value */
1881 if ( (PARAMFLAG_FHASDEFAULT &
1882 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1883 ((pFuncRec->FKCCIC) & 0x1000) )
1885 INT* pInt = (INT *)((char *)pFuncRec +
1886 reclength -
1887 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1889 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1891 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1892 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1894 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1895 pInt[j], pcx);
1897 /* custom info */
1898 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1900 MSFT_CustData(pcx,
1901 pFuncRec->OptAttr[7+j],
1902 &(*pptfd)->pParamDesc[j].pCustData);
1907 /* scode is not used: archaic win16 stuff FIXME: right? */
1908 (*pptfd)->funcdesc.cScodes = 0 ;
1909 (*pptfd)->funcdesc.lprgscode = NULL ;
1911 pptfd = & ((*pptfd)->next);
1912 recoffset += reclength;
1916 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1917 int cVars, int offset, TLBVarDesc ** pptvd)
1919 int infolen, nameoffset, reclength;
1920 char recbuf[256];
1921 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1922 int i;
1923 int recoffset;
1925 TRACE_(typelib)("\n");
1927 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1928 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1929 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1930 recoffset += offset+sizeof(INT);
1931 for(i=0;i<cVars;i++){
1932 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1933 /* name, eventually add to a hash table */
1934 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1935 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1936 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1937 /* read the variable information record */
1938 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1939 reclength &=0xff;
1940 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1941 /* Optional data */
1942 if(reclength >(6*sizeof(INT)) )
1943 (*pptvd)->HelpContext=pVarRec->HelpContext;
1944 if(reclength >(7*sizeof(INT)) )
1945 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1946 if(reclength >(8*sizeof(INT)) )
1947 if(reclength >(9*sizeof(INT)) )
1948 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1949 /* fill the VarDesc Structure */
1950 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1951 offset + infolen + ( i + 1) * sizeof(INT));
1952 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1953 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1954 MSFT_GetTdesc(pcx, pVarRec->DataType,
1955 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1956 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1957 if(pVarRec->VarKind == VAR_CONST ){
1958 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1959 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1960 pVarRec->OffsValue, pcx);
1961 } else
1962 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1963 pptvd=&((*pptvd)->next);
1964 recoffset += reclength;
1967 /* fill in data for a hreftype (offset). When the referenced type is contained
1968 * in the typelib, it's just an (file) offset in the type info base dir.
1969 * If comes from import, it's an offset+1 in the ImpInfo table
1970 * */
1971 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1972 int offset)
1974 int j;
1975 TLBRefType **ppRefType = &pTI->reflist;
1977 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1979 while(*ppRefType) {
1980 if((*ppRefType)->reference == offset)
1981 return;
1982 ppRefType = &(*ppRefType)->next;
1985 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1986 sizeof(**ppRefType));
1988 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1989 /* external typelib */
1990 MSFT_ImpInfo impinfo;
1991 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1993 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1995 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1996 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1997 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1998 if(pImpLib->offset==impinfo.oImpFile) break;
1999 pImpLib=pImpLib->next;
2001 if(pImpLib){
2002 (*ppRefType)->reference=offset;
2003 (*ppRefType)->pImpTLInfo = pImpLib;
2004 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2005 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2006 (*ppRefType)->index = TLB_REF_USE_GUID;
2007 } else
2008 (*ppRefType)->index = impinfo.oGuid;
2009 }else{
2010 ERR("Cannot find a reference\n");
2011 (*ppRefType)->reference=-1;
2012 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2014 }else{
2015 /* in this typelib */
2016 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2017 (*ppRefType)->reference=offset;
2018 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2022 /* process Implemented Interfaces of a com class */
2023 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2024 int offset)
2026 int i;
2027 MSFT_RefRecord refrec;
2028 TLBImplType **ppImpl = &pTI->impltypelist;
2030 TRACE_(typelib)("\n");
2032 for(i=0;i<count;i++){
2033 if(offset<0) break; /* paranoia */
2034 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2035 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2036 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2037 (*ppImpl)->hRef = refrec.reftype;
2038 (*ppImpl)->implflags=refrec.flags;
2039 (*ppImpl)->ctCustData=
2040 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2041 offset=refrec.onext;
2042 ppImpl=&((*ppImpl)->next);
2046 * process a typeinfo record
2048 static ITypeInfoImpl * MSFT_DoTypeInfo(
2049 TLBContext *pcx,
2050 int count,
2051 ITypeLibImpl * pLibInfo)
2053 MSFT_TypeInfoBase tiBase;
2054 ITypeInfoImpl *ptiRet;
2056 TRACE_(typelib)("count=%u\n", count);
2058 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2059 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2060 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2062 /* this is where we are coming from */
2063 ptiRet->pTypeLib = pLibInfo;
2064 ptiRet->index=count;
2065 /* fill in the typeattr fields */
2066 WARN("Assign constructor/destructor memid\n");
2068 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2069 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2070 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2071 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2072 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2073 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2074 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2075 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2076 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2077 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2078 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2079 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2080 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2081 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2082 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2083 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2084 MSFT_GetTdesc(pcx, tiBase.datatype1,
2085 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2087 /* FIXME: */
2088 /* IDLDESC idldescType; *//* never saw this one != zero */
2090 /* name, eventually add to a hash table */
2091 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2092 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2093 /* help info */
2094 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2095 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2096 ptiRet->dwHelpContext=tiBase.helpcontext;
2098 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2099 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2101 /* note: InfoType's Help file and HelpStringDll come from the containing
2102 * library. Further HelpString and Docstring appear to be the same thing :(
2104 /* functions */
2105 if(ptiRet->TypeAttr.cFuncs >0 )
2106 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2107 ptiRet->TypeAttr.cVars,
2108 tiBase.memoffset, & ptiRet->funclist);
2109 /* variables */
2110 if(ptiRet->TypeAttr.cVars >0 )
2111 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2112 ptiRet->TypeAttr.cVars,
2113 tiBase.memoffset, & ptiRet->varlist);
2114 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2115 switch(ptiRet->TypeAttr.typekind)
2117 case TKIND_COCLASS:
2118 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2119 tiBase.datatype1);
2120 break;
2121 case TKIND_DISPATCH:
2122 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2124 if (tiBase.datatype1 != -1)
2126 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2127 ptiRet->impltypelist->hRef = tiBase.datatype1;
2129 else
2130 { /* FIXME: This is a really bad hack to add IDispatch */
2131 const char* szStdOle = "stdole2.tlb\0";
2132 int nStdOleLen = strlen(szStdOle);
2133 TLBRefType **ppRef = &ptiRet->reflist;
2135 while(*ppRef) {
2136 if((*ppRef)->reference == -1)
2137 break;
2138 ppRef = &(*ppRef)->next;
2140 if(!*ppRef) {
2141 *ppRef = TLB_Alloc(sizeof(**ppRef));
2142 (*ppRef)->guid = IID_IDispatch;
2143 (*ppRef)->reference = -1;
2144 (*ppRef)->index = TLB_REF_USE_GUID;
2145 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2146 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2147 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2148 nStdOleLen + 1);
2150 MultiByteToWideChar(CP_ACP,
2151 MB_PRECOMPOSED,
2152 szStdOle,
2154 (*ppRef)->pImpTLInfo->name,
2155 SysStringLen((*ppRef)->pImpTLInfo->name));
2157 (*ppRef)->pImpTLInfo->lcid = 0;
2158 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2159 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2162 break;
2163 default:
2164 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2165 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2166 ptiRet->impltypelist->hRef = tiBase.datatype1;
2167 break;
2170 ptiRet->ctCustData=
2171 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2173 TRACE_(typelib)("%s guid: %s kind:%s\n",
2174 debugstr_w(ptiRet->Name),
2175 debugstr_guid(&ptiRet->TypeAttr.guid),
2176 typekind_desc[ptiRet->TypeAttr.typekind]);
2178 return ptiRet;
2181 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2182 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2183 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2184 * tradeoff here.
2186 static ITypeLibImpl *tlb_cache_first;
2187 static CRITICAL_SECTION cache_section;
2188 static CRITICAL_SECTION_DEBUG cache_section_debug =
2190 0, 0, &cache_section,
2191 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2192 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2194 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2197 /****************************************************************************
2198 * TLB_ReadTypeLib
2200 * find the type of the typelib file and map the typelib resource into
2201 * the memory
2203 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2204 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2205 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2207 ITypeLibImpl *entry;
2208 int ret = TYPE_E_CANTLOADLIBRARY;
2209 DWORD dwSignature = 0;
2210 HANDLE hFile;
2212 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2214 *ppTypeLib = NULL;
2216 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2217 EnterCriticalSection(&cache_section);
2218 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2220 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2222 TRACE("cache hit\n");
2223 *ppTypeLib = (ITypeLib2*)entry;
2224 ITypeLib_AddRef(*ppTypeLib);
2225 LeaveCriticalSection(&cache_section);
2226 return S_OK;
2229 LeaveCriticalSection(&cache_section);
2231 /* check the signature of the file */
2232 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2233 if (INVALID_HANDLE_VALUE != hFile)
2235 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2236 if (hMapping)
2238 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2239 if(pBase)
2241 /* retrieve file size */
2242 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2244 /* first try to load as *.tlb */
2245 dwSignature = FromLEDWord(*((DWORD*) pBase));
2246 if ( dwSignature == MSFT_SIGNATURE)
2248 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2250 else if ( dwSignature == SLTG_SIGNATURE)
2252 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2254 UnmapViewOfFile(pBase);
2256 CloseHandle(hMapping);
2258 CloseHandle(hFile);
2260 else
2262 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2265 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2266 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2268 /* find the typelibrary resource*/
2269 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2270 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2271 if (hinstDLL)
2273 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2274 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2275 if (hrsrc)
2277 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2278 if (hGlobal)
2280 LPVOID pBase = LockResource(hGlobal);
2281 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2283 if (pBase)
2285 /* try to load as incore resource */
2286 dwSignature = FromLEDWord(*((DWORD*) pBase));
2287 if ( dwSignature == MSFT_SIGNATURE)
2289 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2291 else if ( dwSignature == SLTG_SIGNATURE)
2293 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2295 else
2297 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2300 FreeResource( hGlobal );
2303 FreeLibrary(hinstDLL);
2307 if(*ppTypeLib) {
2308 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2310 TRACE("adding to cache\n");
2311 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2312 lstrcpyW(impl->path, pszFileName);
2313 /* We should really canonicalise the path here. */
2314 impl->index = index;
2316 /* FIXME: check if it has added already in the meantime */
2317 EnterCriticalSection(&cache_section);
2318 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2319 impl->prev = NULL;
2320 tlb_cache_first = impl;
2321 LeaveCriticalSection(&cache_section);
2322 ret = S_OK;
2323 } else
2324 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2326 return ret;
2329 /*================== ITypeLib(2) Methods ===================================*/
2331 /****************************************************************************
2332 * ITypeLib2_Constructor_MSFT
2334 * loading an MSFT typelib from an in-memory image
2336 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2338 TLBContext cx;
2339 long lPSegDir;
2340 MSFT_Header tlbHeader;
2341 MSFT_SegDir tlbSegDir;
2342 ITypeLibImpl * pTypeLibImpl;
2344 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2346 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2347 if (!pTypeLibImpl) return NULL;
2349 pTypeLibImpl->lpVtbl = &tlbvt;
2350 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2351 pTypeLibImpl->ref = 1;
2353 /* get pointer to beginning of typelib data */
2354 cx.pos = 0;
2355 cx.oStart=0;
2356 cx.mapping = pLib;
2357 cx.pLibInfo = pTypeLibImpl;
2358 cx.length = dwTLBLength;
2360 /* read header */
2361 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2362 TRACE("header:\n");
2363 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2364 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2365 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2366 return NULL;
2368 /* there is a small amount of information here until the next important
2369 * part:
2370 * the segment directory . Try to calculate the amount of data */
2371 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2373 /* now read the segment directory */
2374 TRACE("read segment directory (at %ld)\n",lPSegDir);
2375 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2376 cx.pTblDir = &tlbSegDir;
2378 /* just check two entries */
2379 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2381 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2382 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2383 return NULL;
2386 /* now fill our internal data */
2387 /* TLIBATTR fields */
2388 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2390 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2391 /* Windows seems to have zero here, is this correct? */
2392 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2393 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2394 else
2395 pTypeLibImpl->LibAttr.lcid = 0;
2397 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2398 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2399 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2400 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2402 /* name, eventually add to a hash table */
2403 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2405 /* help info */
2406 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2407 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2409 if( tlbHeader.varflags & HELPDLLFLAG)
2411 int offset;
2412 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2413 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2416 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2418 /* custom data */
2419 if(tlbHeader.CustomDataOffset >= 0)
2421 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2424 /* fill in typedescriptions */
2425 if(tlbSegDir.pTypdescTab.length > 0)
2427 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2428 INT16 td[4];
2429 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2430 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2431 for(i=0; i<cTD; )
2433 /* FIXME: add several sanity checks here */
2434 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2435 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2437 /* FIXME: check safearray */
2438 if(td[3] < 0)
2439 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2440 else
2441 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2443 else if(td[0] == VT_CARRAY)
2445 /* array descr table here */
2446 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2448 else if(td[0] == VT_USERDEFINED)
2450 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2452 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2455 /* second time around to fill the array subscript info */
2456 for(i=0;i<cTD;i++)
2458 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2459 if(tlbSegDir.pArrayDescriptions.offset>0)
2461 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2462 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2464 if(td[1]<0)
2465 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2466 else
2467 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2469 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2471 for(j = 0; j<td[2]; j++)
2473 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2474 sizeof(INT), &cx, DO_NOT_SEEK);
2475 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2476 sizeof(INT), &cx, DO_NOT_SEEK);
2479 else
2481 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2482 ERR("didn't find array description data\n");
2487 /* imported type libs */
2488 if(tlbSegDir.pImpFiles.offset>0)
2490 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2491 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2492 UINT16 size;
2494 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2496 char *name;
2497 DWORD len;
2499 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2500 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2501 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2503 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2504 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2505 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2506 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2508 size >>= 2;
2509 name = TLB_Alloc(size+1);
2510 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2511 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2512 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2513 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2514 TLB_Free(name);
2516 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2517 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2519 ppImpLib = &(*ppImpLib)->next;
2523 /* type info's */
2524 if(tlbHeader.nrtypeinfos >= 0 )
2526 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2527 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2528 int i;
2530 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2532 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2534 ppTI = &((*ppTI)->next);
2535 (pTypeLibImpl->TypeInfoCount)++;
2539 TRACE("(%p)\n", pTypeLibImpl);
2540 return (ITypeLib2*) pTypeLibImpl;
2544 static BSTR TLB_MultiByteToBSTR(char *ptr)
2546 DWORD len;
2547 WCHAR *nameW;
2548 BSTR ret;
2550 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2551 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2552 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2553 ret = SysAllocString(nameW);
2554 HeapFree(GetProcessHeap(), 0, nameW);
2555 return ret;
2558 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2560 char b[3];
2561 int i;
2562 short s;
2564 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2565 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2566 return FALSE;
2569 guid->Data4[0] = s >> 8;
2570 guid->Data4[1] = s & 0xff;
2572 b[2] = '\0';
2573 for(i = 0; i < 6; i++) {
2574 memcpy(b, str + 24 + 2 * i, 2);
2575 guid->Data4[i + 2] = strtol(b, NULL, 16);
2577 return TRUE;
2580 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2582 WORD bytelen;
2583 DWORD len;
2584 WCHAR *nameW;
2586 *pBstr = NULL;
2587 bytelen = *(WORD*)ptr;
2588 if(bytelen == 0xffff) return 2;
2589 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2590 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2591 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2592 *pBstr = SysAllocStringLen(nameW, len);
2593 HeapFree(GetProcessHeap(), 0, nameW);
2594 return bytelen + 2;
2597 static WORD SLTG_ReadStringA(char *ptr, char **str)
2599 WORD bytelen;
2601 *str = NULL;
2602 bytelen = *(WORD*)ptr;
2603 if(bytelen == 0xffff) return 2;
2604 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2605 memcpy(*str, ptr + 2, bytelen);
2606 (*str)[bytelen] = '\0';
2607 return bytelen + 2;
2610 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2612 char *ptr = pLibBlk;
2613 WORD w;
2615 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2616 FIXME("libblk magic = %04x\n", w);
2617 return 0;
2620 ptr += 6;
2621 if((w = *(WORD*)ptr) != 0xffff) {
2622 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2623 ptr += w;
2625 ptr += 2;
2627 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2629 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2631 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2632 ptr += 4;
2634 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2635 ptr += 2;
2637 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2638 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2639 else
2640 pTypeLibImpl->LibAttr.lcid = 0;
2641 ptr += 2;
2643 ptr += 4; /* skip res12 */
2645 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2646 ptr += 2;
2648 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2649 ptr += 2;
2651 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2652 ptr += 2;
2654 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2655 ptr += sizeof(GUID);
2657 return ptr - (char*)pLibBlk;
2660 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2662 BOOL done = FALSE;
2663 TYPEDESC *pTD = &pElem->tdesc;
2665 /* Handle [in/out] first */
2666 if((*pType & 0xc000) == 0xc000)
2667 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2668 else if(*pType & 0x8000)
2669 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2670 else if(*pType & 0x4000)
2671 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2672 else
2673 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2675 if(*pType & 0x2000)
2676 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2678 if(*pType & 0x80)
2679 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2681 while(!done) {
2682 if((*pType & 0xe00) == 0xe00) {
2683 pTD->vt = VT_PTR;
2684 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2685 sizeof(TYPEDESC));
2686 pTD = pTD->u.lptdesc;
2688 switch(*pType & 0x7f) {
2689 case VT_PTR:
2690 pTD->vt = VT_PTR;
2691 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2692 sizeof(TYPEDESC));
2693 pTD = pTD->u.lptdesc;
2694 break;
2696 case VT_USERDEFINED:
2697 pTD->vt = VT_USERDEFINED;
2698 pTD->u.hreftype = *(++pType) / 4;
2699 done = TRUE;
2700 break;
2702 case VT_CARRAY:
2704 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2705 array */
2707 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2709 pTD->vt = VT_CARRAY;
2710 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2711 sizeof(ARRAYDESC) +
2712 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2713 pTD->u.lpadesc->cDims = pSA->cDims;
2714 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2715 pSA->cDims * sizeof(SAFEARRAYBOUND));
2717 pTD = &pTD->u.lpadesc->tdescElem;
2718 break;
2721 case VT_SAFEARRAY:
2723 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2724 useful? */
2726 pType++;
2727 pTD->vt = VT_SAFEARRAY;
2728 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2729 sizeof(TYPEDESC));
2730 pTD = pTD->u.lptdesc;
2731 break;
2733 default:
2734 pTD->vt = *pType & 0x7f;
2735 done = TRUE;
2736 break;
2738 pType++;
2740 return pType;
2744 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2745 char *pNameTable)
2747 int ref;
2748 char *name;
2749 TLBRefType **ppRefType;
2751 if(pRef->magic != SLTG_REF_MAGIC) {
2752 FIXME("Ref magic = %x\n", pRef->magic);
2753 return;
2755 name = ( (char*)(&pRef->names) + pRef->number);
2757 ppRefType = &pTI->reflist;
2758 for(ref = 0; ref < pRef->number >> 3; ref++) {
2759 char *refname;
2760 unsigned int lib_offs, type_num;
2762 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2763 sizeof(**ppRefType));
2765 name += SLTG_ReadStringA(name, &refname);
2766 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2767 FIXME("Can't sscanf ref\n");
2768 if(lib_offs != 0xffff) {
2769 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2771 while(*import) {
2772 if((*import)->offset == lib_offs)
2773 break;
2774 import = &(*import)->next;
2776 if(!*import) {
2777 char fname[MAX_PATH+1];
2778 int len;
2780 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2781 sizeof(**import));
2782 (*import)->offset = lib_offs;
2783 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2784 &(*import)->guid);
2785 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2786 &(*import)->wVersionMajor,
2787 &(*import)->wVersionMinor,
2788 &(*import)->lcid, fname) != 4) {
2789 FIXME("can't sscanf ref %s\n",
2790 pNameTable + lib_offs + 40);
2792 len = strlen(fname);
2793 if(fname[len-1] != '#')
2794 FIXME("fname = %s\n", fname);
2795 fname[len-1] = '\0';
2796 (*import)->name = TLB_MultiByteToBSTR(fname);
2798 (*ppRefType)->pImpTLInfo = *import;
2799 } else { /* internal ref */
2800 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2802 (*ppRefType)->reference = ref;
2803 (*ppRefType)->index = type_num;
2805 HeapFree(GetProcessHeap(), 0, refname);
2806 ppRefType = &(*ppRefType)->next;
2808 if((BYTE)*name != SLTG_REF_MAGIC)
2809 FIXME("End of ref block magic = %x\n", *name);
2810 dump_TLBRefType(pTI->reflist);
2813 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2814 BOOL OneOnly)
2816 SLTG_ImplInfo *info;
2817 TLBImplType **ppImplType = &pTI->impltypelist;
2818 /* I don't really get this structure, usually it's 0x16 bytes
2819 long, but iuser.tlb contains some that are 0x18 bytes long.
2820 That's ok because we can use the next ptr to jump to the next
2821 one. But how do we know the length of the last one? The WORD
2822 at offs 0x8 might be the clue. For now I'm just assuming that
2823 the last one is the regular 0x16 bytes. */
2825 info = (SLTG_ImplInfo*)pBlk;
2826 while(1) {
2827 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2828 sizeof(**ppImplType));
2829 (*ppImplType)->hRef = info->ref;
2830 (*ppImplType)->implflags = info->impltypeflags;
2831 pTI->TypeAttr.cImplTypes++;
2832 ppImplType = &(*ppImplType)->next;
2834 if(info->next == 0xffff)
2835 break;
2836 if(OneOnly)
2837 FIXME("Interface inheriting more than one interface\n");
2838 info = (SLTG_ImplInfo*)(pBlk + info->next);
2840 info++; /* see comment at top of function */
2841 return (char*)info;
2844 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2845 char *pNameTable)
2847 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2848 SLTG_MemberHeader *pMemHeader;
2849 char *pFirstItem, *pNextItem;
2851 if(pTIHeader->href_table != 0xffffffff) {
2852 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2853 pNameTable);
2857 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2859 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2861 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2862 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2865 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2869 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2870 char *pNameTable)
2872 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2873 SLTG_MemberHeader *pMemHeader;
2874 SLTG_Function *pFunc;
2875 char *pFirstItem, *pNextItem;
2876 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2877 int num = 0;
2879 if(pTIHeader->href_table != 0xffffffff) {
2880 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2881 pNameTable);
2884 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2886 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2888 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2889 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2892 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2893 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2895 int param;
2896 WORD *pType, *pArg;
2898 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2899 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2900 FIXME("func magic = %02x\n", pFunc->magic);
2901 return NULL;
2903 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2904 sizeof(**ppFuncDesc));
2905 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2907 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2908 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2909 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2910 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2911 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2912 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2914 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2915 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2917 if(pFunc->retnextopt & 0x80)
2918 pType = &pFunc->rettype;
2919 else
2920 pType = (WORD*)(pFirstItem + pFunc->rettype);
2923 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2925 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2926 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2927 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2928 (*ppFuncDesc)->pParamDesc =
2929 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2930 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2932 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2934 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2935 char *paramName = pNameTable + *pArg;
2936 BOOL HaveOffs;
2937 /* If arg type follows then paramName points to the 2nd
2938 letter of the name, else the next WORD is an offset to
2939 the arg type and paramName points to the first letter.
2940 So let's take one char off paramName and see if we're
2941 pointing at an alpha-numeric char. However if *pArg is
2942 0xffff or 0xfffe then the param has no name, the former
2943 meaning that the next WORD is the type, the latter
2944 meaning the the next WORD is an offset to the type. */
2946 HaveOffs = FALSE;
2947 if(*pArg == 0xffff)
2948 paramName = NULL;
2949 else if(*pArg == 0xfffe) {
2950 paramName = NULL;
2951 HaveOffs = TRUE;
2953 else if(paramName[-1] && !isalnum(paramName[-1]))
2954 HaveOffs = TRUE;
2956 pArg++;
2958 if(HaveOffs) { /* the next word is an offset to type */
2959 pType = (WORD*)(pFirstItem + *pArg);
2960 SLTG_DoType(pType, pFirstItem,
2961 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2962 pArg++;
2963 } else {
2964 if(paramName)
2965 paramName--;
2966 pArg = SLTG_DoType(pArg, pFirstItem,
2967 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2970 /* Are we an optional param ? */
2971 if((*ppFuncDesc)->funcdesc.cParams - param <=
2972 (*ppFuncDesc)->funcdesc.cParamsOpt)
2973 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2975 if(paramName) {
2976 (*ppFuncDesc)->pParamDesc[param].Name =
2977 TLB_MultiByteToBSTR(paramName);
2981 ppFuncDesc = &((*ppFuncDesc)->next);
2982 if(pFunc->next == 0xffff) break;
2984 pTI->TypeAttr.cFuncs = num;
2985 dump_TLBFuncDesc(pTI->funclist);
2986 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2989 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2990 char *pNameTable)
2992 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2993 SLTG_MemberHeader *pMemHeader;
2994 SLTG_RecordItem *pItem;
2995 char *pFirstItem;
2996 TLBVarDesc **ppVarDesc = &pTI->varlist;
2997 int num = 0;
2998 WORD *pType;
2999 char buf[300];
3001 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3003 pFirstItem = (char*)(pMemHeader + 1);
3004 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
3005 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
3006 if(pItem->magic != SLTG_RECORD_MAGIC) {
3007 FIXME("record magic = %02x\n", pItem->magic);
3008 return NULL;
3010 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3011 sizeof(**ppVarDesc));
3012 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3013 (*ppVarDesc)->vardesc.memid = pItem->memid;
3014 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3015 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3017 if(pItem->typepos == 0x02)
3018 pType = &pItem->type;
3019 else if(pItem->typepos == 0x00)
3020 pType = (WORD*)(pFirstItem + pItem->type);
3021 else {
3022 FIXME("typepos = %02x\n", pItem->typepos);
3023 break;
3026 SLTG_DoType(pType, pFirstItem,
3027 &(*ppVarDesc)->vardesc.elemdescVar);
3029 /* FIXME("helpcontext, helpstring\n"); */
3031 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3033 ppVarDesc = &((*ppVarDesc)->next);
3034 if(pItem->next == 0xffff) break;
3036 pTI->TypeAttr.cVars = num;
3037 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3040 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3041 char *pNameTable)
3043 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3044 SLTG_MemberHeader *pMemHeader;
3045 SLTG_AliasItem *pItem;
3046 int i, mustbelast;
3048 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3049 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3051 mustbelast = 0;
3052 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3053 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3054 if (pItem->vt == 0xffff) {
3055 if (i<(pMemHeader->cbExtra/4-1))
3056 FIXME("Endmarker too early in process alias data!\n");
3057 break;
3059 if (mustbelast) {
3060 FIXME("Chain extends over last entry?\n");
3061 break;
3063 if (pItem->vt == VT_USERDEFINED) {
3064 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3065 /* guessing here ... */
3066 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3067 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3068 mustbelast = 1;
3069 } else {
3070 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3071 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3073 pItem++;
3075 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3078 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3079 char *pNameTable)
3081 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3082 SLTG_MemberHeader *pMemHeader;
3083 SLTG_AliasItem *pItem;
3085 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3086 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3087 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3088 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3089 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3092 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3093 char *pNameTable)
3095 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3096 SLTG_MemberHeader *pMemHeader;
3097 SLTG_EnumItem *pItem;
3098 char *pFirstItem;
3099 TLBVarDesc **ppVarDesc = &pTI->varlist;
3100 int num = 0;
3102 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3104 pFirstItem = (char*)(pMemHeader + 1);
3105 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3106 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3107 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3108 FIXME("enumitem magic = %04x\n", pItem->magic);
3109 return NULL;
3111 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3112 sizeof(**ppVarDesc));
3113 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3114 (*ppVarDesc)->vardesc.memid = pItem->memid;
3115 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3116 sizeof(VARIANT));
3117 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3118 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3119 *(INT*)(pItem->value + pFirstItem);
3120 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3121 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3122 /* FIXME("helpcontext, helpstring\n"); */
3124 ppVarDesc = &((*ppVarDesc)->next);
3125 if(pItem->next == 0xffff) break;
3127 pTI->TypeAttr.cVars = num;
3128 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3131 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3132 managable copy of it into this */
3133 typedef struct {
3134 WORD small_no;
3135 char *index_name;
3136 char *other_name;
3137 WORD res1a;
3138 WORD name_offs;
3139 WORD more_bytes;
3140 char *extra;
3141 WORD res20;
3142 DWORD helpcontext;
3143 WORD res26;
3144 GUID uuid;
3145 } SLTG_InternalOtherTypeInfo;
3147 /****************************************************************************
3148 * ITypeLib2_Constructor_SLTG
3150 * loading a SLTG typelib from an in-memory image
3152 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3154 ITypeLibImpl *pTypeLibImpl;
3155 SLTG_Header *pHeader;
3156 SLTG_BlkEntry *pBlkEntry;
3157 SLTG_Magic *pMagic;
3158 SLTG_Index *pIndex;
3159 SLTG_Pad9 *pPad9;
3160 LPVOID pBlk, pFirstBlk;
3161 SLTG_LibBlk *pLibBlk;
3162 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3163 char *pAfterOTIBlks = NULL;
3164 char *pNameTable, *ptr;
3165 int i;
3166 DWORD len, order;
3167 ITypeInfoImpl **ppTypeInfoImpl;
3169 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3171 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3172 if (!pTypeLibImpl) return NULL;
3174 pTypeLibImpl->lpVtbl = &tlbvt;
3175 pTypeLibImpl->ref = 1;
3177 pHeader = pLib;
3179 TRACE_(typelib)("header:\n");
3180 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3181 pHeader->nrOfFileBlks );
3182 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3183 FIXME("Header type magic 0x%08lx not supported.\n",
3184 pHeader->SLTG_magic);
3185 return NULL;
3188 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3189 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3191 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3192 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3194 /* Next we have a magic block */
3195 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3197 /* Let's see if we're still in sync */
3198 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3199 sizeof(SLTG_COMPOBJ_MAGIC))) {
3200 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3201 return NULL;
3203 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3204 sizeof(SLTG_DIR_MAGIC))) {
3205 FIXME("dir magic = %s\n", pMagic->dir_magic);
3206 return NULL;
3209 pIndex = (SLTG_Index*)(pMagic+1);
3211 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3213 pFirstBlk = (LPVOID)(pPad9 + 1);
3215 /* We'll set up a ptr to the main library block, which is the last one. */
3217 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3218 pBlkEntry[order].next != 0;
3219 order = pBlkEntry[order].next - 1, i++) {
3220 pBlk = (char*)pBlk + pBlkEntry[order].len;
3222 pLibBlk = pBlk;
3224 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3226 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3227 interspersed */
3229 len += 0x40;
3231 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3233 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3234 sizeof(*pOtherTypeInfoBlks) *
3235 pTypeLibImpl->TypeInfoCount);
3238 ptr = (char*)pLibBlk + len;
3240 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3241 WORD w, extra;
3242 len = 0;
3244 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3246 w = *(WORD*)(ptr + 2);
3247 if(w != 0xffff) {
3248 len += w;
3249 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3250 w+1);
3251 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3252 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3254 w = *(WORD*)(ptr + 4 + len);
3255 if(w != 0xffff) {
3256 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3257 len += w;
3258 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3259 w+1);
3260 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3261 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3263 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3264 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3265 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3266 if(extra) {
3267 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3268 extra);
3269 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3270 len += extra;
3272 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3273 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3274 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3275 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3276 len += sizeof(SLTG_OtherTypeInfo);
3277 ptr += len;
3280 pAfterOTIBlks = ptr;
3282 /* Skip this WORD and get the next DWORD */
3283 len = *(DWORD*)(pAfterOTIBlks + 2);
3285 /* Now add this to pLibBLk look at what we're pointing at and
3286 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3287 dust and we should be pointing at the beginning of the name
3288 table */
3290 pNameTable = (char*)pLibBlk + len;
3292 switch(*(WORD*)pNameTable) {
3293 case 0xffff:
3294 break;
3295 case 0x0200:
3296 pNameTable += 0x20;
3297 break;
3298 default:
3299 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3300 break;
3303 pNameTable += 0x216;
3305 pNameTable += 2;
3307 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3309 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3312 /* Hopefully we now have enough ptrs set up to actually read in
3313 some TypeInfos. It's not clear which order to do them in, so
3314 I'll just follow the links along the BlkEntry chain and read
3315 them in in the order in which they're in the file */
3317 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3319 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3320 pBlkEntry[order].next != 0;
3321 order = pBlkEntry[order].next - 1, i++) {
3323 SLTG_TypeInfoHeader *pTIHeader;
3324 SLTG_TypeInfoTail *pTITail;
3326 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3327 pOtherTypeInfoBlks[i].index_name)) {
3328 FIXME("Index strings don't match\n");
3329 return NULL;
3332 pTIHeader = pBlk;
3333 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3334 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3335 return NULL;
3337 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3338 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3339 (*ppTypeInfoImpl)->index = i;
3340 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3341 pOtherTypeInfoBlks[i].name_offs +
3342 pNameTable);
3343 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3344 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3345 sizeof(GUID));
3346 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3347 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3348 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3349 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3350 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3352 if((pTIHeader->typeflags1 & 7) != 2)
3353 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3354 if(pTIHeader->typeflags3 != 2)
3355 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3357 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3358 debugstr_w((*ppTypeInfoImpl)->Name),
3359 typekind_desc[pTIHeader->typekind],
3360 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3361 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3363 switch(pTIHeader->typekind) {
3364 case TKIND_ENUM:
3365 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3366 break;
3368 case TKIND_RECORD:
3369 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3370 break;
3372 case TKIND_INTERFACE:
3373 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3374 break;
3376 case TKIND_COCLASS:
3377 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3378 break;
3380 case TKIND_ALIAS:
3381 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3382 if (pTITail->tdescalias_vt)
3383 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3384 break;
3386 case TKIND_DISPATCH:
3387 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3388 break;
3390 default:
3391 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3392 pTITail = NULL;
3393 break;
3397 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3398 but we've already set those */
3399 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3400 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3401 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3403 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3404 X(06);
3405 X(08);
3406 X(0a);
3407 X(0c);
3408 X(0e);
3409 X(10);
3410 X(12);
3411 X(16);
3412 X(18);
3413 X(1a);
3414 X(1c);
3415 X(1e);
3416 X(24);
3417 X(26);
3418 X(2a);
3419 X(2c);
3420 X(2e);
3421 X(30);
3422 X(32);
3423 X(34);
3425 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3426 pBlk = (char*)pBlk + pBlkEntry[order].len;
3429 if(i != pTypeLibImpl->TypeInfoCount) {
3430 FIXME("Somehow processed %d TypeInfos\n", i);
3431 return NULL;
3434 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3435 return (ITypeLib2*)pTypeLibImpl;
3438 /* ITypeLib::QueryInterface
3440 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3441 ITypeLib2 * iface,
3442 REFIID riid,
3443 VOID **ppvObject)
3445 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3447 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3449 *ppvObject=NULL;
3450 if(IsEqualIID(riid, &IID_IUnknown) ||
3451 IsEqualIID(riid,&IID_ITypeLib)||
3452 IsEqualIID(riid,&IID_ITypeLib2))
3454 *ppvObject = This;
3457 if(*ppvObject)
3459 ITypeLib2_AddRef(iface);
3460 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3461 return S_OK;
3463 TRACE("-- Interface: E_NOINTERFACE\n");
3464 return E_NOINTERFACE;
3467 /* ITypeLib::AddRef
3469 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3471 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3472 ULONG ref = InterlockedIncrement(&This->ref);
3474 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3476 return ref;
3479 /* ITypeLib::Release
3481 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3483 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3484 ULONG ref = InterlockedDecrement(&This->ref);
3486 TRACE("(%p)->(%lu)\n",This, ref);
3488 if (!ref)
3490 /* remove cache entry */
3491 TRACE("removing from cache list\n");
3492 EnterCriticalSection(&cache_section);
3493 if (This->next) This->next->prev = This->prev;
3494 if (This->prev) This->prev->next = This->next;
3495 else tlb_cache_first = This->next;
3496 LeaveCriticalSection(&cache_section);
3498 /* FIXME destroy child objects */
3499 TRACE(" destroying ITypeLib(%p)\n",This);
3501 if (This->Name)
3503 SysFreeString(This->Name);
3504 This->Name = NULL;
3507 if (This->DocString)
3509 SysFreeString(This->DocString);
3510 This->DocString = NULL;
3513 if (This->HelpFile)
3515 SysFreeString(This->HelpFile);
3516 This->HelpFile = NULL;
3519 if (This->HelpStringDll)
3521 SysFreeString(This->HelpStringDll);
3522 This->HelpStringDll = NULL;
3525 if (This->pTypeInfo) /* can be NULL */
3526 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3527 HeapFree(GetProcessHeap(),0,This);
3528 return 0;
3531 return ref;
3534 /* ITypeLib::GetTypeInfoCount
3536 * Returns the number of type descriptions in the type library
3538 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3540 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3541 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3542 return This->TypeInfoCount;
3545 /* ITypeLib::GetTypeInfo
3547 * retrieves the specified type description in the library.
3549 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3550 ITypeLib2 *iface,
3551 UINT index,
3552 ITypeInfo **ppTInfo)
3554 int i;
3556 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3557 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3559 TRACE("(%p)->(index=%d)\n", This, index);
3561 if (!ppTInfo) return E_INVALIDARG;
3563 /* search element n in list */
3564 for(i=0; i < index; i++)
3566 pTypeInfo = pTypeInfo->next;
3567 if (!pTypeInfo)
3569 TRACE("-- element not found\n");
3570 return TYPE_E_ELEMENTNOTFOUND;
3574 *ppTInfo = (ITypeInfo *) pTypeInfo;
3576 ITypeInfo_AddRef(*ppTInfo);
3577 TRACE("-- found (%p)\n",*ppTInfo);
3578 return S_OK;
3582 /* ITypeLibs::GetTypeInfoType
3584 * Retrieves the type of a type description.
3586 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3587 ITypeLib2 *iface,
3588 UINT index,
3589 TYPEKIND *pTKind)
3591 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3592 int i;
3593 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3595 TRACE("(%p) index %d\n", This, index);
3597 if(!pTKind) return E_INVALIDARG;
3599 /* search element n in list */
3600 for(i=0; i < index; i++)
3602 if(!pTInfo)
3604 TRACE("-- element not found\n");
3605 return TYPE_E_ELEMENTNOTFOUND;
3607 pTInfo = pTInfo->next;
3610 *pTKind = pTInfo->TypeAttr.typekind;
3611 TRACE("-- found Type (%d)\n", *pTKind);
3612 return S_OK;
3615 /* ITypeLib::GetTypeInfoOfGuid
3617 * Retrieves the type description that corresponds to the specified GUID.
3620 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3621 ITypeLib2 *iface,
3622 REFGUID guid,
3623 ITypeInfo **ppTInfo)
3625 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3626 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3628 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3630 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3632 /* search linked list for guid */
3633 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3635 pTypeInfo = pTypeInfo->next;
3637 if (!pTypeInfo)
3639 /* end of list reached */
3640 TRACE("-- element not found\n");
3641 return TYPE_E_ELEMENTNOTFOUND;
3645 TRACE("-- found (%p, %s)\n",
3646 pTypeInfo,
3647 debugstr_w(pTypeInfo->Name));
3649 *ppTInfo = (ITypeInfo*)pTypeInfo;
3650 ITypeInfo_AddRef(*ppTInfo);
3651 return S_OK;
3654 /* ITypeLib::GetLibAttr
3656 * Retrieves the structure that contains the library's attributes.
3659 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3660 ITypeLib2 *iface,
3661 LPTLIBATTR *ppTLibAttr)
3663 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3664 TRACE("(%p)\n",This);
3665 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3666 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3667 return S_OK;
3670 /* ITypeLib::GetTypeComp
3672 * Enables a client compiler to bind to a library's types, variables,
3673 * constants, and global functions.
3676 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3677 ITypeLib2 *iface,
3678 ITypeComp **ppTComp)
3680 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3682 TRACE("(%p)->(%p)\n",This,ppTComp);
3683 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3684 ITypeComp_AddRef(*ppTComp);
3686 return S_OK;
3689 /* ITypeLib::GetDocumentation
3691 * Retrieves the library's documentation string, the complete Help file name
3692 * and path, and the context identifier for the library Help topic in the Help
3693 * file.
3695 * On a successful return all non-null BSTR pointers will have been set,
3696 * possibly to NULL.
3698 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3699 ITypeLib2 *iface,
3700 INT index,
3701 BSTR *pBstrName,
3702 BSTR *pBstrDocString,
3703 DWORD *pdwHelpContext,
3704 BSTR *pBstrHelpFile)
3706 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3708 HRESULT result = E_INVALIDARG;
3710 ITypeInfo *pTInfo;
3713 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3714 This, index,
3715 pBstrName, pBstrDocString,
3716 pdwHelpContext, pBstrHelpFile);
3718 if(index<0)
3720 /* documentation for the typelib */
3721 if(pBstrName)
3723 if (This->Name)
3725 if(!(*pBstrName = SysAllocString(This->Name)))
3726 goto memerr1;
3728 else
3729 *pBstrName = NULL;
3731 if(pBstrDocString)
3733 if (This->DocString)
3735 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3736 goto memerr2;
3738 else if (This->Name)
3740 if(!(*pBstrDocString = SysAllocString(This->Name)))
3741 goto memerr2;
3743 else
3744 *pBstrDocString = NULL;
3746 if(pdwHelpContext)
3748 *pdwHelpContext = This->dwHelpContext;
3750 if(pBstrHelpFile)
3752 if (This->HelpFile)
3754 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3755 goto memerr3;
3757 else
3758 *pBstrHelpFile = NULL;
3761 result = S_OK;
3763 else
3765 /* for a typeinfo */
3766 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3768 if(SUCCEEDED(result))
3770 result = ITypeInfo_GetDocumentation(pTInfo,
3771 MEMBERID_NIL,
3772 pBstrName,
3773 pBstrDocString,
3774 pdwHelpContext, pBstrHelpFile);
3776 ITypeInfo_Release(pTInfo);
3779 return result;
3780 memerr3:
3781 if (pBstrDocString) SysFreeString (*pBstrDocString);
3782 memerr2:
3783 if (pBstrName) SysFreeString (*pBstrName);
3784 memerr1:
3785 return STG_E_INSUFFICIENTMEMORY;
3788 /* ITypeLib::IsName
3790 * Indicates whether a passed-in string contains the name of a type or member
3791 * described in the library.
3794 static HRESULT WINAPI ITypeLib2_fnIsName(
3795 ITypeLib2 *iface,
3796 LPOLESTR szNameBuf,
3797 ULONG lHashVal,
3798 BOOL *pfName)
3800 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3801 ITypeInfoImpl *pTInfo;
3802 TLBFuncDesc *pFInfo;
3803 TLBVarDesc *pVInfo;
3804 int i;
3805 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3807 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3808 pfName);
3810 *pfName=TRUE;
3811 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3812 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3813 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3814 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3815 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3816 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3817 goto ITypeLib2_fnIsName_exit;
3819 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3820 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3823 *pfName=FALSE;
3825 ITypeLib2_fnIsName_exit:
3826 TRACE("(%p)slow! search for %s: %s found!\n", This,
3827 debugstr_w(szNameBuf), *pfName?"NOT":"");
3829 return S_OK;
3832 /* ITypeLib::FindName
3834 * Finds occurrences of a type description in a type library. This may be used
3835 * to quickly verify that a name exists in a type library.
3838 static HRESULT WINAPI ITypeLib2_fnFindName(
3839 ITypeLib2 *iface,
3840 LPOLESTR szNameBuf,
3841 ULONG lHashVal,
3842 ITypeInfo **ppTInfo,
3843 MEMBERID *rgMemId,
3844 UINT16 *pcFound)
3846 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3847 ITypeInfoImpl *pTInfo;
3848 TLBFuncDesc *pFInfo;
3849 TLBVarDesc *pVInfo;
3850 int i,j = 0;
3851 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3853 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3854 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3855 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3856 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3857 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3858 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3859 goto ITypeLib2_fnFindName_exit;
3862 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3863 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3864 continue;
3865 ITypeLib2_fnFindName_exit:
3866 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3867 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3868 j++;
3870 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3871 This, *pcFound, debugstr_w(szNameBuf), j);
3873 *pcFound=j;
3875 return S_OK;
3878 /* ITypeLib::ReleaseTLibAttr
3880 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3883 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3884 ITypeLib2 *iface,
3885 TLIBATTR *pTLibAttr)
3887 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3888 TRACE("freeing (%p)\n",This);
3889 HeapFree(GetProcessHeap(),0,pTLibAttr);
3893 /* ITypeLib2::GetCustData
3895 * gets the custom data
3897 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3898 ITypeLib2 * iface,
3899 REFGUID guid,
3900 VARIANT *pVarVal)
3902 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3903 TLBCustData *pCData;
3905 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3907 if( IsEqualIID(guid, &pCData->guid)) break;
3910 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3912 if(pCData)
3914 VariantInit( pVarVal);
3915 VariantCopy( pVarVal, &pCData->data);
3916 return S_OK;
3918 return E_INVALIDARG; /* FIXME: correct? */
3921 /* ITypeLib2::GetLibStatistics
3923 * Returns statistics about a type library that are required for efficient
3924 * sizing of hash tables.
3927 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3928 ITypeLib2 * iface,
3929 ULONG *pcUniqueNames,
3930 ULONG *pcchUniqueNames)
3932 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3934 FIXME("(%p): stub!\n", This);
3936 if(pcUniqueNames) *pcUniqueNames=1;
3937 if(pcchUniqueNames) *pcchUniqueNames=1;
3938 return S_OK;
3941 /* ITypeLib2::GetDocumentation2
3943 * Retrieves the library's documentation string, the complete Help file name
3944 * and path, the localization context to use, and the context ID for the
3945 * library Help topic in the Help file.
3948 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3949 ITypeLib2 * iface,
3950 INT index,
3951 LCID lcid,
3952 BSTR *pbstrHelpString,
3953 DWORD *pdwHelpStringContext,
3954 BSTR *pbstrHelpStringDll)
3956 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3957 HRESULT result;
3958 ITypeInfo *pTInfo;
3960 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3962 /* the help string should be obtained from the helpstringdll,
3963 * using the _DLLGetDocumentation function, based on the supplied
3964 * lcid. Nice to do sometime...
3966 if(index<0)
3968 /* documentation for the typelib */
3969 if(pbstrHelpString)
3970 *pbstrHelpString=SysAllocString(This->DocString);
3971 if(pdwHelpStringContext)
3972 *pdwHelpStringContext=This->dwHelpContext;
3973 if(pbstrHelpStringDll)
3974 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3976 result = S_OK;
3978 else
3980 /* for a typeinfo */
3981 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3983 if(SUCCEEDED(result))
3985 ITypeInfo2 * pTInfo2;
3986 result = ITypeInfo_QueryInterface(pTInfo,
3987 &IID_ITypeInfo2,
3988 (LPVOID*) &pTInfo2);
3990 if(SUCCEEDED(result))
3992 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3993 MEMBERID_NIL,
3994 lcid,
3995 pbstrHelpString,
3996 pdwHelpStringContext,
3997 pbstrHelpStringDll);
3999 ITypeInfo2_Release(pTInfo2);
4002 ITypeInfo_Release(pTInfo);
4005 return result;
4008 /* ITypeLib2::GetAllCustData
4010 * Gets all custom data items for the library.
4013 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4014 ITypeLib2 * iface,
4015 CUSTDATA *pCustData)
4017 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4018 TLBCustData *pCData;
4019 int i;
4020 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4021 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4022 if(pCustData->prgCustData ){
4023 pCustData->cCustData=This->ctCustData;
4024 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4025 pCustData->prgCustData[i].guid=pCData->guid;
4026 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4028 }else{
4029 ERR(" OUT OF MEMORY!\n");
4030 return E_OUTOFMEMORY;
4032 return S_OK;
4035 static const ITypeLib2Vtbl tlbvt = {
4036 ITypeLib2_fnQueryInterface,
4037 ITypeLib2_fnAddRef,
4038 ITypeLib2_fnRelease,
4039 ITypeLib2_fnGetTypeInfoCount,
4040 ITypeLib2_fnGetTypeInfo,
4041 ITypeLib2_fnGetTypeInfoType,
4042 ITypeLib2_fnGetTypeInfoOfGuid,
4043 ITypeLib2_fnGetLibAttr,
4044 ITypeLib2_fnGetTypeComp,
4045 ITypeLib2_fnGetDocumentation,
4046 ITypeLib2_fnIsName,
4047 ITypeLib2_fnFindName,
4048 ITypeLib2_fnReleaseTLibAttr,
4050 ITypeLib2_fnGetCustData,
4051 ITypeLib2_fnGetLibStatistics,
4052 ITypeLib2_fnGetDocumentation2,
4053 ITypeLib2_fnGetAllCustData
4057 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4059 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4061 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4064 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4066 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4068 return ITypeLib2_AddRef((ITypeLib2 *)This);
4071 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4073 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4075 return ITypeLib2_Release((ITypeLib2 *)This);
4078 static HRESULT WINAPI ITypeLibComp_fnBind(
4079 ITypeComp * iface,
4080 OLECHAR * szName,
4081 ULONG lHash,
4082 WORD wFlags,
4083 ITypeInfo ** ppTInfo,
4084 DESCKIND * pDescKind,
4085 BINDPTR * pBindPtr)
4087 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4088 return E_NOTIMPL;
4091 static HRESULT WINAPI ITypeLibComp_fnBindType(
4092 ITypeComp * iface,
4093 OLECHAR * szName,
4094 ULONG lHash,
4095 ITypeInfo ** ppTInfo,
4096 ITypeComp ** ppTComp)
4098 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4099 return E_NOTIMPL;
4102 static const ITypeCompVtbl tlbtcvt =
4105 ITypeLibComp_fnQueryInterface,
4106 ITypeLibComp_fnAddRef,
4107 ITypeLibComp_fnRelease,
4109 ITypeLibComp_fnBind,
4110 ITypeLibComp_fnBindType
4113 /*================== ITypeInfo(2) Methods ===================================*/
4114 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4116 ITypeInfoImpl * pTypeInfoImpl;
4118 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4119 if (pTypeInfoImpl)
4121 pTypeInfoImpl->lpVtbl = &tinfvt;
4122 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4123 pTypeInfoImpl->ref=1;
4125 TRACE("(%p)\n", pTypeInfoImpl);
4126 return (ITypeInfo2*) pTypeInfoImpl;
4129 /* ITypeInfo::QueryInterface
4131 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4132 ITypeInfo2 *iface,
4133 REFIID riid,
4134 VOID **ppvObject)
4136 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4138 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4140 *ppvObject=NULL;
4141 if(IsEqualIID(riid, &IID_IUnknown) ||
4142 IsEqualIID(riid,&IID_ITypeInfo)||
4143 IsEqualIID(riid,&IID_ITypeInfo2))
4144 *ppvObject = This;
4146 if(*ppvObject){
4147 ITypeInfo_AddRef(iface);
4148 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4149 return S_OK;
4151 TRACE("-- Interface: E_NOINTERFACE\n");
4152 return E_NOINTERFACE;
4155 /* ITypeInfo::AddRef
4157 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4160 ULONG ref = InterlockedIncrement(&This->ref);
4162 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4164 TRACE("(%p)->ref is %lu\n",This, ref);
4165 return ref;
4168 /* ITypeInfo::Release
4170 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4172 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4173 ULONG ref = InterlockedDecrement(&This->ref);
4175 TRACE("(%p)->(%lu)\n",This, ref);
4177 if (ref) {
4178 /* We don't release ITypeLib when ref=0 because
4179 it means that function is called by ITypeLib2_Release */
4180 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4181 } else {
4182 FIXME("destroy child objects\n");
4184 TRACE("destroying ITypeInfo(%p)\n",This);
4185 if (This->Name)
4187 SysFreeString(This->Name);
4188 This->Name = 0;
4191 if (This->DocString)
4193 SysFreeString(This->DocString);
4194 This->DocString = 0;
4197 if (This->DllName)
4199 SysFreeString(This->DllName);
4200 This->DllName = 0;
4203 if (This->next)
4205 ITypeInfo_Release((ITypeInfo*)This->next);
4208 HeapFree(GetProcessHeap(),0,This);
4209 return 0;
4211 return ref;
4214 /* ITypeInfo::GetTypeAttr
4216 * Retrieves a TYPEATTR structure that contains the attributes of the type
4217 * description.
4220 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4221 LPTYPEATTR *ppTypeAttr)
4223 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4224 SIZE_T size;
4226 TRACE("(%p)\n",This);
4228 size = sizeof(**ppTypeAttr);
4229 if (This->TypeAttr.typekind == TKIND_ALIAS)
4230 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4232 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4233 if (!*ppTypeAttr)
4234 return E_OUTOFMEMORY;
4236 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4238 if (This->TypeAttr.typekind == TKIND_ALIAS)
4239 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4240 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4242 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4243 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4244 funcs */
4245 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4246 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4248 return S_OK;
4251 /* ITypeInfo::GetTypeComp
4253 * Retrieves the ITypeComp interface for the type description, which enables a
4254 * client compiler to bind to the type description's members.
4257 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4258 ITypeComp * *ppTComp)
4260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4262 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4264 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4265 ITypeComp_AddRef(*ppTComp);
4266 return S_OK;
4269 /* ITypeInfo::GetFuncDesc
4271 * Retrieves the FUNCDESC structure that contains information about a
4272 * specified function.
4275 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4276 LPFUNCDESC *ppFuncDesc)
4278 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4279 int i;
4280 TLBFuncDesc * pFDesc;
4281 TRACE("(%p) index %d\n", This, index);
4282 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4284 if(pFDesc){
4285 /* FIXME: must do a copy here */
4286 *ppFuncDesc=&pFDesc->funcdesc;
4287 return S_OK;
4289 return E_INVALIDARG;
4292 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4294 VARDESC *dest;
4295 char *buffer;
4296 SIZE_T size = sizeof(*src);
4298 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4299 if (src->varkind == VAR_CONST)
4300 size += sizeof(VARIANT);
4301 size += TLB_SizeTypeDesc(&src->elemdescVar.tdesc, FALSE);
4302 if (src->elemdescVar.u.paramdesc.pparamdescex)
4303 size += sizeof(*src->elemdescVar.u.paramdesc.pparamdescex);
4305 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4306 if (!dest) return E_OUTOFMEMORY;
4308 *dest = *src;
4309 buffer = (char *)(dest + 1);
4310 if (src->lpstrSchema)
4312 int len;
4313 dest->lpstrSchema = (LPOLESTR)buffer;
4314 len = strlenW(src->lpstrSchema);
4315 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4316 buffer += (len + 1) * sizeof(WCHAR);
4319 if (src->varkind == VAR_CONST)
4321 HRESULT hr;
4323 dest->u.lpvarValue = (VARIANT *)buffer;
4324 *dest->u.lpvarValue = *src->u.lpvarValue;
4325 buffer += sizeof(VARIANT);
4326 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4327 if (FAILED(hr))
4329 SysFreeString((BSTR)dest_ptr);
4330 return hr;
4333 buffer = TLB_CopyTypeDesc(&dest->elemdescVar.tdesc, &src->elemdescVar.tdesc, buffer);
4334 if (src->elemdescVar.u.paramdesc.pparamdescex)
4336 PARAMDESCEX *pparamdescex_src = src->elemdescVar.u.paramdesc.pparamdescex;
4337 PARAMDESCEX *pparamdescex_dest = dest->elemdescVar.u.paramdesc.pparamdescex = (PARAMDESCEX *)buffer;
4338 HRESULT hr;
4339 buffer += sizeof(PARAMDESCEX);
4340 *pparamdescex_dest = *pparamdescex_src;
4341 hr = VariantCopy(&pparamdescex_dest->varDefaultValue, &pparamdescex_src->varDefaultValue);
4342 if (FAILED(hr))
4344 if (src->varkind == VAR_CONST)
4345 VariantClear(dest->u.lpvarValue);
4346 SysFreeString((BSTR)dest);
4347 return hr;
4350 *dest_ptr = dest;
4351 return S_OK;
4354 /* ITypeInfo::GetVarDesc
4356 * Retrieves a VARDESC structure that describes the specified variable.
4359 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4360 LPVARDESC *ppVarDesc)
4362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4363 int i;
4364 TLBVarDesc * pVDesc;
4365 TRACE("(%p) index %d\n", This, index);
4366 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4369 if (pVDesc)
4370 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4372 return E_INVALIDARG;
4375 /* ITypeInfo_GetNames
4377 * Retrieves the variable with the specified member ID (or the name of the
4378 * property or method and its parameters) that correspond to the specified
4379 * function ID.
4381 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4382 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4384 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4385 TLBFuncDesc * pFDesc;
4386 TLBVarDesc * pVDesc;
4387 int i;
4388 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4389 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4390 if(pFDesc)
4392 /* function found, now return function and parameter names */
4393 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4395 if(!i)
4396 *rgBstrNames=SysAllocString(pFDesc->Name);
4397 else
4398 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4400 *pcNames=i;
4402 else
4404 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4405 if(pVDesc)
4407 *rgBstrNames=SysAllocString(pVDesc->Name);
4408 *pcNames=1;
4410 else
4412 if(This->TypeAttr.cImplTypes &&
4413 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4414 /* recursive search */
4415 ITypeInfo *pTInfo;
4416 HRESULT result;
4417 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4418 &pTInfo);
4419 if(SUCCEEDED(result))
4421 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4422 ITypeInfo_Release(pTInfo);
4423 return result;
4425 WARN("Could not search inherited interface!\n");
4427 else
4429 WARN("no names found\n");
4431 *pcNames=0;
4432 return TYPE_E_ELEMENTNOTFOUND;
4435 return S_OK;
4439 /* ITypeInfo::GetRefTypeOfImplType
4441 * If a type description describes a COM class, it retrieves the type
4442 * description of the implemented interface types. For an interface,
4443 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4444 * if any exist.
4447 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4448 ITypeInfo2 *iface,
4449 UINT index,
4450 HREFTYPE *pRefType)
4452 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4453 int i;
4454 HRESULT hr = S_OK;
4455 TLBImplType *pImpl = This->impltypelist;
4457 TRACE("(%p) index %d\n", This, index);
4458 if (TRACE_ON(ole)) dump_TypeInfo(This);
4460 if(index==(UINT)-1)
4462 /* only valid on dual interfaces;
4463 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4465 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4467 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4468 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4470 *pRefType = -1;
4472 else
4474 hr = TYPE_E_ELEMENTNOTFOUND;
4477 else
4479 /* get element n from linked list */
4480 for(i=0; pImpl && i<index; i++)
4482 pImpl = pImpl->next;
4485 if (pImpl)
4486 *pRefType = pImpl->hRef;
4487 else
4488 hr = TYPE_E_ELEMENTNOTFOUND;
4491 if(TRACE_ON(ole))
4493 if(SUCCEEDED(hr))
4494 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4495 else
4496 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4499 return hr;
4502 /* ITypeInfo::GetImplTypeFlags
4504 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4505 * or base interface in a type description.
4507 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4508 UINT index, INT *pImplTypeFlags)
4510 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4511 int i;
4512 TLBImplType *pImpl;
4514 TRACE("(%p) index %d\n", This, index);
4515 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4516 i++, pImpl=pImpl->next)
4518 if(i==index && pImpl){
4519 *pImplTypeFlags=pImpl->implflags;
4520 return S_OK;
4522 *pImplTypeFlags=0;
4523 return TYPE_E_ELEMENTNOTFOUND;
4526 /* GetIDsOfNames
4527 * Maps between member names and member IDs, and parameter names and
4528 * parameter IDs.
4530 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4531 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4533 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4534 TLBFuncDesc * pFDesc;
4535 TLBVarDesc * pVDesc;
4536 HRESULT ret=S_OK;
4538 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4539 cNames);
4540 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4541 int i, j;
4542 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4543 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4544 for(i=1; i < cNames; i++){
4545 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4546 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4547 break;
4548 if( j<pFDesc->funcdesc.cParams)
4549 pMemId[i]=j;
4550 else
4551 ret=DISP_E_UNKNOWNNAME;
4553 return ret;
4556 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4557 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4558 if(cNames) *pMemId=pVDesc->vardesc.memid;
4559 return ret;
4562 /* not found, see if this is and interface with an inheritance */
4563 if(This->TypeAttr.cImplTypes &&
4564 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4565 /* recursive search */
4566 ITypeInfo *pTInfo;
4567 ret=ITypeInfo_GetRefTypeInfo(iface,
4568 This->impltypelist->hRef, &pTInfo);
4569 if(SUCCEEDED(ret)){
4570 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4571 ITypeInfo_Release(pTInfo);
4572 return ret;
4574 WARN("Could not search inherited interface!\n");
4575 } else
4576 WARN("no names found\n");
4577 return DISP_E_UNKNOWNNAME;
4580 /* ITypeInfo::Invoke
4582 * Invokes a method, or accesses a property of an object, that implements the
4583 * interface described by the type description.
4585 DWORD
4586 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4587 DWORD res;
4589 if (TRACE_ON(ole)) {
4590 int i;
4591 TRACE("Calling %p(",func);
4592 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4593 TRACE(")\n");
4596 switch (callconv) {
4597 case CC_STDCALL:
4599 switch (nrargs) {
4600 case 0:
4601 res = func();
4602 break;
4603 case 1:
4604 res = func(args[0]);
4605 break;
4606 case 2:
4607 res = func(args[0],args[1]);
4608 break;
4609 case 3:
4610 res = func(args[0],args[1],args[2]);
4611 break;
4612 case 4:
4613 res = func(args[0],args[1],args[2],args[3]);
4614 break;
4615 case 5:
4616 res = func(args[0],args[1],args[2],args[3],args[4]);
4617 break;
4618 case 6:
4619 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4620 break;
4621 case 7:
4622 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4623 break;
4624 case 8:
4625 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4626 break;
4627 case 9:
4628 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4629 break;
4630 case 10:
4631 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4632 break;
4633 case 11:
4634 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4635 break;
4636 case 12:
4637 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]);
4638 break;
4639 case 13:
4640 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]);
4641 break;
4642 case 14:
4643 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]);
4644 break;
4645 default:
4646 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4647 res = -1;
4648 break;
4650 break;
4651 default:
4652 FIXME("unsupported calling convention %d\n",callconv);
4653 res = -1;
4654 break;
4656 TRACE("returns %08lx\n",res);
4657 return res;
4660 extern int _argsize(DWORD vt);
4662 /****************************************************************************
4663 * Helper functions for Dispcall / Invoke, which copies one variant
4664 * with target type onto the argument stack.
4666 static HRESULT
4667 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4668 DWORD *argpos, VARIANT *arg, VARTYPE vt
4670 UINT arglen = _argsize(vt)*sizeof(DWORD);
4671 VARIANT va;
4673 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4674 memcpy(argpos,&arg,sizeof(void*));
4675 return S_OK;
4678 if (V_VT(arg) == vt) {
4679 memcpy(argpos, &V_I4(arg), arglen);
4680 return S_OK;
4683 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4684 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4685 return S_OK;
4688 if (vt == VT_VARIANT) {
4689 memcpy(argpos, arg, arglen);
4690 return S_OK;
4692 /* Deref BYREF vars if there is need */
4693 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4694 memcpy(argpos,(void*)V_I4(arg), arglen);
4695 return S_OK;
4697 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4698 /* in this context, if the type lib specifies IUnknown*, giving an
4699 IDispatch* is correct; so, don't invoke VariantChangeType */
4700 memcpy(argpos,&V_I4(arg), arglen);
4701 return S_OK;
4703 if ((vt == VT_PTR) && tdesc)
4704 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4706 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4707 ITypeInfo *tinfo2 = NULL;
4708 TYPEATTR *tattr = NULL;
4709 HRESULT hres;
4711 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4712 if (hres) {
4713 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4714 "while coercing from vt 0x%x. Copying 4 byte.\n",
4715 tdesc->u.hreftype,V_VT(arg));
4716 memcpy(argpos, &V_I4(arg), 4);
4717 return S_OK;
4719 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4720 if( hres )
4722 ERR("GetTypeAttr failed\n");
4723 ITypeInfo_Release(tinfo2);
4724 return hres;
4726 switch (tattr->typekind) {
4727 case TKIND_ENUM:
4728 switch ( V_VT( arg ) ) {
4729 case VT_I2:
4730 *argpos = V_I2(arg);
4731 hres = S_OK;
4732 break;
4733 case VT_I4:
4734 memcpy(argpos, &V_I4(arg), 4);
4735 hres = S_OK;
4736 break;
4737 case VT_BYREF|VT_I4:
4738 memcpy(argpos, V_I4REF(arg), 4);
4739 hres = S_OK;
4740 break;
4741 default:
4742 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4743 hres = E_FAIL;
4744 break;
4746 break;
4748 case TKIND_ALIAS:
4749 tdesc = &(tattr->tdescAlias);
4750 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4751 break;
4753 case TKIND_INTERFACE:
4754 if (V_VT(arg) == VT_DISPATCH) {
4755 IDispatch *disp;
4756 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4757 memcpy(argpos, &V_DISPATCH(arg), 4);
4758 hres = S_OK;
4759 break;
4761 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4762 &IID_IDispatch,(LPVOID*)&disp);
4763 if (SUCCEEDED(hres)) {
4764 memcpy(argpos,&disp,4);
4765 IUnknown_Release(V_DISPATCH(arg));
4766 hres = S_OK;
4767 break;
4769 FIXME("Failed to query IDispatch interface from %s while "
4770 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4771 hres = E_FAIL;
4772 break;
4774 if (V_VT(arg) == VT_UNKNOWN) {
4775 memcpy(argpos, &V_UNKNOWN(arg), 4);
4776 hres = S_OK;
4777 break;
4779 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4780 V_VT(arg),debugstr_guid(&(tattr->guid)));
4781 hres = E_FAIL;
4782 break;
4784 case TKIND_DISPATCH:
4785 if (V_VT(arg) == VT_DISPATCH) {
4786 memcpy(argpos, &V_DISPATCH(arg), 4);
4787 hres = S_OK;
4789 else {
4790 hres = E_FAIL;
4791 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4793 break;
4794 case TKIND_RECORD:
4795 FIXME("TKIND_RECORD unhandled.\n");
4796 hres = E_FAIL;
4797 break;
4798 default:
4799 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4800 hres = E_FAIL;
4801 break;
4803 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4804 ITypeInfo_Release(tinfo2);
4805 return hres;
4808 VariantInit(&va);
4809 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4810 memcpy(argpos,&V_I4(&va), arglen);
4811 FIXME("Should not use VariantChangeType here."
4812 " (conversion from 0x%x -> 0x%x) %08lx\n",
4813 V_VT(arg), vt, *argpos
4815 return S_OK;
4817 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4818 return E_FAIL;
4821 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4823 HRESULT hr = S_OK;
4824 ITypeInfo *tinfo2 = NULL;
4825 TYPEATTR *tattr = NULL;
4827 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4828 if (hr)
4830 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4831 "hr = 0x%08lx\n",
4832 tdesc->u.hreftype, hr);
4833 return hr;
4835 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4836 if (hr)
4838 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4839 ITypeInfo_Release(tinfo2);
4840 return hr;
4843 switch (tattr->typekind)
4845 case TKIND_ENUM:
4846 *vt |= VT_I4;
4847 break;
4849 case TKIND_ALIAS:
4850 tdesc = &tattr->tdescAlias;
4851 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4852 break;
4854 case TKIND_INTERFACE:
4855 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4856 *vt |= VT_DISPATCH;
4857 else
4858 *vt |= VT_UNKNOWN;
4859 break;
4861 case TKIND_DISPATCH:
4862 *vt |= VT_DISPATCH;
4863 break;
4865 case TKIND_RECORD:
4866 FIXME("TKIND_RECORD unhandled.\n");
4867 hr = E_NOTIMPL;
4868 break;
4870 case TKIND_UNION:
4871 FIXME("TKIND_RECORD unhandled.\n");
4872 hr = E_NOTIMPL;
4873 break;
4875 default:
4876 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4877 hr = E_NOTIMPL;
4878 break;
4880 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4881 ITypeInfo_Release(tinfo2);
4882 return hr;
4885 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4887 HRESULT hr = S_OK;
4889 /* enforce only one level of pointer indirection */
4890 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
4892 tdesc = tdesc->u.lptdesc;
4894 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4895 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4896 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4897 if ((tdesc->vt == VT_USERDEFINED) ||
4898 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4900 VARTYPE vt_userdefined = 0;
4901 TYPEDESC *tdesc_userdefined = tdesc;
4902 if (tdesc->vt == VT_PTR)
4904 vt_userdefined = VT_BYREF;
4905 tdesc_userdefined = tdesc->u.lptdesc;
4907 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
4908 if ((hr == S_OK) &&
4909 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
4910 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
4912 *vt |= vt_userdefined;
4913 return S_OK;
4916 *vt = VT_BYREF;
4919 switch (tdesc->vt)
4921 case VT_HRESULT:
4922 *vt |= VT_ERROR;
4923 break;
4924 case VT_USERDEFINED:
4925 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
4926 break;
4927 case VT_PTR:
4928 ERR("cannot convert VT_PTR into variant VT\n");
4929 hr = E_FAIL;
4930 break;
4931 default:
4932 *vt |= tdesc->vt;
4933 break;
4935 return hr;
4938 /***********************************************************************
4939 * DispCallFunc (OLEAUT32.@)
4941 HRESULT WINAPI
4942 DispCallFunc(
4943 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4944 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
4946 int i, argsize, argspos;
4947 DWORD *args;
4948 HRESULT hres;
4950 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4951 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
4952 pvargResult, V_VT(pvargResult));
4954 /* DispCallFunc is only used to invoke methods belonging to an
4955 * IDispatch-derived COM interface. So we need to add a first parameter
4956 * to the list of arguments, to supply the interface pointer */
4957 argsize = 1;
4958 for (i=0;i<cActuals;i++)
4960 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4961 dump_Variant(prgpvarg[i]);
4962 argsize += _argsize(prgvt[i]);
4964 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4965 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4966 argspos = 1;
4967 for (i=0;i<cActuals;i++)
4969 VARIANT *arg = prgpvarg[i];
4970 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4971 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
4972 argspos += _argsize(prgvt[i]);
4975 hres = _invoke((*(FARPROC**)pvInstance)[oVft/sizeof(void *)],cc,argsize,args);
4976 if (pvargResult && (vtReturn != VT_EMPTY))
4978 TRACE("Method returned 0x%08lx\n",hres);
4979 V_VT(pvargResult) = vtReturn;
4980 V_UI4(pvargResult) = hres;
4983 HeapFree(GetProcessHeap(),0,args);
4984 return S_OK;
4987 static HRESULT WINAPI ITypeInfo_fnInvoke(
4988 ITypeInfo2 *iface,
4989 VOID *pIUnk,
4990 MEMBERID memid,
4991 UINT16 dwFlags,
4992 DISPPARAMS *pDispParams,
4993 VARIANT *pVarResult,
4994 EXCEPINFO *pExcepInfo,
4995 UINT *pArgErr)
4997 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4998 int i;
4999 unsigned int func_index, var_index;
5000 TYPEKIND type_kind;
5001 HRESULT hres;
5003 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
5004 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5006 dump_DispParms(pDispParams);
5008 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
5009 if (SUCCEEDED(hres)) {
5010 FUNCDESC *func_desc;
5012 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
5013 if(FAILED(hres)) return hres;
5014 if (TRACE_ON(ole))
5016 TRACE("invoking:\n");
5017 dump_FUNCDESC(func_desc);
5020 switch (func_desc->funckind) {
5021 case FUNC_PUREVIRTUAL:
5022 case FUNC_VIRTUAL: {
5023 DWORD res;
5024 int numargs, numargs2, argspos, args2pos;
5025 DWORD *args , *args2;
5026 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
5027 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
5029 hres = S_OK;
5030 numargs = 1; /* sizeof(thisptr) */
5031 numargs2 = 0;
5032 for (i = 0; i < func_desc->cParams; i++) {
5033 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5035 numargs += _argsize(tdesc->vt);
5036 if (i>=pDispParams->cArgs) { /* arguments to return */
5037 if (tdesc->vt == VT_PTR) {
5038 numargs2 += _argsize(tdesc->u.lptdesc->vt);
5039 } else {
5040 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
5041 numargs2 += _argsize(tdesc->vt);
5046 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
5047 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
5049 args[0] = (DWORD)pIUnk;
5050 argspos = 1; args2pos = 0;
5051 for (i = 0; i < func_desc->cParams; i++) {
5052 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
5053 TYPEDESC *tdesc = &(elemdesc->tdesc);
5054 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
5055 int arglen = _argsize(tdesc->vt);
5057 if (i<pDispParams->cArgs) {
5058 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
5060 if (paramFlags & PARAMFLAG_FOPT) {
5061 if(i < func_desc->cParams - func_desc->cParamsOpt)
5062 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5063 if(V_VT(arg) == VT_EMPTY
5064 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
5065 /* FIXME: Documentation says that we do this when parameter is left unspecified.
5066 How to determine it? */
5068 if(paramFlags & PARAMFLAG_FHASDEFAULT)
5069 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5070 V_VT(arg) = VT_ERROR;
5071 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5072 arglen = _argsize(VT_ERROR);
5075 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5076 if (FAILED(hres)) goto func_fail;
5077 argspos += arglen;
5078 } else if (paramFlags & PARAMFLAG_FOPT) {
5079 VARIANT *arg = &rgvarg[i];
5081 if (i < func_desc->cParams - func_desc->cParamsOpt)
5082 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5083 if (paramFlags & PARAMFLAG_FHASDEFAULT)
5084 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5086 V_VT(arg) = VT_ERROR;
5087 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5088 arglen = _argsize(VT_ERROR);
5089 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5090 if (FAILED(hres)) goto func_fail;
5091 argspos += arglen;
5092 } else {
5093 if (tdesc->vt == VT_PTR)
5094 arglen = _argsize(tdesc->u.lptdesc->vt);
5095 else
5096 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5098 /* Supply pointers for the rest, so propertyget works*/
5099 args[argspos] = (DWORD)&args2[args2pos];
5101 /* If pointer to variant, pass reference it. */
5102 if ((tdesc->vt == VT_PTR) &&
5103 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5104 pVarResult
5106 args[argspos]= (DWORD)pVarResult;
5107 argspos += 1;
5108 args2pos += arglen;
5111 if (func_desc->cParamsOpt < 0)
5112 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5114 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5115 func_desc->callconv,
5116 numargs,
5117 args
5120 if (pVarResult) {
5121 for (i = 0; i < func_desc->cParams; i++) {
5122 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5123 if (wParamFlags & PARAMFLAG_FRETVAL) {
5124 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5125 TYPEDESC *tdesc = &elemdesc->tdesc;
5126 VARIANTARG varresult;
5127 V_VT(&varresult) = 0;
5128 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5129 if (hres)
5130 break;
5131 /* FIXME: this is really messy - we should keep the
5132 * args in VARIANTARGs rather than a DWORD array */
5133 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5134 if (TRACE_ON(ole))
5136 TRACE("varresult: ");
5137 dump_Variant(&varresult);
5139 hres = VariantCopyInd(pVarResult, &varresult);
5140 /* free data stored in varresult. Note that
5141 * VariantClear doesn't do what we want because we are
5142 * working with byref types. */
5143 /* FIXME: clear safearrays, bstrs, records and
5144 * variants here too */
5145 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5146 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5148 if(*V_UNKNOWNREF(&varresult))
5149 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5151 break;
5156 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5157 WARN("invoked function failed with error 0x%08lx\n", res);
5158 hres = DISP_E_EXCEPTION;
5159 if (pExcepInfo) pExcepInfo->scode = res;
5161 func_fail:
5162 HeapFree(GetProcessHeap(), 0, rgvarg);
5163 HeapFree(GetProcessHeap(),0,args2);
5164 HeapFree(GetProcessHeap(),0,args);
5165 break;
5167 case FUNC_DISPATCH: {
5168 IDispatch *disp;
5170 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5171 if (SUCCEEDED(hres)) {
5172 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5173 hres = IDispatch_Invoke(
5174 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5175 pVarResult,pExcepInfo,pArgErr
5177 if (FAILED(hres))
5178 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5179 IDispatch_Release(disp);
5180 } else
5181 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5182 break;
5184 default:
5185 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5186 hres = E_FAIL;
5187 break;
5190 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5191 TRACE("-- 0x%08lx\n", hres);
5192 return hres;
5194 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5195 VARDESC *var_desc;
5197 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5198 if(FAILED(hres)) return hres;
5200 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5201 dump_VARDESC(var_desc);
5202 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5203 return E_NOTIMPL;
5206 /* not found, look for it in inherited interfaces */
5207 ITypeInfo2_GetTypeKind(iface, &type_kind);
5208 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5209 HREFTYPE ref_type;
5210 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5211 /* recursive search */
5212 ITypeInfo *pTInfo;
5213 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5214 if(SUCCEEDED(hres)){
5215 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5216 ITypeInfo_Release(pTInfo);
5217 return hres;
5219 WARN("Could not search inherited interface!\n");
5222 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5223 return DISP_E_MEMBERNOTFOUND;
5226 /* ITypeInfo::GetDocumentation
5228 * Retrieves the documentation string, the complete Help file name and path,
5229 * and the context ID for the Help topic for a specified type description.
5231 * (Can be tested by the Visual Basic Editor in Word for instance.)
5233 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5234 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5235 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5237 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5238 TLBFuncDesc * pFDesc;
5239 TLBVarDesc * pVDesc;
5240 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5241 " HelpContext(%p) HelpFile(%p)\n",
5242 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5243 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5244 if(pBstrName)
5245 *pBstrName=SysAllocString(This->Name);
5246 if(pBstrDocString)
5247 *pBstrDocString=SysAllocString(This->DocString);
5248 if(pdwHelpContext)
5249 *pdwHelpContext=This->dwHelpContext;
5250 if(pBstrHelpFile)
5251 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5252 return S_OK;
5253 }else {/* for a member */
5254 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5255 if(pFDesc->funcdesc.memid==memid){
5256 if(pBstrName)
5257 *pBstrName = SysAllocString(pFDesc->Name);
5258 if(pBstrDocString)
5259 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5260 if(pdwHelpContext)
5261 *pdwHelpContext=pFDesc->helpcontext;
5262 return S_OK;
5264 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5265 if(pVDesc->vardesc.memid==memid){
5266 if(pBstrName)
5267 *pBstrName = SysAllocString(pVDesc->Name);
5268 if(pBstrDocString)
5269 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5270 if(pdwHelpContext)
5271 *pdwHelpContext=pVDesc->HelpContext;
5272 return S_OK;
5275 WARN("member %ld not found\n", memid);
5276 return TYPE_E_ELEMENTNOTFOUND;
5279 /* ITypeInfo::GetDllEntry
5281 * Retrieves a description or specification of an entry point for a function
5282 * in a DLL.
5284 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5285 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5286 WORD *pwOrdinal)
5288 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5289 TLBFuncDesc *pFDesc;
5291 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5293 if (pBstrDllName) *pBstrDllName = NULL;
5294 if (pBstrName) *pBstrName = NULL;
5295 if (pwOrdinal) *pwOrdinal = 0;
5297 if (This->TypeAttr.typekind != TKIND_MODULE)
5298 return TYPE_E_BADMODULEKIND;
5300 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5301 if(pFDesc->funcdesc.memid==memid){
5302 dump_TypeInfo(This);
5303 dump_TLBFuncDescOne(pFDesc);
5305 if (pBstrDllName)
5306 *pBstrDllName = SysAllocString(This->DllName);
5308 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5309 if (pBstrName)
5310 *pBstrName = SysAllocString(pFDesc->Entry);
5311 if (pwOrdinal)
5312 *pwOrdinal = -1;
5313 return S_OK;
5315 if (pBstrName)
5316 *pBstrName = NULL;
5317 if (pwOrdinal)
5318 *pwOrdinal = (DWORD)pFDesc->Entry;
5319 return S_OK;
5321 return TYPE_E_ELEMENTNOTFOUND;
5324 /* ITypeInfo::GetRefTypeInfo
5326 * If a type description references other type descriptions, it retrieves
5327 * the referenced type descriptions.
5329 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5330 ITypeInfo2 *iface,
5331 HREFTYPE hRefType,
5332 ITypeInfo **ppTInfo)
5334 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5335 HRESULT result = E_FAIL;
5337 if (hRefType == -1 &&
5338 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5339 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5341 /* when we meet a DUAL dispinterface, we must create the interface
5342 * version of it.
5344 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5347 /* the interface version contains the same information as the dispinterface
5348 * copy the contents of the structs.
5350 *pTypeInfoImpl = *This;
5351 pTypeInfoImpl->ref = 1;
5353 /* change the type to interface */
5354 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5356 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5358 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5360 result = S_OK;
5362 } else {
5363 TLBRefType *pRefType;
5364 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5365 if(pRefType->reference == hRefType)
5366 break;
5368 if(!pRefType)
5369 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5370 if(pRefType && hRefType != -1) {
5371 ITypeLib *pTLib = NULL;
5373 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5374 UINT Index;
5375 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5376 } else {
5377 if(pRefType->pImpTLInfo->pImpTypeLib) {
5378 TRACE("typeinfo in imported typelib that is already loaded\n");
5379 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5380 ITypeLib2_AddRef((ITypeLib*) pTLib);
5381 result = S_OK;
5382 } else {
5383 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5384 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5385 pRefType->pImpTLInfo->wVersionMajor,
5386 pRefType->pImpTLInfo->wVersionMinor,
5387 pRefType->pImpTLInfo->lcid,
5388 &pTLib);
5390 if(!SUCCEEDED(result)) {
5391 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5392 result=LoadTypeLib(libnam, &pTLib);
5393 SysFreeString(libnam);
5395 if(SUCCEEDED(result)) {
5396 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5397 ITypeLib2_AddRef(pTLib);
5401 if(SUCCEEDED(result)) {
5402 if(pRefType->index == TLB_REF_USE_GUID)
5403 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5404 &pRefType->guid,
5405 ppTInfo);
5406 else
5407 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5408 ppTInfo);
5410 if (pTLib != NULL)
5411 ITypeLib2_Release(pTLib);
5415 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5416 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5417 return result;
5420 /* ITypeInfo::AddressOfMember
5422 * Retrieves the addresses of static functions or variables, such as those
5423 * defined in a DLL.
5425 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5426 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5428 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5429 FIXME("(%p) stub!\n", This);
5430 return S_OK;
5433 /* ITypeInfo::CreateInstance
5435 * Creates a new instance of a type that describes a component object class
5436 * (coclass).
5438 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5439 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5441 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5442 FIXME("(%p) stub!\n", This);
5443 return S_OK;
5446 /* ITypeInfo::GetMops
5448 * Retrieves marshalling information.
5450 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5451 BSTR *pBstrMops)
5453 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5454 FIXME("(%p) stub!\n", This);
5455 return S_OK;
5458 /* ITypeInfo::GetContainingTypeLib
5460 * Retrieves the containing type library and the index of the type description
5461 * within that type library.
5463 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5464 ITypeLib * *ppTLib, UINT *pIndex)
5466 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5468 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5469 if (pIndex) {
5470 *pIndex=This->index;
5471 TRACE("returning pIndex=%d\n", *pIndex);
5474 if (ppTLib) {
5475 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5476 ITypeLib2_AddRef(*ppTLib);
5477 TRACE("returning ppTLib=%p\n", *ppTLib);
5480 return S_OK;
5483 /* ITypeInfo::ReleaseTypeAttr
5485 * Releases a TYPEATTR previously returned by GetTypeAttr.
5488 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5489 TYPEATTR* pTypeAttr)
5491 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5492 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5493 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5496 /* ITypeInfo::ReleaseFuncDesc
5498 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5500 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5501 ITypeInfo2 *iface,
5502 FUNCDESC *pFuncDesc)
5504 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5505 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5508 /* ITypeInfo::ReleaseVarDesc
5510 * Releases a VARDESC previously returned by GetVarDesc.
5512 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5513 VARDESC *pVarDesc)
5515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5516 TRACE("(%p)->(%p)\n", This, pVarDesc);
5518 if (pVarDesc->elemdescVar.u.paramdesc.pparamdescex)
5519 VariantClear(&pVarDesc->elemdescVar.u.paramdesc.pparamdescex->varDefaultValue);
5520 if (pVarDesc->varkind == VAR_CONST)
5521 VariantClear(pVarDesc->u.lpvarValue);
5522 SysFreeString((BSTR)pVarDesc);
5525 /* ITypeInfo2::GetTypeKind
5527 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5530 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5531 TYPEKIND *pTypeKind)
5533 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5534 *pTypeKind=This->TypeAttr.typekind;
5535 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5536 return S_OK;
5539 /* ITypeInfo2::GetTypeFlags
5541 * Returns the type flags without any allocations. This returns a DWORD type
5542 * flag, which expands the type flags without growing the TYPEATTR (type
5543 * attribute).
5546 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5548 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5549 *pTypeFlags=This->TypeAttr.wTypeFlags;
5550 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5551 return S_OK;
5554 /* ITypeInfo2::GetFuncIndexOfMemId
5555 * Binds to a specific member based on a known DISPID, where the member name
5556 * is not known (for example, when binding to a default member).
5559 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5560 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5562 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5563 TLBFuncDesc *pFuncInfo;
5564 int i;
5565 HRESULT result;
5567 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5568 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5569 break;
5570 if(pFuncInfo) {
5571 *pFuncIndex = i;
5572 result = S_OK;
5573 } else
5574 result = TYPE_E_ELEMENTNOTFOUND;
5576 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5577 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5578 return result;
5581 /* TypeInfo2::GetVarIndexOfMemId
5583 * Binds to a specific member based on a known DISPID, where the member name
5584 * is not known (for example, when binding to a default member).
5587 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5588 MEMBERID memid, UINT *pVarIndex)
5590 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5591 TLBVarDesc *pVarInfo;
5592 int i;
5593 HRESULT result;
5594 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5595 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5597 if(pVarInfo) {
5598 *pVarIndex = i;
5599 result = S_OK;
5600 } else
5601 result = TYPE_E_ELEMENTNOTFOUND;
5603 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5604 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5605 return result;
5608 /* ITypeInfo2::GetCustData
5610 * Gets the custom data
5612 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5613 ITypeInfo2 * iface,
5614 REFGUID guid,
5615 VARIANT *pVarVal)
5617 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5618 TLBCustData *pCData;
5620 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5621 if( IsEqualIID(guid, &pCData->guid)) break;
5623 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5625 if(pCData)
5627 VariantInit( pVarVal);
5628 VariantCopy( pVarVal, &pCData->data);
5629 return S_OK;
5631 return E_INVALIDARG; /* FIXME: correct? */
5634 /* ITypeInfo2::GetFuncCustData
5636 * Gets the custom data
5638 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5639 ITypeInfo2 * iface,
5640 UINT index,
5641 REFGUID guid,
5642 VARIANT *pVarVal)
5644 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5645 TLBCustData *pCData=NULL;
5646 TLBFuncDesc * pFDesc;
5647 int i;
5648 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5649 pFDesc=pFDesc->next);
5651 if(pFDesc)
5652 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5653 if( IsEqualIID(guid, &pCData->guid)) break;
5655 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5657 if(pCData){
5658 VariantInit( pVarVal);
5659 VariantCopy( pVarVal, &pCData->data);
5660 return S_OK;
5662 return E_INVALIDARG; /* FIXME: correct? */
5665 /* ITypeInfo2::GetParamCustData
5667 * Gets the custom data
5669 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5670 ITypeInfo2 * iface,
5671 UINT indexFunc,
5672 UINT indexParam,
5673 REFGUID guid,
5674 VARIANT *pVarVal)
5676 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5677 TLBCustData *pCData=NULL;
5678 TLBFuncDesc * pFDesc;
5679 int i;
5681 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5683 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5684 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5685 pCData = pCData->next)
5686 if( IsEqualIID(guid, &pCData->guid)) break;
5688 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5690 if(pCData)
5692 VariantInit( pVarVal);
5693 VariantCopy( pVarVal, &pCData->data);
5694 return S_OK;
5696 return E_INVALIDARG; /* FIXME: correct? */
5699 /* ITypeInfo2::GetVarCustData
5701 * Gets the custom data
5703 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5704 ITypeInfo2 * iface,
5705 UINT index,
5706 REFGUID guid,
5707 VARIANT *pVarVal)
5709 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5710 TLBCustData *pCData=NULL;
5711 TLBVarDesc * pVDesc;
5712 int i;
5714 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5716 if(pVDesc)
5718 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5720 if( IsEqualIID(guid, &pCData->guid)) break;
5724 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5726 if(pCData)
5728 VariantInit( pVarVal);
5729 VariantCopy( pVarVal, &pCData->data);
5730 return S_OK;
5732 return E_INVALIDARG; /* FIXME: correct? */
5735 /* ITypeInfo2::GetImplCustData
5737 * Gets the custom data
5739 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5740 ITypeInfo2 * iface,
5741 UINT index,
5742 REFGUID guid,
5743 VARIANT *pVarVal)
5745 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5746 TLBCustData *pCData=NULL;
5747 TLBImplType * pRDesc;
5748 int i;
5750 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5752 if(pRDesc)
5754 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5756 if( IsEqualIID(guid, &pCData->guid)) break;
5760 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5762 if(pCData)
5764 VariantInit( pVarVal);
5765 VariantCopy( pVarVal, &pCData->data);
5766 return S_OK;
5768 return E_INVALIDARG; /* FIXME: correct? */
5771 /* ITypeInfo2::GetDocumentation2
5773 * Retrieves the documentation string, the complete Help file name and path,
5774 * the localization context to use, and the context ID for the library Help
5775 * topic in the Help file.
5778 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5779 ITypeInfo2 * iface,
5780 MEMBERID memid,
5781 LCID lcid,
5782 BSTR *pbstrHelpString,
5783 DWORD *pdwHelpStringContext,
5784 BSTR *pbstrHelpStringDll)
5786 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5787 TLBFuncDesc * pFDesc;
5788 TLBVarDesc * pVDesc;
5789 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5790 "HelpStringContext(%p) HelpStringDll(%p)\n",
5791 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5792 pbstrHelpStringDll );
5793 /* the help string should be obtained from the helpstringdll,
5794 * using the _DLLGetDocumentation function, based on the supplied
5795 * lcid. Nice to do sometime...
5797 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5798 if(pbstrHelpString)
5799 *pbstrHelpString=SysAllocString(This->Name);
5800 if(pdwHelpStringContext)
5801 *pdwHelpStringContext=This->dwHelpStringContext;
5802 if(pbstrHelpStringDll)
5803 *pbstrHelpStringDll=
5804 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5805 return S_OK;
5806 }else {/* for a member */
5807 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5808 if(pFDesc->funcdesc.memid==memid){
5809 if(pbstrHelpString)
5810 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5811 if(pdwHelpStringContext)
5812 *pdwHelpStringContext=pFDesc->HelpStringContext;
5813 if(pbstrHelpStringDll)
5814 *pbstrHelpStringDll=
5815 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5816 return S_OK;
5818 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5819 if(pVDesc->vardesc.memid==memid){
5820 if(pbstrHelpString)
5821 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5822 if(pdwHelpStringContext)
5823 *pdwHelpStringContext=pVDesc->HelpStringContext;
5824 if(pbstrHelpStringDll)
5825 *pbstrHelpStringDll=
5826 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5827 return S_OK;
5830 return TYPE_E_ELEMENTNOTFOUND;
5833 /* ITypeInfo2::GetAllCustData
5835 * Gets all custom data items for the Type info.
5838 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5839 ITypeInfo2 * iface,
5840 CUSTDATA *pCustData)
5842 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5843 TLBCustData *pCData;
5844 int i;
5846 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5848 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5849 if(pCustData->prgCustData ){
5850 pCustData->cCustData=This->ctCustData;
5851 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5852 pCustData->prgCustData[i].guid=pCData->guid;
5853 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5855 }else{
5856 ERR(" OUT OF MEMORY!\n");
5857 return E_OUTOFMEMORY;
5859 return S_OK;
5862 /* ITypeInfo2::GetAllFuncCustData
5864 * Gets all custom data items for the specified Function
5867 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5868 ITypeInfo2 * iface,
5869 UINT index,
5870 CUSTDATA *pCustData)
5872 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5873 TLBCustData *pCData;
5874 TLBFuncDesc * pFDesc;
5875 int i;
5876 TRACE("(%p) index %d\n", This, index);
5877 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5878 pFDesc=pFDesc->next)
5880 if(pFDesc){
5881 pCustData->prgCustData =
5882 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5883 if(pCustData->prgCustData ){
5884 pCustData->cCustData=pFDesc->ctCustData;
5885 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5886 pCData = pCData->next){
5887 pCustData->prgCustData[i].guid=pCData->guid;
5888 VariantCopy(& pCustData->prgCustData[i].varValue,
5889 & pCData->data);
5891 }else{
5892 ERR(" OUT OF MEMORY!\n");
5893 return E_OUTOFMEMORY;
5895 return S_OK;
5897 return TYPE_E_ELEMENTNOTFOUND;
5900 /* ITypeInfo2::GetAllParamCustData
5902 * Gets all custom data items for the Functions
5905 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5906 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5908 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5909 TLBCustData *pCData=NULL;
5910 TLBFuncDesc * pFDesc;
5911 int i;
5912 TRACE("(%p) index %d\n", This, indexFunc);
5913 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5914 pFDesc=pFDesc->next)
5916 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5917 pCustData->prgCustData =
5918 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5919 sizeof(CUSTDATAITEM));
5920 if(pCustData->prgCustData ){
5921 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5922 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5923 pCData; i++, pCData = pCData->next){
5924 pCustData->prgCustData[i].guid=pCData->guid;
5925 VariantCopy(& pCustData->prgCustData[i].varValue,
5926 & pCData->data);
5928 }else{
5929 ERR(" OUT OF MEMORY!\n");
5930 return E_OUTOFMEMORY;
5932 return S_OK;
5934 return TYPE_E_ELEMENTNOTFOUND;
5937 /* ITypeInfo2::GetAllVarCustData
5939 * Gets all custom data items for the specified Variable
5942 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5943 UINT index, CUSTDATA *pCustData)
5945 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5946 TLBCustData *pCData;
5947 TLBVarDesc * pVDesc;
5948 int i;
5949 TRACE("(%p) index %d\n", This, index);
5950 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5951 pVDesc=pVDesc->next)
5953 if(pVDesc){
5954 pCustData->prgCustData =
5955 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5956 if(pCustData->prgCustData ){
5957 pCustData->cCustData=pVDesc->ctCustData;
5958 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5959 pCData = pCData->next){
5960 pCustData->prgCustData[i].guid=pCData->guid;
5961 VariantCopy(& pCustData->prgCustData[i].varValue,
5962 & pCData->data);
5964 }else{
5965 ERR(" OUT OF MEMORY!\n");
5966 return E_OUTOFMEMORY;
5968 return S_OK;
5970 return TYPE_E_ELEMENTNOTFOUND;
5973 /* ITypeInfo2::GetAllImplCustData
5975 * Gets all custom data items for the specified implementation type
5978 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5979 ITypeInfo2 * iface,
5980 UINT index,
5981 CUSTDATA *pCustData)
5983 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5984 TLBCustData *pCData;
5985 TLBImplType * pRDesc;
5986 int i;
5987 TRACE("(%p) index %d\n", This, index);
5988 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5989 pRDesc=pRDesc->next)
5991 if(pRDesc){
5992 pCustData->prgCustData =
5993 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5994 if(pCustData->prgCustData ){
5995 pCustData->cCustData=pRDesc->ctCustData;
5996 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5997 pCData = pCData->next){
5998 pCustData->prgCustData[i].guid=pCData->guid;
5999 VariantCopy(& pCustData->prgCustData[i].varValue,
6000 & pCData->data);
6002 }else{
6003 ERR(" OUT OF MEMORY!\n");
6004 return E_OUTOFMEMORY;
6006 return S_OK;
6008 return TYPE_E_ELEMENTNOTFOUND;
6011 static const ITypeInfo2Vtbl tinfvt =
6014 ITypeInfo_fnQueryInterface,
6015 ITypeInfo_fnAddRef,
6016 ITypeInfo_fnRelease,
6018 ITypeInfo_fnGetTypeAttr,
6019 ITypeInfo_fnGetTypeComp,
6020 ITypeInfo_fnGetFuncDesc,
6021 ITypeInfo_fnGetVarDesc,
6022 ITypeInfo_fnGetNames,
6023 ITypeInfo_fnGetRefTypeOfImplType,
6024 ITypeInfo_fnGetImplTypeFlags,
6025 ITypeInfo_fnGetIDsOfNames,
6026 ITypeInfo_fnInvoke,
6027 ITypeInfo_fnGetDocumentation,
6028 ITypeInfo_fnGetDllEntry,
6029 ITypeInfo_fnGetRefTypeInfo,
6030 ITypeInfo_fnAddressOfMember,
6031 ITypeInfo_fnCreateInstance,
6032 ITypeInfo_fnGetMops,
6033 ITypeInfo_fnGetContainingTypeLib,
6034 ITypeInfo_fnReleaseTypeAttr,
6035 ITypeInfo_fnReleaseFuncDesc,
6036 ITypeInfo_fnReleaseVarDesc,
6038 ITypeInfo2_fnGetTypeKind,
6039 ITypeInfo2_fnGetTypeFlags,
6040 ITypeInfo2_fnGetFuncIndexOfMemId,
6041 ITypeInfo2_fnGetVarIndexOfMemId,
6042 ITypeInfo2_fnGetCustData,
6043 ITypeInfo2_fnGetFuncCustData,
6044 ITypeInfo2_fnGetParamCustData,
6045 ITypeInfo2_fnGetVarCustData,
6046 ITypeInfo2_fnGetImplTypeCustData,
6047 ITypeInfo2_fnGetDocumentation2,
6048 ITypeInfo2_fnGetAllCustData,
6049 ITypeInfo2_fnGetAllFuncCustData,
6050 ITypeInfo2_fnGetAllParamCustData,
6051 ITypeInfo2_fnGetAllVarCustData,
6052 ITypeInfo2_fnGetAllImplTypeCustData,
6055 /******************************************************************************
6056 * CreateDispTypeInfo [OLEAUT32.31]
6058 * Build type information for an object so it can be called through an
6059 * IDispatch interface.
6061 * RETURNS
6062 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6063 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6065 * NOTES
6066 * This call allows an objects methods to be accessed through IDispatch, by
6067 * building an ITypeInfo object that IDispatch can use to call through.
6069 HRESULT WINAPI CreateDispTypeInfo(
6070 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6071 LCID lcid, /* [I] Locale Id */
6072 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6074 ITypeInfoImpl *pTIImpl;
6075 int param, func;
6076 TLBFuncDesc **ppFuncDesc;
6078 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
6079 pTIImpl->pTypeLib = NULL;
6080 pTIImpl->index = 0;
6081 pTIImpl->Name = NULL;
6082 pTIImpl->dwHelpContext = -1;
6083 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
6084 pTIImpl->TypeAttr.lcid = lcid;
6085 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
6086 pTIImpl->TypeAttr.wMajorVerNum = 0;
6087 pTIImpl->TypeAttr.wMinorVerNum = 0;
6088 pTIImpl->TypeAttr.cbAlignment = 2;
6089 pTIImpl->TypeAttr.cbSizeInstance = -1;
6090 pTIImpl->TypeAttr.cbSizeVft = -1;
6091 pTIImpl->TypeAttr.cFuncs = 0;
6092 pTIImpl->TypeAttr.cImplTypes = 1;
6093 pTIImpl->TypeAttr.cVars = 0;
6094 pTIImpl->TypeAttr.wTypeFlags = 0;
6096 ppFuncDesc = &pTIImpl->funclist;
6097 for(func = 0; func < pidata->cMembers; func++) {
6098 METHODDATA *md = pidata->pmethdata + func;
6099 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6100 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6101 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6102 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6103 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6104 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6105 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6106 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6107 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6108 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6109 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6110 md->cArgs * sizeof(ELEMDESC));
6111 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6112 md->cArgs * sizeof(TLBParDesc));
6113 for(param = 0; param < md->cArgs; param++) {
6114 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6115 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6117 ppFuncDesc = &(*ppFuncDesc)->next;
6119 *pptinfo = (ITypeInfo*)pTIImpl;
6120 return S_OK;
6124 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6126 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6128 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6131 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6133 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6135 return ITypeInfo_AddRef((ITypeInfo *)This);
6138 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6140 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6142 return ITypeInfo_Release((ITypeInfo *)This);
6145 static HRESULT WINAPI ITypeComp_fnBind(
6146 ITypeComp * iface,
6147 OLECHAR * szName,
6148 ULONG lHash,
6149 WORD wFlags,
6150 ITypeInfo ** ppTInfo,
6151 DESCKIND * pDescKind,
6152 BINDPTR * pBindPtr)
6154 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6155 TLBFuncDesc * pFDesc;
6156 TLBVarDesc * pVDesc;
6158 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6160 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6161 if (pFDesc->funcdesc.invkind & wFlags)
6162 if (!strcmpW(pFDesc->Name, szName)) {
6163 break;
6166 if (pFDesc)
6168 *pDescKind = DESCKIND_FUNCDESC;
6169 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
6170 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6171 return S_OK;
6172 } else {
6173 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
6175 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6176 if (!strcmpW(pVDesc->Name, szName)) {
6177 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6178 if (FAILED(hr))
6179 return hr;
6180 *pDescKind = DESCKIND_VARDESC;
6181 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6182 return S_OK;
6187 /* not found, look for it in inherited interfaces */
6188 if (This->TypeAttr.cImplTypes &&
6189 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
6190 /* recursive search */
6191 ITypeInfo *pTInfo;
6192 ITypeComp *pTComp;
6193 HRESULT hr;
6194 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6195 if (SUCCEEDED(hr))
6197 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6198 ITypeInfo_Release(pTInfo);
6200 if (SUCCEEDED(hr))
6202 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6203 ITypeComp_Release(pTComp);
6204 return hr;
6206 WARN("Could not search inherited interface!\n");
6208 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6209 *pDescKind = DESCKIND_NONE;
6210 pBindPtr->lpfuncdesc = NULL;
6211 *ppTInfo = NULL;
6212 return DISP_E_MEMBERNOTFOUND;
6215 static HRESULT WINAPI ITypeComp_fnBindType(
6216 ITypeComp * iface,
6217 OLECHAR * szName,
6218 ULONG lHash,
6219 ITypeInfo ** ppTInfo,
6220 ITypeComp ** ppTComp)
6222 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6224 /* strange behaviour (does nothing) but like the
6225 * original */
6227 if (!ppTInfo || !ppTComp)
6228 return E_POINTER;
6230 *ppTInfo = NULL;
6231 *ppTComp = NULL;
6233 return S_OK;
6236 static const ITypeCompVtbl tcompvt =
6239 ITypeComp_fnQueryInterface,
6240 ITypeComp_fnAddRef,
6241 ITypeComp_fnRelease,
6243 ITypeComp_fnBind,
6244 ITypeComp_fnBindType