- use Interlocked* functions in AddRef and Release.
[wine/wine64.git] / dlls / oleaut32 / typelib.c
blobce8d56cf908ad6c7e7b180f0ae93226b5aad019e
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("\n");
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 *pptLib = NULL;
319 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
320 NULL)) {
322 /* Look for a trailing '\\' followed by an index */
323 pIndexStr = strrchrW(szFile, '\\');
324 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
325 index = atoiW(pIndexStr);
326 memcpy(szFileCopy, szFile,
327 (pIndexStr - szFile - 1) * sizeof(WCHAR));
328 szFileCopy[pIndexStr - szFile - 1] = '\0';
329 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
330 szPath,NULL))
331 return TYPE_E_CANTLOADLIBRARY;
332 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
333 return TYPE_E_CANTLOADLIBRARY;
334 } else {
335 WCHAR tstpath[260];
336 static const WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
337 int i;
339 lstrcpyW(tstpath,szFile);
340 CharLowerW(tstpath);
341 for (i=0;i<strlenW(tstpath);i++) {
342 if (tstpath[i] == 's') {
343 if (!strcmpW(tstpath+i,stdole32tlb)) {
344 MESSAGE("\n");
345 MESSAGE("**************************************************************************\n");
346 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
347 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
348 MESSAGE("on the Microsoft Download Pages.\n");
349 MESSAGE("**************************************************************************\n");
350 break;
354 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
355 return TYPE_E_CANTLOADLIBRARY;
359 TRACE("File %s index %d\n", debugstr_w(szPath), index);
361 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
363 if (SUCCEEDED(res))
364 switch(regkind)
366 case REGKIND_DEFAULT:
367 /* don't register typelibs supplied with full path. Experimentation confirms the following */
368 if ((!szFile) ||
369 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
370 (szFile[0] && (szFile[1] == ':'))) break;
371 /* else fall-through */
373 case REGKIND_REGISTER:
374 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
376 IUnknown_Release(*pptLib);
377 *pptLib = 0;
379 break;
380 case REGKIND_NONE:
381 break;
384 TRACE(" returns %08lx\n",res);
385 return res;
388 /******************************************************************************
389 * LoadRegTypeLib [OLEAUT32.162]
391 HRESULT WINAPI LoadRegTypeLib(
392 REFGUID rguid, /* [in] referenced guid */
393 WORD wVerMajor, /* [in] major version */
394 WORD wVerMinor, /* [in] minor version */
395 LCID lcid, /* [in] locale id */
396 ITypeLib **ppTLib) /* [out] path of typelib */
398 BSTR bstr=NULL;
399 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
401 if(SUCCEEDED(res))
403 res= LoadTypeLib(bstr, ppTLib);
404 SysFreeString(bstr);
407 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
409 return res;
413 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
414 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
415 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
416 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
417 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
418 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
420 /******************************************************************************
421 * RegisterTypeLib [OLEAUT32.163]
422 * Adds information about a type library to the System Registry
423 * NOTES
424 * Docs: ITypeLib FAR * ptlib
425 * Docs: OLECHAR FAR* szFullPath
426 * Docs: OLECHAR FAR* szHelpDir
428 * RETURNS
429 * Success: S_OK
430 * Failure: Status
432 HRESULT WINAPI RegisterTypeLib(
433 ITypeLib * ptlib, /* [in] Pointer to the library*/
434 OLECHAR * szFullPath, /* [in] full Path of the library*/
435 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
436 may be NULL*/
438 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
439 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
440 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
441 HRESULT res;
442 TLIBATTR *attr;
443 WCHAR keyName[60];
444 WCHAR tmp[16];
445 HKEY key, subKey;
446 UINT types, tidx;
447 TYPEKIND kind;
448 DWORD disposition;
450 if (ptlib == NULL || szFullPath == NULL)
451 return E_INVALIDARG;
453 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
454 return E_FAIL;
456 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
458 res = S_OK;
459 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
460 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
462 LPOLESTR doc;
464 /* Set the human-readable name of the typelib */
465 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
467 if (RegSetValueExW(key, NULL, 0, REG_SZ,
468 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
469 res = E_FAIL;
471 SysFreeString(doc);
473 else
474 res = E_FAIL;
476 /* Make up the name of the typelib path subkey */
477 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
479 /* Create the typelib path subkey */
480 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
481 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
483 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
484 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
485 res = E_FAIL;
487 RegCloseKey(subKey);
489 else
490 res = E_FAIL;
492 /* Create the flags subkey */
493 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
494 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
496 /* FIXME: is %u correct? */
497 static const WCHAR formatW[] = {'%','u',0};
498 WCHAR buf[20];
499 sprintfW(buf, formatW, attr->wLibFlags);
500 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
501 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
502 res = E_FAIL;
504 RegCloseKey(subKey);
506 else
507 res = E_FAIL;
509 /* create the helpdir subkey */
510 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
511 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
513 BOOL freeHelpDir = FALSE;
514 OLECHAR* pIndexStr;
516 /* if we created a new key, and helpDir was null, set the helpdir
517 to the directory which contains the typelib. However,
518 if we just opened an existing key, we leave the helpdir alone */
519 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
520 szHelpDir = SysAllocString(szFullPath);
521 pIndexStr = strrchrW(szHelpDir, '\\');
522 if (pIndexStr) {
523 *pIndexStr = 0;
525 freeHelpDir = TRUE;
528 /* if we have an szHelpDir, set it! */
529 if (szHelpDir != NULL) {
530 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
531 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
532 res = E_FAIL;
536 /* tidy up */
537 if (freeHelpDir) SysFreeString(szHelpDir);
538 RegCloseKey(subKey);
540 } else {
541 res = E_FAIL;
544 RegCloseKey(key);
546 else
547 res = E_FAIL;
549 /* register OLE Automation-compatible interfaces for this typelib */
550 types = ITypeLib_GetTypeInfoCount(ptlib);
551 for (tidx=0; tidx<types; tidx++) {
552 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
553 LPOLESTR name = NULL;
554 ITypeInfo *tinfo = NULL;
556 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
558 switch (kind) {
559 case TKIND_INTERFACE:
560 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
561 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
562 break;
564 case TKIND_DISPATCH:
565 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
566 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
567 break;
569 default:
570 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
571 break;
574 if (tinfo) {
575 TYPEATTR *tattr = NULL;
576 ITypeInfo_GetTypeAttr(tinfo, &tattr);
578 if (tattr) {
579 TRACE_(typelib)("guid=%s, flags=%04x (",
580 debugstr_guid(&tattr->guid),
581 tattr->wTypeFlags);
583 if (TRACE_ON(typelib)) {
584 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
585 XX(FAPPOBJECT);
586 XX(FCANCREATE);
587 XX(FLICENSED);
588 XX(FPREDECLID);
589 XX(FHIDDEN);
590 XX(FCONTROL);
591 XX(FDUAL);
592 XX(FNONEXTENSIBLE);
593 XX(FOLEAUTOMATION);
594 XX(FRESTRICTED);
595 XX(FAGGREGATABLE);
596 XX(FREPLACEABLE);
597 XX(FDISPATCHABLE);
598 XX(FREVERSEBIND);
599 XX(FPROXY);
600 #undef XX
601 MESSAGE("\n");
605 * FIXME: The 1 is just here until we implement rpcrt4
606 * stub/proxy handling. Until then it helps IShield
607 * v6 to work.
609 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
611 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
612 FIXME("Registering non-oleautomation interface!\n");
615 /* register interface<->typelib coupling */
616 get_interface_key( &tattr->guid, keyName );
617 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
618 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
620 if (name)
621 RegSetValueExW(key, NULL, 0, REG_SZ,
622 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
624 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
625 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
626 RegSetValueExW(subKey, NULL, 0, REG_SZ,
627 (BYTE*)PSOA, sizeof PSOA);
628 RegCloseKey(subKey);
631 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
632 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
633 RegSetValueExW(subKey, NULL, 0, REG_SZ,
634 (BYTE*)PSOA, sizeof PSOA);
635 RegCloseKey(subKey);
638 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
639 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
641 WCHAR buffer[40];
642 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
643 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
645 StringFromGUID2(&attr->guid, buffer, 40);
646 RegSetValueExW(subKey, NULL, 0, REG_SZ,
647 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
648 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
649 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
650 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
651 RegCloseKey(subKey);
654 RegCloseKey(key);
658 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
661 ITypeInfo_Release(tinfo);
664 SysFreeString(name);
668 ITypeLib_ReleaseTLibAttr(ptlib, attr);
670 return res;
674 /******************************************************************************
675 * UnRegisterTypeLib [OLEAUT32.186]
676 * Removes information about a type library from the System Registry
677 * NOTES
679 * RETURNS
680 * Success: S_OK
681 * Failure: Status
683 HRESULT WINAPI UnRegisterTypeLib(
684 REFGUID libid, /* [in] Guid of the library */
685 WORD wVerMajor, /* [in] major version */
686 WORD wVerMinor, /* [in] minor version */
687 LCID lcid, /* [in] locale id */
688 SYSKIND syskind)
690 BSTR tlibPath = NULL;
691 DWORD tmpLength;
692 WCHAR keyName[60];
693 WCHAR subKeyName[50];
694 int result = S_OK;
695 DWORD i = 0;
696 BOOL deleteOtherStuff;
697 HKEY key = NULL;
698 HKEY subKey = NULL;
699 TYPEATTR* typeAttr = NULL;
700 TYPEKIND kind;
701 ITypeInfo* typeInfo = NULL;
702 ITypeLib* typeLib = NULL;
703 int numTypes;
705 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
707 /* Create the path to the key */
708 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
710 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
712 TRACE("Unsupported syskind %i\n", syskind);
713 result = E_INVALIDARG;
714 goto end;
717 /* get the path to the typelib on disk */
718 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
719 result = E_INVALIDARG;
720 goto end;
723 /* Try and open the key to the type library. */
724 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
725 result = E_INVALIDARG;
726 goto end;
729 /* Try and load the type library */
730 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
731 result = TYPE_E_INVALIDSTATE;
732 goto end;
735 /* remove any types registered with this typelib */
736 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
737 for (i=0; i<numTypes; i++) {
738 /* get the kind of type */
739 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
740 goto enddeleteloop;
743 /* skip non-interfaces, and get type info for the type */
744 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
745 goto enddeleteloop;
747 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
748 goto enddeleteloop;
750 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
751 goto enddeleteloop;
754 /* the path to the type */
755 get_interface_key( &typeAttr->guid, subKeyName );
757 /* Delete its bits */
758 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
759 goto enddeleteloop;
761 RegDeleteKeyW(subKey, ProxyStubClsidW);
762 RegDeleteKeyW(subKey, ProxyStubClsid32W);
763 RegDeleteKeyW(subKey, TypeLibW);
764 RegCloseKey(subKey);
765 subKey = NULL;
766 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
768 enddeleteloop:
769 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
770 typeAttr = NULL;
771 if (typeInfo) ITypeInfo_Release(typeInfo);
772 typeInfo = NULL;
775 /* Now, delete the type library path subkey */
776 get_lcid_subkey( lcid, syskind, subKeyName );
777 RegDeleteKeyW(key, subKeyName);
778 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
779 RegDeleteKeyW(key, subKeyName);
781 /* check if there is anything besides the FLAGS/HELPDIR keys.
782 If there is, we don't delete them */
783 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
784 deleteOtherStuff = TRUE;
785 i = 0;
786 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
787 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
789 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
790 if (!strcmpW(subKeyName, FLAGSW)) continue;
791 if (!strcmpW(subKeyName, HELPDIRW)) continue;
792 deleteOtherStuff = FALSE;
793 break;
796 /* only delete the other parts of the key if we're absolutely sure */
797 if (deleteOtherStuff) {
798 RegDeleteKeyW(key, FLAGSW);
799 RegDeleteKeyW(key, HELPDIRW);
800 RegCloseKey(key);
801 key = NULL;
803 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
804 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
805 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
808 end:
809 if (tlibPath) SysFreeString(tlibPath);
810 if (typeLib) ITypeLib_Release(typeLib);
811 if (subKey) RegCloseKey(subKey);
812 if (key) RegCloseKey(key);
813 return result;
816 /*======================= ITypeLib implementation =======================*/
818 typedef struct tagTLBCustData
820 GUID guid;
821 VARIANT data;
822 struct tagTLBCustData* next;
823 } TLBCustData;
825 /* data structure for import typelibs */
826 typedef struct tagTLBImpLib
828 int offset; /* offset in the file (MSFT)
829 offset in nametable (SLTG)
830 just used to identify library while reading
831 data from file */
832 GUID guid; /* libid */
833 BSTR name; /* name */
835 LCID lcid; /* lcid of imported typelib */
837 WORD wVersionMajor; /* major version number */
838 WORD wVersionMinor; /* minor version number */
840 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
841 NULL if not yet loaded */
842 struct tagTLBImpLib * next;
843 } TLBImpLib;
845 /* internal ITypeLib data */
846 typedef struct tagITypeLibImpl
848 ITypeLib2Vtbl *lpVtbl;
849 ITypeCompVtbl *lpVtblTypeComp;
850 ULONG ref;
851 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
853 /* strings can be stored in tlb as multibyte strings BUT they are *always*
854 * exported to the application as a UNICODE string.
856 BSTR Name;
857 BSTR DocString;
858 BSTR HelpFile;
859 BSTR HelpStringDll;
860 unsigned long dwHelpContext;
861 int TypeInfoCount; /* nr of typeinfo's in librarry */
862 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
863 int ctCustData; /* number of items in cust data list */
864 TLBCustData * pCustData; /* linked list to cust data */
865 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
866 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
867 libary. Only used while read MSFT
868 typelibs */
870 /* typelibs are cached, keyed by path, so store the linked list info within them */
871 struct tagITypeLibImpl *next, *prev;
872 WCHAR *path;
873 } ITypeLibImpl;
875 static struct ITypeLib2Vtbl tlbvt;
876 static struct ITypeCompVtbl tlbtcvt;
878 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
879 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
881 /* ITypeLib methods */
882 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
883 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
885 /*======================= ITypeInfo implementation =======================*/
887 /* data for refernced types */
888 typedef struct tagTLBRefType
890 INT index; /* Type index for internal ref or for external ref
891 it the format is SLTG. -2 indicates to
892 use guid */
894 GUID guid; /* guid of the referenced type */
895 /* if index == TLB_REF_USE_GUID */
897 HREFTYPE reference; /* The href of this ref */
898 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
899 TLB_REF_INTERNAL for internal refs
900 TLB_REF_NOT_FOUND for broken refs */
902 struct tagTLBRefType * next;
903 } TLBRefType;
905 #define TLB_REF_USE_GUID -2
907 #define TLB_REF_INTERNAL (void*)-2
908 #define TLB_REF_NOT_FOUND (void*)-1
910 /* internal Parameter data */
911 typedef struct tagTLBParDesc
913 BSTR Name;
914 int ctCustData;
915 TLBCustData * pCustData; /* linked list to cust data */
916 } TLBParDesc;
918 /* internal Function data */
919 typedef struct tagTLBFuncDesc
921 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
922 BSTR Name; /* the name of this function */
923 TLBParDesc *pParamDesc; /* array with param names and custom data */
924 int helpcontext;
925 int HelpStringContext;
926 BSTR HelpString;
927 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
928 int ctCustData;
929 TLBCustData * pCustData; /* linked list to cust data; */
930 struct tagTLBFuncDesc * next;
931 } TLBFuncDesc;
933 /* internal Variable data */
934 typedef struct tagTLBVarDesc
936 VARDESC vardesc; /* lots of info on the variable and its attributes. */
937 BSTR Name; /* the name of this variable */
938 int HelpContext;
939 int HelpStringContext; /* FIXME: where? */
940 BSTR HelpString;
941 int ctCustData;
942 TLBCustData * pCustData;/* linked list to cust data; */
943 struct tagTLBVarDesc * next;
944 } TLBVarDesc;
946 /* internal implemented interface data */
947 typedef struct tagTLBImplType
949 HREFTYPE hRef; /* hRef of interface */
950 int implflags; /* IMPLFLAG_*s */
951 int ctCustData;
952 TLBCustData * pCustData;/* linked list to custom data; */
953 struct tagTLBImplType *next;
954 } TLBImplType;
956 /* internal TypeInfo data */
957 typedef struct tagITypeInfoImpl
959 ITypeInfo2Vtbl *lpVtbl;
960 ITypeCompVtbl *lpVtblTypeComp;
961 ULONG ref;
962 TYPEATTR TypeAttr ; /* _lots_ of type information. */
963 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
964 int index; /* index in this typelib; */
965 /* type libs seem to store the doc strings in ascii
966 * so why should we do it in unicode?
968 BSTR Name;
969 BSTR DocString;
970 unsigned long dwHelpContext;
971 unsigned long dwHelpStringContext;
973 /* functions */
974 TLBFuncDesc * funclist; /* linked list with function descriptions */
976 /* variables */
977 TLBVarDesc * varlist; /* linked list with variable descriptions */
979 /* Implemented Interfaces */
980 TLBImplType * impltypelist;
982 TLBRefType * reflist;
983 int ctCustData;
984 TLBCustData * pCustData; /* linked list to cust data; */
985 struct tagITypeInfoImpl * next;
986 } ITypeInfoImpl;
988 static struct ITypeInfo2Vtbl tinfvt;
989 static struct ITypeCompVtbl tcompvt;
991 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
993 typedef struct tagTLBContext
995 unsigned int oStart; /* start of TLB in file */
996 unsigned int pos; /* current pos */
997 unsigned int length; /* total length */
998 void *mapping; /* memory mapping */
999 MSFT_SegDir * pTblDir;
1000 ITypeLibImpl* pLibInfo;
1001 } TLBContext;
1004 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1007 debug
1009 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1010 if (pTD->vt & VT_RESERVED)
1011 szVarType += strlen(strcpy(szVarType, "reserved | "));
1012 if (pTD->vt & VT_BYREF)
1013 szVarType += strlen(strcpy(szVarType, "ref to "));
1014 if (pTD->vt & VT_ARRAY)
1015 szVarType += strlen(strcpy(szVarType, "array of "));
1016 if (pTD->vt & VT_VECTOR)
1017 szVarType += strlen(strcpy(szVarType, "vector of "));
1018 switch(pTD->vt & VT_TYPEMASK) {
1019 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1020 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1021 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1022 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1023 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1024 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1025 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1026 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1027 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1028 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1029 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1030 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1031 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1032 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1033 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1034 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1035 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1036 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1037 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1038 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1039 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1040 pTD->u.hreftype); break;
1041 case VT_PTR: sprintf(szVarType, "ptr to ");
1042 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1043 break;
1044 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1045 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1046 break;
1047 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1048 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1049 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1050 break;
1052 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1056 void dump_ELEMDESC(ELEMDESC *edesc) {
1057 char buf[200];
1058 dump_TypeDesc(&edesc->tdesc,buf);
1059 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1060 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1061 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1063 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1064 int i;
1065 MESSAGE("memid is %08lx\n",funcdesc->memid);
1066 for (i=0;i<funcdesc->cParams;i++) {
1067 MESSAGE("Param %d:\n",i);
1068 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1070 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1071 switch (funcdesc->funckind) {
1072 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1073 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1074 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1075 case FUNC_STATIC: MESSAGE("static");break;
1076 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1077 default: MESSAGE("unknown");break;
1079 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1080 switch (funcdesc->invkind) {
1081 case INVOKE_FUNC: MESSAGE("func");break;
1082 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1083 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1084 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1086 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1087 switch (funcdesc->callconv) {
1088 case CC_CDECL: MESSAGE("cdecl");break;
1089 case CC_PASCAL: MESSAGE("pascal");break;
1090 case CC_STDCALL: MESSAGE("stdcall");break;
1091 case CC_SYSCALL: MESSAGE("syscall");break;
1092 default:break;
1094 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1095 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1096 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1098 MESSAGE("\telemdescFunc (return value type):\n");
1099 dump_ELEMDESC(&funcdesc->elemdescFunc);
1102 void dump_IDLDESC(IDLDESC *idl) {
1103 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1106 static const char * typekind_desc[] =
1108 "TKIND_ENUM",
1109 "TKIND_RECORD",
1110 "TKIND_MODULE",
1111 "TKIND_INTERFACE",
1112 "TKIND_DISPATCH",
1113 "TKIND_COCLASS",
1114 "TKIND_ALIAS",
1115 "TKIND_UNION",
1116 "TKIND_MAX"
1119 void dump_TYPEATTR(TYPEATTR *tattr) {
1120 char buf[200];
1121 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1122 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1123 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1124 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1125 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1126 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1127 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1128 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1129 MESSAGE("\tcVars: %d\n", tattr->cVars);
1130 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1131 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1132 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1133 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1134 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1135 dump_TypeDesc(&tattr->tdescAlias,buf);
1136 MESSAGE("\ttypedesc: %s\n", buf);
1137 dump_IDLDESC(&tattr->idldescType);
1140 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1142 int i;
1143 if (!TRACE_ON(typelib))
1144 return;
1145 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1146 for (i=0;i<pfd->funcdesc.cParams;i++)
1147 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1150 dump_FUNCDESC(&(pfd->funcdesc));
1152 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1153 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1155 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1157 while (pfd)
1159 dump_TLBFuncDescOne(pfd);
1160 pfd = pfd->next;
1163 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1165 while (pvd)
1167 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1168 pvd = pvd->next;
1172 static void dump_TLBImpLib(TLBImpLib *import)
1174 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1175 debugstr_w(import->name));
1176 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1177 import->wVersionMinor, import->lcid, import->offset);
1180 static void dump_TLBRefType(TLBRefType * prt)
1182 while (prt)
1184 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1185 if(prt->index == -1)
1186 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1187 else
1188 TRACE_(typelib)("type no: %d\n", prt->index);
1190 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1191 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1192 TRACE_(typelib)("in lib\n");
1193 dump_TLBImpLib(prt->pImpTLInfo);
1195 prt = prt->next;
1199 static void dump_TLBImplType(TLBImplType * impl)
1201 while (impl) {
1202 TRACE_(typelib)(
1203 "implementing/inheriting interface hRef = %lx implflags %x\n",
1204 impl->hRef, impl->implflags);
1205 impl = impl->next;
1209 void dump_Variant(VARIANT * pvar)
1211 SYSTEMTIME st;
1213 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1215 if (pvar)
1217 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1218 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1220 TRACE(",%p", V_BYREF(pvar));
1222 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1224 TRACE(",FIXME");
1226 else switch (V_TYPE(pvar))
1228 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1229 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1230 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1231 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1232 case VT_INT:
1233 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1234 case VT_UINT:
1235 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1236 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1237 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1238 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1239 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1240 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1241 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1242 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1243 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1244 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1245 V_CY(pvar).s.Lo); break;
1246 case VT_DATE:
1247 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1248 TRACE(",<invalid>");
1249 else
1250 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1251 st.wHour, st.wMinute, st.wSecond);
1252 break;
1253 case VT_ERROR:
1254 case VT_VOID:
1255 case VT_USERDEFINED:
1256 case VT_EMPTY:
1257 case VT_NULL: break;
1258 default: TRACE(",?"); break;
1261 TRACE("}\n");
1264 static void dump_DispParms(DISPPARAMS * pdp)
1266 int index = 0;
1268 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1270 while (index < pdp->cArgs)
1272 dump_Variant( &pdp->rgvarg[index] );
1273 ++index;
1277 static void dump_TypeInfo(ITypeInfoImpl * pty)
1279 TRACE("%p ref=%lu\n", pty, pty->ref);
1280 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1281 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1282 TRACE("fct:%u var:%u impl:%u\n",
1283 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1284 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1285 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1286 dump_TLBFuncDesc(pty->funclist);
1287 dump_TLBVarDesc(pty->varlist);
1288 dump_TLBImplType(pty->impltypelist);
1291 void dump_VARDESC(VARDESC *v)
1293 MESSAGE("memid %ld\n",v->memid);
1294 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1295 MESSAGE("oInst %ld\n",v->u.oInst);
1296 dump_ELEMDESC(&(v->elemdescVar));
1297 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1298 MESSAGE("varkind %d\n",v->varkind);
1301 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1303 /* VT_LPWSTR is largest type that */
1304 /* may appear in type description*/
1305 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1306 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1307 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1308 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1309 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1310 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1311 {{0},30},{{0},31}
1314 static void TLB_abort()
1316 DebugBreak();
1318 static void * TLB_Alloc(unsigned size)
1320 void * ret;
1321 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1322 /* FIXME */
1323 ERR("cannot allocate memory\n");
1325 return ret;
1328 static void TLB_Free(void * ptr)
1330 HeapFree(GetProcessHeap(), 0, ptr);
1333 /* deep copy a typedesc */
1334 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1336 out->vt = in->vt;
1337 switch(in->vt) {
1338 case VT_PTR:
1339 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1340 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1341 break;
1342 case VT_USERDEFINED:
1343 out->u.hreftype = in->u.hreftype;
1344 break;
1345 case VT_CARRAY:
1346 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1347 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1348 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1349 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1350 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1351 break;
1352 default:
1353 break;
1357 /* free()s any allocated memory pointed to by the tdesc. NB does not
1358 free the tdesc itself - this is because the tdesc is typically part
1359 of a larger structure */
1360 static void free_deep_typedesc(TYPEDESC *tdesc)
1362 switch(tdesc->vt) {
1363 case VT_PTR:
1364 free_deep_typedesc(tdesc->u.lptdesc);
1365 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1366 tdesc->u.lptdesc = NULL;
1367 break;
1368 case VT_CARRAY:
1369 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1370 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1371 tdesc->u.lpadesc = NULL;
1372 break;
1373 default:
1374 break;
1378 /**********************************************************************
1380 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1382 /* read function */
1383 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1385 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1386 pcx->pos, count, pcx->oStart, pcx->length, where);
1388 if (where != DO_NOT_SEEK)
1390 where += pcx->oStart;
1391 if (where > pcx->length)
1393 /* FIXME */
1394 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1395 TLB_abort();
1397 pcx->pos = where;
1399 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1400 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1401 pcx->pos += count;
1402 return count;
1405 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1406 long where )
1408 DWORD ret;
1410 ret = MSFT_Read(buffer, count, pcx, where);
1411 FromLEDWords(buffer, ret);
1413 return ret;
1416 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1417 long where )
1419 DWORD ret;
1421 ret = MSFT_Read(buffer, count, pcx, where);
1422 FromLEWords(buffer, ret);
1424 return ret;
1427 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1429 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1430 memset(pGuid,0, sizeof(GUID));
1431 return;
1433 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1434 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1435 pGuid->Data2 = FromLEWord(pGuid->Data2);
1436 pGuid->Data3 = FromLEWord(pGuid->Data3);
1437 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1440 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1442 char * name;
1443 MSFT_NameIntro niName;
1444 int lengthInChars;
1445 WCHAR* pwstring = NULL;
1446 BSTR bstrName = NULL;
1448 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1449 pcx->pTblDir->pNametab.offset+offset);
1450 niName.namelen &= 0xFF; /* FIXME: correct ? */
1451 name=TLB_Alloc((niName.namelen & 0xff) +1);
1452 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1453 name[niName.namelen & 0xff]='\0';
1455 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1456 name, -1, NULL, 0);
1458 /* no invalid characters in string */
1459 if (lengthInChars)
1461 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1463 /* don't check for invalid character since this has been done previously */
1464 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1466 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1467 lengthInChars = SysStringLen(bstrName);
1468 HeapFree(GetProcessHeap(), 0, pwstring);
1471 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1472 return bstrName;
1475 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1477 char * string;
1478 INT16 length;
1479 int lengthInChars;
1480 BSTR bstr = NULL;
1482 if(offset<0) return NULL;
1483 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1484 if(length <= 0) return 0;
1485 string=TLB_Alloc(length +1);
1486 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1487 string[length]='\0';
1489 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1490 string, -1, NULL, 0);
1492 /* no invalid characters in string */
1493 if (lengthInChars)
1495 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1497 /* don't check for invalid character since this has been done previously */
1498 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1500 bstr = SysAllocStringLen(pwstring, lengthInChars);
1501 lengthInChars = SysStringLen(bstr);
1502 HeapFree(GetProcessHeap(), 0, pwstring);
1505 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1506 return bstr;
1509 * read a value and fill a VARIANT structure
1511 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1513 int size;
1515 TRACE_(typelib)("\n");
1517 if(offset <0) { /* data are packed in here */
1518 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1519 V_UNION(pVar, iVal) = offset & 0x3ffffff;
1520 return;
1522 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1523 pcx->pTblDir->pCustData.offset + offset );
1524 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1525 switch (V_VT(pVar)){
1526 case VT_EMPTY: /* FIXME: is this right? */
1527 case VT_NULL: /* FIXME: is this right? */
1528 case VT_I2 : /* this should not happen */
1529 case VT_I4 :
1530 case VT_R4 :
1531 case VT_ERROR :
1532 case VT_BOOL :
1533 case VT_I1 :
1534 case VT_UI1 :
1535 case VT_UI2 :
1536 case VT_UI4 :
1537 case VT_INT :
1538 case VT_UINT :
1539 case VT_VOID : /* FIXME: is this right? */
1540 case VT_HRESULT :
1541 size=4; break;
1542 case VT_R8 :
1543 case VT_CY :
1544 case VT_DATE :
1545 case VT_I8 :
1546 case VT_UI8 :
1547 case VT_DECIMAL : /* FIXME: is this right? */
1548 case VT_FILETIME :
1549 size=8;break;
1550 /* pointer types with known behaviour */
1551 case VT_BSTR :{
1552 char * ptr;
1553 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1554 if(size < 0) {
1555 FIXME("BSTR length = %d?\n", size);
1556 } else {
1557 ptr=TLB_Alloc(size);/* allocate temp buffer */
1558 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1559 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1560 /* FIXME: do we need a AtoW conversion here? */
1561 V_UNION(pVar, bstrVal[size])=L'\0';
1562 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1563 TLB_Free(ptr);
1566 size=-4; break;
1567 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1568 case VT_DISPATCH :
1569 case VT_VARIANT :
1570 case VT_UNKNOWN :
1571 case VT_PTR :
1572 case VT_SAFEARRAY :
1573 case VT_CARRAY :
1574 case VT_USERDEFINED :
1575 case VT_LPSTR :
1576 case VT_LPWSTR :
1577 case VT_BLOB :
1578 case VT_STREAM :
1579 case VT_STORAGE :
1580 case VT_STREAMED_OBJECT :
1581 case VT_STORED_OBJECT :
1582 case VT_BLOB_OBJECT :
1583 case VT_CF :
1584 case VT_CLSID :
1585 default:
1586 size=0;
1587 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1588 V_VT(pVar));
1591 if(size>0) /* (big|small) endian correct? */
1592 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1593 return;
1596 * create a linked list with custom data
1598 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1600 MSFT_CDGuid entry;
1601 TLBCustData* pNew;
1602 int count=0;
1604 TRACE_(typelib)("\n");
1606 while(offset >=0){
1607 count++;
1608 pNew=TLB_Alloc(sizeof(TLBCustData));
1609 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1610 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1611 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1612 /* add new custom data at head of the list */
1613 pNew->next=*ppCustData;
1614 *ppCustData=pNew;
1615 offset = entry.next;
1617 return count;
1620 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1621 ITypeInfoImpl *pTI)
1623 if(type <0)
1624 pTd->vt=type & VT_TYPEMASK;
1625 else
1626 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1628 if(pTd->vt == VT_USERDEFINED)
1629 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1631 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1634 static void
1635 MSFT_DoFuncs(TLBContext* pcx,
1636 ITypeInfoImpl* pTI,
1637 int cFuncs,
1638 int cVars,
1639 int offset,
1640 TLBFuncDesc** pptfd)
1643 * member information is stored in a data structure at offset
1644 * indicated by the memoffset field of the typeinfo structure
1645 * There are several distinctive parts.
1646 * the first part starts with a field that holds the total length
1647 * of this (first) part excluding this field. Then follow the records,
1648 * for each member there is one record.
1650 * First entry is always the length of the record (including this
1651 * length word).
1652 * Rest of the record depends on the type of the member. If there is
1653 * a field indicating the member type (function variable intereface etc)
1654 * I have not found it yet. At this time we depend on the information
1655 * in the type info and the usual order how things are stored.
1657 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1658 * for each member;
1660 * Third is a equal sized array with file offsets to the name entry
1661 * of each member.
1663 * Forth and last (?) part is an array with offsets to the records in the
1664 * first part of this file segment.
1667 int infolen, nameoffset, reclength, nrattributes, i;
1668 int recoffset = offset + sizeof(INT);
1670 char recbuf[512];
1671 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1673 TRACE_(typelib)("\n");
1675 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1677 for ( i = 0; i < cFuncs ; i++ )
1679 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1681 /* name, eventually add to a hash table */
1682 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1683 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1685 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1687 /* read the function information record */
1688 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1690 reclength &= 0x1ff;
1692 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1694 /* do the attributes */
1695 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1696 / sizeof(int);
1698 if ( nrattributes > 0 )
1700 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1702 if ( nrattributes > 1 )
1704 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1705 pFuncRec->OptAttr[1]) ;
1707 if ( nrattributes > 2 )
1709 if ( pFuncRec->FKCCIC & 0x2000 )
1711 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1713 else
1715 (*pptfd)->Entry = MSFT_ReadString(pcx,
1716 pFuncRec->OptAttr[2]);
1718 if( nrattributes > 5 )
1720 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1722 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1724 MSFT_CustData(pcx,
1725 pFuncRec->OptAttr[6],
1726 &(*pptfd)->pCustData);
1733 /* fill the FuncDesc Structure */
1734 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1735 offset + infolen + ( i + 1) * sizeof(INT));
1737 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1738 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1739 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1740 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1741 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1742 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1743 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1745 MSFT_GetTdesc(pcx,
1746 pFuncRec->DataType,
1747 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1748 pTI);
1750 /* do the parameters/arguments */
1751 if(pFuncRec->nrargs)
1753 int j = 0;
1754 MSFT_ParameterInfo paraminfo;
1756 (*pptfd)->funcdesc.lprgelemdescParam =
1757 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1759 (*pptfd)->pParamDesc =
1760 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1762 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1763 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1765 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1767 TYPEDESC* lpArgTypeDesc = 0;
1769 MSFT_GetTdesc(pcx,
1770 paraminfo.DataType,
1771 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1772 pTI);
1774 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1776 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1778 /* SEEK value = jump to offset,
1779 * from there jump to the end of record,
1780 * go back by (j-1) arguments
1782 MSFT_ReadLEDWords( &paraminfo ,
1783 sizeof(MSFT_ParameterInfo), pcx,
1784 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1785 * sizeof(MSFT_ParameterInfo)));
1786 lpArgTypeDesc =
1787 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1789 while ( lpArgTypeDesc != NULL )
1791 switch ( lpArgTypeDesc->vt )
1793 case VT_PTR:
1794 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1795 break;
1797 case VT_CARRAY:
1798 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1799 break;
1801 case VT_USERDEFINED:
1802 MSFT_DoRefType(pcx, pTI,
1803 lpArgTypeDesc->u.hreftype);
1805 lpArgTypeDesc = NULL;
1806 break;
1808 default:
1809 lpArgTypeDesc = NULL;
1815 /* parameter is the return value! */
1816 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1818 TYPEDESC* lpArgTypeDesc;
1820 (*pptfd)->funcdesc.elemdescFunc =
1821 (*pptfd)->funcdesc.lprgelemdescParam[j];
1823 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1825 while ( lpArgTypeDesc != NULL )
1827 switch ( lpArgTypeDesc->vt )
1829 case VT_PTR:
1830 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1831 break;
1832 case VT_CARRAY:
1833 lpArgTypeDesc =
1834 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1836 break;
1838 case VT_USERDEFINED:
1839 MSFT_DoRefType(pcx,
1840 pTI,
1841 lpArgTypeDesc->u.hreftype);
1843 lpArgTypeDesc = NULL;
1844 break;
1846 default:
1847 lpArgTypeDesc = NULL;
1852 /* second time around */
1853 for(j=0;j<pFuncRec->nrargs;j++)
1855 /* name */
1856 (*pptfd)->pParamDesc[j].Name =
1857 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1859 /* default value */
1860 if ( (PARAMFLAG_FHASDEFAULT &
1861 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1862 ((pFuncRec->FKCCIC) & 0x1000) )
1864 INT* pInt = (INT *)((char *)pFuncRec +
1865 reclength -
1866 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1868 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1870 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1871 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1873 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1874 pInt[j], pcx);
1876 /* custom info */
1877 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1879 MSFT_CustData(pcx,
1880 pFuncRec->OptAttr[7+j],
1881 &(*pptfd)->pParamDesc[j].pCustData);
1886 /* scode is not used: archaic win16 stuff FIXME: right? */
1887 (*pptfd)->funcdesc.cScodes = 0 ;
1888 (*pptfd)->funcdesc.lprgscode = NULL ;
1890 pptfd = & ((*pptfd)->next);
1891 recoffset += reclength;
1895 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1896 int cVars, int offset, TLBVarDesc ** pptvd)
1898 int infolen, nameoffset, reclength;
1899 char recbuf[256];
1900 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1901 int i;
1902 int recoffset;
1904 TRACE_(typelib)("\n");
1906 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1907 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1908 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1909 recoffset += offset+sizeof(INT);
1910 for(i=0;i<cVars;i++){
1911 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1912 /* name, eventually add to a hash table */
1913 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1914 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1915 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1916 /* read the variable information record */
1917 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1918 reclength &=0xff;
1919 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1920 /* Optional data */
1921 if(reclength >(6*sizeof(INT)) )
1922 (*pptvd)->HelpContext=pVarRec->HelpContext;
1923 if(reclength >(7*sizeof(INT)) )
1924 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1925 if(reclength >(8*sizeof(INT)) )
1926 if(reclength >(9*sizeof(INT)) )
1927 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1928 /* fill the VarDesc Structure */
1929 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1930 offset + infolen + ( i + 1) * sizeof(INT));
1931 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1932 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1933 MSFT_GetTdesc(pcx, pVarRec->DataType,
1934 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1935 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1936 if(pVarRec->VarKind == VAR_CONST ){
1937 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1938 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1939 pVarRec->OffsValue, pcx);
1940 } else
1941 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1942 pptvd=&((*pptvd)->next);
1943 recoffset += reclength;
1946 /* fill in data for a hreftype (offset). When the refernced type is contained
1947 * in the typelib, it's just an (file) offset in the type info base dir.
1948 * If comes from import, it's an offset+1 in the ImpInfo table
1949 * */
1950 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1951 int offset)
1953 int j;
1954 TLBRefType **ppRefType = &pTI->reflist;
1956 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1958 while(*ppRefType) {
1959 if((*ppRefType)->reference == offset)
1960 return;
1961 ppRefType = &(*ppRefType)->next;
1964 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1965 sizeof(**ppRefType));
1967 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1968 /* external typelib */
1969 MSFT_ImpInfo impinfo;
1970 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1972 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1974 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1975 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1976 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1977 if(pImpLib->offset==impinfo.oImpFile) break;
1978 pImpLib=pImpLib->next;
1980 if(pImpLib){
1981 (*ppRefType)->reference=offset;
1982 (*ppRefType)->pImpTLInfo = pImpLib;
1983 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1984 (*ppRefType)->index = TLB_REF_USE_GUID;
1985 }else{
1986 ERR("Cannot find a reference\n");
1987 (*ppRefType)->reference=-1;
1988 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1990 }else{
1991 /* in this typelib */
1992 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1993 (*ppRefType)->reference=offset;
1994 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1998 /* process Implemented Interfaces of a com class */
1999 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2000 int offset)
2002 int i;
2003 MSFT_RefRecord refrec;
2004 TLBImplType **ppImpl = &pTI->impltypelist;
2006 TRACE_(typelib)("\n");
2008 for(i=0;i<count;i++){
2009 if(offset<0) break; /* paranoia */
2010 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2011 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2012 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2013 (*ppImpl)->hRef = refrec.reftype;
2014 (*ppImpl)->implflags=refrec.flags;
2015 (*ppImpl)->ctCustData=
2016 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2017 offset=refrec.onext;
2018 ppImpl=&((*ppImpl)->next);
2022 * process a typeinfo record
2024 ITypeInfoImpl * MSFT_DoTypeInfo(
2025 TLBContext *pcx,
2026 int count,
2027 ITypeLibImpl * pLibInfo)
2029 MSFT_TypeInfoBase tiBase;
2030 ITypeInfoImpl *ptiRet;
2032 TRACE_(typelib)("count=%u\n", count);
2034 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2035 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2036 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2037 /* this is where we are coming from */
2038 ptiRet->pTypeLib = pLibInfo;
2039 ptiRet->index=count;
2040 /* fill in the typeattr fields */
2041 WARN("Assign constructor/destructor memid\n");
2043 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2044 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2045 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2046 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2047 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2048 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2049 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2050 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2051 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2052 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2053 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2054 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2055 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2056 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2057 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2058 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2059 MSFT_GetTdesc(pcx, tiBase.datatype1,
2060 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2062 /* FIXME: */
2063 /* IDLDESC idldescType; *//* never saw this one != zero */
2065 /* name, eventually add to a hash table */
2066 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2067 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2068 /* help info */
2069 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2070 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2071 ptiRet->dwHelpContext=tiBase.helpcontext;
2072 /* note: InfoType's Help file and HelpStringDll come from the containing
2073 * library. Further HelpString and Docstring appear to be the same thing :(
2075 /* functions */
2076 if(ptiRet->TypeAttr.cFuncs >0 )
2077 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2078 ptiRet->TypeAttr.cVars,
2079 tiBase.memoffset, & ptiRet->funclist);
2080 /* variables */
2081 if(ptiRet->TypeAttr.cVars >0 )
2082 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2083 ptiRet->TypeAttr.cVars,
2084 tiBase.memoffset, & ptiRet->varlist);
2085 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2086 switch(ptiRet->TypeAttr.typekind)
2088 case TKIND_COCLASS:
2089 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2090 tiBase.datatype1);
2091 break;
2092 case TKIND_DISPATCH:
2093 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2095 if (tiBase.datatype1 != -1)
2097 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2098 ptiRet->impltypelist->hRef = tiBase.datatype1;
2100 else
2101 { /* FIXME: This is a really bad hack to add IDispatch */
2102 const char* szStdOle = "stdole2.tlb\0";
2103 int nStdOleLen = strlen(szStdOle);
2104 TLBRefType **ppRef = &ptiRet->reflist;
2106 while(*ppRef) {
2107 if((*ppRef)->reference == -1)
2108 break;
2109 ppRef = &(*ppRef)->next;
2111 if(!*ppRef) {
2112 *ppRef = TLB_Alloc(sizeof(**ppRef));
2113 (*ppRef)->guid = IID_IDispatch;
2114 (*ppRef)->reference = -1;
2115 (*ppRef)->index = TLB_REF_USE_GUID;
2116 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2117 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2118 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2119 nStdOleLen + 1);
2121 MultiByteToWideChar(CP_ACP,
2122 MB_PRECOMPOSED,
2123 szStdOle,
2125 (*ppRef)->pImpTLInfo->name,
2126 SysStringLen((*ppRef)->pImpTLInfo->name));
2128 (*ppRef)->pImpTLInfo->lcid = 0;
2129 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2130 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2133 break;
2134 default:
2135 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2136 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2137 ptiRet->impltypelist->hRef = tiBase.datatype1;
2138 break;
2141 ptiRet->ctCustData=
2142 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2144 TRACE_(typelib)("%s guid: %s kind:%s\n",
2145 debugstr_w(ptiRet->Name),
2146 debugstr_guid(&ptiRet->TypeAttr.guid),
2147 typekind_desc[ptiRet->TypeAttr.typekind]);
2149 return ptiRet;
2152 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2153 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2154 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2155 * tradeoff here.
2157 static ITypeLibImpl *tlb_cache_first;
2158 static CRITICAL_SECTION cache_section;
2159 static CRITICAL_SECTION_DEBUG cache_section_debug =
2161 0, 0, &cache_section,
2162 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2163 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2165 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2168 /****************************************************************************
2169 * TLB_ReadTypeLib
2171 * find the type of the typelib file and map the typelib resource into
2172 * the memory
2174 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2175 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2176 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2178 ITypeLibImpl *entry;
2179 int ret = TYPE_E_CANTLOADLIBRARY;
2180 DWORD dwSignature = 0;
2181 HANDLE hFile;
2183 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2185 *ppTypeLib = NULL;
2187 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2188 EnterCriticalSection(&cache_section);
2189 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2191 if (!strcmpiW(entry->path, pszFileName))
2193 TRACE("cache hit\n");
2194 *ppTypeLib = (ITypeLib2*)entry;
2195 ITypeLib_AddRef(*ppTypeLib);
2196 LeaveCriticalSection(&cache_section);
2197 return S_OK;
2200 LeaveCriticalSection(&cache_section);
2202 /* check the signature of the file */
2203 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2204 if (INVALID_HANDLE_VALUE != hFile)
2206 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2207 if (hMapping)
2209 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2210 if(pBase)
2212 /* retrieve file size */
2213 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2215 /* first try to load as *.tlb */
2216 dwSignature = FromLEDWord(*((DWORD*) pBase));
2217 if ( dwSignature == MSFT_SIGNATURE)
2219 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2221 else if ( dwSignature == SLTG_SIGNATURE)
2223 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2225 UnmapViewOfFile(pBase);
2227 CloseHandle(hMapping);
2229 CloseHandle(hFile);
2232 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2234 /* find the typelibrary resource*/
2235 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2236 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2237 if (hinstDLL)
2239 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2240 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2241 if (hrsrc)
2243 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2244 if (hGlobal)
2246 LPVOID pBase = LockResource(hGlobal);
2247 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2249 if (pBase)
2251 /* try to load as incore resource */
2252 dwSignature = FromLEDWord(*((DWORD*) pBase));
2253 if ( dwSignature == MSFT_SIGNATURE)
2255 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2257 else if ( dwSignature == SLTG_SIGNATURE)
2259 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2261 else
2263 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2266 FreeResource( hGlobal );
2269 FreeLibrary(hinstDLL);
2273 if(*ppTypeLib) {
2274 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2276 TRACE("adding to cache\n");
2277 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2278 lstrcpyW(impl->path, pszFileName);
2279 /* We should really canonicalise the path here. */
2281 /* FIXME: check if it has added already in the meantime */
2282 EnterCriticalSection(&cache_section);
2283 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2284 impl->prev = NULL;
2285 tlb_cache_first = impl;
2286 LeaveCriticalSection(&cache_section);
2287 ret = S_OK;
2288 } else
2289 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2291 return ret;
2294 /*================== ITypeLib(2) Methods ===================================*/
2296 /****************************************************************************
2297 * ITypeLib2_Constructor_MSFT
2299 * loading an MSFT typelib from an in-memory image
2301 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2303 TLBContext cx;
2304 long lPSegDir;
2305 MSFT_Header tlbHeader;
2306 MSFT_SegDir tlbSegDir;
2307 ITypeLibImpl * pTypeLibImpl;
2309 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2311 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2312 if (!pTypeLibImpl) return NULL;
2314 pTypeLibImpl->lpVtbl = &tlbvt;
2315 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2316 pTypeLibImpl->ref = 1;
2318 /* get pointer to beginning of typelib data */
2319 cx.pos = 0;
2320 cx.oStart=0;
2321 cx.mapping = pLib;
2322 cx.pLibInfo = pTypeLibImpl;
2323 cx.length = dwTLBLength;
2325 /* read header */
2326 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2327 TRACE("header:\n");
2328 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2329 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2330 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2331 return NULL;
2333 /* there is a small amount of information here until the next important
2334 * part:
2335 * the segment directory . Try to calculate the amount of data */
2336 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2338 /* now read the segment directory */
2339 TRACE("read segment directory (at %ld)\n",lPSegDir);
2340 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2341 cx.pTblDir = &tlbSegDir;
2343 /* just check two entries */
2344 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2346 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2347 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2348 return NULL;
2351 /* now fill our internal data */
2352 /* TLIBATTR fields */
2353 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2355 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2356 /* Windows seems to have zero here, is this correct? */
2357 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2358 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2359 else
2360 pTypeLibImpl->LibAttr.lcid = 0;
2362 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2363 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2364 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2365 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2367 /* name, eventually add to a hash table */
2368 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2370 /* help info */
2371 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2372 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2374 if( tlbHeader.varflags & HELPDLLFLAG)
2376 int offset;
2377 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2378 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2381 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2383 /* custom data */
2384 if(tlbHeader.CustomDataOffset >= 0)
2386 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2389 /* fill in typedescriptions */
2390 if(tlbSegDir.pTypdescTab.length > 0)
2392 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2393 INT16 td[4];
2394 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2395 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2396 for(i=0; i<cTD; )
2398 /* FIXME: add several sanity checks here */
2399 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2400 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2402 /* FIXME: check safearray */
2403 if(td[3] < 0)
2404 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2405 else
2406 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2408 else if(td[0] == VT_CARRAY)
2410 /* array descr table here */
2411 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2413 else if(td[0] == VT_USERDEFINED)
2415 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2417 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2420 /* second time around to fill the array subscript info */
2421 for(i=0;i<cTD;i++)
2423 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2424 if(tlbSegDir.pArrayDescriptions.offset>0)
2426 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2427 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2429 if(td[1]<0)
2430 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2431 else
2432 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2434 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2436 for(j = 0; j<td[2]; j++)
2438 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2439 sizeof(INT), &cx, DO_NOT_SEEK);
2440 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2441 sizeof(INT), &cx, DO_NOT_SEEK);
2444 else
2446 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2447 ERR("didn't find array description data\n");
2452 /* imported type libs */
2453 if(tlbSegDir.pImpFiles.offset>0)
2455 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2456 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2457 UINT16 size;
2459 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2461 char *name;
2462 DWORD len;
2464 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2465 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2466 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2468 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2469 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2470 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2471 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2473 size >>= 2;
2474 name = TLB_Alloc(size+1);
2475 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2476 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2477 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2478 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2479 TLB_Free(name);
2481 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2482 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2484 ppImpLib = &(*ppImpLib)->next;
2488 /* type info's */
2489 if(tlbHeader.nrtypeinfos >= 0 )
2491 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2492 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2493 int i;
2495 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2497 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2499 ppTI = &((*ppTI)->next);
2500 (pTypeLibImpl->TypeInfoCount)++;
2504 TRACE("(%p)\n", pTypeLibImpl);
2505 return (ITypeLib2*) pTypeLibImpl;
2509 static BSTR TLB_MultiByteToBSTR(char *ptr)
2511 DWORD len;
2512 WCHAR *nameW;
2513 BSTR ret;
2515 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2516 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2517 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2518 ret = SysAllocString(nameW);
2519 HeapFree(GetProcessHeap(), 0, nameW);
2520 return ret;
2523 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2525 char b[3];
2526 int i;
2527 short s;
2529 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2530 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2531 return FALSE;
2534 guid->Data4[0] = s >> 8;
2535 guid->Data4[1] = s & 0xff;
2537 b[2] = '\0';
2538 for(i = 0; i < 6; i++) {
2539 memcpy(b, str + 24 + 2 * i, 2);
2540 guid->Data4[i + 2] = strtol(b, NULL, 16);
2542 return TRUE;
2545 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2547 WORD bytelen;
2548 DWORD len;
2549 WCHAR *nameW;
2551 *pBstr = NULL;
2552 bytelen = *(WORD*)ptr;
2553 if(bytelen == 0xffff) return 2;
2554 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2555 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2556 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2557 *pBstr = SysAllocStringLen(nameW, len);
2558 HeapFree(GetProcessHeap(), 0, nameW);
2559 return bytelen + 2;
2562 static WORD SLTG_ReadStringA(char *ptr, char **str)
2564 WORD bytelen;
2566 *str = NULL;
2567 bytelen = *(WORD*)ptr;
2568 if(bytelen == 0xffff) return 2;
2569 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2570 memcpy(*str, ptr + 2, bytelen);
2571 (*str)[bytelen] = '\0';
2572 return bytelen + 2;
2575 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2577 char *ptr = pLibBlk;
2578 WORD w;
2580 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2581 FIXME("libblk magic = %04x\n", w);
2582 return 0;
2585 ptr += 6;
2586 if((w = *(WORD*)ptr) != 0xffff) {
2587 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2588 ptr += w;
2590 ptr += 2;
2592 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2594 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2596 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2597 ptr += 4;
2599 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2600 ptr += 2;
2602 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2603 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2604 else
2605 pTypeLibImpl->LibAttr.lcid = 0;
2606 ptr += 2;
2608 ptr += 4; /* skip res12 */
2610 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2611 ptr += 2;
2613 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2614 ptr += 2;
2616 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2617 ptr += 2;
2619 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2620 ptr += sizeof(GUID);
2622 return ptr - (char*)pLibBlk;
2625 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2627 BOOL done = FALSE;
2628 TYPEDESC *pTD = &pElem->tdesc;
2630 /* Handle [in/out] first */
2631 if((*pType & 0xc000) == 0xc000)
2632 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2633 else if(*pType & 0x8000)
2634 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2635 else if(*pType & 0x4000)
2636 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2637 else
2638 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2640 if(*pType & 0x2000)
2641 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2643 if(*pType & 0x80)
2644 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2646 while(!done) {
2647 if((*pType & 0xe00) == 0xe00) {
2648 pTD->vt = VT_PTR;
2649 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2650 sizeof(TYPEDESC));
2651 pTD = pTD->u.lptdesc;
2653 switch(*pType & 0x7f) {
2654 case VT_PTR:
2655 pTD->vt = VT_PTR;
2656 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2657 sizeof(TYPEDESC));
2658 pTD = pTD->u.lptdesc;
2659 break;
2661 case VT_USERDEFINED:
2662 pTD->vt = VT_USERDEFINED;
2663 pTD->u.hreftype = *(++pType) / 4;
2664 done = TRUE;
2665 break;
2667 case VT_CARRAY:
2669 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2670 array */
2672 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2674 pTD->vt = VT_CARRAY;
2675 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2676 sizeof(ARRAYDESC) +
2677 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2678 pTD->u.lpadesc->cDims = pSA->cDims;
2679 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2680 pSA->cDims * sizeof(SAFEARRAYBOUND));
2682 pTD = &pTD->u.lpadesc->tdescElem;
2683 break;
2686 case VT_SAFEARRAY:
2688 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2689 useful? */
2691 pType++;
2692 pTD->vt = VT_SAFEARRAY;
2693 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2694 sizeof(TYPEDESC));
2695 pTD = pTD->u.lptdesc;
2696 break;
2698 default:
2699 pTD->vt = *pType & 0x7f;
2700 done = TRUE;
2701 break;
2703 pType++;
2705 return pType;
2709 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2710 char *pNameTable)
2712 int ref;
2713 char *name;
2714 TLBRefType **ppRefType;
2716 if(pRef->magic != SLTG_REF_MAGIC) {
2717 FIXME("Ref magic = %x\n", pRef->magic);
2718 return;
2720 name = ( (char*)(&pRef->names) + pRef->number);
2722 ppRefType = &pTI->reflist;
2723 for(ref = 0; ref < pRef->number >> 3; ref++) {
2724 char *refname;
2725 unsigned int lib_offs, type_num;
2727 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2728 sizeof(**ppRefType));
2730 name += SLTG_ReadStringA(name, &refname);
2731 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2732 FIXME("Can't sscanf ref\n");
2733 if(lib_offs != 0xffff) {
2734 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2736 while(*import) {
2737 if((*import)->offset == lib_offs)
2738 break;
2739 import = &(*import)->next;
2741 if(!*import) {
2742 char fname[MAX_PATH+1];
2743 int len;
2745 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2746 sizeof(**import));
2747 (*import)->offset = lib_offs;
2748 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2749 &(*import)->guid);
2750 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2751 &(*import)->wVersionMajor,
2752 &(*import)->wVersionMinor,
2753 &(*import)->lcid, fname) != 4) {
2754 FIXME("can't sscanf ref %s\n",
2755 pNameTable + lib_offs + 40);
2757 len = strlen(fname);
2758 if(fname[len-1] != '#')
2759 FIXME("fname = %s\n", fname);
2760 fname[len-1] = '\0';
2761 (*import)->name = TLB_MultiByteToBSTR(fname);
2763 (*ppRefType)->pImpTLInfo = *import;
2764 } else { /* internal ref */
2765 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2767 (*ppRefType)->reference = ref;
2768 (*ppRefType)->index = type_num;
2770 HeapFree(GetProcessHeap(), 0, refname);
2771 ppRefType = &(*ppRefType)->next;
2773 if((BYTE)*name != SLTG_REF_MAGIC)
2774 FIXME("End of ref block magic = %x\n", *name);
2775 dump_TLBRefType(pTI->reflist);
2778 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2779 BOOL OneOnly)
2781 SLTG_ImplInfo *info;
2782 TLBImplType **ppImplType = &pTI->impltypelist;
2783 /* I don't really get this structure, usually it's 0x16 bytes
2784 long, but iuser.tlb contains some that are 0x18 bytes long.
2785 That's ok because we can use the next ptr to jump to the next
2786 one. But how do we know the length of the last one? The WORD
2787 at offs 0x8 might be the clue. For now I'm just assuming that
2788 the last one is the regular 0x16 bytes. */
2790 info = (SLTG_ImplInfo*)pBlk;
2791 while(1) {
2792 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2793 sizeof(**ppImplType));
2794 (*ppImplType)->hRef = info->ref;
2795 (*ppImplType)->implflags = info->impltypeflags;
2796 pTI->TypeAttr.cImplTypes++;
2797 ppImplType = &(*ppImplType)->next;
2799 if(info->next == 0xffff)
2800 break;
2801 if(OneOnly)
2802 FIXME("Interface inheriting more than one interface\n");
2803 info = (SLTG_ImplInfo*)(pBlk + info->next);
2805 info++; /* see comment at top of function */
2806 return (char*)info;
2809 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2810 char *pNameTable)
2812 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2813 SLTG_MemberHeader *pMemHeader;
2814 char *pFirstItem, *pNextItem;
2816 if(pTIHeader->href_table != 0xffffffff) {
2817 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2818 pNameTable);
2822 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2824 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2826 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2827 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2830 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2834 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2835 char *pNameTable)
2837 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2838 SLTG_MemberHeader *pMemHeader;
2839 SLTG_Function *pFunc;
2840 char *pFirstItem, *pNextItem;
2841 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2842 int num = 0;
2844 if(pTIHeader->href_table != 0xffffffff) {
2845 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2846 pNameTable);
2849 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2851 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2853 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2854 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2857 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2858 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2860 int param;
2861 WORD *pType, *pArg;
2863 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2864 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2865 FIXME("func magic = %02x\n", pFunc->magic);
2866 return NULL;
2868 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2869 sizeof(**ppFuncDesc));
2870 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2872 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2873 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2874 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2875 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2876 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2877 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2879 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2880 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2882 if(pFunc->retnextopt & 0x80)
2883 pType = &pFunc->rettype;
2884 else
2885 pType = (WORD*)(pFirstItem + pFunc->rettype);
2888 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2890 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2891 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2892 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2893 (*ppFuncDesc)->pParamDesc =
2894 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2895 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2897 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2899 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2900 char *paramName = pNameTable + *pArg;
2901 BOOL HaveOffs;
2902 /* If arg type follows then paramName points to the 2nd
2903 letter of the name, else the next WORD is an offset to
2904 the arg type and paramName points to the first letter.
2905 So let's take one char off paramName and see if we're
2906 pointing at an alpha-numeric char. However if *pArg is
2907 0xffff or 0xfffe then the param has no name, the former
2908 meaning that the next WORD is the type, the latter
2909 meaning the the next WORD is an offset to the type. */
2911 HaveOffs = FALSE;
2912 if(*pArg == 0xffff)
2913 paramName = NULL;
2914 else if(*pArg == 0xfffe) {
2915 paramName = NULL;
2916 HaveOffs = TRUE;
2918 else if(!isalnum(*(paramName-1)))
2919 HaveOffs = TRUE;
2921 pArg++;
2923 if(HaveOffs) { /* the next word is an offset to type */
2924 pType = (WORD*)(pFirstItem + *pArg);
2925 SLTG_DoType(pType, pFirstItem,
2926 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2927 pArg++;
2928 } else {
2929 if(paramName)
2930 paramName--;
2931 pArg = SLTG_DoType(pArg, pFirstItem,
2932 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2935 /* Are we an optional param ? */
2936 if((*ppFuncDesc)->funcdesc.cParams - param <=
2937 (*ppFuncDesc)->funcdesc.cParamsOpt)
2938 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2940 if(paramName) {
2941 (*ppFuncDesc)->pParamDesc[param].Name =
2942 TLB_MultiByteToBSTR(paramName);
2946 ppFuncDesc = &((*ppFuncDesc)->next);
2947 if(pFunc->next == 0xffff) break;
2949 pTI->TypeAttr.cFuncs = num;
2950 dump_TLBFuncDesc(pTI->funclist);
2951 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2954 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2955 char *pNameTable)
2957 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2958 SLTG_MemberHeader *pMemHeader;
2959 SLTG_RecordItem *pItem;
2960 char *pFirstItem;
2961 TLBVarDesc **ppVarDesc = &pTI->varlist;
2962 int num = 0;
2963 WORD *pType;
2964 char buf[300];
2966 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2968 pFirstItem = (char*)(pMemHeader + 1);
2969 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2970 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2971 if(pItem->magic != SLTG_RECORD_MAGIC) {
2972 FIXME("record magic = %02x\n", pItem->magic);
2973 return NULL;
2975 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2976 sizeof(**ppVarDesc));
2977 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2978 (*ppVarDesc)->vardesc.memid = pItem->memid;
2979 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2980 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2982 if(pItem->typepos == 0x02)
2983 pType = &pItem->type;
2984 else if(pItem->typepos == 0x00)
2985 pType = (WORD*)(pFirstItem + pItem->type);
2986 else {
2987 FIXME("typepos = %02x\n", pItem->typepos);
2988 break;
2991 SLTG_DoType(pType, pFirstItem,
2992 &(*ppVarDesc)->vardesc.elemdescVar);
2994 /* FIXME("helpcontext, helpstring\n"); */
2996 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2998 ppVarDesc = &((*ppVarDesc)->next);
2999 if(pItem->next == 0xffff) break;
3001 pTI->TypeAttr.cVars = num;
3002 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3005 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3006 char *pNameTable)
3008 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3009 SLTG_MemberHeader *pMemHeader;
3010 SLTG_AliasItem *pItem;
3011 int i, mustbelast;
3013 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3014 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3016 mustbelast = 0;
3017 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3018 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3019 if (pItem->vt == 0xffff) {
3020 if (i<(pMemHeader->cbExtra/4-1))
3021 FIXME("Endmarker too early in process alias data!\n");
3022 break;
3024 if (mustbelast) {
3025 FIXME("Chain extends over last entry?\n");
3026 break;
3028 if (pItem->vt == VT_USERDEFINED) {
3029 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3030 /* guessing here ... */
3031 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3032 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3033 mustbelast = 1;
3034 } else {
3035 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3036 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3038 pItem++;
3040 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3043 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3044 char *pNameTable)
3046 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3047 SLTG_MemberHeader *pMemHeader;
3048 SLTG_AliasItem *pItem;
3050 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3051 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3052 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3053 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3054 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3057 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3058 char *pNameTable)
3060 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3061 SLTG_MemberHeader *pMemHeader;
3062 SLTG_EnumItem *pItem;
3063 char *pFirstItem;
3064 TLBVarDesc **ppVarDesc = &pTI->varlist;
3065 int num = 0;
3067 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3069 pFirstItem = (char*)(pMemHeader + 1);
3070 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3071 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3072 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3073 FIXME("enumitem magic = %04x\n", pItem->magic);
3074 return NULL;
3076 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3077 sizeof(**ppVarDesc));
3078 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3079 (*ppVarDesc)->vardesc.memid = pItem->memid;
3080 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3081 sizeof(VARIANT));
3082 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3083 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3084 *(INT*)(pItem->value + pFirstItem);
3085 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3086 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3087 /* FIXME("helpcontext, helpstring\n"); */
3089 ppVarDesc = &((*ppVarDesc)->next);
3090 if(pItem->next == 0xffff) break;
3092 pTI->TypeAttr.cVars = num;
3093 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3096 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3097 managable copy of it into this */
3098 typedef struct {
3099 WORD small_no;
3100 char *index_name;
3101 char *other_name;
3102 WORD res1a;
3103 WORD name_offs;
3104 WORD more_bytes;
3105 char *extra;
3106 WORD res20;
3107 DWORD helpcontext;
3108 WORD res26;
3109 GUID uuid;
3110 } SLTG_InternalOtherTypeInfo;
3112 /****************************************************************************
3113 * ITypeLib2_Constructor_SLTG
3115 * loading a SLTG typelib from an in-memory image
3117 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3119 ITypeLibImpl *pTypeLibImpl;
3120 SLTG_Header *pHeader;
3121 SLTG_BlkEntry *pBlkEntry;
3122 SLTG_Magic *pMagic;
3123 SLTG_Index *pIndex;
3124 SLTG_Pad9 *pPad9;
3125 LPVOID pBlk, pFirstBlk;
3126 SLTG_LibBlk *pLibBlk;
3127 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3128 char *pAfterOTIBlks = NULL;
3129 char *pNameTable, *ptr;
3130 int i;
3131 DWORD len, order;
3132 ITypeInfoImpl **ppTypeInfoImpl;
3134 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3136 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3137 if (!pTypeLibImpl) return NULL;
3139 pTypeLibImpl->lpVtbl = &tlbvt;
3140 pTypeLibImpl->ref = 1;
3142 pHeader = pLib;
3144 TRACE("header:\n");
3145 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3146 pHeader->nrOfFileBlks );
3147 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3148 FIXME("Header type magic 0x%08lx not supported.\n",
3149 pHeader->SLTG_magic);
3150 return NULL;
3153 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3154 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3156 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3157 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3159 /* Next we have a magic block */
3160 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3162 /* Let's see if we're still in sync */
3163 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3164 sizeof(SLTG_COMPOBJ_MAGIC))) {
3165 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3166 return NULL;
3168 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3169 sizeof(SLTG_DIR_MAGIC))) {
3170 FIXME("dir magic = %s\n", pMagic->dir_magic);
3171 return NULL;
3174 pIndex = (SLTG_Index*)(pMagic+1);
3176 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3178 pFirstBlk = (LPVOID)(pPad9 + 1);
3180 /* We'll set up a ptr to the main library block, which is the last one. */
3182 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3183 pBlkEntry[order].next != 0;
3184 order = pBlkEntry[order].next - 1, i++) {
3185 pBlk = (char*)pBlk + pBlkEntry[order].len;
3187 pLibBlk = pBlk;
3189 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3191 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3192 interspersed */
3194 len += 0x40;
3196 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3198 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3199 sizeof(*pOtherTypeInfoBlks) *
3200 pTypeLibImpl->TypeInfoCount);
3203 ptr = (char*)pLibBlk + len;
3205 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3206 WORD w, extra;
3207 len = 0;
3209 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3211 w = *(WORD*)(ptr + 2);
3212 if(w != 0xffff) {
3213 len += w;
3214 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3215 w+1);
3216 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3217 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3219 w = *(WORD*)(ptr + 4 + len);
3220 if(w != 0xffff) {
3221 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3222 len += w;
3223 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3224 w+1);
3225 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3226 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3228 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3229 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3230 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3231 if(extra) {
3232 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3233 extra);
3234 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3235 len += extra;
3237 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3238 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3239 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3240 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3241 len += sizeof(SLTG_OtherTypeInfo);
3242 ptr += len;
3245 pAfterOTIBlks = ptr;
3247 /* Skip this WORD and get the next DWORD */
3248 len = *(DWORD*)(pAfterOTIBlks + 2);
3250 /* Now add this to pLibBLk look at what we're pointing at and
3251 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3252 dust and we should be pointing at the beginning of the name
3253 table */
3255 pNameTable = (char*)pLibBlk + len;
3257 switch(*(WORD*)pNameTable) {
3258 case 0xffff:
3259 break;
3260 case 0x0200:
3261 pNameTable += 0x20;
3262 break;
3263 default:
3264 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3265 break;
3268 pNameTable += 0x216;
3270 pNameTable += 2;
3272 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3274 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3277 /* Hopefully we now have enough ptrs set up to actually read in
3278 some TypeInfos. It's not clear which order to do them in, so
3279 I'll just follow the links along the BlkEntry chain and read
3280 them in in the order in which they're in the file */
3282 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3284 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3285 pBlkEntry[order].next != 0;
3286 order = pBlkEntry[order].next - 1, i++) {
3288 SLTG_TypeInfoHeader *pTIHeader;
3289 SLTG_TypeInfoTail *pTITail;
3291 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3292 pOtherTypeInfoBlks[i].index_name)) {
3293 FIXME("Index strings don't match\n");
3294 return NULL;
3297 pTIHeader = pBlk;
3298 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3299 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3300 return NULL;
3302 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3303 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3304 (*ppTypeInfoImpl)->index = i;
3305 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3306 pOtherTypeInfoBlks[i].name_offs +
3307 pNameTable);
3308 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3309 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3310 sizeof(GUID));
3311 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3312 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3313 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3314 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3315 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3317 if((pTIHeader->typeflags1 & 7) != 2)
3318 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3319 if(pTIHeader->typeflags3 != 2)
3320 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3322 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3323 debugstr_w((*ppTypeInfoImpl)->Name),
3324 typekind_desc[pTIHeader->typekind],
3325 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3326 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3328 switch(pTIHeader->typekind) {
3329 case TKIND_ENUM:
3330 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3331 break;
3333 case TKIND_RECORD:
3334 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3335 break;
3337 case TKIND_INTERFACE:
3338 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3339 break;
3341 case TKIND_COCLASS:
3342 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3343 break;
3345 case TKIND_ALIAS:
3346 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3347 if (pTITail->tdescalias_vt)
3348 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3349 break;
3351 case TKIND_DISPATCH:
3352 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3353 break;
3355 default:
3356 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3357 pTITail = NULL;
3358 break;
3362 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3363 but we've already set those */
3364 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3365 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3366 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3368 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3369 X(06);
3370 X(08);
3371 X(0a);
3372 X(0c);
3373 X(0e);
3374 X(10);
3375 X(12);
3376 X(16);
3377 X(18);
3378 X(1a);
3379 X(1c);
3380 X(1e);
3381 X(24);
3382 X(26);
3383 X(2a);
3384 X(2c);
3385 X(2e);
3386 X(30);
3387 X(32);
3388 X(34);
3390 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3391 pBlk = (char*)pBlk + pBlkEntry[order].len;
3394 if(i != pTypeLibImpl->TypeInfoCount) {
3395 FIXME("Somehow processed %d TypeInfos\n", i);
3396 return NULL;
3399 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3400 return (ITypeLib2*)pTypeLibImpl;
3403 /* ITypeLib::QueryInterface
3405 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3406 ITypeLib2 * iface,
3407 REFIID riid,
3408 VOID **ppvObject)
3410 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3412 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3414 *ppvObject=NULL;
3415 if(IsEqualIID(riid, &IID_IUnknown) ||
3416 IsEqualIID(riid,&IID_ITypeLib)||
3417 IsEqualIID(riid,&IID_ITypeLib2))
3419 *ppvObject = This;
3422 if(*ppvObject)
3424 ITypeLib2_AddRef(iface);
3425 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3426 return S_OK;
3428 TRACE("-- Interface: E_NOINTERFACE\n");
3429 return E_NOINTERFACE;
3432 /* ITypeLib::AddRef
3434 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3436 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3437 ULONG ref = InterlockedIncrement(&This->ref);
3439 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3441 return ref;
3444 /* ITypeLib::Release
3446 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3448 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3449 ULONG ref = InterlockedDecrement(&This->ref);
3451 TRACE("(%p)->(%lu)\n",This, ref);
3453 if (!ref)
3455 /* remove cache entry */
3456 TRACE("removing from cache list\n");
3457 EnterCriticalSection(&cache_section);
3458 if (This->next) This->next->prev = This->prev;
3459 if (This->prev) This->prev->next = This->next;
3460 else tlb_cache_first = This->next;
3461 LeaveCriticalSection(&cache_section);
3463 /* FIXME destroy child objects */
3464 TRACE(" destroying ITypeLib(%p)\n",This);
3466 if (This->Name)
3468 SysFreeString(This->Name);
3469 This->Name = NULL;
3472 if (This->DocString)
3474 SysFreeString(This->DocString);
3475 This->DocString = NULL;
3478 if (This->HelpFile)
3480 SysFreeString(This->HelpFile);
3481 This->HelpFile = NULL;
3484 if (This->HelpStringDll)
3486 SysFreeString(This->HelpStringDll);
3487 This->HelpStringDll = NULL;
3490 if (This->pTypeInfo) /* can be NULL */
3491 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3492 HeapFree(GetProcessHeap(),0,This);
3493 return 0;
3496 return ref;
3499 /* ITypeLib::GetTypeInfoCount
3501 * Returns the number of type descriptions in the type library
3503 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3505 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3506 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3507 return This->TypeInfoCount;
3510 /* ITypeLib::GetTypeInfo
3512 * retrieves the specified type description in the library.
3514 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3515 ITypeLib2 *iface,
3516 UINT index,
3517 ITypeInfo **ppTInfo)
3519 int i;
3521 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3522 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3524 TRACE("(%p)->(index=%d) \n", This, index);
3526 if (!ppTInfo) return E_INVALIDARG;
3528 /* search element n in list */
3529 for(i=0; i < index; i++)
3531 pTypeInfo = pTypeInfo->next;
3532 if (!pTypeInfo)
3534 TRACE("-- element not found\n");
3535 return TYPE_E_ELEMENTNOTFOUND;
3539 *ppTInfo = (ITypeInfo *) pTypeInfo;
3541 ITypeInfo_AddRef(*ppTInfo);
3542 TRACE("-- found (%p)\n",*ppTInfo);
3543 return S_OK;
3547 /* ITypeLibs::GetTypeInfoType
3549 * Retrieves the type of a type description.
3551 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3552 ITypeLib2 *iface,
3553 UINT index,
3554 TYPEKIND *pTKind)
3556 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3557 int i;
3558 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3560 TRACE("(%p) index %d \n",This, index);
3562 if(!pTKind) return E_INVALIDARG;
3564 /* search element n in list */
3565 for(i=0; i < index; i++)
3567 if(!pTInfo)
3569 TRACE("-- element not found\n");
3570 return TYPE_E_ELEMENTNOTFOUND;
3572 pTInfo = pTInfo->next;
3575 *pTKind = pTInfo->TypeAttr.typekind;
3576 TRACE("-- found Type (%d)\n", *pTKind);
3577 return S_OK;
3580 /* ITypeLib::GetTypeInfoOfGuid
3582 * Retrieves the type description that corresponds to the specified GUID.
3585 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3586 ITypeLib2 *iface,
3587 REFGUID guid,
3588 ITypeInfo **ppTInfo)
3590 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3591 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3593 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3595 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3597 /* search linked list for guid */
3598 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3600 pTypeInfo = pTypeInfo->next;
3602 if (!pTypeInfo)
3604 /* end of list reached */
3605 TRACE("-- element not found\n");
3606 return TYPE_E_ELEMENTNOTFOUND;
3610 TRACE("-- found (%p, %s)\n",
3611 pTypeInfo,
3612 debugstr_w(pTypeInfo->Name));
3614 *ppTInfo = (ITypeInfo*)pTypeInfo;
3615 ITypeInfo_AddRef(*ppTInfo);
3616 return S_OK;
3619 /* ITypeLib::GetLibAttr
3621 * Retrieves the structure that contains the library's attributes.
3624 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3625 ITypeLib2 *iface,
3626 LPTLIBATTR *ppTLibAttr)
3628 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3629 TRACE("(%p)\n",This);
3630 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3631 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3632 return S_OK;
3635 /* ITypeLib::GetTypeComp
3637 * Enables a client compiler to bind to a library's types, variables,
3638 * constants, and global functions.
3641 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3642 ITypeLib2 *iface,
3643 ITypeComp **ppTComp)
3645 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3647 TRACE("(%p)->(%p)\n",This,ppTComp);
3648 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3649 ITypeComp_AddRef(*ppTComp);
3651 return S_OK;
3654 /* ITypeLib::GetDocumentation
3656 * Retrieves the library's documentation string, the complete Help file name
3657 * and path, and the context identifier for the library Help topic in the Help
3658 * file.
3660 * On a successful return all non-null BSTR pointers will have been set,
3661 * possibly to NULL.
3663 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3664 ITypeLib2 *iface,
3665 INT index,
3666 BSTR *pBstrName,
3667 BSTR *pBstrDocString,
3668 DWORD *pdwHelpContext,
3669 BSTR *pBstrHelpFile)
3671 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3673 HRESULT result = E_INVALIDARG;
3675 ITypeInfo *pTInfo;
3678 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3679 This, index,
3680 pBstrName, pBstrDocString,
3681 pdwHelpContext, pBstrHelpFile);
3683 if(index<0)
3685 /* documentation for the typelib */
3686 if(pBstrName)
3688 if (This->Name)
3689 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3690 else
3691 *pBstrName = NULL;
3693 if(pBstrDocString)
3695 if (This->DocString)
3696 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3697 else if (This->Name)
3698 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3699 else
3700 *pBstrDocString = NULL;
3702 if(pdwHelpContext)
3704 *pdwHelpContext = This->dwHelpContext;
3706 if(pBstrHelpFile)
3708 if (This->HelpFile)
3709 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3710 else
3711 *pBstrHelpFile = NULL;
3714 result = S_OK;
3716 else
3718 /* for a typeinfo */
3719 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3721 if(SUCCEEDED(result))
3723 result = ITypeInfo_GetDocumentation(pTInfo,
3724 MEMBERID_NIL,
3725 pBstrName,
3726 pBstrDocString,
3727 pdwHelpContext, pBstrHelpFile);
3729 ITypeInfo_Release(pTInfo);
3732 return result;
3733 memerr3:
3734 if (pBstrDocString) SysFreeString (*pBstrDocString);
3735 memerr2:
3736 if (pBstrName) SysFreeString (*pBstrName);
3737 memerr1:
3738 return STG_E_INSUFFICIENTMEMORY;
3741 /* ITypeLib::IsName
3743 * Indicates whether a passed-in string contains the name of a type or member
3744 * described in the library.
3747 static HRESULT WINAPI ITypeLib2_fnIsName(
3748 ITypeLib2 *iface,
3749 LPOLESTR szNameBuf,
3750 ULONG lHashVal,
3751 BOOL *pfName)
3753 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3754 ITypeInfoImpl *pTInfo;
3755 TLBFuncDesc *pFInfo;
3756 TLBVarDesc *pVInfo;
3757 int i;
3758 UINT nNameBufLen = SysStringLen(szNameBuf);
3760 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3761 pfName);
3763 *pfName=TRUE;
3764 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3765 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3766 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3767 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3768 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3769 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3770 goto ITypeLib2_fnIsName_exit;
3772 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3773 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3776 *pfName=FALSE;
3778 ITypeLib2_fnIsName_exit:
3779 TRACE("(%p)slow! search for %s: %s found!\n", This,
3780 debugstr_w(szNameBuf), *pfName?"NOT":"");
3782 return S_OK;
3785 /* ITypeLib::FindName
3787 * Finds occurrences of a type description in a type library. This may be used
3788 * to quickly verify that a name exists in a type library.
3791 static HRESULT WINAPI ITypeLib2_fnFindName(
3792 ITypeLib2 *iface,
3793 LPOLESTR szNameBuf,
3794 ULONG lHashVal,
3795 ITypeInfo **ppTInfo,
3796 MEMBERID *rgMemId,
3797 UINT16 *pcFound)
3799 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3800 ITypeInfoImpl *pTInfo;
3801 TLBFuncDesc *pFInfo;
3802 TLBVarDesc *pVInfo;
3803 int i,j = 0;
3805 UINT nNameBufLen = SysStringLen(szNameBuf);
3807 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3808 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3809 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3810 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3811 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3812 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3813 goto ITypeLib2_fnFindName_exit;
3815 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3816 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3817 continue;
3818 ITypeLib2_fnFindName_exit:
3819 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3820 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3821 j++;
3823 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3824 This, *pcFound, debugstr_w(szNameBuf), j);
3826 *pcFound=j;
3828 return S_OK;
3831 /* ITypeLib::ReleaseTLibAttr
3833 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3836 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3837 ITypeLib2 *iface,
3838 TLIBATTR *pTLibAttr)
3840 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3841 TRACE("freeing (%p)\n",This);
3842 HeapFree(GetProcessHeap(),0,pTLibAttr);
3846 /* ITypeLib2::GetCustData
3848 * gets the custom data
3850 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3851 ITypeLib2 * iface,
3852 REFGUID guid,
3853 VARIANT *pVarVal)
3855 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3856 TLBCustData *pCData;
3858 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3860 if( IsEqualIID(guid, &pCData->guid)) break;
3863 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3865 if(pCData)
3867 VariantInit( pVarVal);
3868 VariantCopy( pVarVal, &pCData->data);
3869 return S_OK;
3871 return E_INVALIDARG; /* FIXME: correct? */
3874 /* ITypeLib2::GetLibStatistics
3876 * Returns statistics about a type library that are required for efficient
3877 * sizing of hash tables.
3880 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3881 ITypeLib2 * iface,
3882 ULONG *pcUniqueNames,
3883 ULONG *pcchUniqueNames)
3885 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3887 FIXME("(%p): stub!\n", This);
3889 if(pcUniqueNames) *pcUniqueNames=1;
3890 if(pcchUniqueNames) *pcchUniqueNames=1;
3891 return S_OK;
3894 /* ITypeLib2::GetDocumentation2
3896 * Retrieves the library's documentation string, the complete Help file name
3897 * and path, the localization context to use, and the context ID for the
3898 * library Help topic in the Help file.
3901 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3902 ITypeLib2 * iface,
3903 INT index,
3904 LCID lcid,
3905 BSTR *pbstrHelpString,
3906 DWORD *pdwHelpStringContext,
3907 BSTR *pbstrHelpStringDll)
3909 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3910 HRESULT result;
3911 ITypeInfo *pTInfo;
3913 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3915 /* the help string should be obtained from the helpstringdll,
3916 * using the _DLLGetDocumentation function, based on the supplied
3917 * lcid. Nice to do sometime...
3919 if(index<0)
3921 /* documentation for the typelib */
3922 if(pbstrHelpString)
3923 *pbstrHelpString=SysAllocString(This->DocString);
3924 if(pdwHelpStringContext)
3925 *pdwHelpStringContext=This->dwHelpContext;
3926 if(pbstrHelpStringDll)
3927 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3929 result = S_OK;
3931 else
3933 /* for a typeinfo */
3934 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3936 if(SUCCEEDED(result))
3938 ITypeInfo2 * pTInfo2;
3939 result = ITypeInfo_QueryInterface(pTInfo,
3940 &IID_ITypeInfo2,
3941 (LPVOID*) &pTInfo2);
3943 if(SUCCEEDED(result))
3945 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3946 MEMBERID_NIL,
3947 lcid,
3948 pbstrHelpString,
3949 pdwHelpStringContext,
3950 pbstrHelpStringDll);
3952 ITypeInfo2_Release(pTInfo2);
3955 ITypeInfo_Release(pTInfo);
3958 return result;
3961 /* ITypeLib2::GetAllCustData
3963 * Gets all custom data items for the library.
3966 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3967 ITypeLib2 * iface,
3968 CUSTDATA *pCustData)
3970 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3971 TLBCustData *pCData;
3972 int i;
3973 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3974 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3975 if(pCustData->prgCustData ){
3976 pCustData->cCustData=This->ctCustData;
3977 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3978 pCustData->prgCustData[i].guid=pCData->guid;
3979 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3981 }else{
3982 ERR(" OUT OF MEMORY! \n");
3983 return E_OUTOFMEMORY;
3985 return S_OK;
3988 static ITypeLib2Vtbl tlbvt = {
3989 ITypeLib2_fnQueryInterface,
3990 ITypeLib2_fnAddRef,
3991 ITypeLib2_fnRelease,
3992 ITypeLib2_fnGetTypeInfoCount,
3993 ITypeLib2_fnGetTypeInfo,
3994 ITypeLib2_fnGetTypeInfoType,
3995 ITypeLib2_fnGetTypeInfoOfGuid,
3996 ITypeLib2_fnGetLibAttr,
3997 ITypeLib2_fnGetTypeComp,
3998 ITypeLib2_fnGetDocumentation,
3999 ITypeLib2_fnIsName,
4000 ITypeLib2_fnFindName,
4001 ITypeLib2_fnReleaseTLibAttr,
4003 ITypeLib2_fnGetCustData,
4004 ITypeLib2_fnGetLibStatistics,
4005 ITypeLib2_fnGetDocumentation2,
4006 ITypeLib2_fnGetAllCustData
4010 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4012 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4014 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
4017 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4019 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4021 return ITypeInfo_AddRef((ITypeInfo *)This);
4024 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4026 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4028 return ITypeInfo_Release((ITypeInfo *)This);
4031 static HRESULT WINAPI ITypeLibComp_fnBind(
4032 ITypeComp * iface,
4033 OLECHAR * szName,
4034 ULONG lHash,
4035 WORD wFlags,
4036 ITypeInfo ** ppTInfo,
4037 DESCKIND * pDescKind,
4038 BINDPTR * pBindPtr)
4040 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4041 return E_NOTIMPL;
4044 static HRESULT WINAPI ITypeLibComp_fnBindType(
4045 ITypeComp * iface,
4046 OLECHAR * szName,
4047 ULONG lHash,
4048 ITypeInfo ** ppTInfo,
4049 ITypeComp ** ppTComp)
4051 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4052 return E_NOTIMPL;
4055 static ITypeCompVtbl tlbtcvt =
4058 ITypeLibComp_fnQueryInterface,
4059 ITypeLibComp_fnAddRef,
4060 ITypeLibComp_fnRelease,
4062 ITypeLibComp_fnBind,
4063 ITypeLibComp_fnBindType
4066 /*================== ITypeInfo(2) Methods ===================================*/
4067 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4069 ITypeInfoImpl * pTypeInfoImpl;
4071 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4072 if (pTypeInfoImpl)
4074 pTypeInfoImpl->lpVtbl = &tinfvt;
4075 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4076 pTypeInfoImpl->ref=1;
4078 TRACE("(%p)\n", pTypeInfoImpl);
4079 return (ITypeInfo2*) pTypeInfoImpl;
4082 /* ITypeInfo::QueryInterface
4084 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4085 ITypeInfo2 *iface,
4086 REFIID riid,
4087 VOID **ppvObject)
4089 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4091 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4093 *ppvObject=NULL;
4094 if(IsEqualIID(riid, &IID_IUnknown) ||
4095 IsEqualIID(riid,&IID_ITypeInfo)||
4096 IsEqualIID(riid,&IID_ITypeInfo2))
4097 *ppvObject = This;
4099 if(*ppvObject){
4100 ITypeInfo_AddRef(iface);
4101 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4102 return S_OK;
4104 TRACE("-- Interface: E_NOINTERFACE\n");
4105 return E_NOINTERFACE;
4108 /* ITypeInfo::AddRef
4110 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4112 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4113 ULONG ref = InterlockedIncrement(&This->ref);
4115 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4117 TRACE("(%p)->ref is %lu\n",This, ref);
4118 return ref;
4121 /* ITypeInfo::Release
4123 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4125 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4126 ULONG ref = InterlockedDecrement(&This->ref);
4128 TRACE("(%p)->(%lu)\n",This, ref);
4130 if (ref) {
4131 /* We don't release ITypeLib when ref=0 becouse
4132 it means that funtion is called by ITypeLi2_Release */
4133 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4134 } else {
4135 FIXME("destroy child objects\n");
4137 TRACE("destroying ITypeInfo(%p)\n",This);
4138 if (This->Name)
4140 SysFreeString(This->Name);
4141 This->Name = 0;
4144 if (This->DocString)
4146 SysFreeString(This->DocString);
4147 This->DocString = 0;
4150 if (This->next)
4152 ITypeInfo_Release((ITypeInfo*)This->next);
4155 HeapFree(GetProcessHeap(),0,This);
4156 return 0;
4158 return ref;
4161 /* ITypeInfo::GetTypeAttr
4163 * Retrieves a TYPEATTR structure that contains the attributes of the type
4164 * description.
4167 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4168 LPTYPEATTR *ppTypeAttr)
4170 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4171 TRACE("(%p)\n",This);
4172 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4173 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4175 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4176 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4178 if((*ppTypeAttr)->typekind == TKIND_DISPATCH && (*ppTypeAttr)->wTypeFlags & TYPEFLAG_FDUAL) {
4179 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4180 funcs */
4181 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4182 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4184 return S_OK;
4187 /* ITypeInfo::GetTypeComp
4189 * Retrieves the ITypeComp interface for the type description, which enables a
4190 * client compiler to bind to the type description's members.
4193 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4194 ITypeComp * *ppTComp)
4196 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4198 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4200 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4201 ITypeComp_AddRef(*ppTComp);
4202 return S_OK;
4205 /* ITypeInfo::GetFuncDesc
4207 * Retrieves the FUNCDESC structure that contains information about a
4208 * specified function.
4211 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4212 LPFUNCDESC *ppFuncDesc)
4214 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4215 int i;
4216 TLBFuncDesc * pFDesc;
4217 TRACE("(%p) index %d\n", This, index);
4218 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4220 if(pFDesc){
4221 /* FIXME: must do a copy here */
4222 *ppFuncDesc=&pFDesc->funcdesc;
4223 return S_OK;
4225 return E_INVALIDARG;
4228 /* ITypeInfo::GetVarDesc
4230 * Retrieves a VARDESC structure that describes the specified variable.
4233 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4234 LPVARDESC *ppVarDesc)
4236 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4237 int i;
4238 TLBVarDesc * pVDesc;
4239 TRACE("(%p) index %d\n", This, index);
4240 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4242 if(pVDesc){
4243 /* FIXME: must do a copy here */
4244 *ppVarDesc=&pVDesc->vardesc;
4245 return S_OK;
4247 return E_INVALIDARG;
4250 /* ITypeInfo_GetNames
4252 * Retrieves the variable with the specified member ID (or the name of the
4253 * property or method and its parameters) that correspond to the specified
4254 * function ID.
4256 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4257 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4259 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4260 TLBFuncDesc * pFDesc;
4261 TLBVarDesc * pVDesc;
4262 int i;
4263 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4264 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4265 if(pFDesc)
4267 /* function found, now return function and parameter names */
4268 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4270 if(!i)
4271 *rgBstrNames=SysAllocString(pFDesc->Name);
4272 else
4273 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4275 *pcNames=i;
4277 else
4279 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4280 if(pVDesc)
4282 *rgBstrNames=SysAllocString(pVDesc->Name);
4283 *pcNames=1;
4285 else
4287 if(This->TypeAttr.cImplTypes &&
4288 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4289 /* recursive search */
4290 ITypeInfo *pTInfo;
4291 HRESULT result;
4292 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4293 &pTInfo);
4294 if(SUCCEEDED(result))
4296 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4297 ITypeInfo_Release(pTInfo);
4298 return result;
4300 WARN("Could not search inherited interface!\n");
4302 else
4304 WARN("no names found\n");
4306 *pcNames=0;
4307 return TYPE_E_ELEMENTNOTFOUND;
4310 return S_OK;
4314 /* ITypeInfo::GetRefTypeOfImplType
4316 * If a type description describes a COM class, it retrieves the type
4317 * description of the implemented interface types. For an interface,
4318 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4319 * if any exist.
4322 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4323 ITypeInfo2 *iface,
4324 UINT index,
4325 HREFTYPE *pRefType)
4327 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4328 int(i);
4329 TLBImplType *pImpl = This->impltypelist;
4331 TRACE("(%p) index %d\n", This, index);
4332 if (TRACE_ON(ole)) dump_TypeInfo(This);
4334 if(index==(UINT)-1)
4336 /* only valid on dual interfaces;
4337 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4339 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4341 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4342 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4344 *pRefType = -1;
4346 else
4348 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4349 *pRefType = pImpl->hRef;
4352 else
4354 /* get element n from linked list */
4355 for(i=0; pImpl && i<index; i++)
4357 pImpl = pImpl->next;
4360 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4362 *pRefType = pImpl->hRef;
4364 TRACE("-- 0x%08lx\n", pImpl->hRef );
4367 return S_OK;
4371 /* ITypeInfo::GetImplTypeFlags
4373 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4374 * or base interface in a type description.
4376 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4377 UINT index, INT *pImplTypeFlags)
4379 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4380 int i;
4381 TLBImplType *pImpl;
4383 TRACE("(%p) index %d\n", This, index);
4384 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4385 i++, pImpl=pImpl->next)
4387 if(i==index && pImpl){
4388 *pImplTypeFlags=pImpl->implflags;
4389 return S_OK;
4391 *pImplTypeFlags=0;
4392 return TYPE_E_ELEMENTNOTFOUND;
4395 /* GetIDsOfNames
4396 * Maps between member names and member IDs, and parameter names and
4397 * parameter IDs.
4399 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4400 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4402 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4403 TLBFuncDesc * pFDesc;
4404 TLBVarDesc * pVDesc;
4405 HRESULT ret=S_OK;
4407 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4408 cNames);
4409 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4410 int i, j;
4411 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4412 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4413 for(i=1; i < cNames; i++){
4414 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4415 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4416 break;
4417 if( j<pFDesc->funcdesc.cParams)
4418 pMemId[i]=j;
4419 else
4420 ret=DISP_E_UNKNOWNNAME;
4422 return ret;
4425 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4426 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4427 if(cNames) *pMemId=pVDesc->vardesc.memid;
4428 return ret;
4431 /* not found, see if this is and interface with an inheritance */
4432 if(This->TypeAttr.cImplTypes &&
4433 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4434 /* recursive search */
4435 ITypeInfo *pTInfo;
4436 ret=ITypeInfo_GetRefTypeInfo(iface,
4437 This->impltypelist->hRef, &pTInfo);
4438 if(SUCCEEDED(ret)){
4439 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4440 ITypeInfo_Release(pTInfo);
4441 return ret;
4443 WARN("Could not search inherited interface!\n");
4444 } else
4445 WARN("no names found\n");
4446 return DISP_E_UNKNOWNNAME;
4449 /* ITypeInfo::Invoke
4451 * Invokes a method, or accesses a property of an object, that implements the
4452 * interface described by the type description.
4454 DWORD
4455 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4456 DWORD res;
4458 if (TRACE_ON(ole)) {
4459 int i;
4460 TRACE("Calling %p(",func);
4461 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4462 TRACE(")\n");
4465 switch (callconv) {
4466 case CC_STDCALL:
4468 switch (nrargs) {
4469 case 0:
4470 res = func();
4471 break;
4472 case 1:
4473 res = func(args[0]);
4474 break;
4475 case 2:
4476 res = func(args[0],args[1]);
4477 break;
4478 case 3:
4479 res = func(args[0],args[1],args[2]);
4480 break;
4481 case 4:
4482 res = func(args[0],args[1],args[2],args[3]);
4483 break;
4484 case 5:
4485 res = func(args[0],args[1],args[2],args[3],args[4]);
4486 break;
4487 case 6:
4488 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4489 break;
4490 case 7:
4491 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4492 break;
4493 case 8:
4494 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4495 break;
4496 case 9:
4497 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4498 break;
4499 case 10:
4500 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4501 break;
4502 case 11:
4503 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4504 break;
4505 default:
4506 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4507 res = -1;
4508 break;
4510 break;
4511 default:
4512 FIXME("unsupported calling convention %d\n",callconv);
4513 res = -1;
4514 break;
4516 TRACE("returns %08lx\n",res);
4517 return res;
4520 extern int _argsize(DWORD vt);
4522 /****************************************************************************
4523 * Helper functions for Dispcall / Invoke, which copies one variant
4524 * with target type onto the argument stack.
4526 static HRESULT
4527 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4528 DWORD *argpos, VARIANT *arg, VARTYPE vt
4530 UINT arglen = _argsize(vt)*sizeof(DWORD);
4531 VARTYPE oldvt;
4532 VARIANT va;
4534 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4535 memcpy(argpos,&arg,sizeof(void*));
4536 return S_OK;
4539 if (V_VT(arg) == vt) {
4540 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4541 return S_OK;
4544 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4545 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4546 return S_OK;
4549 if (vt == VT_VARIANT) {
4550 memcpy(argpos, arg, arglen);
4551 return S_OK;
4553 /* Deref BYREF vars if there is need */
4554 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4555 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4556 return S_OK;
4558 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4559 /* in this context, if the type lib specifies IUnknown*, giving an
4560 IDispatch* is correct; so, don't invoke VariantChangeType */
4561 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4562 return S_OK;
4564 if ((vt == VT_PTR) && tdesc)
4565 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4567 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4568 ITypeInfo *tinfo2 = NULL;
4569 TYPEATTR *tattr = NULL;
4570 HRESULT hres;
4572 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4573 if (hres) {
4574 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4575 "while coercing from vt 0x%x. Copying 4 byte.\n",
4576 tdesc->u.hreftype,V_VT(arg));
4577 memcpy(argpos, &V_UNION(arg,lVal), 4);
4578 return S_OK;
4580 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4581 if( hres )
4583 ERR("GetTypeAttr failed\n");
4584 ITypeInfo_Release(tinfo2);
4585 return hres;
4587 switch (tattr->typekind) {
4588 case TKIND_ENUM:
4589 switch ( V_VT( arg ) ) {
4590 case VT_I2:
4591 *argpos = V_UNION(arg,iVal);
4592 hres = S_OK;
4593 break;
4594 case VT_I4:
4595 memcpy(argpos, &V_UNION(arg,lVal), 4);
4596 hres = S_OK;
4597 break;
4598 default:
4599 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4600 hres = E_FAIL;
4601 break;
4603 break;
4605 case TKIND_ALIAS:
4606 tdesc = &(tattr->tdescAlias);
4607 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4608 break;
4610 case TKIND_INTERFACE:
4611 if (V_VT(arg) == VT_DISPATCH) {
4612 IDispatch *disp;
4613 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4614 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4615 hres = S_OK;
4616 break;
4618 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),
4619 &IID_IDispatch,(LPVOID*)&disp);
4620 if (SUCCEEDED(hres)) {
4621 memcpy(argpos,&disp,4);
4622 IUnknown_Release(V_UNION(arg,pdispVal));
4623 hres = S_OK;
4624 break;
4626 FIXME("Failed to query IDispatch interface from %s while "
4627 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4628 hres = E_FAIL;
4629 break;
4631 if (V_VT(arg) == VT_UNKNOWN) {
4632 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4633 hres = S_OK;
4634 break;
4636 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4637 V_VT(arg),debugstr_guid(&(tattr->guid)));
4638 hres = E_FAIL;
4639 break;
4641 case TKIND_DISPATCH:
4642 if (V_VT(arg) == VT_DISPATCH) {
4643 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4644 hres = S_OK;
4646 else {
4647 hres = E_FAIL;
4648 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4650 break;
4651 case TKIND_RECORD:
4652 FIXME("TKIND_RECORD unhandled.\n");
4653 hres = E_FAIL;
4654 break;
4655 default:
4656 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4657 hres = E_FAIL;
4658 break;
4660 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4661 ITypeInfo_Release(tinfo2);
4662 return hres;
4665 oldvt = V_VT(arg);
4666 VariantInit(&va);
4667 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4668 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4669 FIXME("Should not use VariantChangeType here."
4670 " (conversion from 0x%x -> 0x%x) %08lx\n",
4671 V_VT(arg), vt, *argpos
4673 return S_OK;
4675 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4676 return E_FAIL;
4679 /***********************************************************************
4680 * DispCallFunc (OLEAUT32.@)
4682 HRESULT WINAPI
4683 DispCallFunc(
4684 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4685 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4687 int i, argsize, argspos;
4688 DWORD *args;
4689 HRESULT hres;
4691 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4692 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4694 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4695 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4696 argsize = 1;
4697 for (i=0;i<cActuals;i++) {
4698 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4699 dump_Variant(prgpvarg[i]);
4700 argsize += _argsize(prgvt[i]);
4702 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4703 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4704 argspos = 1;
4705 for (i=0;i<cActuals;i++) {
4706 VARIANT *arg = prgpvarg[i];
4707 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4708 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4709 argspos += _argsize(prgvt[i]);
4712 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4714 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4715 hres=S_OK;
4717 else
4719 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4720 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4721 FIXME("Method returned %lx\n",hres);
4723 HeapFree(GetProcessHeap(),0,args);
4724 return hres;
4727 static HRESULT WINAPI ITypeInfo_fnInvoke(
4728 ITypeInfo2 *iface,
4729 VOID *pIUnk,
4730 MEMBERID memid,
4731 UINT16 dwFlags,
4732 DISPPARAMS *pDispParams,
4733 VARIANT *pVarResult,
4734 EXCEPINFO *pExcepInfo,
4735 UINT *pArgErr)
4737 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4738 int i;
4739 unsigned int func_index, var_index;
4740 TYPEKIND type_kind;
4741 HRESULT hres;
4743 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4744 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4746 dump_DispParms(pDispParams);
4748 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4749 if (SUCCEEDED(hres)) {
4750 FUNCDESC *func_desc;
4752 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4753 if(FAILED(hres)) return hres;
4755 switch (func_desc->funckind) {
4756 case FUNC_PUREVIRTUAL:
4757 case FUNC_VIRTUAL: {
4758 DWORD res;
4759 int numargs, numargs2, argspos, args2pos;
4760 DWORD *args , *args2;
4761 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4762 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4764 hres = S_OK;
4765 numargs = 1; numargs2 = 0;
4766 for (i = 0; i < func_desc->cParams; i++) {
4767 if (i<pDispParams->cArgs)
4768 numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4769 else {
4770 numargs += 1; /* sizeof(lpvoid) */
4771 numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4775 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4776 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4778 args[0] = (DWORD)pIUnk;
4779 argspos = 1; args2pos = 0;
4780 for (i = 0; i < func_desc->cParams; i++) {
4781 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4782 if (i<pDispParams->cArgs) {
4783 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4784 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4785 USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
4786 if (paramFlags & PARAMFLAG_FOPT) {
4787 if(i < func_desc->cParams - func_desc->cParamsOpt)
4788 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4789 if(V_VT(arg) == VT_EMPTY
4790 || ((V_VT(arg) & VT_BYREF) && !V_BYREF(arg))) {
4791 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4792 How to determine it? */
4794 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4795 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4796 V_VT(arg) = VT_ERROR;
4797 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4798 arglen = _argsize(VT_ERROR);
4801 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4802 if (FAILED(hres)) goto func_fail;
4803 argspos += arglen;
4804 } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
4805 VARIANT *arg = &rgvarg[i];
4806 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4807 if(i < func_desc->cParams - func_desc->cParamsOpt)
4808 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4809 if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4810 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4811 V_VT(arg) = VT_ERROR;
4812 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4813 arglen = _argsize(VT_ERROR);
4814 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4815 if (FAILED(hres)) goto func_fail;
4816 argspos += arglen;
4817 } else {
4818 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);
4819 if (tdesc->vt != VT_PTR)
4820 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4821 /*FIXME: give pointers for the rest, so propertyget works*/
4822 args[argspos] = (DWORD)&args2[args2pos];
4824 /* If pointer to variant, pass reference it. */
4825 if ((tdesc->vt == VT_PTR) &&
4826 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4827 pVarResult
4829 args[argspos]= (DWORD)pVarResult;
4830 argspos += 1;
4831 args2pos += arglen;
4834 if (func_desc->cParamsOpt < 0)
4835 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4837 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4838 func_desc->callconv,
4839 numargs,
4840 args
4843 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4844 args2pos = 0;
4845 for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
4846 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4847 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);
4848 TYPEDESC i4_tdesc;
4849 i4_tdesc.vt = VT_I4;
4851 /* If we are a pointer to a variant, we are done already */
4852 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4853 continue;
4855 VariantInit(pVarResult);
4856 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4858 if (tdesc->vt == VT_PTR)
4859 tdesc = tdesc->u.lptdesc;
4860 if (tdesc->vt == VT_USERDEFINED) {
4861 ITypeInfo *tinfo2;
4862 TYPEATTR *tattr;
4864 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4865 if (FAILED(hres)) {
4866 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4867 goto func_fail;
4869 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4870 switch (tattr->typekind) {
4871 case TKIND_ENUM:
4872 /* force the return type to be VT_I4 */
4873 tdesc = &i4_tdesc;
4874 break;
4875 case TKIND_ALIAS:
4876 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4877 tdesc = &(tattr->tdescAlias);
4878 break;
4880 case TKIND_INTERFACE:
4881 FIXME("TKIND_INTERFACE unhandled.\n");
4882 break;
4883 case TKIND_DISPATCH:
4884 FIXME("TKIND_DISPATCH unhandled.\n");
4885 break;
4886 case TKIND_RECORD:
4887 FIXME("TKIND_RECORD unhandled.\n");
4888 break;
4889 default:
4890 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4891 break;
4893 ITypeInfo_Release(tinfo2);
4895 V_VT(pVarResult) = tdesc->vt;
4897 /* HACK: VB5 likes this.
4898 * I do not know why. There is 1 example in MSDN which uses
4899 * this which appears broken (mixes int vals and
4900 * IDispatch*.).
4902 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4903 V_VT(pVarResult) = VT_DISPATCH;
4904 TRACE("storing into variant:\n");
4905 dump_Variant(pVarResult);
4906 args2pos += arglen;
4909 func_fail:
4910 HeapFree(GetProcessHeap(), 0, rgvarg);
4911 HeapFree(GetProcessHeap(),0,args2);
4912 HeapFree(GetProcessHeap(),0,args);
4913 break;
4915 case FUNC_DISPATCH: {
4916 IDispatch *disp;
4918 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4919 if (SUCCEEDED(hres)) {
4920 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4921 hres = IDispatch_Invoke(
4922 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4923 pVarResult,pExcepInfo,pArgErr
4925 if (FAILED(hres))
4926 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
4927 IDispatch_Release(disp);
4928 } else
4929 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4930 break;
4932 default:
4933 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
4934 hres = E_FAIL;
4935 break;
4938 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
4939 return hres;
4941 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
4942 VARDESC *var_desc;
4944 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
4945 if(FAILED(hres)) return hres;
4947 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4948 dump_VARDESC(var_desc);
4949 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
4950 return E_NOTIMPL;
4953 /* not found, look for it in inherited interfaces */
4954 ITypeInfo2_GetTypeKind(iface, &type_kind);
4955 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
4956 HREFTYPE ref_type;
4957 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
4958 /* recursive search */
4959 ITypeInfo *pTInfo;
4960 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
4961 if(SUCCEEDED(hres)){
4962 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4963 ITypeInfo_Release(pTInfo);
4964 return hres;
4966 WARN("Could not search inherited interface!\n");
4969 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
4970 return DISP_E_MEMBERNOTFOUND;
4973 /* ITypeInfo::GetDocumentation
4975 * Retrieves the documentation string, the complete Help file name and path,
4976 * and the context ID for the Help topic for a specified type description.
4978 * (Can be tested by the Visual Basic Editor in Word for instance.)
4980 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4981 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4982 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4984 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4985 TLBFuncDesc * pFDesc;
4986 TLBVarDesc * pVDesc;
4987 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4988 " HelpContext(%p) HelpFile(%p)\n",
4989 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4990 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4991 if(pBstrName)
4992 *pBstrName=SysAllocString(This->Name);
4993 if(pBstrDocString)
4994 *pBstrDocString=SysAllocString(This->DocString);
4995 if(pdwHelpContext)
4996 *pdwHelpContext=This->dwHelpContext;
4997 if(pBstrHelpFile)
4998 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4999 return S_OK;
5000 }else {/* for a member */
5001 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5002 if(pFDesc->funcdesc.memid==memid){
5003 if(pBstrName)
5004 *pBstrName = SysAllocString(pFDesc->Name);
5005 if(pBstrDocString)
5006 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5007 if(pdwHelpContext)
5008 *pdwHelpContext=pFDesc->helpcontext;
5009 return S_OK;
5011 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5012 if(pVDesc->vardesc.memid==memid){
5013 if(pBstrName)
5014 *pBstrName = SysAllocString(pVDesc->Name);
5015 if(pBstrDocString)
5016 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5017 if(pdwHelpContext)
5018 *pdwHelpContext=pVDesc->HelpContext;
5019 return S_OK;
5022 return TYPE_E_ELEMENTNOTFOUND;
5025 /* ITypeInfo::GetDllEntry
5027 * Retrieves a description or specification of an entry point for a function
5028 * in a DLL.
5030 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5031 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5032 WORD *pwOrdinal)
5034 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5035 TLBFuncDesc *pFDesc;
5037 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5039 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5040 if(pFDesc->funcdesc.memid==memid){
5041 dump_TypeInfo(This);
5042 dump_TLBFuncDescOne(pFDesc);
5044 /* FIXME: This is wrong, but how do you find that out? */
5045 if (pBstrDllName) {
5046 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5047 *pBstrDllName = SysAllocString(oleaut32W);
5050 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5051 if (pBstrName)
5052 *pBstrName = SysAllocString(pFDesc->Entry);
5053 if (pwOrdinal)
5054 *pwOrdinal = -1;
5055 return S_OK;
5057 if (pBstrName)
5058 *pBstrName = NULL;
5059 if (pwOrdinal)
5060 *pwOrdinal = (DWORD)pFDesc->Entry;
5061 return S_OK;
5063 return E_FAIL;
5066 /* ITypeInfo::GetRefTypeInfo
5068 * If a type description references other type descriptions, it retrieves
5069 * the referenced type descriptions.
5071 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5072 ITypeInfo2 *iface,
5073 HREFTYPE hRefType,
5074 ITypeInfo **ppTInfo)
5076 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5077 HRESULT result = E_FAIL;
5080 if (hRefType == -1 &&
5081 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5082 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5084 /* when we meet a DUAL dispinterface, we must create the interface
5085 * version of it.
5087 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5090 /* the interface version contains the same information as the dispinterface
5091 * copy the contents of the structs.
5093 *pTypeInfoImpl = *This;
5094 pTypeInfoImpl->ref = 1;
5096 /* change the type to interface */
5097 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5099 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5101 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5103 result = S_OK;
5105 } else {
5106 TLBRefType *pRefType;
5107 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5108 if(pRefType->reference == hRefType)
5109 break;
5111 if(!pRefType)
5112 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5113 if(pRefType && hRefType != -1) {
5114 ITypeLib *pTLib = NULL;
5116 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5117 int Index;
5118 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5119 } else {
5120 if(pRefType->pImpTLInfo->pImpTypeLib) {
5121 TRACE("typeinfo in imported typelib that is already loaded\n");
5122 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5123 ITypeLib2_AddRef((ITypeLib*) pTLib);
5124 result = S_OK;
5125 } else {
5126 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5127 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5128 pRefType->pImpTLInfo->wVersionMajor,
5129 pRefType->pImpTLInfo->wVersionMinor,
5130 pRefType->pImpTLInfo->lcid,
5131 &pTLib);
5133 if(!SUCCEEDED(result)) {
5134 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5135 result=LoadTypeLib(libnam, &pTLib);
5136 SysFreeString(libnam);
5138 if(SUCCEEDED(result)) {
5139 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5140 ITypeLib2_AddRef(pTLib);
5144 if(SUCCEEDED(result)) {
5145 if(pRefType->index == TLB_REF_USE_GUID)
5146 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5147 &pRefType->guid,
5148 ppTInfo);
5149 else
5150 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5151 ppTInfo);
5153 if (pTLib != NULL)
5154 ITypeLib2_Release(pTLib);
5158 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5159 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5160 return result;
5163 /* ITypeInfo::AddressOfMember
5165 * Retrieves the addresses of static functions or variables, such as those
5166 * defined in a DLL.
5168 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5169 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5171 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5172 FIXME("(%p) stub!\n", This);
5173 return S_OK;
5176 /* ITypeInfo::CreateInstance
5178 * Creates a new instance of a type that describes a component object class
5179 * (coclass).
5181 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5182 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5184 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5185 FIXME("(%p) stub!\n", This);
5186 return S_OK;
5189 /* ITypeInfo::GetMops
5191 * Retrieves marshalling information.
5193 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5194 BSTR *pBstrMops)
5196 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5197 FIXME("(%p) stub!\n", This);
5198 return S_OK;
5201 /* ITypeInfo::GetContainingTypeLib
5203 * Retrieves the containing type library and the index of the type description
5204 * within that type library.
5206 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5207 ITypeLib * *ppTLib, UINT *pIndex)
5209 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5211 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5212 if (pIndex) {
5213 *pIndex=This->index;
5214 TRACE("returning pIndex=%d\n", *pIndex);
5217 if (ppTLib) {
5218 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5219 ITypeLib2_AddRef(*ppTLib);
5220 TRACE("returning ppTLib=%p\n", *ppTLib);
5223 return S_OK;
5226 /* ITypeInfo::ReleaseTypeAttr
5228 * Releases a TYPEATTR previously returned by GetTypeAttr.
5231 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5232 TYPEATTR* pTypeAttr)
5234 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5235 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5236 if(This->TypeAttr.typekind == TKIND_ALIAS)
5237 free_deep_typedesc(&pTypeAttr->tdescAlias);
5238 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5241 /* ITypeInfo::ReleaseFuncDesc
5243 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5245 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5246 ITypeInfo2 *iface,
5247 FUNCDESC *pFuncDesc)
5249 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5250 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5253 /* ITypeInfo::ReleaseVarDesc
5255 * Releases a VARDESC previously returned by GetVarDesc.
5257 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5258 VARDESC *pVarDesc)
5260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5261 TRACE("(%p)->(%p)\n", This, pVarDesc);
5264 /* ITypeInfo2::GetTypeKind
5266 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5269 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5270 TYPEKIND *pTypeKind)
5272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5273 *pTypeKind=This->TypeAttr.typekind;
5274 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5275 return S_OK;
5278 /* ITypeInfo2::GetTypeFlags
5280 * Returns the type flags without any allocations. This returns a DWORD type
5281 * flag, which expands the type flags without growing the TYPEATTR (type
5282 * attribute).
5285 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5287 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5288 *pTypeFlags=This->TypeAttr.wTypeFlags;
5289 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5290 return S_OK;
5293 /* ITypeInfo2::GetFuncIndexOfMemId
5294 * Binds to a specific member based on a known DISPID, where the member name
5295 * is not known (for example, when binding to a default member).
5298 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5299 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5301 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5302 TLBFuncDesc *pFuncInfo;
5303 int i;
5304 HRESULT result;
5306 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5307 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5308 break;
5309 if(pFuncInfo) {
5310 *pFuncIndex = i;
5311 result = S_OK;
5312 } else
5313 result = TYPE_E_ELEMENTNOTFOUND;
5315 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5316 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5317 return result;
5320 /* TypeInfo2::GetVarIndexOfMemId
5322 * Binds to a specific member based on a known DISPID, where the member name
5323 * is not known (for example, when binding to a default member).
5326 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5327 MEMBERID memid, UINT *pVarIndex)
5329 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5330 TLBVarDesc *pVarInfo;
5331 int i;
5332 HRESULT result;
5333 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5334 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5336 if(pVarInfo) {
5337 *pVarIndex = i;
5338 result = S_OK;
5339 } else
5340 result = TYPE_E_ELEMENTNOTFOUND;
5342 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5343 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5344 return result;
5347 /* ITypeInfo2::GetCustData
5349 * Gets the custom data
5351 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5352 ITypeInfo2 * iface,
5353 REFGUID guid,
5354 VARIANT *pVarVal)
5356 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5357 TLBCustData *pCData;
5359 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5360 if( IsEqualIID(guid, &pCData->guid)) break;
5362 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5364 if(pCData)
5366 VariantInit( pVarVal);
5367 VariantCopy( pVarVal, &pCData->data);
5368 return S_OK;
5370 return E_INVALIDARG; /* FIXME: correct? */
5373 /* ITypeInfo2::GetFuncCustData
5375 * Gets the custom data
5377 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5378 ITypeInfo2 * iface,
5379 UINT index,
5380 REFGUID guid,
5381 VARIANT *pVarVal)
5383 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5384 TLBCustData *pCData=NULL;
5385 TLBFuncDesc * pFDesc;
5386 int i;
5387 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5388 pFDesc=pFDesc->next);
5390 if(pFDesc)
5391 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5392 if( IsEqualIID(guid, &pCData->guid)) break;
5394 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5396 if(pCData){
5397 VariantInit( pVarVal);
5398 VariantCopy( pVarVal, &pCData->data);
5399 return S_OK;
5401 return E_INVALIDARG; /* FIXME: correct? */
5404 /* ITypeInfo2::GetParamCustData
5406 * Gets the custom data
5408 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5409 ITypeInfo2 * iface,
5410 UINT indexFunc,
5411 UINT indexParam,
5412 REFGUID guid,
5413 VARIANT *pVarVal)
5415 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5416 TLBCustData *pCData=NULL;
5417 TLBFuncDesc * pFDesc;
5418 int i;
5420 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5422 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5423 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5424 pCData = pCData->next)
5425 if( IsEqualIID(guid, &pCData->guid)) break;
5427 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5429 if(pCData)
5431 VariantInit( pVarVal);
5432 VariantCopy( pVarVal, &pCData->data);
5433 return S_OK;
5435 return E_INVALIDARG; /* FIXME: correct? */
5438 /* ITypeInfo2::GetVarCustData
5440 * Gets the custom data
5442 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5443 ITypeInfo2 * iface,
5444 UINT index,
5445 REFGUID guid,
5446 VARIANT *pVarVal)
5448 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5449 TLBCustData *pCData=NULL;
5450 TLBVarDesc * pVDesc;
5451 int i;
5453 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5455 if(pVDesc)
5457 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5459 if( IsEqualIID(guid, &pCData->guid)) break;
5463 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5465 if(pCData)
5467 VariantInit( pVarVal);
5468 VariantCopy( pVarVal, &pCData->data);
5469 return S_OK;
5471 return E_INVALIDARG; /* FIXME: correct? */
5474 /* ITypeInfo2::GetImplCustData
5476 * Gets the custom data
5478 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5479 ITypeInfo2 * iface,
5480 UINT index,
5481 REFGUID guid,
5482 VARIANT *pVarVal)
5484 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5485 TLBCustData *pCData=NULL;
5486 TLBImplType * pRDesc;
5487 int i;
5489 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5491 if(pRDesc)
5493 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5495 if( IsEqualIID(guid, &pCData->guid)) break;
5499 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5501 if(pCData)
5503 VariantInit( pVarVal);
5504 VariantCopy( pVarVal, &pCData->data);
5505 return S_OK;
5507 return E_INVALIDARG; /* FIXME: correct? */
5510 /* ITypeInfo2::GetDocumentation2
5512 * Retrieves the documentation string, the complete Help file name and path,
5513 * the localization context to use, and the context ID for the library Help
5514 * topic in the Help file.
5517 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5518 ITypeInfo2 * iface,
5519 MEMBERID memid,
5520 LCID lcid,
5521 BSTR *pbstrHelpString,
5522 DWORD *pdwHelpStringContext,
5523 BSTR *pbstrHelpStringDll)
5525 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5526 TLBFuncDesc * pFDesc;
5527 TLBVarDesc * pVDesc;
5528 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5529 "HelpStringContext(%p) HelpStringDll(%p)\n",
5530 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5531 pbstrHelpStringDll );
5532 /* the help string should be obtained from the helpstringdll,
5533 * using the _DLLGetDocumentation function, based on the supplied
5534 * lcid. Nice to do sometime...
5536 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5537 if(pbstrHelpString)
5538 *pbstrHelpString=SysAllocString(This->Name);
5539 if(pdwHelpStringContext)
5540 *pdwHelpStringContext=This->dwHelpStringContext;
5541 if(pbstrHelpStringDll)
5542 *pbstrHelpStringDll=
5543 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5544 return S_OK;
5545 }else {/* for a member */
5546 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5547 if(pFDesc->funcdesc.memid==memid){
5548 if(pbstrHelpString)
5549 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5550 if(pdwHelpStringContext)
5551 *pdwHelpStringContext=pFDesc->HelpStringContext;
5552 if(pbstrHelpStringDll)
5553 *pbstrHelpStringDll=
5554 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5555 return S_OK;
5557 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5558 if(pVDesc->vardesc.memid==memid){
5559 if(pbstrHelpString)
5560 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5561 if(pdwHelpStringContext)
5562 *pdwHelpStringContext=pVDesc->HelpStringContext;
5563 if(pbstrHelpStringDll)
5564 *pbstrHelpStringDll=
5565 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5566 return S_OK;
5569 return TYPE_E_ELEMENTNOTFOUND;
5572 /* ITypeInfo2::GetAllCustData
5574 * Gets all custom data items for the Type info.
5577 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5578 ITypeInfo2 * iface,
5579 CUSTDATA *pCustData)
5581 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5582 TLBCustData *pCData;
5583 int i;
5585 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5587 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5588 if(pCustData->prgCustData ){
5589 pCustData->cCustData=This->ctCustData;
5590 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5591 pCustData->prgCustData[i].guid=pCData->guid;
5592 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5594 }else{
5595 ERR(" OUT OF MEMORY! \n");
5596 return E_OUTOFMEMORY;
5598 return S_OK;
5601 /* ITypeInfo2::GetAllFuncCustData
5603 * Gets all custom data items for the specified Function
5606 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5607 ITypeInfo2 * iface,
5608 UINT index,
5609 CUSTDATA *pCustData)
5611 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5612 TLBCustData *pCData;
5613 TLBFuncDesc * pFDesc;
5614 int i;
5615 TRACE("(%p) index %d\n", This, index);
5616 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5617 pFDesc=pFDesc->next)
5619 if(pFDesc){
5620 pCustData->prgCustData =
5621 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5622 if(pCustData->prgCustData ){
5623 pCustData->cCustData=pFDesc->ctCustData;
5624 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5625 pCData = pCData->next){
5626 pCustData->prgCustData[i].guid=pCData->guid;
5627 VariantCopy(& pCustData->prgCustData[i].varValue,
5628 & pCData->data);
5630 }else{
5631 ERR(" OUT OF MEMORY! \n");
5632 return E_OUTOFMEMORY;
5634 return S_OK;
5636 return TYPE_E_ELEMENTNOTFOUND;
5639 /* ITypeInfo2::GetAllParamCustData
5641 * Gets all custom data items for the Functions
5644 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5645 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5647 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5648 TLBCustData *pCData=NULL;
5649 TLBFuncDesc * pFDesc;
5650 int i;
5651 TRACE("(%p) index %d\n", This, indexFunc);
5652 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5653 pFDesc=pFDesc->next)
5655 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5656 pCustData->prgCustData =
5657 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5658 sizeof(CUSTDATAITEM));
5659 if(pCustData->prgCustData ){
5660 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5661 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5662 pCData; i++, pCData = pCData->next){
5663 pCustData->prgCustData[i].guid=pCData->guid;
5664 VariantCopy(& pCustData->prgCustData[i].varValue,
5665 & pCData->data);
5667 }else{
5668 ERR(" OUT OF MEMORY! \n");
5669 return E_OUTOFMEMORY;
5671 return S_OK;
5673 return TYPE_E_ELEMENTNOTFOUND;
5676 /* ITypeInfo2::GetAllVarCustData
5678 * Gets all custom data items for the specified Variable
5681 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5682 UINT index, CUSTDATA *pCustData)
5684 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5685 TLBCustData *pCData;
5686 TLBVarDesc * pVDesc;
5687 int i;
5688 TRACE("(%p) index %d\n", This, index);
5689 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5690 pVDesc=pVDesc->next)
5692 if(pVDesc){
5693 pCustData->prgCustData =
5694 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5695 if(pCustData->prgCustData ){
5696 pCustData->cCustData=pVDesc->ctCustData;
5697 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5698 pCData = pCData->next){
5699 pCustData->prgCustData[i].guid=pCData->guid;
5700 VariantCopy(& pCustData->prgCustData[i].varValue,
5701 & pCData->data);
5703 }else{
5704 ERR(" OUT OF MEMORY! \n");
5705 return E_OUTOFMEMORY;
5707 return S_OK;
5709 return TYPE_E_ELEMENTNOTFOUND;
5712 /* ITypeInfo2::GetAllImplCustData
5714 * Gets all custom data items for the specified implementation type
5717 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5718 ITypeInfo2 * iface,
5719 UINT index,
5720 CUSTDATA *pCustData)
5722 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5723 TLBCustData *pCData;
5724 TLBImplType * pRDesc;
5725 int i;
5726 TRACE("(%p) index %d\n", This, index);
5727 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5728 pRDesc=pRDesc->next)
5730 if(pRDesc){
5731 pCustData->prgCustData =
5732 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5733 if(pCustData->prgCustData ){
5734 pCustData->cCustData=pRDesc->ctCustData;
5735 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5736 pCData = pCData->next){
5737 pCustData->prgCustData[i].guid=pCData->guid;
5738 VariantCopy(& pCustData->prgCustData[i].varValue,
5739 & pCData->data);
5741 }else{
5742 ERR(" OUT OF MEMORY! \n");
5743 return E_OUTOFMEMORY;
5745 return S_OK;
5747 return TYPE_E_ELEMENTNOTFOUND;
5750 static ITypeInfo2Vtbl tinfvt =
5753 ITypeInfo_fnQueryInterface,
5754 ITypeInfo_fnAddRef,
5755 ITypeInfo_fnRelease,
5757 ITypeInfo_fnGetTypeAttr,
5758 ITypeInfo_fnGetTypeComp,
5759 ITypeInfo_fnGetFuncDesc,
5760 ITypeInfo_fnGetVarDesc,
5761 ITypeInfo_fnGetNames,
5762 ITypeInfo_fnGetRefTypeOfImplType,
5763 ITypeInfo_fnGetImplTypeFlags,
5764 ITypeInfo_fnGetIDsOfNames,
5765 ITypeInfo_fnInvoke,
5766 ITypeInfo_fnGetDocumentation,
5767 ITypeInfo_fnGetDllEntry,
5768 ITypeInfo_fnGetRefTypeInfo,
5769 ITypeInfo_fnAddressOfMember,
5770 ITypeInfo_fnCreateInstance,
5771 ITypeInfo_fnGetMops,
5772 ITypeInfo_fnGetContainingTypeLib,
5773 ITypeInfo_fnReleaseTypeAttr,
5774 ITypeInfo_fnReleaseFuncDesc,
5775 ITypeInfo_fnReleaseVarDesc,
5777 ITypeInfo2_fnGetTypeKind,
5778 ITypeInfo2_fnGetTypeFlags,
5779 ITypeInfo2_fnGetFuncIndexOfMemId,
5780 ITypeInfo2_fnGetVarIndexOfMemId,
5781 ITypeInfo2_fnGetCustData,
5782 ITypeInfo2_fnGetFuncCustData,
5783 ITypeInfo2_fnGetParamCustData,
5784 ITypeInfo2_fnGetVarCustData,
5785 ITypeInfo2_fnGetImplTypeCustData,
5786 ITypeInfo2_fnGetDocumentation2,
5787 ITypeInfo2_fnGetAllCustData,
5788 ITypeInfo2_fnGetAllFuncCustData,
5789 ITypeInfo2_fnGetAllParamCustData,
5790 ITypeInfo2_fnGetAllVarCustData,
5791 ITypeInfo2_fnGetAllImplTypeCustData,
5794 /******************************************************************************
5795 * CreateDispTypeInfo [OLEAUT32.31]
5797 * Build type information for an object so it can be called through an
5798 * IDispatch interface.
5800 * RETURNS
5801 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5802 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5804 * NOTES
5805 * This call allows an objects methods to be accessed through IDispatch, by
5806 * building an ITypeInfo object that IDispatch can use to call through.
5808 HRESULT WINAPI CreateDispTypeInfo(
5809 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5810 LCID lcid, /* [I] Locale Id */
5811 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5813 ITypeInfoImpl *pTIImpl;
5814 int param, func;
5815 TLBFuncDesc **ppFuncDesc;
5817 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5818 pTIImpl->pTypeLib = NULL;
5819 pTIImpl->index = 0;
5820 pTIImpl->Name = NULL;
5821 pTIImpl->dwHelpContext = -1;
5822 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5823 pTIImpl->TypeAttr.lcid = lcid;
5824 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5825 pTIImpl->TypeAttr.wMajorVerNum = 0;
5826 pTIImpl->TypeAttr.wMinorVerNum = 0;
5827 pTIImpl->TypeAttr.cbAlignment = 2;
5828 pTIImpl->TypeAttr.cbSizeInstance = -1;
5829 pTIImpl->TypeAttr.cbSizeVft = -1;
5830 pTIImpl->TypeAttr.cFuncs = 0;
5831 pTIImpl->TypeAttr.cImplTypes = 1;
5832 pTIImpl->TypeAttr.cVars = 0;
5833 pTIImpl->TypeAttr.wTypeFlags = 0;
5835 ppFuncDesc = &pTIImpl->funclist;
5836 for(func = 0; func < pidata->cMembers; func++) {
5837 METHODDATA *md = pidata->pmethdata + func;
5838 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5839 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5840 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5841 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5842 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5843 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5844 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5845 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5846 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5847 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5848 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5849 md->cArgs * sizeof(ELEMDESC));
5850 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5851 md->cArgs * sizeof(TLBParDesc));
5852 for(param = 0; param < md->cArgs; param++) {
5853 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5854 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5856 ppFuncDesc = &(*ppFuncDesc)->next;
5858 *pptinfo = (ITypeInfo*)pTIImpl;
5859 return S_OK;
5863 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5865 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5867 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5870 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5872 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5874 return ITypeInfo_AddRef((ITypeInfo *)This);
5877 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5879 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5881 return ITypeInfo_Release((ITypeInfo *)This);
5884 static HRESULT WINAPI ITypeComp_fnBind(
5885 ITypeComp * iface,
5886 OLECHAR * szName,
5887 ULONG lHash,
5888 WORD wFlags,
5889 ITypeInfo ** ppTInfo,
5890 DESCKIND * pDescKind,
5891 BINDPTR * pBindPtr)
5893 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5894 TLBFuncDesc * pFDesc;
5895 TLBVarDesc * pVDesc;
5897 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5899 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5900 if (pFDesc->funcdesc.invkind & wFlags)
5901 if (!strcmpW(pFDesc->Name, szName)) {
5902 break;
5905 if (pFDesc)
5907 *pDescKind = DESCKIND_FUNCDESC;
5908 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5909 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5910 return S_OK;
5911 } else {
5912 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5914 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5915 if (!strcmpW(pVDesc->Name, szName)) {
5916 *pDescKind = DESCKIND_VARDESC;
5917 pBindPtr->lpvardesc = &pVDesc->vardesc;
5918 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5919 return S_OK;
5924 /* not found, look for it in inherited interfaces */
5925 if (This->TypeAttr.cImplTypes &&
5926 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5927 /* recursive search */
5928 ITypeInfo *pTInfo;
5929 ITypeComp *pTComp;
5930 HRESULT hr;
5931 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5932 if (SUCCEEDED(hr))
5934 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5935 ITypeInfo_Release(pTInfo);
5937 if (SUCCEEDED(hr))
5939 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5940 ITypeComp_Release(pTComp);
5941 return hr;
5943 WARN("Could not search inherited interface!\n");
5945 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5946 *pDescKind = DESCKIND_NONE;
5947 pBindPtr->lpfuncdesc = NULL;
5948 *ppTInfo = NULL;
5949 return DISP_E_MEMBERNOTFOUND;
5952 static HRESULT WINAPI ITypeComp_fnBindType(
5953 ITypeComp * iface,
5954 OLECHAR * szName,
5955 ULONG lHash,
5956 ITypeInfo ** ppTInfo,
5957 ITypeComp ** ppTComp)
5959 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5961 /* strange behaviour (does nothing) but like the
5962 * original */
5964 if (!ppTInfo || !ppTComp)
5965 return E_POINTER;
5967 *ppTInfo = NULL;
5968 *ppTComp = NULL;
5970 return S_OK;
5973 static ITypeCompVtbl tcompvt =
5976 ITypeComp_fnQueryInterface,
5977 ITypeComp_fnAddRef,
5978 ITypeComp_fnRelease,
5980 ITypeComp_fnBind,
5981 ITypeComp_fnBindType