Assorted spelling fixes.
[wine/dcerpc.git] / dlls / oleaut32 / typelib.c
blob15359267597da8f732ed21e03bc734e8de3469ba
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
47 * behaviour.
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
55 #include "config.h"
56 #include "wine/port.h"
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdarg.h>
61 #include <stdio.h>
62 #include <ctype.h>
64 #define COBJMACROS
65 #define NONAMELESSUNION
66 #define NONAMELESSSTRUCT
68 #include "winerror.h"
69 #include "windef.h"
70 #include "winbase.h"
71 #include "winnls.h"
72 #include "winreg.h"
73 #include "winuser.h"
75 #include "wine/unicode.h"
76 #include "objbase.h"
77 #include "typelib.h"
78 #include "wine/debug.h"
79 #include "variant.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 /****************************************************************************
88 * FromLExxx
90 * Takes p_iVal (which is in little endian) and returns it
91 * in the host machine's byte order.
93 #ifdef WORDS_BIGENDIAN
94 static WORD FromLEWord(WORD p_iVal)
96 return (((p_iVal & 0x00FF) << 8) |
97 ((p_iVal & 0xFF00) >> 8));
101 static DWORD FromLEDWord(DWORD p_iVal)
103 return (((p_iVal & 0x000000FF) << 24) |
104 ((p_iVal & 0x0000FF00) << 8) |
105 ((p_iVal & 0x00FF0000) >> 8) |
106 ((p_iVal & 0xFF000000) >> 24));
108 #else
109 #define FromLEWord(X) (X)
110 #define FromLEDWord(X) (X)
111 #endif
114 /****************************************************************************
115 * FromLExxx
117 * Fix byte order in any structure if necessary
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val, int p_iSize)
122 WORD *Val = p_Val;
124 p_iSize /= sizeof(WORD);
126 while (p_iSize) {
127 *Val = FromLEWord(*Val);
128 Val++;
129 p_iSize--;
134 static void FromLEDWords(void *p_Val, int p_iSize)
136 DWORD *Val = p_Val;
138 p_iSize /= sizeof(DWORD);
140 while (p_iSize) {
141 *Val = FromLEDWord(*Val);
142 Val++;
143 p_iSize--;
146 #else
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
149 #endif
151 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
152 /* buffer must be at least 60 characters long */
153 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
155 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
156 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
158 memcpy( buffer, TypelibW, sizeof(TypelibW) );
159 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
160 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
161 return buffer;
164 /* get the path of an interface key, in the form "Interface\\<guid>" */
165 /* buffer must be at least 50 characters long */
166 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
168 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
170 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
171 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
172 return buffer;
175 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
176 /* buffer must be at least 16 characters long */
177 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
179 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
180 static const WCHAR win16W[] = {'w','i','n','1','6',0};
181 static const WCHAR win32W[] = {'w','i','n','3','2',0};
183 sprintfW( buffer, LcidFormatW, lcid );
184 switch(syskind)
186 case SYS_WIN16: strcatW( buffer, win16W ); break;
187 case SYS_WIN32: strcatW( buffer, win32W ); break;
188 default:
189 TRACE("Typelib is for unsupported syskind %i\n", syskind);
190 return NULL;
192 return buffer;
196 /****************************************************************************
197 * QueryPathOfRegTypeLib [OLEAUT32.164]
198 * RETURNS
199 * path of typelib
201 HRESULT WINAPI
202 QueryPathOfRegTypeLib(
203 REFGUID guid, /* [in] referenced guid */
204 WORD wMaj, /* [in] major version */
205 WORD wMin, /* [in] minor version */
206 LCID lcid, /* [in] locale id */
207 LPBSTR path ) /* [out] path of typelib */
209 HRESULT hr = E_FAIL;
210 LCID myLCID = lcid;
211 HKEY hkey;
212 WCHAR buffer[60];
213 WCHAR Path[MAX_PATH];
215 if ( !HIWORD(guid) )
217 FIXME("(guid %p,%d,%d,0x%04lx,%p),stub!\n", guid, wMaj, wMin, lcid, path);
218 return E_FAIL;
221 get_typelib_key( guid, wMaj, wMin, buffer );
223 if (RegOpenKeyW( HKEY_CLASSES_ROOT, buffer, &hkey ) != ERROR_SUCCESS)
225 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
226 return E_FAIL;
229 while (hr != S_OK)
231 DWORD dwPathLen = sizeof(Path);
233 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
235 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
237 if (!lcid)
238 break;
239 else if (myLCID == lcid)
241 /* try with sub-langid */
242 myLCID = SUBLANGID(lcid);
244 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
246 /* try with system langid */
247 myLCID = 0;
249 else
251 break;
254 else
256 *path = SysAllocString( Path );
257 hr = S_OK;
260 RegCloseKey( hkey );
261 return hr;
264 /******************************************************************************
265 * CreateTypeLib [OLEAUT32.160] creates a typelib
267 * RETURNS
268 * Success: S_OK
269 * Failure: Status
271 HRESULT WINAPI CreateTypeLib(
272 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
274 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
275 return E_FAIL;
277 /******************************************************************************
278 * LoadTypeLib [OLEAUT32.161]
279 * Loads and registers a type library
280 * NOTES
281 * Docs: OLECHAR FAR* szFile
282 * Docs: iTypeLib FAR* FAR* pptLib
284 * RETURNS
285 * Success: S_OK
286 * Failure: Status
288 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
290 HRESULT WINAPI LoadTypeLib(
291 const OLECHAR *szFile,/* [in] Name of file to load from */
292 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
294 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
295 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
298 /******************************************************************************
299 * LoadTypeLibEx [OLEAUT32.183]
300 * Loads and optionally registers a type library
302 * RETURNS
303 * Success: S_OK
304 * Failure: Status
306 HRESULT WINAPI LoadTypeLibEx(
307 LPCOLESTR szFile, /* [in] Name of file to load from */
308 REGKIND regkind, /* [in] Specify kind of registration */
309 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
311 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
312 WCHAR *pIndexStr;
313 HRESULT res;
314 INT index = 1;
316 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
318 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
319 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
321 *pptLib = NULL;
322 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
323 NULL)) {
325 /* Look for a trailing '\\' followed by an index */
326 pIndexStr = strrchrW(szFile, '\\');
327 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
328 index = atoiW(pIndexStr);
329 memcpy(szFileCopy, szFile,
330 (pIndexStr - szFile - 1) * sizeof(WCHAR));
331 szFileCopy[pIndexStr - szFile - 1] = '\0';
332 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
333 szPath,NULL))
334 return TYPE_E_CANTLOADLIBRARY;
335 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
336 return TYPE_E_CANTLOADLIBRARY;
340 TRACE("File %s index %d\n", debugstr_w(szPath), index);
342 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
344 if (SUCCEEDED(res))
345 switch(regkind)
347 case REGKIND_DEFAULT:
348 /* don't register typelibs supplied with full path. Experimentation confirms the following */
349 if ((!szFile) ||
350 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
351 (szFile[0] && (szFile[1] == ':'))) break;
352 /* else fall-through */
354 case REGKIND_REGISTER:
355 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
357 IUnknown_Release(*pptLib);
358 *pptLib = 0;
360 break;
361 case REGKIND_NONE:
362 break;
365 TRACE(" returns %08lx\n",res);
366 return res;
369 /******************************************************************************
370 * LoadRegTypeLib [OLEAUT32.162]
372 HRESULT WINAPI LoadRegTypeLib(
373 REFGUID rguid, /* [in] referenced guid */
374 WORD wVerMajor, /* [in] major version */
375 WORD wVerMinor, /* [in] minor version */
376 LCID lcid, /* [in] locale id */
377 ITypeLib **ppTLib) /* [out] path of typelib */
379 BSTR bstr=NULL;
380 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
382 if(SUCCEEDED(res))
384 res= LoadTypeLib(bstr, ppTLib);
385 SysFreeString(bstr);
388 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
390 return res;
394 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
395 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
396 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
397 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
398 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
399 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
401 /******************************************************************************
402 * RegisterTypeLib [OLEAUT32.163]
403 * Adds information about a type library to the System Registry
404 * NOTES
405 * Docs: ITypeLib FAR * ptlib
406 * Docs: OLECHAR FAR* szFullPath
407 * Docs: OLECHAR FAR* szHelpDir
409 * RETURNS
410 * Success: S_OK
411 * Failure: Status
413 HRESULT WINAPI RegisterTypeLib(
414 ITypeLib * ptlib, /* [in] Pointer to the library*/
415 OLECHAR * szFullPath, /* [in] full Path of the library*/
416 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
417 may be NULL*/
419 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
420 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
421 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
422 HRESULT res;
423 TLIBATTR *attr;
424 WCHAR keyName[60];
425 WCHAR tmp[16];
426 HKEY key, subKey;
427 UINT types, tidx;
428 TYPEKIND kind;
429 DWORD disposition;
431 if (ptlib == NULL || szFullPath == NULL)
432 return E_INVALIDARG;
434 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
435 return E_FAIL;
437 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
439 res = S_OK;
440 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
441 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
443 LPOLESTR doc;
445 /* Set the human-readable name of the typelib */
446 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
448 if (RegSetValueExW(key, NULL, 0, REG_SZ,
449 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
450 res = E_FAIL;
452 SysFreeString(doc);
454 else
455 res = E_FAIL;
457 /* Make up the name of the typelib path subkey */
458 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
460 /* Create the typelib path subkey */
461 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
462 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
464 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
465 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
466 res = E_FAIL;
468 RegCloseKey(subKey);
470 else
471 res = E_FAIL;
473 /* Create the flags subkey */
474 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
475 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
477 /* FIXME: is %u correct? */
478 static const WCHAR formatW[] = {'%','u',0};
479 WCHAR buf[20];
480 sprintfW(buf, formatW, attr->wLibFlags);
481 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
482 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
483 res = E_FAIL;
485 RegCloseKey(subKey);
487 else
488 res = E_FAIL;
490 /* create the helpdir subkey */
491 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
492 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
494 BOOL freeHelpDir = FALSE;
495 OLECHAR* pIndexStr;
497 /* if we created a new key, and helpDir was null, set the helpdir
498 to the directory which contains the typelib. However,
499 if we just opened an existing key, we leave the helpdir alone */
500 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
501 szHelpDir = SysAllocString(szFullPath);
502 pIndexStr = strrchrW(szHelpDir, '\\');
503 if (pIndexStr) {
504 *pIndexStr = 0;
506 freeHelpDir = TRUE;
509 /* if we have an szHelpDir, set it! */
510 if (szHelpDir != NULL) {
511 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
512 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
513 res = E_FAIL;
517 /* tidy up */
518 if (freeHelpDir) SysFreeString(szHelpDir);
519 RegCloseKey(subKey);
521 } else {
522 res = E_FAIL;
525 RegCloseKey(key);
527 else
528 res = E_FAIL;
530 /* register OLE Automation-compatible interfaces for this typelib */
531 types = ITypeLib_GetTypeInfoCount(ptlib);
532 for (tidx=0; tidx<types; tidx++) {
533 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
534 LPOLESTR name = NULL;
535 ITypeInfo *tinfo = NULL;
537 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
539 switch (kind) {
540 case TKIND_INTERFACE:
541 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
542 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
543 break;
545 case TKIND_DISPATCH:
546 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
547 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
548 break;
550 default:
551 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
552 break;
555 if (tinfo) {
556 TYPEATTR *tattr = NULL;
557 ITypeInfo_GetTypeAttr(tinfo, &tattr);
559 if (tattr) {
560 TRACE_(typelib)("guid=%s, flags=%04x (",
561 debugstr_guid(&tattr->guid),
562 tattr->wTypeFlags);
564 if (TRACE_ON(typelib)) {
565 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
566 XX(FAPPOBJECT);
567 XX(FCANCREATE);
568 XX(FLICENSED);
569 XX(FPREDECLID);
570 XX(FHIDDEN);
571 XX(FCONTROL);
572 XX(FDUAL);
573 XX(FNONEXTENSIBLE);
574 XX(FOLEAUTOMATION);
575 XX(FRESTRICTED);
576 XX(FAGGREGATABLE);
577 XX(FREPLACEABLE);
578 XX(FDISPATCHABLE);
579 XX(FREVERSEBIND);
580 XX(FPROXY);
581 #undef XX
582 MESSAGE("\n");
586 * FIXME: The 1 is just here until we implement rpcrt4
587 * stub/proxy handling. Until then it helps IShield
588 * v6 to work.
590 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
592 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
593 FIXME("Registering non-oleautomation interface!\n");
596 /* register interface<->typelib coupling */
597 get_interface_key( &tattr->guid, keyName );
598 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
599 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
601 if (name)
602 RegSetValueExW(key, NULL, 0, REG_SZ,
603 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
605 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
606 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
607 RegSetValueExW(subKey, NULL, 0, REG_SZ,
608 (BYTE*)PSOA, sizeof PSOA);
609 RegCloseKey(subKey);
612 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
613 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
614 RegSetValueExW(subKey, NULL, 0, REG_SZ,
615 (BYTE*)PSOA, sizeof PSOA);
616 RegCloseKey(subKey);
619 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
620 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
622 WCHAR buffer[40];
623 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
624 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
626 StringFromGUID2(&attr->guid, buffer, 40);
627 RegSetValueExW(subKey, NULL, 0, REG_SZ,
628 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
629 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
630 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
631 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
632 RegCloseKey(subKey);
635 RegCloseKey(key);
639 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
642 ITypeInfo_Release(tinfo);
645 SysFreeString(name);
649 ITypeLib_ReleaseTLibAttr(ptlib, attr);
651 return res;
655 /******************************************************************************
656 * UnRegisterTypeLib [OLEAUT32.186]
657 * Removes information about a type library from the System Registry
658 * NOTES
660 * RETURNS
661 * Success: S_OK
662 * Failure: Status
664 HRESULT WINAPI UnRegisterTypeLib(
665 REFGUID libid, /* [in] Guid of the library */
666 WORD wVerMajor, /* [in] major version */
667 WORD wVerMinor, /* [in] minor version */
668 LCID lcid, /* [in] locale id */
669 SYSKIND syskind)
671 BSTR tlibPath = NULL;
672 DWORD tmpLength;
673 WCHAR keyName[60];
674 WCHAR subKeyName[50];
675 int result = S_OK;
676 DWORD i = 0;
677 BOOL deleteOtherStuff;
678 HKEY key = NULL;
679 HKEY subKey = NULL;
680 TYPEATTR* typeAttr = NULL;
681 TYPEKIND kind;
682 ITypeInfo* typeInfo = NULL;
683 ITypeLib* typeLib = NULL;
684 int numTypes;
686 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
688 /* Create the path to the key */
689 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
691 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
693 TRACE("Unsupported syskind %i\n", syskind);
694 result = E_INVALIDARG;
695 goto end;
698 /* get the path to the typelib on disk */
699 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
700 result = E_INVALIDARG;
701 goto end;
704 /* Try and open the key to the type library. */
705 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
706 result = E_INVALIDARG;
707 goto end;
710 /* Try and load the type library */
711 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
712 result = TYPE_E_INVALIDSTATE;
713 goto end;
716 /* remove any types registered with this typelib */
717 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
718 for (i=0; i<numTypes; i++) {
719 /* get the kind of type */
720 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
721 goto enddeleteloop;
724 /* skip non-interfaces, and get type info for the type */
725 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
726 goto enddeleteloop;
728 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
729 goto enddeleteloop;
731 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
732 goto enddeleteloop;
735 /* the path to the type */
736 get_interface_key( &typeAttr->guid, subKeyName );
738 /* Delete its bits */
739 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
740 goto enddeleteloop;
742 RegDeleteKeyW(subKey, ProxyStubClsidW);
743 RegDeleteKeyW(subKey, ProxyStubClsid32W);
744 RegDeleteKeyW(subKey, TypeLibW);
745 RegCloseKey(subKey);
746 subKey = NULL;
747 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
749 enddeleteloop:
750 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
751 typeAttr = NULL;
752 if (typeInfo) ITypeInfo_Release(typeInfo);
753 typeInfo = NULL;
756 /* Now, delete the type library path subkey */
757 get_lcid_subkey( lcid, syskind, subKeyName );
758 RegDeleteKeyW(key, subKeyName);
759 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
760 RegDeleteKeyW(key, subKeyName);
762 /* check if there is anything besides the FLAGS/HELPDIR keys.
763 If there is, we don't delete them */
764 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
765 deleteOtherStuff = TRUE;
766 i = 0;
767 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
768 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
770 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
771 if (!strcmpW(subKeyName, FLAGSW)) continue;
772 if (!strcmpW(subKeyName, HELPDIRW)) continue;
773 deleteOtherStuff = FALSE;
774 break;
777 /* only delete the other parts of the key if we're absolutely sure */
778 if (deleteOtherStuff) {
779 RegDeleteKeyW(key, FLAGSW);
780 RegDeleteKeyW(key, HELPDIRW);
781 RegCloseKey(key);
782 key = NULL;
784 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
785 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
786 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
789 end:
790 if (tlibPath) SysFreeString(tlibPath);
791 if (typeLib) ITypeLib_Release(typeLib);
792 if (subKey) RegCloseKey(subKey);
793 if (key) RegCloseKey(key);
794 return result;
797 /*======================= ITypeLib implementation =======================*/
799 typedef struct tagTLBCustData
801 GUID guid;
802 VARIANT data;
803 struct tagTLBCustData* next;
804 } TLBCustData;
806 /* data structure for import typelibs */
807 typedef struct tagTLBImpLib
809 int offset; /* offset in the file (MSFT)
810 offset in nametable (SLTG)
811 just used to identify library while reading
812 data from file */
813 GUID guid; /* libid */
814 BSTR name; /* name */
816 LCID lcid; /* lcid of imported typelib */
818 WORD wVersionMajor; /* major version number */
819 WORD wVersionMinor; /* minor version number */
821 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
822 NULL if not yet loaded */
823 struct tagTLBImpLib * next;
824 } TLBImpLib;
826 /* internal ITypeLib data */
827 typedef struct tagITypeLibImpl
829 ITypeLib2Vtbl *lpVtbl;
830 ITypeCompVtbl *lpVtblTypeComp;
831 ULONG ref;
832 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
834 /* strings can be stored in tlb as multibyte strings BUT they are *always*
835 * exported to the application as a UNICODE string.
837 BSTR Name;
838 BSTR DocString;
839 BSTR HelpFile;
840 BSTR HelpStringDll;
841 unsigned long dwHelpContext;
842 int TypeInfoCount; /* nr of typeinfo's in librarry */
843 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
844 int ctCustData; /* number of items in cust data list */
845 TLBCustData * pCustData; /* linked list to cust data */
846 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
847 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
848 libary. Only used while read MSFT
849 typelibs */
851 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
852 struct tagITypeLibImpl *next, *prev;
853 WCHAR *path;
854 INT index;
855 } ITypeLibImpl;
857 static struct ITypeLib2Vtbl tlbvt;
858 static struct ITypeCompVtbl tlbtcvt;
860 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
861 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
863 /* ITypeLib methods */
864 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
865 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
867 /*======================= ITypeInfo implementation =======================*/
869 /* data for referenced types */
870 typedef struct tagTLBRefType
872 INT index; /* Type index for internal ref or for external ref
873 it the format is SLTG. -2 indicates to
874 use guid */
876 GUID guid; /* guid of the referenced type */
877 /* if index == TLB_REF_USE_GUID */
879 HREFTYPE reference; /* The href of this ref */
880 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
881 TLB_REF_INTERNAL for internal refs
882 TLB_REF_NOT_FOUND for broken refs */
884 struct tagTLBRefType * next;
885 } TLBRefType;
887 #define TLB_REF_USE_GUID -2
889 #define TLB_REF_INTERNAL (void*)-2
890 #define TLB_REF_NOT_FOUND (void*)-1
892 /* internal Parameter data */
893 typedef struct tagTLBParDesc
895 BSTR Name;
896 int ctCustData;
897 TLBCustData * pCustData; /* linked list to cust data */
898 } TLBParDesc;
900 /* internal Function data */
901 typedef struct tagTLBFuncDesc
903 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
904 BSTR Name; /* the name of this function */
905 TLBParDesc *pParamDesc; /* array with param names and custom data */
906 int helpcontext;
907 int HelpStringContext;
908 BSTR HelpString;
909 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
910 int ctCustData;
911 TLBCustData * pCustData; /* linked list to cust data; */
912 struct tagTLBFuncDesc * next;
913 } TLBFuncDesc;
915 /* internal Variable data */
916 typedef struct tagTLBVarDesc
918 VARDESC vardesc; /* lots of info on the variable and its attributes. */
919 BSTR Name; /* the name of this variable */
920 int HelpContext;
921 int HelpStringContext; /* FIXME: where? */
922 BSTR HelpString;
923 int ctCustData;
924 TLBCustData * pCustData;/* linked list to cust data; */
925 struct tagTLBVarDesc * next;
926 } TLBVarDesc;
928 /* internal implemented interface data */
929 typedef struct tagTLBImplType
931 HREFTYPE hRef; /* hRef of interface */
932 int implflags; /* IMPLFLAG_*s */
933 int ctCustData;
934 TLBCustData * pCustData;/* linked list to custom data; */
935 struct tagTLBImplType *next;
936 } TLBImplType;
938 /* internal TypeInfo data */
939 typedef struct tagITypeInfoImpl
941 ITypeInfo2Vtbl *lpVtbl;
942 ITypeCompVtbl *lpVtblTypeComp;
943 ULONG ref;
944 TYPEATTR TypeAttr ; /* _lots_ of type information. */
945 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
946 int index; /* index in this typelib; */
947 /* type libs seem to store the doc strings in ascii
948 * so why should we do it in unicode?
950 BSTR Name;
951 BSTR DocString;
952 unsigned long dwHelpContext;
953 unsigned long dwHelpStringContext;
955 /* functions */
956 TLBFuncDesc * funclist; /* linked list with function descriptions */
958 /* variables */
959 TLBVarDesc * varlist; /* linked list with variable descriptions */
961 /* Implemented Interfaces */
962 TLBImplType * impltypelist;
964 TLBRefType * reflist;
965 int ctCustData;
966 TLBCustData * pCustData; /* linked list to cust data; */
967 struct tagITypeInfoImpl * next;
968 } ITypeInfoImpl;
970 static struct ITypeInfo2Vtbl tinfvt;
971 static struct ITypeCompVtbl tcompvt;
973 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
975 typedef struct tagTLBContext
977 unsigned int oStart; /* start of TLB in file */
978 unsigned int pos; /* current pos */
979 unsigned int length; /* total length */
980 void *mapping; /* memory mapping */
981 MSFT_SegDir * pTblDir;
982 ITypeLibImpl* pLibInfo;
983 } TLBContext;
986 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
989 debug
991 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
992 if (pTD->vt & VT_RESERVED)
993 szVarType += strlen(strcpy(szVarType, "reserved | "));
994 if (pTD->vt & VT_BYREF)
995 szVarType += strlen(strcpy(szVarType, "ref to "));
996 if (pTD->vt & VT_ARRAY)
997 szVarType += strlen(strcpy(szVarType, "array of "));
998 if (pTD->vt & VT_VECTOR)
999 szVarType += strlen(strcpy(szVarType, "vector of "));
1000 switch(pTD->vt & VT_TYPEMASK) {
1001 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1002 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1003 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1004 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1005 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1006 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1007 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1008 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1009 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1010 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1011 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1012 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1013 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1014 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1015 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1016 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1017 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1018 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1019 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1020 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1021 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1022 pTD->u.hreftype); break;
1023 case VT_PTR: sprintf(szVarType, "ptr to ");
1024 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1025 break;
1026 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1027 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1028 break;
1029 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1030 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1031 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1032 break;
1034 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1038 void dump_ELEMDESC(ELEMDESC *edesc) {
1039 char buf[200];
1040 dump_TypeDesc(&edesc->tdesc,buf);
1041 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1042 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1043 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1045 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1046 int i;
1047 MESSAGE("memid is %08lx\n",funcdesc->memid);
1048 for (i=0;i<funcdesc->cParams;i++) {
1049 MESSAGE("Param %d:\n",i);
1050 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1052 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1053 switch (funcdesc->funckind) {
1054 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1055 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1056 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1057 case FUNC_STATIC: MESSAGE("static");break;
1058 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1059 default: MESSAGE("unknown");break;
1061 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1062 switch (funcdesc->invkind) {
1063 case INVOKE_FUNC: MESSAGE("func");break;
1064 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1065 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1066 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1068 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1069 switch (funcdesc->callconv) {
1070 case CC_CDECL: MESSAGE("cdecl");break;
1071 case CC_PASCAL: MESSAGE("pascal");break;
1072 case CC_STDCALL: MESSAGE("stdcall");break;
1073 case CC_SYSCALL: MESSAGE("syscall");break;
1074 default:break;
1076 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1077 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1078 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1080 MESSAGE("\telemdescFunc (return value type):\n");
1081 dump_ELEMDESC(&funcdesc->elemdescFunc);
1084 void dump_IDLDESC(IDLDESC *idl) {
1085 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1088 static const char * typekind_desc[] =
1090 "TKIND_ENUM",
1091 "TKIND_RECORD",
1092 "TKIND_MODULE",
1093 "TKIND_INTERFACE",
1094 "TKIND_DISPATCH",
1095 "TKIND_COCLASS",
1096 "TKIND_ALIAS",
1097 "TKIND_UNION",
1098 "TKIND_MAX"
1101 void dump_TYPEATTR(TYPEATTR *tattr) {
1102 char buf[200];
1103 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1104 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1105 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1106 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1107 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1108 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1109 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1110 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1111 MESSAGE("\tcVars: %d\n", tattr->cVars);
1112 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1113 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1114 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1115 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1116 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1117 dump_TypeDesc(&tattr->tdescAlias,buf);
1118 MESSAGE("\ttypedesc: %s\n", buf);
1119 dump_IDLDESC(&tattr->idldescType);
1122 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1124 int i;
1125 if (!TRACE_ON(typelib))
1126 return;
1127 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1128 for (i=0;i<pfd->funcdesc.cParams;i++)
1129 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1132 dump_FUNCDESC(&(pfd->funcdesc));
1134 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1135 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1137 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1139 while (pfd)
1141 dump_TLBFuncDescOne(pfd);
1142 pfd = pfd->next;
1145 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1147 while (pvd)
1149 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1150 pvd = pvd->next;
1154 static void dump_TLBImpLib(TLBImpLib *import)
1156 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1157 debugstr_w(import->name));
1158 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1159 import->wVersionMinor, import->lcid, import->offset);
1162 static void dump_TLBRefType(TLBRefType * prt)
1164 while (prt)
1166 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1167 if(prt->index == -1)
1168 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1169 else
1170 TRACE_(typelib)("type no: %d\n", prt->index);
1172 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1173 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1174 TRACE_(typelib)("in lib\n");
1175 dump_TLBImpLib(prt->pImpTLInfo);
1177 prt = prt->next;
1181 static void dump_TLBImplType(TLBImplType * impl)
1183 while (impl) {
1184 TRACE_(typelib)(
1185 "implementing/inheriting interface hRef = %lx implflags %x\n",
1186 impl->hRef, impl->implflags);
1187 impl = impl->next;
1191 void dump_Variant(VARIANT * pvar)
1193 SYSTEMTIME st;
1195 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1197 if (pvar)
1199 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1200 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1202 TRACE(",%p", V_BYREF(pvar));
1204 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1206 TRACE(",FIXME");
1208 else switch (V_TYPE(pvar))
1210 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1211 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1212 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1213 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1214 case VT_INT:
1215 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1216 case VT_UINT:
1217 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1218 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1219 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1220 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1221 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1222 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1223 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1224 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1225 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1226 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1227 V_CY(pvar).s.Lo); break;
1228 case VT_DATE:
1229 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1230 TRACE(",<invalid>");
1231 else
1232 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1233 st.wHour, st.wMinute, st.wSecond);
1234 break;
1235 case VT_ERROR:
1236 case VT_VOID:
1237 case VT_USERDEFINED:
1238 case VT_EMPTY:
1239 case VT_NULL: break;
1240 default: TRACE(",?"); break;
1243 TRACE("}\n");
1246 static void dump_DispParms(DISPPARAMS * pdp)
1248 int index = 0;
1250 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1252 while (index < pdp->cArgs)
1254 dump_Variant( &pdp->rgvarg[index] );
1255 ++index;
1259 static void dump_TypeInfo(ITypeInfoImpl * pty)
1261 TRACE("%p ref=%lu\n", pty, pty->ref);
1262 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1263 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1264 TRACE("fct:%u var:%u impl:%u\n",
1265 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1266 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1267 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1268 dump_TLBFuncDesc(pty->funclist);
1269 dump_TLBVarDesc(pty->varlist);
1270 dump_TLBImplType(pty->impltypelist);
1273 void dump_VARDESC(VARDESC *v)
1275 MESSAGE("memid %ld\n",v->memid);
1276 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1277 MESSAGE("oInst %ld\n",v->u.oInst);
1278 dump_ELEMDESC(&(v->elemdescVar));
1279 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1280 MESSAGE("varkind %d\n",v->varkind);
1283 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1285 /* VT_LPWSTR is largest type that */
1286 /* may appear in type description*/
1287 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1288 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1289 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1290 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1291 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1292 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1293 {{0},30},{{0},31}
1296 static void TLB_abort()
1298 DebugBreak();
1300 static void * TLB_Alloc(unsigned size)
1302 void * ret;
1303 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1304 /* FIXME */
1305 ERR("cannot allocate memory\n");
1307 return ret;
1310 static void TLB_Free(void * ptr)
1312 HeapFree(GetProcessHeap(), 0, ptr);
1315 /* deep copy a typedesc */
1316 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1318 out->vt = in->vt;
1319 switch(in->vt) {
1320 case VT_PTR:
1321 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1322 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1323 break;
1324 case VT_USERDEFINED:
1325 out->u.hreftype = in->u.hreftype;
1326 break;
1327 case VT_CARRAY:
1328 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1329 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1330 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1331 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1332 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1333 break;
1334 default:
1335 break;
1339 /* free()s any allocated memory pointed to by the tdesc. NB does not
1340 free the tdesc itself - this is because the tdesc is typically part
1341 of a larger structure */
1342 static void free_deep_typedesc(TYPEDESC *tdesc)
1344 switch(tdesc->vt) {
1345 case VT_PTR:
1346 free_deep_typedesc(tdesc->u.lptdesc);
1347 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1348 tdesc->u.lptdesc = NULL;
1349 break;
1350 case VT_CARRAY:
1351 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1352 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1353 tdesc->u.lpadesc = NULL;
1354 break;
1355 default:
1356 break;
1360 /**********************************************************************
1362 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1364 /* read function */
1365 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1367 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1368 pcx->pos, count, pcx->oStart, pcx->length, where);
1370 if (where != DO_NOT_SEEK)
1372 where += pcx->oStart;
1373 if (where > pcx->length)
1375 /* FIXME */
1376 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1377 TLB_abort();
1379 pcx->pos = where;
1381 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1382 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1383 pcx->pos += count;
1384 return count;
1387 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1388 long where )
1390 DWORD ret;
1392 ret = MSFT_Read(buffer, count, pcx, where);
1393 FromLEDWords(buffer, ret);
1395 return ret;
1398 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1399 long where )
1401 DWORD ret;
1403 ret = MSFT_Read(buffer, count, pcx, where);
1404 FromLEWords(buffer, ret);
1406 return ret;
1409 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1411 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1412 memset(pGuid,0, sizeof(GUID));
1413 return;
1415 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1416 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1417 pGuid->Data2 = FromLEWord(pGuid->Data2);
1418 pGuid->Data3 = FromLEWord(pGuid->Data3);
1419 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1422 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1424 char * name;
1425 MSFT_NameIntro niName;
1426 int lengthInChars;
1427 WCHAR* pwstring = NULL;
1428 BSTR bstrName = NULL;
1430 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1431 pcx->pTblDir->pNametab.offset+offset);
1432 niName.namelen &= 0xFF; /* FIXME: correct ? */
1433 name=TLB_Alloc((niName.namelen & 0xff) +1);
1434 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1435 name[niName.namelen & 0xff]='\0';
1437 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1438 name, -1, NULL, 0);
1440 /* no invalid characters in string */
1441 if (lengthInChars)
1443 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1445 /* don't check for invalid character since this has been done previously */
1446 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1448 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1449 lengthInChars = SysStringLen(bstrName);
1450 HeapFree(GetProcessHeap(), 0, pwstring);
1453 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1454 return bstrName;
1457 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1459 char * string;
1460 INT16 length;
1461 int lengthInChars;
1462 BSTR bstr = NULL;
1464 if(offset<0) return NULL;
1465 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1466 if(length <= 0) return 0;
1467 string=TLB_Alloc(length +1);
1468 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1469 string[length]='\0';
1471 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1472 string, -1, NULL, 0);
1474 /* no invalid characters in string */
1475 if (lengthInChars)
1477 WCHAR* 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, string, -1, pwstring, lengthInChars);
1482 bstr = SysAllocStringLen(pwstring, lengthInChars);
1483 lengthInChars = SysStringLen(bstr);
1484 HeapFree(GetProcessHeap(), 0, pwstring);
1487 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1488 return bstr;
1491 * read a value and fill a VARIANT structure
1493 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1495 int size;
1497 TRACE_(typelib)("\n");
1499 if(offset <0) { /* data are packed in here */
1500 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1501 V_I2(pVar) = offset & 0x3ffffff;
1502 return;
1504 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1505 pcx->pTblDir->pCustData.offset + offset );
1506 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1507 switch (V_VT(pVar)){
1508 case VT_EMPTY: /* FIXME: is this right? */
1509 case VT_NULL: /* FIXME: is this right? */
1510 case VT_I2 : /* this should not happen */
1511 case VT_I4 :
1512 case VT_R4 :
1513 case VT_ERROR :
1514 case VT_BOOL :
1515 case VT_I1 :
1516 case VT_UI1 :
1517 case VT_UI2 :
1518 case VT_UI4 :
1519 case VT_INT :
1520 case VT_UINT :
1521 case VT_VOID : /* FIXME: is this right? */
1522 case VT_HRESULT :
1523 size=4; break;
1524 case VT_R8 :
1525 case VT_CY :
1526 case VT_DATE :
1527 case VT_I8 :
1528 case VT_UI8 :
1529 case VT_DECIMAL : /* FIXME: is this right? */
1530 case VT_FILETIME :
1531 size=8;break;
1532 /* pointer types with known behaviour */
1533 case VT_BSTR :{
1534 char * ptr;
1535 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1536 if(size < 0) {
1537 FIXME("BSTR length = %d?\n", size);
1538 } else {
1539 ptr=TLB_Alloc(size);/* allocate temp buffer */
1540 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1541 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1542 /* FIXME: do we need a AtoW conversion here? */
1543 V_UNION(pVar, bstrVal[size])=L'\0';
1544 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1545 TLB_Free(ptr);
1548 size=-4; break;
1549 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1550 case VT_DISPATCH :
1551 case VT_VARIANT :
1552 case VT_UNKNOWN :
1553 case VT_PTR :
1554 case VT_SAFEARRAY :
1555 case VT_CARRAY :
1556 case VT_USERDEFINED :
1557 case VT_LPSTR :
1558 case VT_LPWSTR :
1559 case VT_BLOB :
1560 case VT_STREAM :
1561 case VT_STORAGE :
1562 case VT_STREAMED_OBJECT :
1563 case VT_STORED_OBJECT :
1564 case VT_BLOB_OBJECT :
1565 case VT_CF :
1566 case VT_CLSID :
1567 default:
1568 size=0;
1569 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1570 V_VT(pVar));
1573 if(size>0) /* (big|small) endian correct? */
1574 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1575 return;
1578 * create a linked list with custom data
1580 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1582 MSFT_CDGuid entry;
1583 TLBCustData* pNew;
1584 int count=0;
1586 TRACE_(typelib)("\n");
1588 while(offset >=0){
1589 count++;
1590 pNew=TLB_Alloc(sizeof(TLBCustData));
1591 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1592 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1593 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1594 /* add new custom data at head of the list */
1595 pNew->next=*ppCustData;
1596 *ppCustData=pNew;
1597 offset = entry.next;
1599 return count;
1602 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1603 ITypeInfoImpl *pTI)
1605 if(type <0)
1606 pTd->vt=type & VT_TYPEMASK;
1607 else
1608 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1610 if(pTd->vt == VT_USERDEFINED)
1611 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1613 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1616 static void
1617 MSFT_DoFuncs(TLBContext* pcx,
1618 ITypeInfoImpl* pTI,
1619 int cFuncs,
1620 int cVars,
1621 int offset,
1622 TLBFuncDesc** pptfd)
1625 * member information is stored in a data structure at offset
1626 * indicated by the memoffset field of the typeinfo structure
1627 * There are several distinctive parts.
1628 * the first part starts with a field that holds the total length
1629 * of this (first) part excluding this field. Then follow the records,
1630 * for each member there is one record.
1632 * First entry is always the length of the record (including this
1633 * length word).
1634 * Rest of the record depends on the type of the member. If there is
1635 * a field indicating the member type (function variable intereface etc)
1636 * I have not found it yet. At this time we depend on the information
1637 * in the type info and the usual order how things are stored.
1639 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1640 * for each member;
1642 * Third is a equal sized array with file offsets to the name entry
1643 * of each member.
1645 * Forth and last (?) part is an array with offsets to the records in the
1646 * first part of this file segment.
1649 int infolen, nameoffset, reclength, nrattributes, i;
1650 int recoffset = offset + sizeof(INT);
1652 char recbuf[512];
1653 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1655 TRACE_(typelib)("\n");
1657 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1659 for ( i = 0; i < cFuncs ; i++ )
1661 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1663 /* name, eventually add to a hash table */
1664 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1665 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1667 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1669 /* read the function information record */
1670 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1672 reclength &= 0x1ff;
1674 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1676 /* do the attributes */
1677 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1678 / sizeof(int);
1680 if ( nrattributes > 0 )
1682 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1684 if ( nrattributes > 1 )
1686 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1687 pFuncRec->OptAttr[1]) ;
1689 if ( nrattributes > 2 )
1691 if ( pFuncRec->FKCCIC & 0x2000 )
1693 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1695 else
1697 (*pptfd)->Entry = MSFT_ReadString(pcx,
1698 pFuncRec->OptAttr[2]);
1700 if( nrattributes > 5 )
1702 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1704 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1706 MSFT_CustData(pcx,
1707 pFuncRec->OptAttr[6],
1708 &(*pptfd)->pCustData);
1715 /* fill the FuncDesc Structure */
1716 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1717 offset + infolen + ( i + 1) * sizeof(INT));
1719 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1720 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1721 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1722 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1723 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1724 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1725 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1727 MSFT_GetTdesc(pcx,
1728 pFuncRec->DataType,
1729 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1730 pTI);
1732 /* do the parameters/arguments */
1733 if(pFuncRec->nrargs)
1735 int j = 0;
1736 MSFT_ParameterInfo paraminfo;
1738 (*pptfd)->funcdesc.lprgelemdescParam =
1739 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1741 (*pptfd)->pParamDesc =
1742 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1744 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1745 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1747 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1749 TYPEDESC* lpArgTypeDesc = 0;
1751 MSFT_GetTdesc(pcx,
1752 paraminfo.DataType,
1753 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1754 pTI);
1756 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1758 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1760 /* SEEK value = jump to offset,
1761 * from there jump to the end of record,
1762 * go back by (j-1) arguments
1764 MSFT_ReadLEDWords( &paraminfo ,
1765 sizeof(MSFT_ParameterInfo), pcx,
1766 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1767 * sizeof(MSFT_ParameterInfo)));
1768 lpArgTypeDesc =
1769 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1771 while ( lpArgTypeDesc != NULL )
1773 switch ( lpArgTypeDesc->vt )
1775 case VT_PTR:
1776 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1777 break;
1779 case VT_CARRAY:
1780 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1781 break;
1783 case VT_USERDEFINED:
1784 MSFT_DoRefType(pcx, pTI,
1785 lpArgTypeDesc->u.hreftype);
1787 lpArgTypeDesc = NULL;
1788 break;
1790 default:
1791 lpArgTypeDesc = NULL;
1797 /* parameter is the return value! */
1798 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1800 TYPEDESC* lpArgTypeDesc;
1802 (*pptfd)->funcdesc.elemdescFunc =
1803 (*pptfd)->funcdesc.lprgelemdescParam[j];
1805 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1807 while ( lpArgTypeDesc != NULL )
1809 switch ( lpArgTypeDesc->vt )
1811 case VT_PTR:
1812 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1813 break;
1814 case VT_CARRAY:
1815 lpArgTypeDesc =
1816 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1818 break;
1820 case VT_USERDEFINED:
1821 MSFT_DoRefType(pcx,
1822 pTI,
1823 lpArgTypeDesc->u.hreftype);
1825 lpArgTypeDesc = NULL;
1826 break;
1828 default:
1829 lpArgTypeDesc = NULL;
1834 /* second time around */
1835 for(j=0;j<pFuncRec->nrargs;j++)
1837 /* name */
1838 (*pptfd)->pParamDesc[j].Name =
1839 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1841 /* default value */
1842 if ( (PARAMFLAG_FHASDEFAULT &
1843 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1844 ((pFuncRec->FKCCIC) & 0x1000) )
1846 INT* pInt = (INT *)((char *)pFuncRec +
1847 reclength -
1848 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1850 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1852 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1853 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1855 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1856 pInt[j], pcx);
1858 /* custom info */
1859 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1861 MSFT_CustData(pcx,
1862 pFuncRec->OptAttr[7+j],
1863 &(*pptfd)->pParamDesc[j].pCustData);
1868 /* scode is not used: archaic win16 stuff FIXME: right? */
1869 (*pptfd)->funcdesc.cScodes = 0 ;
1870 (*pptfd)->funcdesc.lprgscode = NULL ;
1872 pptfd = & ((*pptfd)->next);
1873 recoffset += reclength;
1877 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1878 int cVars, int offset, TLBVarDesc ** pptvd)
1880 int infolen, nameoffset, reclength;
1881 char recbuf[256];
1882 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1883 int i;
1884 int recoffset;
1886 TRACE_(typelib)("\n");
1888 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1889 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1890 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1891 recoffset += offset+sizeof(INT);
1892 for(i=0;i<cVars;i++){
1893 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1894 /* name, eventually add to a hash table */
1895 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1896 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1897 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1898 /* read the variable information record */
1899 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1900 reclength &=0xff;
1901 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1902 /* Optional data */
1903 if(reclength >(6*sizeof(INT)) )
1904 (*pptvd)->HelpContext=pVarRec->HelpContext;
1905 if(reclength >(7*sizeof(INT)) )
1906 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1907 if(reclength >(8*sizeof(INT)) )
1908 if(reclength >(9*sizeof(INT)) )
1909 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1910 /* fill the VarDesc Structure */
1911 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1912 offset + infolen + ( i + 1) * sizeof(INT));
1913 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1914 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1915 MSFT_GetTdesc(pcx, pVarRec->DataType,
1916 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1917 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1918 if(pVarRec->VarKind == VAR_CONST ){
1919 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1920 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1921 pVarRec->OffsValue, pcx);
1922 } else
1923 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1924 pptvd=&((*pptvd)->next);
1925 recoffset += reclength;
1928 /* fill in data for a hreftype (offset). When the referenced type is contained
1929 * in the typelib, it's just an (file) offset in the type info base dir.
1930 * If comes from import, it's an offset+1 in the ImpInfo table
1931 * */
1932 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1933 int offset)
1935 int j;
1936 TLBRefType **ppRefType = &pTI->reflist;
1938 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1940 while(*ppRefType) {
1941 if((*ppRefType)->reference == offset)
1942 return;
1943 ppRefType = &(*ppRefType)->next;
1946 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1947 sizeof(**ppRefType));
1949 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1950 /* external typelib */
1951 MSFT_ImpInfo impinfo;
1952 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1954 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1956 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1957 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1958 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1959 if(pImpLib->offset==impinfo.oImpFile) break;
1960 pImpLib=pImpLib->next;
1962 if(pImpLib){
1963 (*ppRefType)->reference=offset;
1964 (*ppRefType)->pImpTLInfo = pImpLib;
1965 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1966 (*ppRefType)->index = TLB_REF_USE_GUID;
1967 }else{
1968 ERR("Cannot find a reference\n");
1969 (*ppRefType)->reference=-1;
1970 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1972 }else{
1973 /* in this typelib */
1974 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1975 (*ppRefType)->reference=offset;
1976 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1980 /* process Implemented Interfaces of a com class */
1981 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1982 int offset)
1984 int i;
1985 MSFT_RefRecord refrec;
1986 TLBImplType **ppImpl = &pTI->impltypelist;
1988 TRACE_(typelib)("\n");
1990 for(i=0;i<count;i++){
1991 if(offset<0) break; /* paranoia */
1992 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1993 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1994 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1995 (*ppImpl)->hRef = refrec.reftype;
1996 (*ppImpl)->implflags=refrec.flags;
1997 (*ppImpl)->ctCustData=
1998 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1999 offset=refrec.onext;
2000 ppImpl=&((*ppImpl)->next);
2004 * process a typeinfo record
2006 ITypeInfoImpl * MSFT_DoTypeInfo(
2007 TLBContext *pcx,
2008 int count,
2009 ITypeLibImpl * pLibInfo)
2011 MSFT_TypeInfoBase tiBase;
2012 ITypeInfoImpl *ptiRet;
2014 TRACE_(typelib)("count=%u\n", count);
2016 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2017 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2018 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2019 /* this is where we are coming from */
2020 ptiRet->pTypeLib = pLibInfo;
2021 ptiRet->index=count;
2022 /* fill in the typeattr fields */
2023 WARN("Assign constructor/destructor memid\n");
2025 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2026 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2027 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2028 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2029 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2030 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2031 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2032 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2033 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2034 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2035 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2036 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2037 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2038 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2039 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2040 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2041 MSFT_GetTdesc(pcx, tiBase.datatype1,
2042 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2044 /* FIXME: */
2045 /* IDLDESC idldescType; *//* never saw this one != zero */
2047 /* name, eventually add to a hash table */
2048 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2049 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2050 /* help info */
2051 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2052 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2053 ptiRet->dwHelpContext=tiBase.helpcontext;
2054 /* note: InfoType's Help file and HelpStringDll come from the containing
2055 * library. Further HelpString and Docstring appear to be the same thing :(
2057 /* functions */
2058 if(ptiRet->TypeAttr.cFuncs >0 )
2059 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2060 ptiRet->TypeAttr.cVars,
2061 tiBase.memoffset, & ptiRet->funclist);
2062 /* variables */
2063 if(ptiRet->TypeAttr.cVars >0 )
2064 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2065 ptiRet->TypeAttr.cVars,
2066 tiBase.memoffset, & ptiRet->varlist);
2067 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2068 switch(ptiRet->TypeAttr.typekind)
2070 case TKIND_COCLASS:
2071 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2072 tiBase.datatype1);
2073 break;
2074 case TKIND_DISPATCH:
2075 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2077 if (tiBase.datatype1 != -1)
2079 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2080 ptiRet->impltypelist->hRef = tiBase.datatype1;
2082 else
2083 { /* FIXME: This is a really bad hack to add IDispatch */
2084 const char* szStdOle = "stdole2.tlb\0";
2085 int nStdOleLen = strlen(szStdOle);
2086 TLBRefType **ppRef = &ptiRet->reflist;
2088 while(*ppRef) {
2089 if((*ppRef)->reference == -1)
2090 break;
2091 ppRef = &(*ppRef)->next;
2093 if(!*ppRef) {
2094 *ppRef = TLB_Alloc(sizeof(**ppRef));
2095 (*ppRef)->guid = IID_IDispatch;
2096 (*ppRef)->reference = -1;
2097 (*ppRef)->index = TLB_REF_USE_GUID;
2098 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2099 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2100 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2101 nStdOleLen + 1);
2103 MultiByteToWideChar(CP_ACP,
2104 MB_PRECOMPOSED,
2105 szStdOle,
2107 (*ppRef)->pImpTLInfo->name,
2108 SysStringLen((*ppRef)->pImpTLInfo->name));
2110 (*ppRef)->pImpTLInfo->lcid = 0;
2111 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2112 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2115 break;
2116 default:
2117 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2118 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2119 ptiRet->impltypelist->hRef = tiBase.datatype1;
2120 break;
2123 ptiRet->ctCustData=
2124 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2126 TRACE_(typelib)("%s guid: %s kind:%s\n",
2127 debugstr_w(ptiRet->Name),
2128 debugstr_guid(&ptiRet->TypeAttr.guid),
2129 typekind_desc[ptiRet->TypeAttr.typekind]);
2131 return ptiRet;
2134 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2135 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2136 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2137 * tradeoff here.
2139 static ITypeLibImpl *tlb_cache_first;
2140 static CRITICAL_SECTION cache_section;
2141 static CRITICAL_SECTION_DEBUG cache_section_debug =
2143 0, 0, &cache_section,
2144 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2145 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2147 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2150 /****************************************************************************
2151 * TLB_ReadTypeLib
2153 * find the type of the typelib file and map the typelib resource into
2154 * the memory
2156 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2157 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2158 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2160 ITypeLibImpl *entry;
2161 int ret = TYPE_E_CANTLOADLIBRARY;
2162 DWORD dwSignature = 0;
2163 HANDLE hFile;
2165 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2167 *ppTypeLib = NULL;
2169 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2170 EnterCriticalSection(&cache_section);
2171 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2173 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2175 TRACE("cache hit\n");
2176 *ppTypeLib = (ITypeLib2*)entry;
2177 ITypeLib_AddRef(*ppTypeLib);
2178 LeaveCriticalSection(&cache_section);
2179 return S_OK;
2182 LeaveCriticalSection(&cache_section);
2184 /* check the signature of the file */
2185 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2186 if (INVALID_HANDLE_VALUE != hFile)
2188 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2189 if (hMapping)
2191 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2192 if(pBase)
2194 /* retrieve file size */
2195 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2197 /* first try to load as *.tlb */
2198 dwSignature = FromLEDWord(*((DWORD*) pBase));
2199 if ( dwSignature == MSFT_SIGNATURE)
2201 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2203 else if ( dwSignature == SLTG_SIGNATURE)
2205 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2207 UnmapViewOfFile(pBase);
2209 CloseHandle(hMapping);
2211 CloseHandle(hFile);
2213 else
2215 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2218 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2219 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2221 /* find the typelibrary resource*/
2222 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2223 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2224 if (hinstDLL)
2226 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2227 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2228 if (hrsrc)
2230 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2231 if (hGlobal)
2233 LPVOID pBase = LockResource(hGlobal);
2234 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2236 if (pBase)
2238 /* try to load as incore resource */
2239 dwSignature = FromLEDWord(*((DWORD*) pBase));
2240 if ( dwSignature == MSFT_SIGNATURE)
2242 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2244 else if ( dwSignature == SLTG_SIGNATURE)
2246 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2248 else
2250 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2253 FreeResource( hGlobal );
2256 FreeLibrary(hinstDLL);
2260 if(*ppTypeLib) {
2261 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2263 TRACE("adding to cache\n");
2264 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2265 lstrcpyW(impl->path, pszFileName);
2266 /* We should really canonicalise the path here. */
2267 impl->index = index;
2269 /* FIXME: check if it has added already in the meantime */
2270 EnterCriticalSection(&cache_section);
2271 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2272 impl->prev = NULL;
2273 tlb_cache_first = impl;
2274 LeaveCriticalSection(&cache_section);
2275 ret = S_OK;
2276 } else
2277 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2279 return ret;
2282 /*================== ITypeLib(2) Methods ===================================*/
2284 /****************************************************************************
2285 * ITypeLib2_Constructor_MSFT
2287 * loading an MSFT typelib from an in-memory image
2289 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2291 TLBContext cx;
2292 long lPSegDir;
2293 MSFT_Header tlbHeader;
2294 MSFT_SegDir tlbSegDir;
2295 ITypeLibImpl * pTypeLibImpl;
2297 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2299 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2300 if (!pTypeLibImpl) return NULL;
2302 pTypeLibImpl->lpVtbl = &tlbvt;
2303 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2304 pTypeLibImpl->ref = 1;
2306 /* get pointer to beginning of typelib data */
2307 cx.pos = 0;
2308 cx.oStart=0;
2309 cx.mapping = pLib;
2310 cx.pLibInfo = pTypeLibImpl;
2311 cx.length = dwTLBLength;
2313 /* read header */
2314 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2315 TRACE("header:\n");
2316 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2317 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2318 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2319 return NULL;
2321 /* there is a small amount of information here until the next important
2322 * part:
2323 * the segment directory . Try to calculate the amount of data */
2324 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2326 /* now read the segment directory */
2327 TRACE("read segment directory (at %ld)\n",lPSegDir);
2328 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2329 cx.pTblDir = &tlbSegDir;
2331 /* just check two entries */
2332 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2334 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2335 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2336 return NULL;
2339 /* now fill our internal data */
2340 /* TLIBATTR fields */
2341 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2343 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2344 /* Windows seems to have zero here, is this correct? */
2345 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2346 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2347 else
2348 pTypeLibImpl->LibAttr.lcid = 0;
2350 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2351 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2352 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2353 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2355 /* name, eventually add to a hash table */
2356 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2358 /* help info */
2359 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2360 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2362 if( tlbHeader.varflags & HELPDLLFLAG)
2364 int offset;
2365 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2366 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2369 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2371 /* custom data */
2372 if(tlbHeader.CustomDataOffset >= 0)
2374 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2377 /* fill in typedescriptions */
2378 if(tlbSegDir.pTypdescTab.length > 0)
2380 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2381 INT16 td[4];
2382 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2383 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2384 for(i=0; i<cTD; )
2386 /* FIXME: add several sanity checks here */
2387 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2388 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2390 /* FIXME: check safearray */
2391 if(td[3] < 0)
2392 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2393 else
2394 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2396 else if(td[0] == VT_CARRAY)
2398 /* array descr table here */
2399 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2401 else if(td[0] == VT_USERDEFINED)
2403 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2405 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2408 /* second time around to fill the array subscript info */
2409 for(i=0;i<cTD;i++)
2411 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2412 if(tlbSegDir.pArrayDescriptions.offset>0)
2414 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2415 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2417 if(td[1]<0)
2418 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2419 else
2420 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2422 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2424 for(j = 0; j<td[2]; j++)
2426 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2427 sizeof(INT), &cx, DO_NOT_SEEK);
2428 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2429 sizeof(INT), &cx, DO_NOT_SEEK);
2432 else
2434 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2435 ERR("didn't find array description data\n");
2440 /* imported type libs */
2441 if(tlbSegDir.pImpFiles.offset>0)
2443 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2444 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2445 UINT16 size;
2447 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2449 char *name;
2450 DWORD len;
2452 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2453 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2454 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2456 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2457 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2458 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2459 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2461 size >>= 2;
2462 name = TLB_Alloc(size+1);
2463 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2464 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2465 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2466 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2467 TLB_Free(name);
2469 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2470 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2472 ppImpLib = &(*ppImpLib)->next;
2476 /* type info's */
2477 if(tlbHeader.nrtypeinfos >= 0 )
2479 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2480 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2481 int i;
2483 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2485 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2487 ppTI = &((*ppTI)->next);
2488 (pTypeLibImpl->TypeInfoCount)++;
2492 TRACE("(%p)\n", pTypeLibImpl);
2493 return (ITypeLib2*) pTypeLibImpl;
2497 static BSTR TLB_MultiByteToBSTR(char *ptr)
2499 DWORD len;
2500 WCHAR *nameW;
2501 BSTR ret;
2503 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2504 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2505 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2506 ret = SysAllocString(nameW);
2507 HeapFree(GetProcessHeap(), 0, nameW);
2508 return ret;
2511 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2513 char b[3];
2514 int i;
2515 short s;
2517 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2518 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2519 return FALSE;
2522 guid->Data4[0] = s >> 8;
2523 guid->Data4[1] = s & 0xff;
2525 b[2] = '\0';
2526 for(i = 0; i < 6; i++) {
2527 memcpy(b, str + 24 + 2 * i, 2);
2528 guid->Data4[i + 2] = strtol(b, NULL, 16);
2530 return TRUE;
2533 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2535 WORD bytelen;
2536 DWORD len;
2537 WCHAR *nameW;
2539 *pBstr = NULL;
2540 bytelen = *(WORD*)ptr;
2541 if(bytelen == 0xffff) return 2;
2542 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2543 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2544 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2545 *pBstr = SysAllocStringLen(nameW, len);
2546 HeapFree(GetProcessHeap(), 0, nameW);
2547 return bytelen + 2;
2550 static WORD SLTG_ReadStringA(char *ptr, char **str)
2552 WORD bytelen;
2554 *str = NULL;
2555 bytelen = *(WORD*)ptr;
2556 if(bytelen == 0xffff) return 2;
2557 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2558 memcpy(*str, ptr + 2, bytelen);
2559 (*str)[bytelen] = '\0';
2560 return bytelen + 2;
2563 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2565 char *ptr = pLibBlk;
2566 WORD w;
2568 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2569 FIXME("libblk magic = %04x\n", w);
2570 return 0;
2573 ptr += 6;
2574 if((w = *(WORD*)ptr) != 0xffff) {
2575 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2576 ptr += w;
2578 ptr += 2;
2580 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2582 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2584 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2585 ptr += 4;
2587 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2588 ptr += 2;
2590 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2591 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2592 else
2593 pTypeLibImpl->LibAttr.lcid = 0;
2594 ptr += 2;
2596 ptr += 4; /* skip res12 */
2598 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2599 ptr += 2;
2601 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2602 ptr += 2;
2604 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2605 ptr += 2;
2607 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2608 ptr += sizeof(GUID);
2610 return ptr - (char*)pLibBlk;
2613 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2615 BOOL done = FALSE;
2616 TYPEDESC *pTD = &pElem->tdesc;
2618 /* Handle [in/out] first */
2619 if((*pType & 0xc000) == 0xc000)
2620 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2621 else if(*pType & 0x8000)
2622 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2623 else if(*pType & 0x4000)
2624 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2625 else
2626 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2628 if(*pType & 0x2000)
2629 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2631 if(*pType & 0x80)
2632 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2634 while(!done) {
2635 if((*pType & 0xe00) == 0xe00) {
2636 pTD->vt = VT_PTR;
2637 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2638 sizeof(TYPEDESC));
2639 pTD = pTD->u.lptdesc;
2641 switch(*pType & 0x7f) {
2642 case VT_PTR:
2643 pTD->vt = VT_PTR;
2644 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2645 sizeof(TYPEDESC));
2646 pTD = pTD->u.lptdesc;
2647 break;
2649 case VT_USERDEFINED:
2650 pTD->vt = VT_USERDEFINED;
2651 pTD->u.hreftype = *(++pType) / 4;
2652 done = TRUE;
2653 break;
2655 case VT_CARRAY:
2657 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2658 array */
2660 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2662 pTD->vt = VT_CARRAY;
2663 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2664 sizeof(ARRAYDESC) +
2665 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2666 pTD->u.lpadesc->cDims = pSA->cDims;
2667 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2668 pSA->cDims * sizeof(SAFEARRAYBOUND));
2670 pTD = &pTD->u.lpadesc->tdescElem;
2671 break;
2674 case VT_SAFEARRAY:
2676 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2677 useful? */
2679 pType++;
2680 pTD->vt = VT_SAFEARRAY;
2681 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2682 sizeof(TYPEDESC));
2683 pTD = pTD->u.lptdesc;
2684 break;
2686 default:
2687 pTD->vt = *pType & 0x7f;
2688 done = TRUE;
2689 break;
2691 pType++;
2693 return pType;
2697 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2698 char *pNameTable)
2700 int ref;
2701 char *name;
2702 TLBRefType **ppRefType;
2704 if(pRef->magic != SLTG_REF_MAGIC) {
2705 FIXME("Ref magic = %x\n", pRef->magic);
2706 return;
2708 name = ( (char*)(&pRef->names) + pRef->number);
2710 ppRefType = &pTI->reflist;
2711 for(ref = 0; ref < pRef->number >> 3; ref++) {
2712 char *refname;
2713 unsigned int lib_offs, type_num;
2715 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2716 sizeof(**ppRefType));
2718 name += SLTG_ReadStringA(name, &refname);
2719 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2720 FIXME("Can't sscanf ref\n");
2721 if(lib_offs != 0xffff) {
2722 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2724 while(*import) {
2725 if((*import)->offset == lib_offs)
2726 break;
2727 import = &(*import)->next;
2729 if(!*import) {
2730 char fname[MAX_PATH+1];
2731 int len;
2733 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2734 sizeof(**import));
2735 (*import)->offset = lib_offs;
2736 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2737 &(*import)->guid);
2738 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2739 &(*import)->wVersionMajor,
2740 &(*import)->wVersionMinor,
2741 &(*import)->lcid, fname) != 4) {
2742 FIXME("can't sscanf ref %s\n",
2743 pNameTable + lib_offs + 40);
2745 len = strlen(fname);
2746 if(fname[len-1] != '#')
2747 FIXME("fname = %s\n", fname);
2748 fname[len-1] = '\0';
2749 (*import)->name = TLB_MultiByteToBSTR(fname);
2751 (*ppRefType)->pImpTLInfo = *import;
2752 } else { /* internal ref */
2753 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2755 (*ppRefType)->reference = ref;
2756 (*ppRefType)->index = type_num;
2758 HeapFree(GetProcessHeap(), 0, refname);
2759 ppRefType = &(*ppRefType)->next;
2761 if((BYTE)*name != SLTG_REF_MAGIC)
2762 FIXME("End of ref block magic = %x\n", *name);
2763 dump_TLBRefType(pTI->reflist);
2766 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2767 BOOL OneOnly)
2769 SLTG_ImplInfo *info;
2770 TLBImplType **ppImplType = &pTI->impltypelist;
2771 /* I don't really get this structure, usually it's 0x16 bytes
2772 long, but iuser.tlb contains some that are 0x18 bytes long.
2773 That's ok because we can use the next ptr to jump to the next
2774 one. But how do we know the length of the last one? The WORD
2775 at offs 0x8 might be the clue. For now I'm just assuming that
2776 the last one is the regular 0x16 bytes. */
2778 info = (SLTG_ImplInfo*)pBlk;
2779 while(1) {
2780 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2781 sizeof(**ppImplType));
2782 (*ppImplType)->hRef = info->ref;
2783 (*ppImplType)->implflags = info->impltypeflags;
2784 pTI->TypeAttr.cImplTypes++;
2785 ppImplType = &(*ppImplType)->next;
2787 if(info->next == 0xffff)
2788 break;
2789 if(OneOnly)
2790 FIXME("Interface inheriting more than one interface\n");
2791 info = (SLTG_ImplInfo*)(pBlk + info->next);
2793 info++; /* see comment at top of function */
2794 return (char*)info;
2797 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2798 char *pNameTable)
2800 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2801 SLTG_MemberHeader *pMemHeader;
2802 char *pFirstItem, *pNextItem;
2804 if(pTIHeader->href_table != 0xffffffff) {
2805 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2806 pNameTable);
2810 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2812 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2814 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2815 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2818 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2822 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2823 char *pNameTable)
2825 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2826 SLTG_MemberHeader *pMemHeader;
2827 SLTG_Function *pFunc;
2828 char *pFirstItem, *pNextItem;
2829 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2830 int num = 0;
2832 if(pTIHeader->href_table != 0xffffffff) {
2833 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2834 pNameTable);
2837 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2839 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2841 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2842 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2845 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2846 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2848 int param;
2849 WORD *pType, *pArg;
2851 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2852 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2853 FIXME("func magic = %02x\n", pFunc->magic);
2854 return NULL;
2856 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2857 sizeof(**ppFuncDesc));
2858 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2860 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2861 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2862 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2863 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2864 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2865 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2867 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2868 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2870 if(pFunc->retnextopt & 0x80)
2871 pType = &pFunc->rettype;
2872 else
2873 pType = (WORD*)(pFirstItem + pFunc->rettype);
2876 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2878 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2879 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2880 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2881 (*ppFuncDesc)->pParamDesc =
2882 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2883 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2885 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2887 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2888 char *paramName = pNameTable + *pArg;
2889 BOOL HaveOffs;
2890 /* If arg type follows then paramName points to the 2nd
2891 letter of the name, else the next WORD is an offset to
2892 the arg type and paramName points to the first letter.
2893 So let's take one char off paramName and see if we're
2894 pointing at an alpha-numeric char. However if *pArg is
2895 0xffff or 0xfffe then the param has no name, the former
2896 meaning that the next WORD is the type, the latter
2897 meaning the the next WORD is an offset to the type. */
2899 HaveOffs = FALSE;
2900 if(*pArg == 0xffff)
2901 paramName = NULL;
2902 else if(*pArg == 0xfffe) {
2903 paramName = NULL;
2904 HaveOffs = TRUE;
2906 else if(!isalnum(*(paramName-1)))
2907 HaveOffs = TRUE;
2909 pArg++;
2911 if(HaveOffs) { /* the next word is an offset to type */
2912 pType = (WORD*)(pFirstItem + *pArg);
2913 SLTG_DoType(pType, pFirstItem,
2914 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2915 pArg++;
2916 } else {
2917 if(paramName)
2918 paramName--;
2919 pArg = SLTG_DoType(pArg, pFirstItem,
2920 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2923 /* Are we an optional param ? */
2924 if((*ppFuncDesc)->funcdesc.cParams - param <=
2925 (*ppFuncDesc)->funcdesc.cParamsOpt)
2926 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2928 if(paramName) {
2929 (*ppFuncDesc)->pParamDesc[param].Name =
2930 TLB_MultiByteToBSTR(paramName);
2934 ppFuncDesc = &((*ppFuncDesc)->next);
2935 if(pFunc->next == 0xffff) break;
2937 pTI->TypeAttr.cFuncs = num;
2938 dump_TLBFuncDesc(pTI->funclist);
2939 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2942 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2943 char *pNameTable)
2945 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2946 SLTG_MemberHeader *pMemHeader;
2947 SLTG_RecordItem *pItem;
2948 char *pFirstItem;
2949 TLBVarDesc **ppVarDesc = &pTI->varlist;
2950 int num = 0;
2951 WORD *pType;
2952 char buf[300];
2954 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2956 pFirstItem = (char*)(pMemHeader + 1);
2957 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2958 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2959 if(pItem->magic != SLTG_RECORD_MAGIC) {
2960 FIXME("record magic = %02x\n", pItem->magic);
2961 return NULL;
2963 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2964 sizeof(**ppVarDesc));
2965 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2966 (*ppVarDesc)->vardesc.memid = pItem->memid;
2967 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2968 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2970 if(pItem->typepos == 0x02)
2971 pType = &pItem->type;
2972 else if(pItem->typepos == 0x00)
2973 pType = (WORD*)(pFirstItem + pItem->type);
2974 else {
2975 FIXME("typepos = %02x\n", pItem->typepos);
2976 break;
2979 SLTG_DoType(pType, pFirstItem,
2980 &(*ppVarDesc)->vardesc.elemdescVar);
2982 /* FIXME("helpcontext, helpstring\n"); */
2984 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2986 ppVarDesc = &((*ppVarDesc)->next);
2987 if(pItem->next == 0xffff) break;
2989 pTI->TypeAttr.cVars = num;
2990 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2993 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2994 char *pNameTable)
2996 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2997 SLTG_MemberHeader *pMemHeader;
2998 SLTG_AliasItem *pItem;
2999 int i, mustbelast;
3001 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3002 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3004 mustbelast = 0;
3005 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3006 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3007 if (pItem->vt == 0xffff) {
3008 if (i<(pMemHeader->cbExtra/4-1))
3009 FIXME("Endmarker too early in process alias data!\n");
3010 break;
3012 if (mustbelast) {
3013 FIXME("Chain extends over last entry?\n");
3014 break;
3016 if (pItem->vt == VT_USERDEFINED) {
3017 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3018 /* guessing here ... */
3019 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3020 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3021 mustbelast = 1;
3022 } else {
3023 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3024 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3026 pItem++;
3028 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3031 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3032 char *pNameTable)
3034 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3035 SLTG_MemberHeader *pMemHeader;
3036 SLTG_AliasItem *pItem;
3038 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3039 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3040 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3041 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3042 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3045 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3046 char *pNameTable)
3048 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3049 SLTG_MemberHeader *pMemHeader;
3050 SLTG_EnumItem *pItem;
3051 char *pFirstItem;
3052 TLBVarDesc **ppVarDesc = &pTI->varlist;
3053 int num = 0;
3055 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3057 pFirstItem = (char*)(pMemHeader + 1);
3058 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3059 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3060 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3061 FIXME("enumitem magic = %04x\n", pItem->magic);
3062 return NULL;
3064 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3065 sizeof(**ppVarDesc));
3066 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3067 (*ppVarDesc)->vardesc.memid = pItem->memid;
3068 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3069 sizeof(VARIANT));
3070 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3071 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3072 *(INT*)(pItem->value + pFirstItem);
3073 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3074 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3075 /* FIXME("helpcontext, helpstring\n"); */
3077 ppVarDesc = &((*ppVarDesc)->next);
3078 if(pItem->next == 0xffff) break;
3080 pTI->TypeAttr.cVars = num;
3081 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3084 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3085 managable copy of it into this */
3086 typedef struct {
3087 WORD small_no;
3088 char *index_name;
3089 char *other_name;
3090 WORD res1a;
3091 WORD name_offs;
3092 WORD more_bytes;
3093 char *extra;
3094 WORD res20;
3095 DWORD helpcontext;
3096 WORD res26;
3097 GUID uuid;
3098 } SLTG_InternalOtherTypeInfo;
3100 /****************************************************************************
3101 * ITypeLib2_Constructor_SLTG
3103 * loading a SLTG typelib from an in-memory image
3105 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3107 ITypeLibImpl *pTypeLibImpl;
3108 SLTG_Header *pHeader;
3109 SLTG_BlkEntry *pBlkEntry;
3110 SLTG_Magic *pMagic;
3111 SLTG_Index *pIndex;
3112 SLTG_Pad9 *pPad9;
3113 LPVOID pBlk, pFirstBlk;
3114 SLTG_LibBlk *pLibBlk;
3115 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3116 char *pAfterOTIBlks = NULL;
3117 char *pNameTable, *ptr;
3118 int i;
3119 DWORD len, order;
3120 ITypeInfoImpl **ppTypeInfoImpl;
3122 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3124 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3125 if (!pTypeLibImpl) return NULL;
3127 pTypeLibImpl->lpVtbl = &tlbvt;
3128 pTypeLibImpl->ref = 1;
3130 pHeader = pLib;
3132 TRACE("header:\n");
3133 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3134 pHeader->nrOfFileBlks );
3135 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3136 FIXME("Header type magic 0x%08lx not supported.\n",
3137 pHeader->SLTG_magic);
3138 return NULL;
3141 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3142 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3144 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3145 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3147 /* Next we have a magic block */
3148 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3150 /* Let's see if we're still in sync */
3151 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3152 sizeof(SLTG_COMPOBJ_MAGIC))) {
3153 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3154 return NULL;
3156 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3157 sizeof(SLTG_DIR_MAGIC))) {
3158 FIXME("dir magic = %s\n", pMagic->dir_magic);
3159 return NULL;
3162 pIndex = (SLTG_Index*)(pMagic+1);
3164 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3166 pFirstBlk = (LPVOID)(pPad9 + 1);
3168 /* We'll set up a ptr to the main library block, which is the last one. */
3170 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3171 pBlkEntry[order].next != 0;
3172 order = pBlkEntry[order].next - 1, i++) {
3173 pBlk = (char*)pBlk + pBlkEntry[order].len;
3175 pLibBlk = pBlk;
3177 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3179 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3180 interspersed */
3182 len += 0x40;
3184 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3186 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3187 sizeof(*pOtherTypeInfoBlks) *
3188 pTypeLibImpl->TypeInfoCount);
3191 ptr = (char*)pLibBlk + len;
3193 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3194 WORD w, extra;
3195 len = 0;
3197 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3199 w = *(WORD*)(ptr + 2);
3200 if(w != 0xffff) {
3201 len += w;
3202 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3203 w+1);
3204 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3205 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3207 w = *(WORD*)(ptr + 4 + len);
3208 if(w != 0xffff) {
3209 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3210 len += w;
3211 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3212 w+1);
3213 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3214 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3216 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3217 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3218 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3219 if(extra) {
3220 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3221 extra);
3222 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3223 len += extra;
3225 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3226 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3227 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3228 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3229 len += sizeof(SLTG_OtherTypeInfo);
3230 ptr += len;
3233 pAfterOTIBlks = ptr;
3235 /* Skip this WORD and get the next DWORD */
3236 len = *(DWORD*)(pAfterOTIBlks + 2);
3238 /* Now add this to pLibBLk look at what we're pointing at and
3239 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3240 dust and we should be pointing at the beginning of the name
3241 table */
3243 pNameTable = (char*)pLibBlk + len;
3245 switch(*(WORD*)pNameTable) {
3246 case 0xffff:
3247 break;
3248 case 0x0200:
3249 pNameTable += 0x20;
3250 break;
3251 default:
3252 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3253 break;
3256 pNameTable += 0x216;
3258 pNameTable += 2;
3260 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3262 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3265 /* Hopefully we now have enough ptrs set up to actually read in
3266 some TypeInfos. It's not clear which order to do them in, so
3267 I'll just follow the links along the BlkEntry chain and read
3268 them in in the order in which they're in the file */
3270 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3272 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3273 pBlkEntry[order].next != 0;
3274 order = pBlkEntry[order].next - 1, i++) {
3276 SLTG_TypeInfoHeader *pTIHeader;
3277 SLTG_TypeInfoTail *pTITail;
3279 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3280 pOtherTypeInfoBlks[i].index_name)) {
3281 FIXME("Index strings don't match\n");
3282 return NULL;
3285 pTIHeader = pBlk;
3286 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3287 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3288 return NULL;
3290 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3291 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3292 (*ppTypeInfoImpl)->index = i;
3293 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3294 pOtherTypeInfoBlks[i].name_offs +
3295 pNameTable);
3296 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3297 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3298 sizeof(GUID));
3299 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3300 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3301 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3302 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3303 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3305 if((pTIHeader->typeflags1 & 7) != 2)
3306 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3307 if(pTIHeader->typeflags3 != 2)
3308 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3310 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3311 debugstr_w((*ppTypeInfoImpl)->Name),
3312 typekind_desc[pTIHeader->typekind],
3313 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3314 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3316 switch(pTIHeader->typekind) {
3317 case TKIND_ENUM:
3318 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3319 break;
3321 case TKIND_RECORD:
3322 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3323 break;
3325 case TKIND_INTERFACE:
3326 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3327 break;
3329 case TKIND_COCLASS:
3330 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3331 break;
3333 case TKIND_ALIAS:
3334 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3335 if (pTITail->tdescalias_vt)
3336 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3337 break;
3339 case TKIND_DISPATCH:
3340 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3341 break;
3343 default:
3344 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3345 pTITail = NULL;
3346 break;
3350 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3351 but we've already set those */
3352 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3353 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3354 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3356 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3357 X(06);
3358 X(08);
3359 X(0a);
3360 X(0c);
3361 X(0e);
3362 X(10);
3363 X(12);
3364 X(16);
3365 X(18);
3366 X(1a);
3367 X(1c);
3368 X(1e);
3369 X(24);
3370 X(26);
3371 X(2a);
3372 X(2c);
3373 X(2e);
3374 X(30);
3375 X(32);
3376 X(34);
3378 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3379 pBlk = (char*)pBlk + pBlkEntry[order].len;
3382 if(i != pTypeLibImpl->TypeInfoCount) {
3383 FIXME("Somehow processed %d TypeInfos\n", i);
3384 return NULL;
3387 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3388 return (ITypeLib2*)pTypeLibImpl;
3391 /* ITypeLib::QueryInterface
3393 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3394 ITypeLib2 * iface,
3395 REFIID riid,
3396 VOID **ppvObject)
3398 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3400 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3402 *ppvObject=NULL;
3403 if(IsEqualIID(riid, &IID_IUnknown) ||
3404 IsEqualIID(riid,&IID_ITypeLib)||
3405 IsEqualIID(riid,&IID_ITypeLib2))
3407 *ppvObject = This;
3410 if(*ppvObject)
3412 ITypeLib2_AddRef(iface);
3413 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3414 return S_OK;
3416 TRACE("-- Interface: E_NOINTERFACE\n");
3417 return E_NOINTERFACE;
3420 /* ITypeLib::AddRef
3422 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3424 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3425 ULONG ref = InterlockedIncrement(&This->ref);
3427 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3429 return ref;
3432 /* ITypeLib::Release
3434 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3436 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3437 ULONG ref = InterlockedDecrement(&This->ref);
3439 TRACE("(%p)->(%lu)\n",This, ref);
3441 if (!ref)
3443 /* remove cache entry */
3444 TRACE("removing from cache list\n");
3445 EnterCriticalSection(&cache_section);
3446 if (This->next) This->next->prev = This->prev;
3447 if (This->prev) This->prev->next = This->next;
3448 else tlb_cache_first = This->next;
3449 LeaveCriticalSection(&cache_section);
3451 /* FIXME destroy child objects */
3452 TRACE(" destroying ITypeLib(%p)\n",This);
3454 if (This->Name)
3456 SysFreeString(This->Name);
3457 This->Name = NULL;
3460 if (This->DocString)
3462 SysFreeString(This->DocString);
3463 This->DocString = NULL;
3466 if (This->HelpFile)
3468 SysFreeString(This->HelpFile);
3469 This->HelpFile = NULL;
3472 if (This->HelpStringDll)
3474 SysFreeString(This->HelpStringDll);
3475 This->HelpStringDll = NULL;
3478 if (This->pTypeInfo) /* can be NULL */
3479 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3480 HeapFree(GetProcessHeap(),0,This);
3481 return 0;
3484 return ref;
3487 /* ITypeLib::GetTypeInfoCount
3489 * Returns the number of type descriptions in the type library
3491 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3493 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3494 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3495 return This->TypeInfoCount;
3498 /* ITypeLib::GetTypeInfo
3500 * retrieves the specified type description in the library.
3502 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3503 ITypeLib2 *iface,
3504 UINT index,
3505 ITypeInfo **ppTInfo)
3507 int i;
3509 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3510 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3512 TRACE("(%p)->(index=%d) \n", This, index);
3514 if (!ppTInfo) return E_INVALIDARG;
3516 /* search element n in list */
3517 for(i=0; i < index; i++)
3519 pTypeInfo = pTypeInfo->next;
3520 if (!pTypeInfo)
3522 TRACE("-- element not found\n");
3523 return TYPE_E_ELEMENTNOTFOUND;
3527 *ppTInfo = (ITypeInfo *) pTypeInfo;
3529 ITypeInfo_AddRef(*ppTInfo);
3530 TRACE("-- found (%p)\n",*ppTInfo);
3531 return S_OK;
3535 /* ITypeLibs::GetTypeInfoType
3537 * Retrieves the type of a type description.
3539 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3540 ITypeLib2 *iface,
3541 UINT index,
3542 TYPEKIND *pTKind)
3544 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3545 int i;
3546 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3548 TRACE("(%p) index %d \n",This, index);
3550 if(!pTKind) return E_INVALIDARG;
3552 /* search element n in list */
3553 for(i=0; i < index; i++)
3555 if(!pTInfo)
3557 TRACE("-- element not found\n");
3558 return TYPE_E_ELEMENTNOTFOUND;
3560 pTInfo = pTInfo->next;
3563 *pTKind = pTInfo->TypeAttr.typekind;
3564 TRACE("-- found Type (%d)\n", *pTKind);
3565 return S_OK;
3568 /* ITypeLib::GetTypeInfoOfGuid
3570 * Retrieves the type description that corresponds to the specified GUID.
3573 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3574 ITypeLib2 *iface,
3575 REFGUID guid,
3576 ITypeInfo **ppTInfo)
3578 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3579 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3581 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3583 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3585 /* search linked list for guid */
3586 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3588 pTypeInfo = pTypeInfo->next;
3590 if (!pTypeInfo)
3592 /* end of list reached */
3593 TRACE("-- element not found\n");
3594 return TYPE_E_ELEMENTNOTFOUND;
3598 TRACE("-- found (%p, %s)\n",
3599 pTypeInfo,
3600 debugstr_w(pTypeInfo->Name));
3602 *ppTInfo = (ITypeInfo*)pTypeInfo;
3603 ITypeInfo_AddRef(*ppTInfo);
3604 return S_OK;
3607 /* ITypeLib::GetLibAttr
3609 * Retrieves the structure that contains the library's attributes.
3612 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3613 ITypeLib2 *iface,
3614 LPTLIBATTR *ppTLibAttr)
3616 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3617 TRACE("(%p)\n",This);
3618 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3619 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3620 return S_OK;
3623 /* ITypeLib::GetTypeComp
3625 * Enables a client compiler to bind to a library's types, variables,
3626 * constants, and global functions.
3629 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3630 ITypeLib2 *iface,
3631 ITypeComp **ppTComp)
3633 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3635 TRACE("(%p)->(%p)\n",This,ppTComp);
3636 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3637 ITypeComp_AddRef(*ppTComp);
3639 return S_OK;
3642 /* ITypeLib::GetDocumentation
3644 * Retrieves the library's documentation string, the complete Help file name
3645 * and path, and the context identifier for the library Help topic in the Help
3646 * file.
3648 * On a successful return all non-null BSTR pointers will have been set,
3649 * possibly to NULL.
3651 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3652 ITypeLib2 *iface,
3653 INT index,
3654 BSTR *pBstrName,
3655 BSTR *pBstrDocString,
3656 DWORD *pdwHelpContext,
3657 BSTR *pBstrHelpFile)
3659 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3661 HRESULT result = E_INVALIDARG;
3663 ITypeInfo *pTInfo;
3666 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3667 This, index,
3668 pBstrName, pBstrDocString,
3669 pdwHelpContext, pBstrHelpFile);
3671 if(index<0)
3673 /* documentation for the typelib */
3674 if(pBstrName)
3676 if (This->Name)
3677 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3678 else
3679 *pBstrName = NULL;
3681 if(pBstrDocString)
3683 if (This->DocString)
3684 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3685 else if (This->Name)
3686 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3687 else
3688 *pBstrDocString = NULL;
3690 if(pdwHelpContext)
3692 *pdwHelpContext = This->dwHelpContext;
3694 if(pBstrHelpFile)
3696 if (This->HelpFile)
3697 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3698 else
3699 *pBstrHelpFile = NULL;
3702 result = S_OK;
3704 else
3706 /* for a typeinfo */
3707 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3709 if(SUCCEEDED(result))
3711 result = ITypeInfo_GetDocumentation(pTInfo,
3712 MEMBERID_NIL,
3713 pBstrName,
3714 pBstrDocString,
3715 pdwHelpContext, pBstrHelpFile);
3717 ITypeInfo_Release(pTInfo);
3720 return result;
3721 memerr3:
3722 if (pBstrDocString) SysFreeString (*pBstrDocString);
3723 memerr2:
3724 if (pBstrName) SysFreeString (*pBstrName);
3725 memerr1:
3726 return STG_E_INSUFFICIENTMEMORY;
3729 /* ITypeLib::IsName
3731 * Indicates whether a passed-in string contains the name of a type or member
3732 * described in the library.
3735 static HRESULT WINAPI ITypeLib2_fnIsName(
3736 ITypeLib2 *iface,
3737 LPOLESTR szNameBuf,
3738 ULONG lHashVal,
3739 BOOL *pfName)
3741 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3742 ITypeInfoImpl *pTInfo;
3743 TLBFuncDesc *pFInfo;
3744 TLBVarDesc *pVInfo;
3745 int i;
3746 UINT nNameBufLen = SysStringLen(szNameBuf);
3748 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3749 pfName);
3751 *pfName=TRUE;
3752 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3753 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3754 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3755 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3756 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3757 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3758 goto ITypeLib2_fnIsName_exit;
3760 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3761 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3764 *pfName=FALSE;
3766 ITypeLib2_fnIsName_exit:
3767 TRACE("(%p)slow! search for %s: %s found!\n", This,
3768 debugstr_w(szNameBuf), *pfName?"NOT":"");
3770 return S_OK;
3773 /* ITypeLib::FindName
3775 * Finds occurrences of a type description in a type library. This may be used
3776 * to quickly verify that a name exists in a type library.
3779 static HRESULT WINAPI ITypeLib2_fnFindName(
3780 ITypeLib2 *iface,
3781 LPOLESTR szNameBuf,
3782 ULONG lHashVal,
3783 ITypeInfo **ppTInfo,
3784 MEMBERID *rgMemId,
3785 UINT16 *pcFound)
3787 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3788 ITypeInfoImpl *pTInfo;
3789 TLBFuncDesc *pFInfo;
3790 TLBVarDesc *pVInfo;
3791 int i,j = 0;
3793 UINT nNameBufLen = SysStringLen(szNameBuf);
3795 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3796 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3797 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3798 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3799 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3800 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3801 goto ITypeLib2_fnFindName_exit;
3803 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3804 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3805 continue;
3806 ITypeLib2_fnFindName_exit:
3807 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3808 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3809 j++;
3811 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3812 This, *pcFound, debugstr_w(szNameBuf), j);
3814 *pcFound=j;
3816 return S_OK;
3819 /* ITypeLib::ReleaseTLibAttr
3821 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3824 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3825 ITypeLib2 *iface,
3826 TLIBATTR *pTLibAttr)
3828 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3829 TRACE("freeing (%p)\n",This);
3830 HeapFree(GetProcessHeap(),0,pTLibAttr);
3834 /* ITypeLib2::GetCustData
3836 * gets the custom data
3838 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3839 ITypeLib2 * iface,
3840 REFGUID guid,
3841 VARIANT *pVarVal)
3843 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3844 TLBCustData *pCData;
3846 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3848 if( IsEqualIID(guid, &pCData->guid)) break;
3851 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3853 if(pCData)
3855 VariantInit( pVarVal);
3856 VariantCopy( pVarVal, &pCData->data);
3857 return S_OK;
3859 return E_INVALIDARG; /* FIXME: correct? */
3862 /* ITypeLib2::GetLibStatistics
3864 * Returns statistics about a type library that are required for efficient
3865 * sizing of hash tables.
3868 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3869 ITypeLib2 * iface,
3870 ULONG *pcUniqueNames,
3871 ULONG *pcchUniqueNames)
3873 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3875 FIXME("(%p): stub!\n", This);
3877 if(pcUniqueNames) *pcUniqueNames=1;
3878 if(pcchUniqueNames) *pcchUniqueNames=1;
3879 return S_OK;
3882 /* ITypeLib2::GetDocumentation2
3884 * Retrieves the library's documentation string, the complete Help file name
3885 * and path, the localization context to use, and the context ID for the
3886 * library Help topic in the Help file.
3889 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3890 ITypeLib2 * iface,
3891 INT index,
3892 LCID lcid,
3893 BSTR *pbstrHelpString,
3894 DWORD *pdwHelpStringContext,
3895 BSTR *pbstrHelpStringDll)
3897 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3898 HRESULT result;
3899 ITypeInfo *pTInfo;
3901 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3903 /* the help string should be obtained from the helpstringdll,
3904 * using the _DLLGetDocumentation function, based on the supplied
3905 * lcid. Nice to do sometime...
3907 if(index<0)
3909 /* documentation for the typelib */
3910 if(pbstrHelpString)
3911 *pbstrHelpString=SysAllocString(This->DocString);
3912 if(pdwHelpStringContext)
3913 *pdwHelpStringContext=This->dwHelpContext;
3914 if(pbstrHelpStringDll)
3915 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3917 result = S_OK;
3919 else
3921 /* for a typeinfo */
3922 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3924 if(SUCCEEDED(result))
3926 ITypeInfo2 * pTInfo2;
3927 result = ITypeInfo_QueryInterface(pTInfo,
3928 &IID_ITypeInfo2,
3929 (LPVOID*) &pTInfo2);
3931 if(SUCCEEDED(result))
3933 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3934 MEMBERID_NIL,
3935 lcid,
3936 pbstrHelpString,
3937 pdwHelpStringContext,
3938 pbstrHelpStringDll);
3940 ITypeInfo2_Release(pTInfo2);
3943 ITypeInfo_Release(pTInfo);
3946 return result;
3949 /* ITypeLib2::GetAllCustData
3951 * Gets all custom data items for the library.
3954 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3955 ITypeLib2 * iface,
3956 CUSTDATA *pCustData)
3958 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3959 TLBCustData *pCData;
3960 int i;
3961 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3962 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3963 if(pCustData->prgCustData ){
3964 pCustData->cCustData=This->ctCustData;
3965 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3966 pCustData->prgCustData[i].guid=pCData->guid;
3967 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3969 }else{
3970 ERR(" OUT OF MEMORY! \n");
3971 return E_OUTOFMEMORY;
3973 return S_OK;
3976 static ITypeLib2Vtbl tlbvt = {
3977 ITypeLib2_fnQueryInterface,
3978 ITypeLib2_fnAddRef,
3979 ITypeLib2_fnRelease,
3980 ITypeLib2_fnGetTypeInfoCount,
3981 ITypeLib2_fnGetTypeInfo,
3982 ITypeLib2_fnGetTypeInfoType,
3983 ITypeLib2_fnGetTypeInfoOfGuid,
3984 ITypeLib2_fnGetLibAttr,
3985 ITypeLib2_fnGetTypeComp,
3986 ITypeLib2_fnGetDocumentation,
3987 ITypeLib2_fnIsName,
3988 ITypeLib2_fnFindName,
3989 ITypeLib2_fnReleaseTLibAttr,
3991 ITypeLib2_fnGetCustData,
3992 ITypeLib2_fnGetLibStatistics,
3993 ITypeLib2_fnGetDocumentation2,
3994 ITypeLib2_fnGetAllCustData
3998 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4000 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4002 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
4005 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4007 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4009 return ITypeInfo_AddRef((ITypeInfo *)This);
4012 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4014 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4016 return ITypeInfo_Release((ITypeInfo *)This);
4019 static HRESULT WINAPI ITypeLibComp_fnBind(
4020 ITypeComp * iface,
4021 OLECHAR * szName,
4022 ULONG lHash,
4023 WORD wFlags,
4024 ITypeInfo ** ppTInfo,
4025 DESCKIND * pDescKind,
4026 BINDPTR * pBindPtr)
4028 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4029 return E_NOTIMPL;
4032 static HRESULT WINAPI ITypeLibComp_fnBindType(
4033 ITypeComp * iface,
4034 OLECHAR * szName,
4035 ULONG lHash,
4036 ITypeInfo ** ppTInfo,
4037 ITypeComp ** ppTComp)
4039 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4040 return E_NOTIMPL;
4043 static ITypeCompVtbl tlbtcvt =
4046 ITypeLibComp_fnQueryInterface,
4047 ITypeLibComp_fnAddRef,
4048 ITypeLibComp_fnRelease,
4050 ITypeLibComp_fnBind,
4051 ITypeLibComp_fnBindType
4054 /*================== ITypeInfo(2) Methods ===================================*/
4055 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4057 ITypeInfoImpl * pTypeInfoImpl;
4059 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4060 if (pTypeInfoImpl)
4062 pTypeInfoImpl->lpVtbl = &tinfvt;
4063 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4064 pTypeInfoImpl->ref=1;
4066 TRACE("(%p)\n", pTypeInfoImpl);
4067 return (ITypeInfo2*) pTypeInfoImpl;
4070 /* ITypeInfo::QueryInterface
4072 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4073 ITypeInfo2 *iface,
4074 REFIID riid,
4075 VOID **ppvObject)
4077 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4079 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4081 *ppvObject=NULL;
4082 if(IsEqualIID(riid, &IID_IUnknown) ||
4083 IsEqualIID(riid,&IID_ITypeInfo)||
4084 IsEqualIID(riid,&IID_ITypeInfo2))
4085 *ppvObject = This;
4087 if(*ppvObject){
4088 ITypeInfo_AddRef(iface);
4089 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4090 return S_OK;
4092 TRACE("-- Interface: E_NOINTERFACE\n");
4093 return E_NOINTERFACE;
4096 /* ITypeInfo::AddRef
4098 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4100 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4101 ULONG ref = InterlockedIncrement(&This->ref);
4103 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4105 TRACE("(%p)->ref is %lu\n",This, ref);
4106 return ref;
4109 /* ITypeInfo::Release
4111 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4113 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4114 ULONG ref = InterlockedDecrement(&This->ref);
4116 TRACE("(%p)->(%lu)\n",This, ref);
4118 if (ref) {
4119 /* We don't release ITypeLib when ref=0 because
4120 it means that function is called by ITypeLib2_Release */
4121 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4122 } else {
4123 FIXME("destroy child objects\n");
4125 TRACE("destroying ITypeInfo(%p)\n",This);
4126 if (This->Name)
4128 SysFreeString(This->Name);
4129 This->Name = 0;
4132 if (This->DocString)
4134 SysFreeString(This->DocString);
4135 This->DocString = 0;
4138 if (This->next)
4140 ITypeInfo_Release((ITypeInfo*)This->next);
4143 HeapFree(GetProcessHeap(),0,This);
4144 return 0;
4146 return ref;
4149 /* ITypeInfo::GetTypeAttr
4151 * Retrieves a TYPEATTR structure that contains the attributes of the type
4152 * description.
4155 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4156 LPTYPEATTR *ppTypeAttr)
4158 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4159 TRACE("(%p)\n",This);
4160 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4161 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4163 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4164 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4166 if((*ppTypeAttr)->typekind == TKIND_DISPATCH && (*ppTypeAttr)->wTypeFlags & TYPEFLAG_FDUAL) {
4167 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4168 funcs */
4169 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4170 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4172 return S_OK;
4175 /* ITypeInfo::GetTypeComp
4177 * Retrieves the ITypeComp interface for the type description, which enables a
4178 * client compiler to bind to the type description's members.
4181 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4182 ITypeComp * *ppTComp)
4184 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4186 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4188 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4189 ITypeComp_AddRef(*ppTComp);
4190 return S_OK;
4193 /* ITypeInfo::GetFuncDesc
4195 * Retrieves the FUNCDESC structure that contains information about a
4196 * specified function.
4199 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4200 LPFUNCDESC *ppFuncDesc)
4202 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4203 int i;
4204 TLBFuncDesc * pFDesc;
4205 TRACE("(%p) index %d\n", This, index);
4206 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4208 if(pFDesc){
4209 /* FIXME: must do a copy here */
4210 *ppFuncDesc=&pFDesc->funcdesc;
4211 return S_OK;
4213 return E_INVALIDARG;
4216 /* ITypeInfo::GetVarDesc
4218 * Retrieves a VARDESC structure that describes the specified variable.
4221 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4222 LPVARDESC *ppVarDesc)
4224 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4225 int i;
4226 TLBVarDesc * pVDesc;
4227 TRACE("(%p) index %d\n", This, index);
4228 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4230 if(pVDesc){
4231 /* FIXME: must do a copy here */
4232 *ppVarDesc=&pVDesc->vardesc;
4233 return S_OK;
4235 return E_INVALIDARG;
4238 /* ITypeInfo_GetNames
4240 * Retrieves the variable with the specified member ID (or the name of the
4241 * property or method and its parameters) that correspond to the specified
4242 * function ID.
4244 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4245 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4247 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4248 TLBFuncDesc * pFDesc;
4249 TLBVarDesc * pVDesc;
4250 int i;
4251 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4252 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4253 if(pFDesc)
4255 /* function found, now return function and parameter names */
4256 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4258 if(!i)
4259 *rgBstrNames=SysAllocString(pFDesc->Name);
4260 else
4261 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4263 *pcNames=i;
4265 else
4267 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4268 if(pVDesc)
4270 *rgBstrNames=SysAllocString(pVDesc->Name);
4271 *pcNames=1;
4273 else
4275 if(This->TypeAttr.cImplTypes &&
4276 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4277 /* recursive search */
4278 ITypeInfo *pTInfo;
4279 HRESULT result;
4280 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4281 &pTInfo);
4282 if(SUCCEEDED(result))
4284 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4285 ITypeInfo_Release(pTInfo);
4286 return result;
4288 WARN("Could not search inherited interface!\n");
4290 else
4292 WARN("no names found\n");
4294 *pcNames=0;
4295 return TYPE_E_ELEMENTNOTFOUND;
4298 return S_OK;
4302 /* ITypeInfo::GetRefTypeOfImplType
4304 * If a type description describes a COM class, it retrieves the type
4305 * description of the implemented interface types. For an interface,
4306 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4307 * if any exist.
4310 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4311 ITypeInfo2 *iface,
4312 UINT index,
4313 HREFTYPE *pRefType)
4315 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4316 int(i);
4317 TLBImplType *pImpl = This->impltypelist;
4319 TRACE("(%p) index %d\n", This, index);
4320 if (TRACE_ON(ole)) dump_TypeInfo(This);
4322 if(index==(UINT)-1)
4324 /* only valid on dual interfaces;
4325 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4327 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4329 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4330 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4332 *pRefType = -1;
4334 else
4336 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4337 *pRefType = pImpl->hRef;
4340 else
4342 /* get element n from linked list */
4343 for(i=0; pImpl && i<index; i++)
4345 pImpl = pImpl->next;
4348 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4350 *pRefType = pImpl->hRef;
4352 TRACE("-- 0x%08lx\n", pImpl->hRef );
4355 return S_OK;
4359 /* ITypeInfo::GetImplTypeFlags
4361 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4362 * or base interface in a type description.
4364 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4365 UINT index, INT *pImplTypeFlags)
4367 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4368 int i;
4369 TLBImplType *pImpl;
4371 TRACE("(%p) index %d\n", This, index);
4372 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4373 i++, pImpl=pImpl->next)
4375 if(i==index && pImpl){
4376 *pImplTypeFlags=pImpl->implflags;
4377 return S_OK;
4379 *pImplTypeFlags=0;
4380 return TYPE_E_ELEMENTNOTFOUND;
4383 /* GetIDsOfNames
4384 * Maps between member names and member IDs, and parameter names and
4385 * parameter IDs.
4387 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4388 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4390 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4391 TLBFuncDesc * pFDesc;
4392 TLBVarDesc * pVDesc;
4393 HRESULT ret=S_OK;
4395 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4396 cNames);
4397 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4398 int i, j;
4399 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4400 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4401 for(i=1; i < cNames; i++){
4402 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4403 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4404 break;
4405 if( j<pFDesc->funcdesc.cParams)
4406 pMemId[i]=j;
4407 else
4408 ret=DISP_E_UNKNOWNNAME;
4410 return ret;
4413 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4414 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4415 if(cNames) *pMemId=pVDesc->vardesc.memid;
4416 return ret;
4419 /* not found, see if this is and interface with an inheritance */
4420 if(This->TypeAttr.cImplTypes &&
4421 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4422 /* recursive search */
4423 ITypeInfo *pTInfo;
4424 ret=ITypeInfo_GetRefTypeInfo(iface,
4425 This->impltypelist->hRef, &pTInfo);
4426 if(SUCCEEDED(ret)){
4427 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4428 ITypeInfo_Release(pTInfo);
4429 return ret;
4431 WARN("Could not search inherited interface!\n");
4432 } else
4433 WARN("no names found\n");
4434 return DISP_E_UNKNOWNNAME;
4437 /* ITypeInfo::Invoke
4439 * Invokes a method, or accesses a property of an object, that implements the
4440 * interface described by the type description.
4442 DWORD
4443 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4444 DWORD res;
4446 if (TRACE_ON(ole)) {
4447 int i;
4448 TRACE("Calling %p(",func);
4449 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4450 TRACE(")\n");
4453 switch (callconv) {
4454 case CC_STDCALL:
4456 switch (nrargs) {
4457 case 0:
4458 res = func();
4459 break;
4460 case 1:
4461 res = func(args[0]);
4462 break;
4463 case 2:
4464 res = func(args[0],args[1]);
4465 break;
4466 case 3:
4467 res = func(args[0],args[1],args[2]);
4468 break;
4469 case 4:
4470 res = func(args[0],args[1],args[2],args[3]);
4471 break;
4472 case 5:
4473 res = func(args[0],args[1],args[2],args[3],args[4]);
4474 break;
4475 case 6:
4476 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4477 break;
4478 case 7:
4479 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4480 break;
4481 case 8:
4482 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4483 break;
4484 case 9:
4485 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4486 break;
4487 case 10:
4488 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4489 break;
4490 case 11:
4491 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4492 break;
4493 default:
4494 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4495 res = -1;
4496 break;
4498 break;
4499 default:
4500 FIXME("unsupported calling convention %d\n",callconv);
4501 res = -1;
4502 break;
4504 TRACE("returns %08lx\n",res);
4505 return res;
4508 extern int _argsize(DWORD vt);
4510 /****************************************************************************
4511 * Helper functions for Dispcall / Invoke, which copies one variant
4512 * with target type onto the argument stack.
4514 static HRESULT
4515 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4516 DWORD *argpos, VARIANT *arg, VARTYPE vt
4518 UINT arglen = _argsize(vt)*sizeof(DWORD);
4519 VARTYPE oldvt;
4520 VARIANT va;
4522 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4523 memcpy(argpos,&arg,sizeof(void*));
4524 return S_OK;
4527 if (V_VT(arg) == vt) {
4528 memcpy(argpos, &V_I4(arg), arglen);
4529 return S_OK;
4532 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4533 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4534 return S_OK;
4537 if (vt == VT_VARIANT) {
4538 memcpy(argpos, arg, arglen);
4539 return S_OK;
4541 /* Deref BYREF vars if there is need */
4542 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4543 memcpy(argpos,(void*)V_I4(arg), arglen);
4544 return S_OK;
4546 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4547 /* in this context, if the type lib specifies IUnknown*, giving an
4548 IDispatch* is correct; so, don't invoke VariantChangeType */
4549 memcpy(argpos,&V_I4(arg), arglen);
4550 return S_OK;
4552 if ((vt == VT_PTR) && tdesc)
4553 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4555 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4556 ITypeInfo *tinfo2 = NULL;
4557 TYPEATTR *tattr = NULL;
4558 HRESULT hres;
4560 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4561 if (hres) {
4562 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4563 "while coercing from vt 0x%x. Copying 4 byte.\n",
4564 tdesc->u.hreftype,V_VT(arg));
4565 memcpy(argpos, &V_I4(arg), 4);
4566 return S_OK;
4568 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4569 if( hres )
4571 ERR("GetTypeAttr failed\n");
4572 ITypeInfo_Release(tinfo2);
4573 return hres;
4575 switch (tattr->typekind) {
4576 case TKIND_ENUM:
4577 switch ( V_VT( arg ) ) {
4578 case VT_I2:
4579 *argpos = V_I2(arg);
4580 hres = S_OK;
4581 break;
4582 case VT_I4:
4583 memcpy(argpos, &V_I4(arg), 4);
4584 hres = S_OK;
4585 break;
4586 default:
4587 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4588 hres = E_FAIL;
4589 break;
4591 break;
4593 case TKIND_ALIAS:
4594 tdesc = &(tattr->tdescAlias);
4595 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4596 break;
4598 case TKIND_INTERFACE:
4599 if (V_VT(arg) == VT_DISPATCH) {
4600 IDispatch *disp;
4601 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4602 memcpy(argpos, &V_DISPATCH(arg), 4);
4603 hres = S_OK;
4604 break;
4606 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4607 &IID_IDispatch,(LPVOID*)&disp);
4608 if (SUCCEEDED(hres)) {
4609 memcpy(argpos,&disp,4);
4610 IUnknown_Release(V_DISPATCH(arg));
4611 hres = S_OK;
4612 break;
4614 FIXME("Failed to query IDispatch interface from %s while "
4615 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4616 hres = E_FAIL;
4617 break;
4619 if (V_VT(arg) == VT_UNKNOWN) {
4620 memcpy(argpos, &V_UNKNOWN(arg), 4);
4621 hres = S_OK;
4622 break;
4624 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4625 V_VT(arg),debugstr_guid(&(tattr->guid)));
4626 hres = E_FAIL;
4627 break;
4629 case TKIND_DISPATCH:
4630 if (V_VT(arg) == VT_DISPATCH) {
4631 memcpy(argpos, &V_DISPATCH(arg), 4);
4632 hres = S_OK;
4634 else {
4635 hres = E_FAIL;
4636 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4638 break;
4639 case TKIND_RECORD:
4640 FIXME("TKIND_RECORD unhandled.\n");
4641 hres = E_FAIL;
4642 break;
4643 default:
4644 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4645 hres = E_FAIL;
4646 break;
4648 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4649 ITypeInfo_Release(tinfo2);
4650 return hres;
4653 oldvt = V_VT(arg);
4654 VariantInit(&va);
4655 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4656 memcpy(argpos,&V_I4(&va), arglen);
4657 FIXME("Should not use VariantChangeType here."
4658 " (conversion from 0x%x -> 0x%x) %08lx\n",
4659 V_VT(arg), vt, *argpos
4661 return S_OK;
4663 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4664 return E_FAIL;
4667 /***********************************************************************
4668 * DispCallFunc (OLEAUT32.@)
4670 HRESULT WINAPI
4671 DispCallFunc(
4672 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4673 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4675 int i, argsize, argspos;
4676 DWORD *args;
4677 HRESULT hres;
4679 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4680 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4682 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4683 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4684 argsize = 1;
4685 for (i=0;i<cActuals;i++) {
4686 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4687 dump_Variant(prgpvarg[i]);
4688 argsize += _argsize(prgvt[i]);
4690 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4691 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4692 argspos = 1;
4693 for (i=0;i<cActuals;i++) {
4694 VARIANT *arg = prgpvarg[i];
4695 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4696 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4697 argspos += _argsize(prgvt[i]);
4700 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4702 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4703 hres=S_OK;
4705 else
4707 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4708 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4709 FIXME("Method returned %lx\n",hres);
4711 HeapFree(GetProcessHeap(),0,args);
4712 return hres;
4715 static HRESULT WINAPI ITypeInfo_fnInvoke(
4716 ITypeInfo2 *iface,
4717 VOID *pIUnk,
4718 MEMBERID memid,
4719 UINT16 dwFlags,
4720 DISPPARAMS *pDispParams,
4721 VARIANT *pVarResult,
4722 EXCEPINFO *pExcepInfo,
4723 UINT *pArgErr)
4725 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4726 int i;
4727 unsigned int func_index, var_index;
4728 TYPEKIND type_kind;
4729 HRESULT hres;
4731 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4732 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4734 dump_DispParms(pDispParams);
4736 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4737 if (SUCCEEDED(hres)) {
4738 FUNCDESC *func_desc;
4740 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4741 if(FAILED(hres)) return hres;
4743 switch (func_desc->funckind) {
4744 case FUNC_PUREVIRTUAL:
4745 case FUNC_VIRTUAL: {
4746 DWORD res;
4747 int numargs, numargs2, argspos, args2pos;
4748 DWORD *args , *args2;
4749 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4750 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4752 hres = S_OK;
4753 numargs = 1; numargs2 = 0;
4754 for (i = 0; i < func_desc->cParams; i++) {
4755 if (i<pDispParams->cArgs)
4756 numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4757 else {
4758 numargs += 1; /* sizeof(lpvoid) */
4759 numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4763 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4764 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4766 args[0] = (DWORD)pIUnk;
4767 argspos = 1; args2pos = 0;
4768 for (i = 0; i < func_desc->cParams; i++) {
4769 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4770 if (i<pDispParams->cArgs) {
4771 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4772 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4773 USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
4774 if (paramFlags & PARAMFLAG_FOPT) {
4775 if(i < func_desc->cParams - func_desc->cParamsOpt)
4776 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4777 if(V_VT(arg) == VT_EMPTY
4778 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4779 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4780 How to determine it? */
4782 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4783 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4784 V_VT(arg) = VT_ERROR;
4785 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4786 arglen = _argsize(VT_ERROR);
4789 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4790 if (FAILED(hres)) goto func_fail;
4791 argspos += arglen;
4792 } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
4793 VARIANT *arg = &rgvarg[i];
4794 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4795 if(i < func_desc->cParams - func_desc->cParamsOpt)
4796 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4797 if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4798 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4799 V_VT(arg) = VT_ERROR;
4800 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4801 arglen = _argsize(VT_ERROR);
4802 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4803 if (FAILED(hres)) goto func_fail;
4804 argspos += arglen;
4805 } else {
4806 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);
4807 if (tdesc->vt != VT_PTR)
4808 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4809 /*FIXME: give pointers for the rest, so propertyget works*/
4810 args[argspos] = (DWORD)&args2[args2pos];
4812 /* If pointer to variant, pass reference it. */
4813 if ((tdesc->vt == VT_PTR) &&
4814 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4815 pVarResult
4817 args[argspos]= (DWORD)pVarResult;
4818 argspos += 1;
4819 args2pos += arglen;
4822 if (func_desc->cParamsOpt < 0)
4823 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4825 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4826 func_desc->callconv,
4827 numargs,
4828 args
4831 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4832 args2pos = 0;
4833 for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
4834 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4835 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);
4836 TYPEDESC i4_tdesc;
4837 i4_tdesc.vt = VT_I4;
4839 /* If we are a pointer to a variant, we are done already */
4840 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4841 continue;
4843 VariantInit(pVarResult);
4844 memcpy(&V_INT(pVarResult),&args2[args2pos],arglen*sizeof(DWORD));
4846 if (tdesc->vt == VT_PTR)
4847 tdesc = tdesc->u.lptdesc;
4848 if (tdesc->vt == VT_USERDEFINED) {
4849 ITypeInfo *tinfo2;
4850 TYPEATTR *tattr;
4852 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4853 if (FAILED(hres)) {
4854 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4855 goto func_fail;
4857 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4858 switch (tattr->typekind) {
4859 case TKIND_ENUM:
4860 /* force the return type to be VT_I4 */
4861 tdesc = &i4_tdesc;
4862 break;
4863 case TKIND_ALIAS:
4864 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4865 tdesc = &(tattr->tdescAlias);
4866 break;
4868 case TKIND_INTERFACE:
4869 FIXME("TKIND_INTERFACE unhandled.\n");
4870 break;
4871 case TKIND_DISPATCH:
4872 FIXME("TKIND_DISPATCH unhandled.\n");
4873 break;
4874 case TKIND_RECORD:
4875 FIXME("TKIND_RECORD unhandled.\n");
4876 break;
4877 default:
4878 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4879 break;
4881 ITypeInfo_Release(tinfo2);
4883 V_VT(pVarResult) = tdesc->vt;
4885 /* HACK: VB5 likes this.
4886 * I do not know why. There is 1 example in MSDN which uses
4887 * this which appears broken (mixes int vals and
4888 * IDispatch*.).
4890 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4891 V_VT(pVarResult) = VT_DISPATCH;
4892 TRACE("storing into variant:\n");
4893 dump_Variant(pVarResult);
4894 args2pos += arglen;
4897 func_fail:
4898 HeapFree(GetProcessHeap(), 0, rgvarg);
4899 HeapFree(GetProcessHeap(),0,args2);
4900 HeapFree(GetProcessHeap(),0,args);
4901 break;
4903 case FUNC_DISPATCH: {
4904 IDispatch *disp;
4906 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4907 if (SUCCEEDED(hres)) {
4908 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4909 hres = IDispatch_Invoke(
4910 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4911 pVarResult,pExcepInfo,pArgErr
4913 if (FAILED(hres))
4914 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
4915 IDispatch_Release(disp);
4916 } else
4917 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4918 break;
4920 default:
4921 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
4922 hres = E_FAIL;
4923 break;
4926 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
4927 return hres;
4929 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
4930 VARDESC *var_desc;
4932 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
4933 if(FAILED(hres)) return hres;
4935 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4936 dump_VARDESC(var_desc);
4937 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
4938 return E_NOTIMPL;
4941 /* not found, look for it in inherited interfaces */
4942 ITypeInfo2_GetTypeKind(iface, &type_kind);
4943 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
4944 HREFTYPE ref_type;
4945 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
4946 /* recursive search */
4947 ITypeInfo *pTInfo;
4948 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
4949 if(SUCCEEDED(hres)){
4950 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4951 ITypeInfo_Release(pTInfo);
4952 return hres;
4954 WARN("Could not search inherited interface!\n");
4957 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
4958 return DISP_E_MEMBERNOTFOUND;
4961 /* ITypeInfo::GetDocumentation
4963 * Retrieves the documentation string, the complete Help file name and path,
4964 * and the context ID for the Help topic for a specified type description.
4966 * (Can be tested by the Visual Basic Editor in Word for instance.)
4968 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4969 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4970 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4972 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4973 TLBFuncDesc * pFDesc;
4974 TLBVarDesc * pVDesc;
4975 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4976 " HelpContext(%p) HelpFile(%p)\n",
4977 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4978 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4979 if(pBstrName)
4980 *pBstrName=SysAllocString(This->Name);
4981 if(pBstrDocString)
4982 *pBstrDocString=SysAllocString(This->DocString);
4983 if(pdwHelpContext)
4984 *pdwHelpContext=This->dwHelpContext;
4985 if(pBstrHelpFile)
4986 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4987 return S_OK;
4988 }else {/* for a member */
4989 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4990 if(pFDesc->funcdesc.memid==memid){
4991 if(pBstrName)
4992 *pBstrName = SysAllocString(pFDesc->Name);
4993 if(pBstrDocString)
4994 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4995 if(pdwHelpContext)
4996 *pdwHelpContext=pFDesc->helpcontext;
4997 return S_OK;
4999 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5000 if(pVDesc->vardesc.memid==memid){
5001 if(pBstrName)
5002 *pBstrName = SysAllocString(pVDesc->Name);
5003 if(pBstrDocString)
5004 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5005 if(pdwHelpContext)
5006 *pdwHelpContext=pVDesc->HelpContext;
5007 return S_OK;
5010 return TYPE_E_ELEMENTNOTFOUND;
5013 /* ITypeInfo::GetDllEntry
5015 * Retrieves a description or specification of an entry point for a function
5016 * in a DLL.
5018 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5019 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5020 WORD *pwOrdinal)
5022 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5023 TLBFuncDesc *pFDesc;
5025 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5027 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5028 if(pFDesc->funcdesc.memid==memid){
5029 dump_TypeInfo(This);
5030 dump_TLBFuncDescOne(pFDesc);
5032 /* FIXME: This is wrong, but how do you find that out? */
5033 if (pBstrDllName) {
5034 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5035 *pBstrDllName = SysAllocString(oleaut32W);
5038 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5039 if (pBstrName)
5040 *pBstrName = SysAllocString(pFDesc->Entry);
5041 if (pwOrdinal)
5042 *pwOrdinal = -1;
5043 return S_OK;
5045 if (pBstrName)
5046 *pBstrName = NULL;
5047 if (pwOrdinal)
5048 *pwOrdinal = (DWORD)pFDesc->Entry;
5049 return S_OK;
5051 return E_FAIL;
5054 /* ITypeInfo::GetRefTypeInfo
5056 * If a type description references other type descriptions, it retrieves
5057 * the referenced type descriptions.
5059 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5060 ITypeInfo2 *iface,
5061 HREFTYPE hRefType,
5062 ITypeInfo **ppTInfo)
5064 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5065 HRESULT result = E_FAIL;
5068 if (hRefType == -1 &&
5069 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5070 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5072 /* when we meet a DUAL dispinterface, we must create the interface
5073 * version of it.
5075 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5078 /* the interface version contains the same information as the dispinterface
5079 * copy the contents of the structs.
5081 *pTypeInfoImpl = *This;
5082 pTypeInfoImpl->ref = 1;
5084 /* change the type to interface */
5085 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5087 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5089 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5091 result = S_OK;
5093 } else {
5094 TLBRefType *pRefType;
5095 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5096 if(pRefType->reference == hRefType)
5097 break;
5099 if(!pRefType)
5100 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5101 if(pRefType && hRefType != -1) {
5102 ITypeLib *pTLib = NULL;
5104 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5105 int Index;
5106 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5107 } else {
5108 if(pRefType->pImpTLInfo->pImpTypeLib) {
5109 TRACE("typeinfo in imported typelib that is already loaded\n");
5110 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5111 ITypeLib2_AddRef((ITypeLib*) pTLib);
5112 result = S_OK;
5113 } else {
5114 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5115 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5116 pRefType->pImpTLInfo->wVersionMajor,
5117 pRefType->pImpTLInfo->wVersionMinor,
5118 pRefType->pImpTLInfo->lcid,
5119 &pTLib);
5121 if(!SUCCEEDED(result)) {
5122 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5123 result=LoadTypeLib(libnam, &pTLib);
5124 SysFreeString(libnam);
5126 if(SUCCEEDED(result)) {
5127 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5128 ITypeLib2_AddRef(pTLib);
5132 if(SUCCEEDED(result)) {
5133 if(pRefType->index == TLB_REF_USE_GUID)
5134 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5135 &pRefType->guid,
5136 ppTInfo);
5137 else
5138 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5139 ppTInfo);
5141 if (pTLib != NULL)
5142 ITypeLib2_Release(pTLib);
5146 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5147 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5148 return result;
5151 /* ITypeInfo::AddressOfMember
5153 * Retrieves the addresses of static functions or variables, such as those
5154 * defined in a DLL.
5156 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5157 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5160 FIXME("(%p) stub!\n", This);
5161 return S_OK;
5164 /* ITypeInfo::CreateInstance
5166 * Creates a new instance of a type that describes a component object class
5167 * (coclass).
5169 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5170 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5172 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5173 FIXME("(%p) stub!\n", This);
5174 return S_OK;
5177 /* ITypeInfo::GetMops
5179 * Retrieves marshalling information.
5181 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5182 BSTR *pBstrMops)
5184 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5185 FIXME("(%p) stub!\n", This);
5186 return S_OK;
5189 /* ITypeInfo::GetContainingTypeLib
5191 * Retrieves the containing type library and the index of the type description
5192 * within that type library.
5194 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5195 ITypeLib * *ppTLib, UINT *pIndex)
5197 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5199 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5200 if (pIndex) {
5201 *pIndex=This->index;
5202 TRACE("returning pIndex=%d\n", *pIndex);
5205 if (ppTLib) {
5206 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5207 ITypeLib2_AddRef(*ppTLib);
5208 TRACE("returning ppTLib=%p\n", *ppTLib);
5211 return S_OK;
5214 /* ITypeInfo::ReleaseTypeAttr
5216 * Releases a TYPEATTR previously returned by GetTypeAttr.
5219 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5220 TYPEATTR* pTypeAttr)
5222 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5223 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5224 if(This->TypeAttr.typekind == TKIND_ALIAS)
5225 free_deep_typedesc(&pTypeAttr->tdescAlias);
5226 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5229 /* ITypeInfo::ReleaseFuncDesc
5231 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5233 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5234 ITypeInfo2 *iface,
5235 FUNCDESC *pFuncDesc)
5237 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5238 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5241 /* ITypeInfo::ReleaseVarDesc
5243 * Releases a VARDESC previously returned by GetVarDesc.
5245 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5246 VARDESC *pVarDesc)
5248 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5249 TRACE("(%p)->(%p)\n", This, pVarDesc);
5252 /* ITypeInfo2::GetTypeKind
5254 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5257 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5258 TYPEKIND *pTypeKind)
5260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5261 *pTypeKind=This->TypeAttr.typekind;
5262 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5263 return S_OK;
5266 /* ITypeInfo2::GetTypeFlags
5268 * Returns the type flags without any allocations. This returns a DWORD type
5269 * flag, which expands the type flags without growing the TYPEATTR (type
5270 * attribute).
5273 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5275 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5276 *pTypeFlags=This->TypeAttr.wTypeFlags;
5277 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5278 return S_OK;
5281 /* ITypeInfo2::GetFuncIndexOfMemId
5282 * Binds to a specific member based on a known DISPID, where the member name
5283 * is not known (for example, when binding to a default member).
5286 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5287 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5289 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5290 TLBFuncDesc *pFuncInfo;
5291 int i;
5292 HRESULT result;
5294 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5295 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5296 break;
5297 if(pFuncInfo) {
5298 *pFuncIndex = i;
5299 result = S_OK;
5300 } else
5301 result = TYPE_E_ELEMENTNOTFOUND;
5303 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5304 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5305 return result;
5308 /* TypeInfo2::GetVarIndexOfMemId
5310 * Binds to a specific member based on a known DISPID, where the member name
5311 * is not known (for example, when binding to a default member).
5314 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5315 MEMBERID memid, UINT *pVarIndex)
5317 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5318 TLBVarDesc *pVarInfo;
5319 int i;
5320 HRESULT result;
5321 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5322 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5324 if(pVarInfo) {
5325 *pVarIndex = i;
5326 result = S_OK;
5327 } else
5328 result = TYPE_E_ELEMENTNOTFOUND;
5330 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5331 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5332 return result;
5335 /* ITypeInfo2::GetCustData
5337 * Gets the custom data
5339 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5340 ITypeInfo2 * iface,
5341 REFGUID guid,
5342 VARIANT *pVarVal)
5344 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5345 TLBCustData *pCData;
5347 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5348 if( IsEqualIID(guid, &pCData->guid)) break;
5350 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5352 if(pCData)
5354 VariantInit( pVarVal);
5355 VariantCopy( pVarVal, &pCData->data);
5356 return S_OK;
5358 return E_INVALIDARG; /* FIXME: correct? */
5361 /* ITypeInfo2::GetFuncCustData
5363 * Gets the custom data
5365 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5366 ITypeInfo2 * iface,
5367 UINT index,
5368 REFGUID guid,
5369 VARIANT *pVarVal)
5371 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5372 TLBCustData *pCData=NULL;
5373 TLBFuncDesc * pFDesc;
5374 int i;
5375 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5376 pFDesc=pFDesc->next);
5378 if(pFDesc)
5379 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5380 if( IsEqualIID(guid, &pCData->guid)) break;
5382 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5384 if(pCData){
5385 VariantInit( pVarVal);
5386 VariantCopy( pVarVal, &pCData->data);
5387 return S_OK;
5389 return E_INVALIDARG; /* FIXME: correct? */
5392 /* ITypeInfo2::GetParamCustData
5394 * Gets the custom data
5396 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5397 ITypeInfo2 * iface,
5398 UINT indexFunc,
5399 UINT indexParam,
5400 REFGUID guid,
5401 VARIANT *pVarVal)
5403 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5404 TLBCustData *pCData=NULL;
5405 TLBFuncDesc * pFDesc;
5406 int i;
5408 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5410 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5411 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5412 pCData = pCData->next)
5413 if( IsEqualIID(guid, &pCData->guid)) break;
5415 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5417 if(pCData)
5419 VariantInit( pVarVal);
5420 VariantCopy( pVarVal, &pCData->data);
5421 return S_OK;
5423 return E_INVALIDARG; /* FIXME: correct? */
5426 /* ITypeInfo2::GetVarCustData
5428 * Gets the custom data
5430 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5431 ITypeInfo2 * iface,
5432 UINT index,
5433 REFGUID guid,
5434 VARIANT *pVarVal)
5436 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5437 TLBCustData *pCData=NULL;
5438 TLBVarDesc * pVDesc;
5439 int i;
5441 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5443 if(pVDesc)
5445 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5447 if( IsEqualIID(guid, &pCData->guid)) break;
5451 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5453 if(pCData)
5455 VariantInit( pVarVal);
5456 VariantCopy( pVarVal, &pCData->data);
5457 return S_OK;
5459 return E_INVALIDARG; /* FIXME: correct? */
5462 /* ITypeInfo2::GetImplCustData
5464 * Gets the custom data
5466 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5467 ITypeInfo2 * iface,
5468 UINT index,
5469 REFGUID guid,
5470 VARIANT *pVarVal)
5472 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5473 TLBCustData *pCData=NULL;
5474 TLBImplType * pRDesc;
5475 int i;
5477 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5479 if(pRDesc)
5481 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5483 if( IsEqualIID(guid, &pCData->guid)) break;
5487 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5489 if(pCData)
5491 VariantInit( pVarVal);
5492 VariantCopy( pVarVal, &pCData->data);
5493 return S_OK;
5495 return E_INVALIDARG; /* FIXME: correct? */
5498 /* ITypeInfo2::GetDocumentation2
5500 * Retrieves the documentation string, the complete Help file name and path,
5501 * the localization context to use, and the context ID for the library Help
5502 * topic in the Help file.
5505 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5506 ITypeInfo2 * iface,
5507 MEMBERID memid,
5508 LCID lcid,
5509 BSTR *pbstrHelpString,
5510 DWORD *pdwHelpStringContext,
5511 BSTR *pbstrHelpStringDll)
5513 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5514 TLBFuncDesc * pFDesc;
5515 TLBVarDesc * pVDesc;
5516 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5517 "HelpStringContext(%p) HelpStringDll(%p)\n",
5518 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5519 pbstrHelpStringDll );
5520 /* the help string should be obtained from the helpstringdll,
5521 * using the _DLLGetDocumentation function, based on the supplied
5522 * lcid. Nice to do sometime...
5524 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5525 if(pbstrHelpString)
5526 *pbstrHelpString=SysAllocString(This->Name);
5527 if(pdwHelpStringContext)
5528 *pdwHelpStringContext=This->dwHelpStringContext;
5529 if(pbstrHelpStringDll)
5530 *pbstrHelpStringDll=
5531 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5532 return S_OK;
5533 }else {/* for a member */
5534 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5535 if(pFDesc->funcdesc.memid==memid){
5536 if(pbstrHelpString)
5537 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5538 if(pdwHelpStringContext)
5539 *pdwHelpStringContext=pFDesc->HelpStringContext;
5540 if(pbstrHelpStringDll)
5541 *pbstrHelpStringDll=
5542 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5543 return S_OK;
5545 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5546 if(pVDesc->vardesc.memid==memid){
5547 if(pbstrHelpString)
5548 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5549 if(pdwHelpStringContext)
5550 *pdwHelpStringContext=pVDesc->HelpStringContext;
5551 if(pbstrHelpStringDll)
5552 *pbstrHelpStringDll=
5553 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5554 return S_OK;
5557 return TYPE_E_ELEMENTNOTFOUND;
5560 /* ITypeInfo2::GetAllCustData
5562 * Gets all custom data items for the Type info.
5565 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5566 ITypeInfo2 * iface,
5567 CUSTDATA *pCustData)
5569 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5570 TLBCustData *pCData;
5571 int i;
5573 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5575 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5576 if(pCustData->prgCustData ){
5577 pCustData->cCustData=This->ctCustData;
5578 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5579 pCustData->prgCustData[i].guid=pCData->guid;
5580 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5582 }else{
5583 ERR(" OUT OF MEMORY! \n");
5584 return E_OUTOFMEMORY;
5586 return S_OK;
5589 /* ITypeInfo2::GetAllFuncCustData
5591 * Gets all custom data items for the specified Function
5594 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5595 ITypeInfo2 * iface,
5596 UINT index,
5597 CUSTDATA *pCustData)
5599 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5600 TLBCustData *pCData;
5601 TLBFuncDesc * pFDesc;
5602 int i;
5603 TRACE("(%p) index %d\n", This, index);
5604 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5605 pFDesc=pFDesc->next)
5607 if(pFDesc){
5608 pCustData->prgCustData =
5609 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5610 if(pCustData->prgCustData ){
5611 pCustData->cCustData=pFDesc->ctCustData;
5612 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5613 pCData = pCData->next){
5614 pCustData->prgCustData[i].guid=pCData->guid;
5615 VariantCopy(& pCustData->prgCustData[i].varValue,
5616 & pCData->data);
5618 }else{
5619 ERR(" OUT OF MEMORY! \n");
5620 return E_OUTOFMEMORY;
5622 return S_OK;
5624 return TYPE_E_ELEMENTNOTFOUND;
5627 /* ITypeInfo2::GetAllParamCustData
5629 * Gets all custom data items for the Functions
5632 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5633 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5635 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5636 TLBCustData *pCData=NULL;
5637 TLBFuncDesc * pFDesc;
5638 int i;
5639 TRACE("(%p) index %d\n", This, indexFunc);
5640 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5641 pFDesc=pFDesc->next)
5643 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5644 pCustData->prgCustData =
5645 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5646 sizeof(CUSTDATAITEM));
5647 if(pCustData->prgCustData ){
5648 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5649 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5650 pCData; i++, pCData = pCData->next){
5651 pCustData->prgCustData[i].guid=pCData->guid;
5652 VariantCopy(& pCustData->prgCustData[i].varValue,
5653 & pCData->data);
5655 }else{
5656 ERR(" OUT OF MEMORY! \n");
5657 return E_OUTOFMEMORY;
5659 return S_OK;
5661 return TYPE_E_ELEMENTNOTFOUND;
5664 /* ITypeInfo2::GetAllVarCustData
5666 * Gets all custom data items for the specified Variable
5669 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5670 UINT index, CUSTDATA *pCustData)
5672 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5673 TLBCustData *pCData;
5674 TLBVarDesc * pVDesc;
5675 int i;
5676 TRACE("(%p) index %d\n", This, index);
5677 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5678 pVDesc=pVDesc->next)
5680 if(pVDesc){
5681 pCustData->prgCustData =
5682 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5683 if(pCustData->prgCustData ){
5684 pCustData->cCustData=pVDesc->ctCustData;
5685 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5686 pCData = pCData->next){
5687 pCustData->prgCustData[i].guid=pCData->guid;
5688 VariantCopy(& pCustData->prgCustData[i].varValue,
5689 & pCData->data);
5691 }else{
5692 ERR(" OUT OF MEMORY! \n");
5693 return E_OUTOFMEMORY;
5695 return S_OK;
5697 return TYPE_E_ELEMENTNOTFOUND;
5700 /* ITypeInfo2::GetAllImplCustData
5702 * Gets all custom data items for the specified implementation type
5705 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5706 ITypeInfo2 * iface,
5707 UINT index,
5708 CUSTDATA *pCustData)
5710 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5711 TLBCustData *pCData;
5712 TLBImplType * pRDesc;
5713 int i;
5714 TRACE("(%p) index %d\n", This, index);
5715 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5716 pRDesc=pRDesc->next)
5718 if(pRDesc){
5719 pCustData->prgCustData =
5720 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5721 if(pCustData->prgCustData ){
5722 pCustData->cCustData=pRDesc->ctCustData;
5723 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5724 pCData = pCData->next){
5725 pCustData->prgCustData[i].guid=pCData->guid;
5726 VariantCopy(& pCustData->prgCustData[i].varValue,
5727 & pCData->data);
5729 }else{
5730 ERR(" OUT OF MEMORY! \n");
5731 return E_OUTOFMEMORY;
5733 return S_OK;
5735 return TYPE_E_ELEMENTNOTFOUND;
5738 static ITypeInfo2Vtbl tinfvt =
5741 ITypeInfo_fnQueryInterface,
5742 ITypeInfo_fnAddRef,
5743 ITypeInfo_fnRelease,
5745 ITypeInfo_fnGetTypeAttr,
5746 ITypeInfo_fnGetTypeComp,
5747 ITypeInfo_fnGetFuncDesc,
5748 ITypeInfo_fnGetVarDesc,
5749 ITypeInfo_fnGetNames,
5750 ITypeInfo_fnGetRefTypeOfImplType,
5751 ITypeInfo_fnGetImplTypeFlags,
5752 ITypeInfo_fnGetIDsOfNames,
5753 ITypeInfo_fnInvoke,
5754 ITypeInfo_fnGetDocumentation,
5755 ITypeInfo_fnGetDllEntry,
5756 ITypeInfo_fnGetRefTypeInfo,
5757 ITypeInfo_fnAddressOfMember,
5758 ITypeInfo_fnCreateInstance,
5759 ITypeInfo_fnGetMops,
5760 ITypeInfo_fnGetContainingTypeLib,
5761 ITypeInfo_fnReleaseTypeAttr,
5762 ITypeInfo_fnReleaseFuncDesc,
5763 ITypeInfo_fnReleaseVarDesc,
5765 ITypeInfo2_fnGetTypeKind,
5766 ITypeInfo2_fnGetTypeFlags,
5767 ITypeInfo2_fnGetFuncIndexOfMemId,
5768 ITypeInfo2_fnGetVarIndexOfMemId,
5769 ITypeInfo2_fnGetCustData,
5770 ITypeInfo2_fnGetFuncCustData,
5771 ITypeInfo2_fnGetParamCustData,
5772 ITypeInfo2_fnGetVarCustData,
5773 ITypeInfo2_fnGetImplTypeCustData,
5774 ITypeInfo2_fnGetDocumentation2,
5775 ITypeInfo2_fnGetAllCustData,
5776 ITypeInfo2_fnGetAllFuncCustData,
5777 ITypeInfo2_fnGetAllParamCustData,
5778 ITypeInfo2_fnGetAllVarCustData,
5779 ITypeInfo2_fnGetAllImplTypeCustData,
5782 /******************************************************************************
5783 * CreateDispTypeInfo [OLEAUT32.31]
5785 * Build type information for an object so it can be called through an
5786 * IDispatch interface.
5788 * RETURNS
5789 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5790 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5792 * NOTES
5793 * This call allows an objects methods to be accessed through IDispatch, by
5794 * building an ITypeInfo object that IDispatch can use to call through.
5796 HRESULT WINAPI CreateDispTypeInfo(
5797 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5798 LCID lcid, /* [I] Locale Id */
5799 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5801 ITypeInfoImpl *pTIImpl;
5802 int param, func;
5803 TLBFuncDesc **ppFuncDesc;
5805 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5806 pTIImpl->pTypeLib = NULL;
5807 pTIImpl->index = 0;
5808 pTIImpl->Name = NULL;
5809 pTIImpl->dwHelpContext = -1;
5810 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5811 pTIImpl->TypeAttr.lcid = lcid;
5812 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5813 pTIImpl->TypeAttr.wMajorVerNum = 0;
5814 pTIImpl->TypeAttr.wMinorVerNum = 0;
5815 pTIImpl->TypeAttr.cbAlignment = 2;
5816 pTIImpl->TypeAttr.cbSizeInstance = -1;
5817 pTIImpl->TypeAttr.cbSizeVft = -1;
5818 pTIImpl->TypeAttr.cFuncs = 0;
5819 pTIImpl->TypeAttr.cImplTypes = 1;
5820 pTIImpl->TypeAttr.cVars = 0;
5821 pTIImpl->TypeAttr.wTypeFlags = 0;
5823 ppFuncDesc = &pTIImpl->funclist;
5824 for(func = 0; func < pidata->cMembers; func++) {
5825 METHODDATA *md = pidata->pmethdata + func;
5826 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5827 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5828 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5829 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5830 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5831 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5832 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5833 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5834 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5835 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5836 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5837 md->cArgs * sizeof(ELEMDESC));
5838 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5839 md->cArgs * sizeof(TLBParDesc));
5840 for(param = 0; param < md->cArgs; param++) {
5841 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5842 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5844 ppFuncDesc = &(*ppFuncDesc)->next;
5846 *pptinfo = (ITypeInfo*)pTIImpl;
5847 return S_OK;
5851 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5853 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5855 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5858 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5860 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5862 return ITypeInfo_AddRef((ITypeInfo *)This);
5865 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5867 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5869 return ITypeInfo_Release((ITypeInfo *)This);
5872 static HRESULT WINAPI ITypeComp_fnBind(
5873 ITypeComp * iface,
5874 OLECHAR * szName,
5875 ULONG lHash,
5876 WORD wFlags,
5877 ITypeInfo ** ppTInfo,
5878 DESCKIND * pDescKind,
5879 BINDPTR * pBindPtr)
5881 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5882 TLBFuncDesc * pFDesc;
5883 TLBVarDesc * pVDesc;
5885 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5887 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5888 if (pFDesc->funcdesc.invkind & wFlags)
5889 if (!strcmpW(pFDesc->Name, szName)) {
5890 break;
5893 if (pFDesc)
5895 *pDescKind = DESCKIND_FUNCDESC;
5896 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5897 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5898 return S_OK;
5899 } else {
5900 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5902 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5903 if (!strcmpW(pVDesc->Name, szName)) {
5904 *pDescKind = DESCKIND_VARDESC;
5905 pBindPtr->lpvardesc = &pVDesc->vardesc;
5906 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5907 return S_OK;
5912 /* not found, look for it in inherited interfaces */
5913 if (This->TypeAttr.cImplTypes &&
5914 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5915 /* recursive search */
5916 ITypeInfo *pTInfo;
5917 ITypeComp *pTComp;
5918 HRESULT hr;
5919 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5920 if (SUCCEEDED(hr))
5922 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5923 ITypeInfo_Release(pTInfo);
5925 if (SUCCEEDED(hr))
5927 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5928 ITypeComp_Release(pTComp);
5929 return hr;
5931 WARN("Could not search inherited interface!\n");
5933 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5934 *pDescKind = DESCKIND_NONE;
5935 pBindPtr->lpfuncdesc = NULL;
5936 *ppTInfo = NULL;
5937 return DISP_E_MEMBERNOTFOUND;
5940 static HRESULT WINAPI ITypeComp_fnBindType(
5941 ITypeComp * iface,
5942 OLECHAR * szName,
5943 ULONG lHash,
5944 ITypeInfo ** ppTInfo,
5945 ITypeComp ** ppTComp)
5947 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5949 /* strange behaviour (does nothing) but like the
5950 * original */
5952 if (!ppTInfo || !ppTComp)
5953 return E_POINTER;
5955 *ppTInfo = NULL;
5956 *ppTComp = NULL;
5958 return S_OK;
5961 static ITypeCompVtbl tcompvt =
5964 ITypeComp_fnQueryInterface,
5965 ITypeComp_fnAddRef,
5966 ITypeComp_fnRelease,
5968 ITypeComp_fnBind,
5969 ITypeComp_fnBindType