Added YUV routines needed for v4l driver, and in the future possibly
[wine/gsoc-2012-control.git] / dlls / oleaut32 / typelib.c
blob5cba2bb3167e4831b2bd64056ea19dfadb657960
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 * The first entry is always the length of the record (including this
1633 * length word).
1634 * The rest of the record depends on the type of the member. If there is
1635 * a field indicating the member type (function, variable, interface, 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 member id
1640 * for each member;
1642 * Third is an equal sized array with file offsets to the name entry
1643 * of each member.
1645 * The fourth and last (?) part is an array with offsets to the records
1646 * in the 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 VARIANT va;
4521 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4522 memcpy(argpos,&arg,sizeof(void*));
4523 return S_OK;
4526 if (V_VT(arg) == vt) {
4527 memcpy(argpos, &V_I4(arg), arglen);
4528 return S_OK;
4531 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4532 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4533 return S_OK;
4536 if (vt == VT_VARIANT) {
4537 memcpy(argpos, arg, arglen);
4538 return S_OK;
4540 /* Deref BYREF vars if there is need */
4541 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4542 memcpy(argpos,(void*)V_I4(arg), arglen);
4543 return S_OK;
4545 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4546 /* in this context, if the type lib specifies IUnknown*, giving an
4547 IDispatch* is correct; so, don't invoke VariantChangeType */
4548 memcpy(argpos,&V_I4(arg), arglen);
4549 return S_OK;
4551 if ((vt == VT_PTR) && tdesc)
4552 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4554 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4555 ITypeInfo *tinfo2 = NULL;
4556 TYPEATTR *tattr = NULL;
4557 HRESULT hres;
4559 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4560 if (hres) {
4561 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4562 "while coercing from vt 0x%x. Copying 4 byte.\n",
4563 tdesc->u.hreftype,V_VT(arg));
4564 memcpy(argpos, &V_I4(arg), 4);
4565 return S_OK;
4567 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4568 if( hres )
4570 ERR("GetTypeAttr failed\n");
4571 ITypeInfo_Release(tinfo2);
4572 return hres;
4574 switch (tattr->typekind) {
4575 case TKIND_ENUM:
4576 switch ( V_VT( arg ) ) {
4577 case VT_I2:
4578 *argpos = V_I2(arg);
4579 hres = S_OK;
4580 break;
4581 case VT_I4:
4582 memcpy(argpos, &V_I4(arg), 4);
4583 hres = S_OK;
4584 break;
4585 default:
4586 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4587 hres = E_FAIL;
4588 break;
4590 break;
4592 case TKIND_ALIAS:
4593 tdesc = &(tattr->tdescAlias);
4594 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4595 break;
4597 case TKIND_INTERFACE:
4598 if (V_VT(arg) == VT_DISPATCH) {
4599 IDispatch *disp;
4600 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4601 memcpy(argpos, &V_DISPATCH(arg), 4);
4602 hres = S_OK;
4603 break;
4605 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4606 &IID_IDispatch,(LPVOID*)&disp);
4607 if (SUCCEEDED(hres)) {
4608 memcpy(argpos,&disp,4);
4609 IUnknown_Release(V_DISPATCH(arg));
4610 hres = S_OK;
4611 break;
4613 FIXME("Failed to query IDispatch interface from %s while "
4614 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4615 hres = E_FAIL;
4616 break;
4618 if (V_VT(arg) == VT_UNKNOWN) {
4619 memcpy(argpos, &V_UNKNOWN(arg), 4);
4620 hres = S_OK;
4621 break;
4623 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4624 V_VT(arg),debugstr_guid(&(tattr->guid)));
4625 hres = E_FAIL;
4626 break;
4628 case TKIND_DISPATCH:
4629 if (V_VT(arg) == VT_DISPATCH) {
4630 memcpy(argpos, &V_DISPATCH(arg), 4);
4631 hres = S_OK;
4633 else {
4634 hres = E_FAIL;
4635 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4637 break;
4638 case TKIND_RECORD:
4639 FIXME("TKIND_RECORD unhandled.\n");
4640 hres = E_FAIL;
4641 break;
4642 default:
4643 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4644 hres = E_FAIL;
4645 break;
4647 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4648 ITypeInfo_Release(tinfo2);
4649 return hres;
4652 VariantInit(&va);
4653 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4654 memcpy(argpos,&V_I4(&va), arglen);
4655 FIXME("Should not use VariantChangeType here."
4656 " (conversion from 0x%x -> 0x%x) %08lx\n",
4657 V_VT(arg), vt, *argpos
4659 return S_OK;
4661 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4662 return E_FAIL;
4665 /***********************************************************************
4666 * DispCallFunc (OLEAUT32.@)
4668 HRESULT WINAPI
4669 DispCallFunc(
4670 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4671 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4673 int i, argsize, argspos;
4674 DWORD *args;
4675 HRESULT hres;
4677 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4678 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4680 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4681 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4682 argsize = 1;
4683 for (i=0;i<cActuals;i++) {
4684 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4685 dump_Variant(prgpvarg[i]);
4686 argsize += _argsize(prgvt[i]);
4688 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4689 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4690 argspos = 1;
4691 for (i=0;i<cActuals;i++) {
4692 VARIANT *arg = prgpvarg[i];
4693 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4694 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4695 argspos += _argsize(prgvt[i]);
4698 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4700 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4701 hres=S_OK;
4703 else
4705 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4706 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4707 FIXME("Method returned %lx\n",hres);
4709 HeapFree(GetProcessHeap(),0,args);
4710 return hres;
4713 static HRESULT WINAPI ITypeInfo_fnInvoke(
4714 ITypeInfo2 *iface,
4715 VOID *pIUnk,
4716 MEMBERID memid,
4717 UINT16 dwFlags,
4718 DISPPARAMS *pDispParams,
4719 VARIANT *pVarResult,
4720 EXCEPINFO *pExcepInfo,
4721 UINT *pArgErr)
4723 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4724 int i;
4725 unsigned int func_index, var_index;
4726 TYPEKIND type_kind;
4727 HRESULT hres;
4729 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4730 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4732 dump_DispParms(pDispParams);
4734 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4735 if (SUCCEEDED(hres)) {
4736 FUNCDESC *func_desc;
4738 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4739 if(FAILED(hres)) return hres;
4741 switch (func_desc->funckind) {
4742 case FUNC_PUREVIRTUAL:
4743 case FUNC_VIRTUAL: {
4744 DWORD res;
4745 int numargs, numargs2, argspos, args2pos;
4746 DWORD *args , *args2;
4747 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4748 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4750 hres = S_OK;
4751 numargs = 1; numargs2 = 0;
4752 for (i = 0; i < func_desc->cParams; i++) {
4753 if (i<pDispParams->cArgs)
4754 numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4755 else {
4756 numargs += 1; /* sizeof(lpvoid) */
4757 numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4761 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4762 args2 = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4764 args[0] = (DWORD)pIUnk;
4765 argspos = 1; args2pos = 0;
4766 for (i = 0; i < func_desc->cParams; i++) {
4767 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4768 if (i<pDispParams->cArgs) {
4769 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4770 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4771 USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
4772 if (paramFlags & PARAMFLAG_FOPT) {
4773 if(i < func_desc->cParams - func_desc->cParamsOpt)
4774 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4775 if(V_VT(arg) == VT_EMPTY
4776 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4777 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4778 How to determine it? */
4780 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4781 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4782 V_VT(arg) = VT_ERROR;
4783 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4784 arglen = _argsize(VT_ERROR);
4787 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4788 if (FAILED(hres)) goto func_fail;
4789 argspos += arglen;
4790 } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
4791 VARIANT *arg = &rgvarg[i];
4792 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4793 if(i < func_desc->cParams - func_desc->cParamsOpt)
4794 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4795 if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4796 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4797 V_VT(arg) = VT_ERROR;
4798 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4799 arglen = _argsize(VT_ERROR);
4800 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4801 if (FAILED(hres)) goto func_fail;
4802 argspos += arglen;
4803 } else {
4804 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);
4805 if (tdesc->vt != VT_PTR)
4806 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4807 /*FIXME: give pointers for the rest, so propertyget works*/
4808 args[argspos] = (DWORD)&args2[args2pos];
4810 /* If pointer to variant, pass reference it. */
4811 if ((tdesc->vt == VT_PTR) &&
4812 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4813 pVarResult
4815 args[argspos]= (DWORD)pVarResult;
4816 argspos += 1;
4817 args2pos += arglen;
4820 if (func_desc->cParamsOpt < 0)
4821 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4823 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4824 func_desc->callconv,
4825 numargs,
4826 args
4829 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4830 args2pos = 0;
4831 for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
4832 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4833 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);
4834 TYPEDESC i4_tdesc;
4835 i4_tdesc.vt = VT_I4;
4837 /* If we are a pointer to a variant, we are done already */
4838 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4839 continue;
4841 VariantInit(pVarResult);
4842 memcpy(&V_INT(pVarResult),&args2[args2pos],arglen*sizeof(DWORD));
4844 if (tdesc->vt == VT_PTR)
4845 tdesc = tdesc->u.lptdesc;
4846 if (tdesc->vt == VT_USERDEFINED) {
4847 ITypeInfo *tinfo2;
4848 TYPEATTR *tattr;
4850 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4851 if (FAILED(hres)) {
4852 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4853 goto func_fail;
4855 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4856 switch (tattr->typekind) {
4857 case TKIND_ENUM:
4858 /* force the return type to be VT_I4 */
4859 tdesc = &i4_tdesc;
4860 break;
4861 case TKIND_ALIAS:
4862 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4863 tdesc = &(tattr->tdescAlias);
4864 break;
4866 case TKIND_INTERFACE:
4867 FIXME("TKIND_INTERFACE unhandled.\n");
4868 break;
4869 case TKIND_DISPATCH:
4870 FIXME("TKIND_DISPATCH unhandled.\n");
4871 break;
4872 case TKIND_RECORD:
4873 FIXME("TKIND_RECORD unhandled.\n");
4874 break;
4875 default:
4876 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4877 break;
4879 ITypeInfo_Release(tinfo2);
4881 V_VT(pVarResult) = tdesc->vt;
4883 /* HACK: VB5 likes this.
4884 * I do not know why. There is 1 example in MSDN which uses
4885 * this which appears broken (mixes int vals and
4886 * IDispatch*.).
4888 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4889 V_VT(pVarResult) = VT_DISPATCH;
4890 TRACE("storing into variant:\n");
4891 dump_Variant(pVarResult);
4892 args2pos += arglen;
4895 func_fail:
4896 HeapFree(GetProcessHeap(), 0, rgvarg);
4897 HeapFree(GetProcessHeap(),0,args2);
4898 HeapFree(GetProcessHeap(),0,args);
4899 break;
4901 case FUNC_DISPATCH: {
4902 IDispatch *disp;
4904 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4905 if (SUCCEEDED(hres)) {
4906 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4907 hres = IDispatch_Invoke(
4908 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4909 pVarResult,pExcepInfo,pArgErr
4911 if (FAILED(hres))
4912 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
4913 IDispatch_Release(disp);
4914 } else
4915 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4916 break;
4918 default:
4919 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
4920 hres = E_FAIL;
4921 break;
4924 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
4925 return hres;
4927 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
4928 VARDESC *var_desc;
4930 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
4931 if(FAILED(hres)) return hres;
4933 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4934 dump_VARDESC(var_desc);
4935 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
4936 return E_NOTIMPL;
4939 /* not found, look for it in inherited interfaces */
4940 ITypeInfo2_GetTypeKind(iface, &type_kind);
4941 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
4942 HREFTYPE ref_type;
4943 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
4944 /* recursive search */
4945 ITypeInfo *pTInfo;
4946 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
4947 if(SUCCEEDED(hres)){
4948 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4949 ITypeInfo_Release(pTInfo);
4950 return hres;
4952 WARN("Could not search inherited interface!\n");
4955 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
4956 return DISP_E_MEMBERNOTFOUND;
4959 /* ITypeInfo::GetDocumentation
4961 * Retrieves the documentation string, the complete Help file name and path,
4962 * and the context ID for the Help topic for a specified type description.
4964 * (Can be tested by the Visual Basic Editor in Word for instance.)
4966 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4967 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4968 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4970 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4971 TLBFuncDesc * pFDesc;
4972 TLBVarDesc * pVDesc;
4973 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4974 " HelpContext(%p) HelpFile(%p)\n",
4975 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4976 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4977 if(pBstrName)
4978 *pBstrName=SysAllocString(This->Name);
4979 if(pBstrDocString)
4980 *pBstrDocString=SysAllocString(This->DocString);
4981 if(pdwHelpContext)
4982 *pdwHelpContext=This->dwHelpContext;
4983 if(pBstrHelpFile)
4984 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4985 return S_OK;
4986 }else {/* for a member */
4987 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4988 if(pFDesc->funcdesc.memid==memid){
4989 if(pBstrName)
4990 *pBstrName = SysAllocString(pFDesc->Name);
4991 if(pBstrDocString)
4992 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4993 if(pdwHelpContext)
4994 *pdwHelpContext=pFDesc->helpcontext;
4995 return S_OK;
4997 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4998 if(pVDesc->vardesc.memid==memid){
4999 if(pBstrName)
5000 *pBstrName = SysAllocString(pVDesc->Name);
5001 if(pBstrDocString)
5002 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5003 if(pdwHelpContext)
5004 *pdwHelpContext=pVDesc->HelpContext;
5005 return S_OK;
5008 return TYPE_E_ELEMENTNOTFOUND;
5011 /* ITypeInfo::GetDllEntry
5013 * Retrieves a description or specification of an entry point for a function
5014 * in a DLL.
5016 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5017 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5018 WORD *pwOrdinal)
5020 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5021 TLBFuncDesc *pFDesc;
5023 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5025 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5026 if(pFDesc->funcdesc.memid==memid){
5027 dump_TypeInfo(This);
5028 dump_TLBFuncDescOne(pFDesc);
5030 /* FIXME: This is wrong, but how do you find that out? */
5031 if (pBstrDllName) {
5032 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5033 *pBstrDllName = SysAllocString(oleaut32W);
5036 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5037 if (pBstrName)
5038 *pBstrName = SysAllocString(pFDesc->Entry);
5039 if (pwOrdinal)
5040 *pwOrdinal = -1;
5041 return S_OK;
5043 if (pBstrName)
5044 *pBstrName = NULL;
5045 if (pwOrdinal)
5046 *pwOrdinal = (DWORD)pFDesc->Entry;
5047 return S_OK;
5049 return E_FAIL;
5052 /* ITypeInfo::GetRefTypeInfo
5054 * If a type description references other type descriptions, it retrieves
5055 * the referenced type descriptions.
5057 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5058 ITypeInfo2 *iface,
5059 HREFTYPE hRefType,
5060 ITypeInfo **ppTInfo)
5062 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5063 HRESULT result = E_FAIL;
5066 if (hRefType == -1 &&
5067 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5068 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5070 /* when we meet a DUAL dispinterface, we must create the interface
5071 * version of it.
5073 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5076 /* the interface version contains the same information as the dispinterface
5077 * copy the contents of the structs.
5079 *pTypeInfoImpl = *This;
5080 pTypeInfoImpl->ref = 1;
5082 /* change the type to interface */
5083 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5085 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5087 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5089 result = S_OK;
5091 } else {
5092 TLBRefType *pRefType;
5093 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5094 if(pRefType->reference == hRefType)
5095 break;
5097 if(!pRefType)
5098 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5099 if(pRefType && hRefType != -1) {
5100 ITypeLib *pTLib = NULL;
5102 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5103 int Index;
5104 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5105 } else {
5106 if(pRefType->pImpTLInfo->pImpTypeLib) {
5107 TRACE("typeinfo in imported typelib that is already loaded\n");
5108 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5109 ITypeLib2_AddRef((ITypeLib*) pTLib);
5110 result = S_OK;
5111 } else {
5112 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5113 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5114 pRefType->pImpTLInfo->wVersionMajor,
5115 pRefType->pImpTLInfo->wVersionMinor,
5116 pRefType->pImpTLInfo->lcid,
5117 &pTLib);
5119 if(!SUCCEEDED(result)) {
5120 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5121 result=LoadTypeLib(libnam, &pTLib);
5122 SysFreeString(libnam);
5124 if(SUCCEEDED(result)) {
5125 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5126 ITypeLib2_AddRef(pTLib);
5130 if(SUCCEEDED(result)) {
5131 if(pRefType->index == TLB_REF_USE_GUID)
5132 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5133 &pRefType->guid,
5134 ppTInfo);
5135 else
5136 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5137 ppTInfo);
5139 if (pTLib != NULL)
5140 ITypeLib2_Release(pTLib);
5144 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5145 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5146 return result;
5149 /* ITypeInfo::AddressOfMember
5151 * Retrieves the addresses of static functions or variables, such as those
5152 * defined in a DLL.
5154 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5155 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5157 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5158 FIXME("(%p) stub!\n", This);
5159 return S_OK;
5162 /* ITypeInfo::CreateInstance
5164 * Creates a new instance of a type that describes a component object class
5165 * (coclass).
5167 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5168 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5170 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5171 FIXME("(%p) stub!\n", This);
5172 return S_OK;
5175 /* ITypeInfo::GetMops
5177 * Retrieves marshalling information.
5179 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5180 BSTR *pBstrMops)
5182 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5183 FIXME("(%p) stub!\n", This);
5184 return S_OK;
5187 /* ITypeInfo::GetContainingTypeLib
5189 * Retrieves the containing type library and the index of the type description
5190 * within that type library.
5192 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5193 ITypeLib * *ppTLib, UINT *pIndex)
5195 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5197 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5198 if (pIndex) {
5199 *pIndex=This->index;
5200 TRACE("returning pIndex=%d\n", *pIndex);
5203 if (ppTLib) {
5204 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5205 ITypeLib2_AddRef(*ppTLib);
5206 TRACE("returning ppTLib=%p\n", *ppTLib);
5209 return S_OK;
5212 /* ITypeInfo::ReleaseTypeAttr
5214 * Releases a TYPEATTR previously returned by GetTypeAttr.
5217 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5218 TYPEATTR* pTypeAttr)
5220 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5221 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5222 if(This->TypeAttr.typekind == TKIND_ALIAS)
5223 free_deep_typedesc(&pTypeAttr->tdescAlias);
5224 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5227 /* ITypeInfo::ReleaseFuncDesc
5229 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5231 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5232 ITypeInfo2 *iface,
5233 FUNCDESC *pFuncDesc)
5235 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5236 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5239 /* ITypeInfo::ReleaseVarDesc
5241 * Releases a VARDESC previously returned by GetVarDesc.
5243 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5244 VARDESC *pVarDesc)
5246 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5247 TRACE("(%p)->(%p)\n", This, pVarDesc);
5250 /* ITypeInfo2::GetTypeKind
5252 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5255 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5256 TYPEKIND *pTypeKind)
5258 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5259 *pTypeKind=This->TypeAttr.typekind;
5260 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5261 return S_OK;
5264 /* ITypeInfo2::GetTypeFlags
5266 * Returns the type flags without any allocations. This returns a DWORD type
5267 * flag, which expands the type flags without growing the TYPEATTR (type
5268 * attribute).
5271 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5273 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5274 *pTypeFlags=This->TypeAttr.wTypeFlags;
5275 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5276 return S_OK;
5279 /* ITypeInfo2::GetFuncIndexOfMemId
5280 * Binds to a specific member based on a known DISPID, where the member name
5281 * is not known (for example, when binding to a default member).
5284 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5285 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5287 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5288 TLBFuncDesc *pFuncInfo;
5289 int i;
5290 HRESULT result;
5292 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5293 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5294 break;
5295 if(pFuncInfo) {
5296 *pFuncIndex = i;
5297 result = S_OK;
5298 } else
5299 result = TYPE_E_ELEMENTNOTFOUND;
5301 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5302 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5303 return result;
5306 /* TypeInfo2::GetVarIndexOfMemId
5308 * Binds to a specific member based on a known DISPID, where the member name
5309 * is not known (for example, when binding to a default member).
5312 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5313 MEMBERID memid, UINT *pVarIndex)
5315 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5316 TLBVarDesc *pVarInfo;
5317 int i;
5318 HRESULT result;
5319 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5320 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5322 if(pVarInfo) {
5323 *pVarIndex = i;
5324 result = S_OK;
5325 } else
5326 result = TYPE_E_ELEMENTNOTFOUND;
5328 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5329 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5330 return result;
5333 /* ITypeInfo2::GetCustData
5335 * Gets the custom data
5337 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5338 ITypeInfo2 * iface,
5339 REFGUID guid,
5340 VARIANT *pVarVal)
5342 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5343 TLBCustData *pCData;
5345 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5346 if( IsEqualIID(guid, &pCData->guid)) break;
5348 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5350 if(pCData)
5352 VariantInit( pVarVal);
5353 VariantCopy( pVarVal, &pCData->data);
5354 return S_OK;
5356 return E_INVALIDARG; /* FIXME: correct? */
5359 /* ITypeInfo2::GetFuncCustData
5361 * Gets the custom data
5363 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5364 ITypeInfo2 * iface,
5365 UINT index,
5366 REFGUID guid,
5367 VARIANT *pVarVal)
5369 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5370 TLBCustData *pCData=NULL;
5371 TLBFuncDesc * pFDesc;
5372 int i;
5373 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5374 pFDesc=pFDesc->next);
5376 if(pFDesc)
5377 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5378 if( IsEqualIID(guid, &pCData->guid)) break;
5380 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5382 if(pCData){
5383 VariantInit( pVarVal);
5384 VariantCopy( pVarVal, &pCData->data);
5385 return S_OK;
5387 return E_INVALIDARG; /* FIXME: correct? */
5390 /* ITypeInfo2::GetParamCustData
5392 * Gets the custom data
5394 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5395 ITypeInfo2 * iface,
5396 UINT indexFunc,
5397 UINT indexParam,
5398 REFGUID guid,
5399 VARIANT *pVarVal)
5401 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5402 TLBCustData *pCData=NULL;
5403 TLBFuncDesc * pFDesc;
5404 int i;
5406 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5408 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5409 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5410 pCData = pCData->next)
5411 if( IsEqualIID(guid, &pCData->guid)) break;
5413 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5415 if(pCData)
5417 VariantInit( pVarVal);
5418 VariantCopy( pVarVal, &pCData->data);
5419 return S_OK;
5421 return E_INVALIDARG; /* FIXME: correct? */
5424 /* ITypeInfo2::GetVarCustData
5426 * Gets the custom data
5428 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5429 ITypeInfo2 * iface,
5430 UINT index,
5431 REFGUID guid,
5432 VARIANT *pVarVal)
5434 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5435 TLBCustData *pCData=NULL;
5436 TLBVarDesc * pVDesc;
5437 int i;
5439 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5441 if(pVDesc)
5443 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5445 if( IsEqualIID(guid, &pCData->guid)) break;
5449 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5451 if(pCData)
5453 VariantInit( pVarVal);
5454 VariantCopy( pVarVal, &pCData->data);
5455 return S_OK;
5457 return E_INVALIDARG; /* FIXME: correct? */
5460 /* ITypeInfo2::GetImplCustData
5462 * Gets the custom data
5464 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5465 ITypeInfo2 * iface,
5466 UINT index,
5467 REFGUID guid,
5468 VARIANT *pVarVal)
5470 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5471 TLBCustData *pCData=NULL;
5472 TLBImplType * pRDesc;
5473 int i;
5475 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5477 if(pRDesc)
5479 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5481 if( IsEqualIID(guid, &pCData->guid)) break;
5485 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5487 if(pCData)
5489 VariantInit( pVarVal);
5490 VariantCopy( pVarVal, &pCData->data);
5491 return S_OK;
5493 return E_INVALIDARG; /* FIXME: correct? */
5496 /* ITypeInfo2::GetDocumentation2
5498 * Retrieves the documentation string, the complete Help file name and path,
5499 * the localization context to use, and the context ID for the library Help
5500 * topic in the Help file.
5503 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5504 ITypeInfo2 * iface,
5505 MEMBERID memid,
5506 LCID lcid,
5507 BSTR *pbstrHelpString,
5508 DWORD *pdwHelpStringContext,
5509 BSTR *pbstrHelpStringDll)
5511 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5512 TLBFuncDesc * pFDesc;
5513 TLBVarDesc * pVDesc;
5514 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5515 "HelpStringContext(%p) HelpStringDll(%p)\n",
5516 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5517 pbstrHelpStringDll );
5518 /* the help string should be obtained from the helpstringdll,
5519 * using the _DLLGetDocumentation function, based on the supplied
5520 * lcid. Nice to do sometime...
5522 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5523 if(pbstrHelpString)
5524 *pbstrHelpString=SysAllocString(This->Name);
5525 if(pdwHelpStringContext)
5526 *pdwHelpStringContext=This->dwHelpStringContext;
5527 if(pbstrHelpStringDll)
5528 *pbstrHelpStringDll=
5529 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5530 return S_OK;
5531 }else {/* for a member */
5532 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5533 if(pFDesc->funcdesc.memid==memid){
5534 if(pbstrHelpString)
5535 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5536 if(pdwHelpStringContext)
5537 *pdwHelpStringContext=pFDesc->HelpStringContext;
5538 if(pbstrHelpStringDll)
5539 *pbstrHelpStringDll=
5540 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5541 return S_OK;
5543 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5544 if(pVDesc->vardesc.memid==memid){
5545 if(pbstrHelpString)
5546 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5547 if(pdwHelpStringContext)
5548 *pdwHelpStringContext=pVDesc->HelpStringContext;
5549 if(pbstrHelpStringDll)
5550 *pbstrHelpStringDll=
5551 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5552 return S_OK;
5555 return TYPE_E_ELEMENTNOTFOUND;
5558 /* ITypeInfo2::GetAllCustData
5560 * Gets all custom data items for the Type info.
5563 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5564 ITypeInfo2 * iface,
5565 CUSTDATA *pCustData)
5567 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5568 TLBCustData *pCData;
5569 int i;
5571 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5573 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5574 if(pCustData->prgCustData ){
5575 pCustData->cCustData=This->ctCustData;
5576 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5577 pCustData->prgCustData[i].guid=pCData->guid;
5578 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5580 }else{
5581 ERR(" OUT OF MEMORY! \n");
5582 return E_OUTOFMEMORY;
5584 return S_OK;
5587 /* ITypeInfo2::GetAllFuncCustData
5589 * Gets all custom data items for the specified Function
5592 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5593 ITypeInfo2 * iface,
5594 UINT index,
5595 CUSTDATA *pCustData)
5597 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5598 TLBCustData *pCData;
5599 TLBFuncDesc * pFDesc;
5600 int i;
5601 TRACE("(%p) index %d\n", This, index);
5602 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5603 pFDesc=pFDesc->next)
5605 if(pFDesc){
5606 pCustData->prgCustData =
5607 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5608 if(pCustData->prgCustData ){
5609 pCustData->cCustData=pFDesc->ctCustData;
5610 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5611 pCData = pCData->next){
5612 pCustData->prgCustData[i].guid=pCData->guid;
5613 VariantCopy(& pCustData->prgCustData[i].varValue,
5614 & pCData->data);
5616 }else{
5617 ERR(" OUT OF MEMORY! \n");
5618 return E_OUTOFMEMORY;
5620 return S_OK;
5622 return TYPE_E_ELEMENTNOTFOUND;
5625 /* ITypeInfo2::GetAllParamCustData
5627 * Gets all custom data items for the Functions
5630 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5631 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5633 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5634 TLBCustData *pCData=NULL;
5635 TLBFuncDesc * pFDesc;
5636 int i;
5637 TRACE("(%p) index %d\n", This, indexFunc);
5638 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5639 pFDesc=pFDesc->next)
5641 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5642 pCustData->prgCustData =
5643 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5644 sizeof(CUSTDATAITEM));
5645 if(pCustData->prgCustData ){
5646 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5647 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5648 pCData; i++, pCData = pCData->next){
5649 pCustData->prgCustData[i].guid=pCData->guid;
5650 VariantCopy(& pCustData->prgCustData[i].varValue,
5651 & pCData->data);
5653 }else{
5654 ERR(" OUT OF MEMORY! \n");
5655 return E_OUTOFMEMORY;
5657 return S_OK;
5659 return TYPE_E_ELEMENTNOTFOUND;
5662 /* ITypeInfo2::GetAllVarCustData
5664 * Gets all custom data items for the specified Variable
5667 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5668 UINT index, CUSTDATA *pCustData)
5670 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5671 TLBCustData *pCData;
5672 TLBVarDesc * pVDesc;
5673 int i;
5674 TRACE("(%p) index %d\n", This, index);
5675 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5676 pVDesc=pVDesc->next)
5678 if(pVDesc){
5679 pCustData->prgCustData =
5680 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5681 if(pCustData->prgCustData ){
5682 pCustData->cCustData=pVDesc->ctCustData;
5683 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5684 pCData = pCData->next){
5685 pCustData->prgCustData[i].guid=pCData->guid;
5686 VariantCopy(& pCustData->prgCustData[i].varValue,
5687 & pCData->data);
5689 }else{
5690 ERR(" OUT OF MEMORY! \n");
5691 return E_OUTOFMEMORY;
5693 return S_OK;
5695 return TYPE_E_ELEMENTNOTFOUND;
5698 /* ITypeInfo2::GetAllImplCustData
5700 * Gets all custom data items for the specified implementation type
5703 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5704 ITypeInfo2 * iface,
5705 UINT index,
5706 CUSTDATA *pCustData)
5708 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5709 TLBCustData *pCData;
5710 TLBImplType * pRDesc;
5711 int i;
5712 TRACE("(%p) index %d\n", This, index);
5713 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5714 pRDesc=pRDesc->next)
5716 if(pRDesc){
5717 pCustData->prgCustData =
5718 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5719 if(pCustData->prgCustData ){
5720 pCustData->cCustData=pRDesc->ctCustData;
5721 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5722 pCData = pCData->next){
5723 pCustData->prgCustData[i].guid=pCData->guid;
5724 VariantCopy(& pCustData->prgCustData[i].varValue,
5725 & pCData->data);
5727 }else{
5728 ERR(" OUT OF MEMORY! \n");
5729 return E_OUTOFMEMORY;
5731 return S_OK;
5733 return TYPE_E_ELEMENTNOTFOUND;
5736 static ITypeInfo2Vtbl tinfvt =
5739 ITypeInfo_fnQueryInterface,
5740 ITypeInfo_fnAddRef,
5741 ITypeInfo_fnRelease,
5743 ITypeInfo_fnGetTypeAttr,
5744 ITypeInfo_fnGetTypeComp,
5745 ITypeInfo_fnGetFuncDesc,
5746 ITypeInfo_fnGetVarDesc,
5747 ITypeInfo_fnGetNames,
5748 ITypeInfo_fnGetRefTypeOfImplType,
5749 ITypeInfo_fnGetImplTypeFlags,
5750 ITypeInfo_fnGetIDsOfNames,
5751 ITypeInfo_fnInvoke,
5752 ITypeInfo_fnGetDocumentation,
5753 ITypeInfo_fnGetDllEntry,
5754 ITypeInfo_fnGetRefTypeInfo,
5755 ITypeInfo_fnAddressOfMember,
5756 ITypeInfo_fnCreateInstance,
5757 ITypeInfo_fnGetMops,
5758 ITypeInfo_fnGetContainingTypeLib,
5759 ITypeInfo_fnReleaseTypeAttr,
5760 ITypeInfo_fnReleaseFuncDesc,
5761 ITypeInfo_fnReleaseVarDesc,
5763 ITypeInfo2_fnGetTypeKind,
5764 ITypeInfo2_fnGetTypeFlags,
5765 ITypeInfo2_fnGetFuncIndexOfMemId,
5766 ITypeInfo2_fnGetVarIndexOfMemId,
5767 ITypeInfo2_fnGetCustData,
5768 ITypeInfo2_fnGetFuncCustData,
5769 ITypeInfo2_fnGetParamCustData,
5770 ITypeInfo2_fnGetVarCustData,
5771 ITypeInfo2_fnGetImplTypeCustData,
5772 ITypeInfo2_fnGetDocumentation2,
5773 ITypeInfo2_fnGetAllCustData,
5774 ITypeInfo2_fnGetAllFuncCustData,
5775 ITypeInfo2_fnGetAllParamCustData,
5776 ITypeInfo2_fnGetAllVarCustData,
5777 ITypeInfo2_fnGetAllImplTypeCustData,
5780 /******************************************************************************
5781 * CreateDispTypeInfo [OLEAUT32.31]
5783 * Build type information for an object so it can be called through an
5784 * IDispatch interface.
5786 * RETURNS
5787 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5788 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5790 * NOTES
5791 * This call allows an objects methods to be accessed through IDispatch, by
5792 * building an ITypeInfo object that IDispatch can use to call through.
5794 HRESULT WINAPI CreateDispTypeInfo(
5795 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5796 LCID lcid, /* [I] Locale Id */
5797 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5799 ITypeInfoImpl *pTIImpl;
5800 int param, func;
5801 TLBFuncDesc **ppFuncDesc;
5803 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5804 pTIImpl->pTypeLib = NULL;
5805 pTIImpl->index = 0;
5806 pTIImpl->Name = NULL;
5807 pTIImpl->dwHelpContext = -1;
5808 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5809 pTIImpl->TypeAttr.lcid = lcid;
5810 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5811 pTIImpl->TypeAttr.wMajorVerNum = 0;
5812 pTIImpl->TypeAttr.wMinorVerNum = 0;
5813 pTIImpl->TypeAttr.cbAlignment = 2;
5814 pTIImpl->TypeAttr.cbSizeInstance = -1;
5815 pTIImpl->TypeAttr.cbSizeVft = -1;
5816 pTIImpl->TypeAttr.cFuncs = 0;
5817 pTIImpl->TypeAttr.cImplTypes = 1;
5818 pTIImpl->TypeAttr.cVars = 0;
5819 pTIImpl->TypeAttr.wTypeFlags = 0;
5821 ppFuncDesc = &pTIImpl->funclist;
5822 for(func = 0; func < pidata->cMembers; func++) {
5823 METHODDATA *md = pidata->pmethdata + func;
5824 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5825 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5826 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5827 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5828 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5829 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5830 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5831 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5832 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5833 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5834 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5835 md->cArgs * sizeof(ELEMDESC));
5836 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5837 md->cArgs * sizeof(TLBParDesc));
5838 for(param = 0; param < md->cArgs; param++) {
5839 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5840 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5842 ppFuncDesc = &(*ppFuncDesc)->next;
5844 *pptinfo = (ITypeInfo*)pTIImpl;
5845 return S_OK;
5849 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5851 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5853 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5856 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5858 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5860 return ITypeInfo_AddRef((ITypeInfo *)This);
5863 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5865 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5867 return ITypeInfo_Release((ITypeInfo *)This);
5870 static HRESULT WINAPI ITypeComp_fnBind(
5871 ITypeComp * iface,
5872 OLECHAR * szName,
5873 ULONG lHash,
5874 WORD wFlags,
5875 ITypeInfo ** ppTInfo,
5876 DESCKIND * pDescKind,
5877 BINDPTR * pBindPtr)
5879 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5880 TLBFuncDesc * pFDesc;
5881 TLBVarDesc * pVDesc;
5883 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5885 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5886 if (pFDesc->funcdesc.invkind & wFlags)
5887 if (!strcmpW(pFDesc->Name, szName)) {
5888 break;
5891 if (pFDesc)
5893 *pDescKind = DESCKIND_FUNCDESC;
5894 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5895 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5896 return S_OK;
5897 } else {
5898 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5900 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5901 if (!strcmpW(pVDesc->Name, szName)) {
5902 *pDescKind = DESCKIND_VARDESC;
5903 pBindPtr->lpvardesc = &pVDesc->vardesc;
5904 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5905 return S_OK;
5910 /* not found, look for it in inherited interfaces */
5911 if (This->TypeAttr.cImplTypes &&
5912 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5913 /* recursive search */
5914 ITypeInfo *pTInfo;
5915 ITypeComp *pTComp;
5916 HRESULT hr;
5917 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5918 if (SUCCEEDED(hr))
5920 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5921 ITypeInfo_Release(pTInfo);
5923 if (SUCCEEDED(hr))
5925 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5926 ITypeComp_Release(pTComp);
5927 return hr;
5929 WARN("Could not search inherited interface!\n");
5931 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5932 *pDescKind = DESCKIND_NONE;
5933 pBindPtr->lpfuncdesc = NULL;
5934 *ppTInfo = NULL;
5935 return DISP_E_MEMBERNOTFOUND;
5938 static HRESULT WINAPI ITypeComp_fnBindType(
5939 ITypeComp * iface,
5940 OLECHAR * szName,
5941 ULONG lHash,
5942 ITypeInfo ** ppTInfo,
5943 ITypeComp ** ppTComp)
5945 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5947 /* strange behaviour (does nothing) but like the
5948 * original */
5950 if (!ppTInfo || !ppTComp)
5951 return E_POINTER;
5953 *ppTInfo = NULL;
5954 *ppTComp = NULL;
5956 return S_OK;
5959 static ITypeCompVtbl tcompvt =
5962 ITypeComp_fnQueryInterface,
5963 ITypeComp_fnAddRef,
5964 ITypeComp_fnRelease,
5966 ITypeComp_fnBind,
5967 ITypeComp_fnBindType