The pparamdescex of an ELEMDESC should only be copied if wParamFlags &
[wine.git] / dlls / oleaut32 / typelib.c
blob682cd732b390f02822c7eeb9e86e2ac33272bd95
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
48 * behaviour.
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
56 #include "config.h"
57 #include "wine/port.h"
59 #include <stdlib.h>
60 #include <string.h>
61 #include <stdarg.h>
62 #include <stdio.h>
63 #include <ctype.h>
65 #define COBJMACROS
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
69 #include "winerror.h"
70 #include "windef.h"
71 #include "winbase.h"
72 #include "winnls.h"
73 #include "winreg.h"
74 #include "winuser.h"
76 #include "wine/unicode.h"
77 #include "objbase.h"
78 #include "typelib.h"
79 #include "wine/debug.h"
80 #include "variant.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib);
85 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
86 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
88 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt);
89 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
91 /****************************************************************************
92 * FromLExxx
94 * Takes p_iVal (which is in little endian) and returns it
95 * in the host machine's byte order.
97 #ifdef WORDS_BIGENDIAN
98 static WORD FromLEWord(WORD p_iVal)
100 return (((p_iVal & 0x00FF) << 8) |
101 ((p_iVal & 0xFF00) >> 8));
105 static DWORD FromLEDWord(DWORD p_iVal)
107 return (((p_iVal & 0x000000FF) << 24) |
108 ((p_iVal & 0x0000FF00) << 8) |
109 ((p_iVal & 0x00FF0000) >> 8) |
110 ((p_iVal & 0xFF000000) >> 24));
112 #else
113 #define FromLEWord(X) (X)
114 #define FromLEDWord(X) (X)
115 #endif
118 /****************************************************************************
119 * FromLExxx
121 * Fix byte order in any structure if necessary
123 #ifdef WORDS_BIGENDIAN
124 static void FromLEWords(void *p_Val, int p_iSize)
126 WORD *Val = p_Val;
128 p_iSize /= sizeof(WORD);
130 while (p_iSize) {
131 *Val = FromLEWord(*Val);
132 Val++;
133 p_iSize--;
138 static void FromLEDWords(void *p_Val, int p_iSize)
140 DWORD *Val = p_Val;
142 p_iSize /= sizeof(DWORD);
144 while (p_iSize) {
145 *Val = FromLEDWord(*Val);
146 Val++;
147 p_iSize--;
150 #else
151 #define FromLEWords(X,Y) /*nothing*/
152 #define FromLEDWords(X,Y) /*nothing*/
153 #endif
155 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
156 /* buffer must be at least 60 characters long */
157 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
159 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
160 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
162 memcpy( buffer, TypelibW, sizeof(TypelibW) );
163 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
165 return buffer;
168 /* get the path of an interface key, in the form "Interface\\<guid>" */
169 /* buffer must be at least 50 characters long */
170 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
172 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
174 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
175 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
176 return buffer;
179 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
180 /* buffer must be at least 16 characters long */
181 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
183 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
184 static const WCHAR win16W[] = {'w','i','n','1','6',0};
185 static const WCHAR win32W[] = {'w','i','n','3','2',0};
187 sprintfW( buffer, LcidFormatW, lcid );
188 switch(syskind)
190 case SYS_WIN16: strcatW( buffer, win16W ); break;
191 case SYS_WIN32: strcatW( buffer, win32W ); break;
192 default:
193 TRACE("Typelib is for unsupported syskind %i\n", syskind);
194 return NULL;
196 return buffer;
199 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
202 /****************************************************************************
203 * QueryPathOfRegTypeLib [OLEAUT32.164]
205 * Gets the path to a registered type library.
207 * PARAMS
208 * guid [I] referenced guid
209 * wMaj [I] major version
210 * wMin [I] minor version
211 * lcid [I] locale id
212 * path [O] path of typelib
214 * RETURNS
215 * Success: S_OK.
216 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
217 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
218 * opened.
220 HRESULT WINAPI QueryPathOfRegTypeLib(
221 REFGUID guid,
222 WORD wMaj,
223 WORD wMin,
224 LCID lcid,
225 LPBSTR path )
227 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
228 LCID myLCID = lcid;
229 HKEY hkey;
230 WCHAR buffer[60];
231 WCHAR Path[MAX_PATH];
232 LONG res;
234 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
236 get_typelib_key( guid, wMaj, wMin, buffer );
238 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
239 if (res == ERROR_FILE_NOT_FOUND)
241 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
242 return TYPE_E_LIBNOTREGISTERED;
244 else if (res != ERROR_SUCCESS)
246 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
247 return TYPE_E_REGISTRYACCESS;
250 while (hr != S_OK)
252 LONG dwPathLen = sizeof(Path);
254 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
256 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
258 if (!lcid)
259 break;
260 else if (myLCID == lcid)
262 /* try with sub-langid */
263 myLCID = SUBLANGID(lcid);
265 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
267 /* try with system langid */
268 myLCID = 0;
270 else
272 break;
275 else
277 *path = SysAllocString( Path );
278 hr = S_OK;
281 RegCloseKey( hkey );
282 TRACE_(typelib)("-- 0x%08lx\n", hr);
283 return hr;
286 /******************************************************************************
287 * CreateTypeLib [OLEAUT32.160] creates a typelib
289 * RETURNS
290 * Success: S_OK
291 * Failure: Status
293 HRESULT WINAPI CreateTypeLib(
294 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
296 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
297 return E_FAIL;
300 /******************************************************************************
301 * LoadTypeLib [OLEAUT32.161]
303 * Loads a type library
305 * PARAMS
306 * szFile [I] Name of file to load from.
307 * pptLib [O] Pointer that receives ITypeLib object on success.
309 * RETURNS
310 * Success: S_OK
311 * Failure: Status
313 * SEE
314 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
316 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
318 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
319 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
322 /******************************************************************************
323 * LoadTypeLibEx [OLEAUT32.183]
325 * Loads and optionally registers a type library
327 * RETURNS
328 * Success: S_OK
329 * Failure: Status
331 HRESULT WINAPI LoadTypeLibEx(
332 LPCOLESTR szFile, /* [in] Name of file to load from */
333 REGKIND regkind, /* [in] Specify kind of registration */
334 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
336 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
337 WCHAR *pIndexStr;
338 HRESULT res;
339 INT index = 1;
341 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
343 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
344 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
346 *pptLib = NULL;
347 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
348 NULL)) {
350 /* Look for a trailing '\\' followed by an index */
351 pIndexStr = strrchrW(szFile, '\\');
352 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
353 index = atoiW(pIndexStr);
354 memcpy(szFileCopy, szFile,
355 (pIndexStr - szFile - 1) * sizeof(WCHAR));
356 szFileCopy[pIndexStr - szFile - 1] = '\0';
357 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
358 szPath,NULL))
359 return TYPE_E_CANTLOADLIBRARY;
360 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
361 return TYPE_E_CANTLOADLIBRARY;
365 TRACE("File %s index %d\n", debugstr_w(szPath), index);
367 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
369 if (SUCCEEDED(res))
370 switch(regkind)
372 case REGKIND_DEFAULT:
373 /* don't register typelibs supplied with full path. Experimentation confirms the following */
374 if ((!szFile) ||
375 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
376 (szFile[0] && (szFile[1] == ':'))) break;
377 /* else fall-through */
379 case REGKIND_REGISTER:
380 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
382 IUnknown_Release(*pptLib);
383 *pptLib = 0;
385 break;
386 case REGKIND_NONE:
387 break;
390 TRACE(" returns %08lx\n",res);
391 return res;
394 /******************************************************************************
395 * LoadRegTypeLib [OLEAUT32.162]
397 * Loads a registered type library.
399 * PARAMS
400 * rguid [I] GUID of the registered type library.
401 * wVerMajor [I] major version.
402 * wVerMinor [I] minor version.
403 * lcid [I] locale ID.
404 * ppTLib [O] pointer that receives an ITypeLib object on success.
406 * RETURNS
407 * Success: S_OK.
408 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
409 * LoadTypeLib.
411 HRESULT WINAPI LoadRegTypeLib(
412 REFGUID rguid,
413 WORD wVerMajor,
414 WORD wVerMinor,
415 LCID lcid,
416 ITypeLib **ppTLib)
418 BSTR bstr=NULL;
419 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
421 if(SUCCEEDED(res))
423 res= LoadTypeLib(bstr, ppTLib);
424 SysFreeString(bstr);
427 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
429 return res;
433 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
434 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
435 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
436 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
437 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
438 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
440 /******************************************************************************
441 * RegisterTypeLib [OLEAUT32.163]
442 * Adds information about a type library to the System Registry
443 * NOTES
444 * Docs: ITypeLib FAR * ptlib
445 * Docs: OLECHAR FAR* szFullPath
446 * Docs: OLECHAR FAR* szHelpDir
448 * RETURNS
449 * Success: S_OK
450 * Failure: Status
452 HRESULT WINAPI RegisterTypeLib(
453 ITypeLib * ptlib, /* [in] Pointer to the library*/
454 OLECHAR * szFullPath, /* [in] full Path of the library*/
455 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
456 may be NULL*/
458 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
459 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
460 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
461 HRESULT res;
462 TLIBATTR *attr;
463 WCHAR keyName[60];
464 WCHAR tmp[16];
465 HKEY key, subKey;
466 UINT types, tidx;
467 TYPEKIND kind;
468 DWORD disposition;
470 if (ptlib == NULL || szFullPath == NULL)
471 return E_INVALIDARG;
473 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
474 return E_FAIL;
476 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
478 res = S_OK;
479 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
480 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
482 LPOLESTR doc;
484 /* Set the human-readable name of the typelib */
485 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
487 if (RegSetValueExW(key, NULL, 0, REG_SZ,
488 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
489 res = E_FAIL;
491 SysFreeString(doc);
493 else
494 res = E_FAIL;
496 /* Make up the name of the typelib path subkey */
497 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
499 /* Create the typelib path subkey */
500 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
501 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
503 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
504 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
505 res = E_FAIL;
507 RegCloseKey(subKey);
509 else
510 res = E_FAIL;
512 /* Create the flags subkey */
513 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
514 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
516 /* FIXME: is %u correct? */
517 static const WCHAR formatW[] = {'%','u',0};
518 WCHAR buf[20];
519 sprintfW(buf, formatW, attr->wLibFlags);
520 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
521 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
522 res = E_FAIL;
524 RegCloseKey(subKey);
526 else
527 res = E_FAIL;
529 /* create the helpdir subkey */
530 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
531 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
533 BOOL freeHelpDir = FALSE;
534 OLECHAR* pIndexStr;
536 /* if we created a new key, and helpDir was null, set the helpdir
537 to the directory which contains the typelib. However,
538 if we just opened an existing key, we leave the helpdir alone */
539 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
540 szHelpDir = SysAllocString(szFullPath);
541 pIndexStr = strrchrW(szHelpDir, '\\');
542 if (pIndexStr) {
543 *pIndexStr = 0;
545 freeHelpDir = TRUE;
548 /* if we have an szHelpDir, set it! */
549 if (szHelpDir != NULL) {
550 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
551 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
552 res = E_FAIL;
556 /* tidy up */
557 if (freeHelpDir) SysFreeString(szHelpDir);
558 RegCloseKey(subKey);
560 } else {
561 res = E_FAIL;
564 RegCloseKey(key);
566 else
567 res = E_FAIL;
569 /* register OLE Automation-compatible interfaces for this typelib */
570 types = ITypeLib_GetTypeInfoCount(ptlib);
571 for (tidx=0; tidx<types; tidx++) {
572 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
573 LPOLESTR name = NULL;
574 ITypeInfo *tinfo = NULL;
576 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
578 switch (kind) {
579 case TKIND_INTERFACE:
580 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
581 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
582 break;
584 case TKIND_DISPATCH:
585 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
586 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
587 break;
589 default:
590 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
591 break;
594 if (tinfo) {
595 TYPEATTR *tattr = NULL;
596 ITypeInfo_GetTypeAttr(tinfo, &tattr);
598 if (tattr) {
599 TRACE_(typelib)("guid=%s, flags=%04x (",
600 debugstr_guid(&tattr->guid),
601 tattr->wTypeFlags);
603 if (TRACE_ON(typelib)) {
604 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
605 XX(FAPPOBJECT);
606 XX(FCANCREATE);
607 XX(FLICENSED);
608 XX(FPREDECLID);
609 XX(FHIDDEN);
610 XX(FCONTROL);
611 XX(FDUAL);
612 XX(FNONEXTENSIBLE);
613 XX(FOLEAUTOMATION);
614 XX(FRESTRICTED);
615 XX(FAGGREGATABLE);
616 XX(FREPLACEABLE);
617 XX(FDISPATCHABLE);
618 XX(FREVERSEBIND);
619 XX(FPROXY);
620 #undef XX
621 MESSAGE("\n");
624 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
626 /* register interface<->typelib coupling */
627 get_interface_key( &tattr->guid, keyName );
628 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
629 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
631 if (name)
632 RegSetValueExW(key, NULL, 0, REG_SZ,
633 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
635 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
636 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
637 RegSetValueExW(subKey, NULL, 0, REG_SZ,
638 (BYTE*)PSOA, sizeof PSOA);
639 RegCloseKey(subKey);
642 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
643 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
644 RegSetValueExW(subKey, NULL, 0, REG_SZ,
645 (BYTE*)PSOA, sizeof PSOA);
646 RegCloseKey(subKey);
649 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
650 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
652 WCHAR buffer[40];
653 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
654 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
656 StringFromGUID2(&attr->guid, buffer, 40);
657 RegSetValueExW(subKey, NULL, 0, REG_SZ,
658 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
659 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
660 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
661 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
662 RegCloseKey(subKey);
665 RegCloseKey(key);
669 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
672 ITypeInfo_Release(tinfo);
675 SysFreeString(name);
679 ITypeLib_ReleaseTLibAttr(ptlib, attr);
681 return res;
685 /******************************************************************************
686 * UnRegisterTypeLib [OLEAUT32.186]
687 * Removes information about a type library from the System Registry
688 * NOTES
690 * RETURNS
691 * Success: S_OK
692 * Failure: Status
694 HRESULT WINAPI UnRegisterTypeLib(
695 REFGUID libid, /* [in] Guid of the library */
696 WORD wVerMajor, /* [in] major version */
697 WORD wVerMinor, /* [in] minor version */
698 LCID lcid, /* [in] locale id */
699 SYSKIND syskind)
701 BSTR tlibPath = NULL;
702 DWORD tmpLength;
703 WCHAR keyName[60];
704 WCHAR subKeyName[50];
705 int result = S_OK;
706 DWORD i = 0;
707 BOOL deleteOtherStuff;
708 HKEY key = NULL;
709 HKEY subKey = NULL;
710 TYPEATTR* typeAttr = NULL;
711 TYPEKIND kind;
712 ITypeInfo* typeInfo = NULL;
713 ITypeLib* typeLib = NULL;
714 int numTypes;
716 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
718 /* Create the path to the key */
719 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
721 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
723 TRACE("Unsupported syskind %i\n", syskind);
724 result = E_INVALIDARG;
725 goto end;
728 /* get the path to the typelib on disk */
729 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
730 result = E_INVALIDARG;
731 goto end;
734 /* Try and open the key to the type library. */
735 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
736 result = E_INVALIDARG;
737 goto end;
740 /* Try and load the type library */
741 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
742 result = TYPE_E_INVALIDSTATE;
743 goto end;
746 /* remove any types registered with this typelib */
747 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
748 for (i=0; i<numTypes; i++) {
749 /* get the kind of type */
750 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
751 goto enddeleteloop;
754 /* skip non-interfaces, and get type info for the type */
755 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
756 goto enddeleteloop;
758 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
759 goto enddeleteloop;
761 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
762 goto enddeleteloop;
765 /* the path to the type */
766 get_interface_key( &typeAttr->guid, subKeyName );
768 /* Delete its bits */
769 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
770 goto enddeleteloop;
772 RegDeleteKeyW(subKey, ProxyStubClsidW);
773 RegDeleteKeyW(subKey, ProxyStubClsid32W);
774 RegDeleteKeyW(subKey, TypeLibW);
775 RegCloseKey(subKey);
776 subKey = NULL;
777 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
779 enddeleteloop:
780 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
781 typeAttr = NULL;
782 if (typeInfo) ITypeInfo_Release(typeInfo);
783 typeInfo = NULL;
786 /* Now, delete the type library path subkey */
787 get_lcid_subkey( lcid, syskind, subKeyName );
788 RegDeleteKeyW(key, subKeyName);
789 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
790 RegDeleteKeyW(key, subKeyName);
792 /* check if there is anything besides the FLAGS/HELPDIR keys.
793 If there is, we don't delete them */
794 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
795 deleteOtherStuff = TRUE;
796 i = 0;
797 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
798 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
800 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
801 if (!strcmpW(subKeyName, FLAGSW)) continue;
802 if (!strcmpW(subKeyName, HELPDIRW)) continue;
803 deleteOtherStuff = FALSE;
804 break;
807 /* only delete the other parts of the key if we're absolutely sure */
808 if (deleteOtherStuff) {
809 RegDeleteKeyW(key, FLAGSW);
810 RegDeleteKeyW(key, HELPDIRW);
811 RegCloseKey(key);
812 key = NULL;
814 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
815 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
816 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
819 end:
820 if (tlibPath) SysFreeString(tlibPath);
821 if (typeLib) ITypeLib_Release(typeLib);
822 if (subKey) RegCloseKey(subKey);
823 if (key) RegCloseKey(key);
824 return result;
827 /*======================= ITypeLib implementation =======================*/
829 typedef struct tagTLBCustData
831 GUID guid;
832 VARIANT data;
833 struct tagTLBCustData* next;
834 } TLBCustData;
836 /* data structure for import typelibs */
837 typedef struct tagTLBImpLib
839 int offset; /* offset in the file (MSFT)
840 offset in nametable (SLTG)
841 just used to identify library while reading
842 data from file */
843 GUID guid; /* libid */
844 BSTR name; /* name */
846 LCID lcid; /* lcid of imported typelib */
848 WORD wVersionMajor; /* major version number */
849 WORD wVersionMinor; /* minor version number */
851 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
852 NULL if not yet loaded */
853 struct tagTLBImpLib * next;
854 } TLBImpLib;
856 /* internal ITypeLib data */
857 typedef struct tagITypeLibImpl
859 const ITypeLib2Vtbl *lpVtbl;
860 const ITypeCompVtbl *lpVtblTypeComp;
861 LONG ref;
862 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
864 /* strings can be stored in tlb as multibyte strings BUT they are *always*
865 * exported to the application as a UNICODE string.
867 BSTR Name;
868 BSTR DocString;
869 BSTR HelpFile;
870 BSTR HelpStringDll;
871 unsigned long dwHelpContext;
872 int TypeInfoCount; /* nr of typeinfo's in librarry */
873 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
874 int ctCustData; /* number of items in cust data list */
875 TLBCustData * pCustData; /* linked list to cust data */
876 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
877 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
878 libary. Only used while read MSFT
879 typelibs */
881 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
882 struct tagITypeLibImpl *next, *prev;
883 WCHAR *path;
884 INT index;
885 } ITypeLibImpl;
887 static const ITypeLib2Vtbl tlbvt;
888 static const ITypeCompVtbl tlbtcvt;
890 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
892 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
895 /* ITypeLib methods */
896 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
897 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
899 /*======================= ITypeInfo implementation =======================*/
901 /* data for referenced types */
902 typedef struct tagTLBRefType
904 INT index; /* Type index for internal ref or for external ref
905 it the format is SLTG. -2 indicates to
906 use guid */
908 GUID guid; /* guid of the referenced type */
909 /* if index == TLB_REF_USE_GUID */
911 HREFTYPE reference; /* The href of this ref */
912 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
913 TLB_REF_INTERNAL for internal refs
914 TLB_REF_NOT_FOUND for broken refs */
916 struct tagTLBRefType * next;
917 } TLBRefType;
919 #define TLB_REF_USE_GUID -2
921 #define TLB_REF_INTERNAL (void*)-2
922 #define TLB_REF_NOT_FOUND (void*)-1
924 /* internal Parameter data */
925 typedef struct tagTLBParDesc
927 BSTR Name;
928 int ctCustData;
929 TLBCustData * pCustData; /* linked list to cust data */
930 } TLBParDesc;
932 /* internal Function data */
933 typedef struct tagTLBFuncDesc
935 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
936 BSTR Name; /* the name of this function */
937 TLBParDesc *pParamDesc; /* array with param names and custom data */
938 int helpcontext;
939 int HelpStringContext;
940 BSTR HelpString;
941 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
942 int ctCustData;
943 TLBCustData * pCustData; /* linked list to cust data; */
944 struct tagTLBFuncDesc * next;
945 } TLBFuncDesc;
947 /* internal Variable data */
948 typedef struct tagTLBVarDesc
950 VARDESC vardesc; /* lots of info on the variable and its attributes. */
951 BSTR Name; /* the name of this variable */
952 int HelpContext;
953 int HelpStringContext; /* FIXME: where? */
954 BSTR HelpString;
955 int ctCustData;
956 TLBCustData * pCustData;/* linked list to cust data; */
957 struct tagTLBVarDesc * next;
958 } TLBVarDesc;
960 /* internal implemented interface data */
961 typedef struct tagTLBImplType
963 HREFTYPE hRef; /* hRef of interface */
964 int implflags; /* IMPLFLAG_*s */
965 int ctCustData;
966 TLBCustData * pCustData;/* linked list to custom data; */
967 struct tagTLBImplType *next;
968 } TLBImplType;
970 /* internal TypeInfo data */
971 typedef struct tagITypeInfoImpl
973 const ITypeInfo2Vtbl *lpVtbl;
974 const ITypeCompVtbl *lpVtblTypeComp;
975 LONG ref;
976 TYPEATTR TypeAttr ; /* _lots_ of type information. */
977 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
978 int index; /* index in this typelib; */
979 /* type libs seem to store the doc strings in ascii
980 * so why should we do it in unicode?
982 BSTR Name;
983 BSTR DocString;
984 BSTR DllName;
985 unsigned long dwHelpContext;
986 unsigned long dwHelpStringContext;
988 /* functions */
989 TLBFuncDesc * funclist; /* linked list with function descriptions */
991 /* variables */
992 TLBVarDesc * varlist; /* linked list with variable descriptions */
994 /* Implemented Interfaces */
995 TLBImplType * impltypelist;
997 TLBRefType * reflist;
998 int ctCustData;
999 TLBCustData * pCustData; /* linked list to cust data; */
1000 struct tagITypeInfoImpl * next;
1001 } ITypeInfoImpl;
1003 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1005 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1008 static const ITypeInfo2Vtbl tinfvt;
1009 static const ITypeCompVtbl tcompvt;
1011 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1013 typedef struct tagTLBContext
1015 unsigned int oStart; /* start of TLB in file */
1016 unsigned int pos; /* current pos */
1017 unsigned int length; /* total length */
1018 void *mapping; /* memory mapping */
1019 MSFT_SegDir * pTblDir;
1020 ITypeLibImpl* pLibInfo;
1021 } TLBContext;
1024 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1027 debug
1029 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1030 if (pTD->vt & VT_RESERVED)
1031 szVarType += strlen(strcpy(szVarType, "reserved | "));
1032 if (pTD->vt & VT_BYREF)
1033 szVarType += strlen(strcpy(szVarType, "ref to "));
1034 if (pTD->vt & VT_ARRAY)
1035 szVarType += strlen(strcpy(szVarType, "array of "));
1036 if (pTD->vt & VT_VECTOR)
1037 szVarType += strlen(strcpy(szVarType, "vector of "));
1038 switch(pTD->vt & VT_TYPEMASK) {
1039 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1040 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1041 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1042 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1043 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1044 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1045 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1046 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1047 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1048 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1049 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1050 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1051 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1052 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1053 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1054 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1055 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1056 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1057 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1058 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1059 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1060 pTD->u.hreftype); break;
1061 case VT_PTR: sprintf(szVarType, "ptr to ");
1062 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1063 break;
1064 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1065 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1066 break;
1067 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1068 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1069 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1070 break;
1072 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1076 static void dump_ELEMDESC(ELEMDESC *edesc) {
1077 char buf[200];
1078 USHORT flags = edesc->u.paramdesc.wParamFlags;
1079 dump_TypeDesc(&edesc->tdesc,buf);
1080 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1081 MESSAGE("\t\tu.paramdesc.wParamFlags");
1082 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1083 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1084 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1085 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1086 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1087 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1088 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1089 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1090 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1092 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
1093 int i;
1094 MESSAGE("memid is %08lx\n",funcdesc->memid);
1095 for (i=0;i<funcdesc->cParams;i++) {
1096 MESSAGE("Param %d:\n",i);
1097 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1099 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1100 switch (funcdesc->funckind) {
1101 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1102 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1103 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1104 case FUNC_STATIC: MESSAGE("static");break;
1105 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1106 default: MESSAGE("unknown");break;
1108 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1109 switch (funcdesc->invkind) {
1110 case INVOKE_FUNC: MESSAGE("func");break;
1111 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1112 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1113 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1115 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1116 switch (funcdesc->callconv) {
1117 case CC_CDECL: MESSAGE("cdecl");break;
1118 case CC_PASCAL: MESSAGE("pascal");break;
1119 case CC_STDCALL: MESSAGE("stdcall");break;
1120 case CC_SYSCALL: MESSAGE("syscall");break;
1121 default:break;
1123 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1124 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1125 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1127 MESSAGE("\telemdescFunc (return value type):\n");
1128 dump_ELEMDESC(&funcdesc->elemdescFunc);
1131 static const char * typekind_desc[] =
1133 "TKIND_ENUM",
1134 "TKIND_RECORD",
1135 "TKIND_MODULE",
1136 "TKIND_INTERFACE",
1137 "TKIND_DISPATCH",
1138 "TKIND_COCLASS",
1139 "TKIND_ALIAS",
1140 "TKIND_UNION",
1141 "TKIND_MAX"
1144 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1146 int i;
1147 if (!TRACE_ON(typelib))
1148 return;
1149 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1150 for (i=0;i<pfd->funcdesc.cParams;i++)
1151 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1154 dump_FUNCDESC(&(pfd->funcdesc));
1156 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1157 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1159 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1161 while (pfd)
1163 dump_TLBFuncDescOne(pfd);
1164 pfd = pfd->next;
1167 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1169 while (pvd)
1171 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1172 pvd = pvd->next;
1176 static void dump_TLBImpLib(TLBImpLib *import)
1178 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1179 debugstr_w(import->name));
1180 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1181 import->wVersionMinor, import->lcid, import->offset);
1184 static void dump_TLBRefType(TLBRefType * prt)
1186 while (prt)
1188 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1189 if(prt->index == -1)
1190 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1191 else
1192 TRACE_(typelib)("type no: %d\n", prt->index);
1194 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1195 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1196 TRACE_(typelib)("in lib\n");
1197 dump_TLBImpLib(prt->pImpTLInfo);
1199 prt = prt->next;
1203 static void dump_TLBImplType(TLBImplType * impl)
1205 while (impl) {
1206 TRACE_(typelib)(
1207 "implementing/inheriting interface hRef = %lx implflags %x\n",
1208 impl->hRef, impl->implflags);
1209 impl = impl->next;
1213 void dump_Variant(VARIANT * pvar)
1215 SYSTEMTIME st;
1217 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1219 if (pvar)
1221 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1222 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1224 TRACE(",%p", V_BYREF(pvar));
1226 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1228 TRACE(",FIXME");
1230 else switch (V_TYPE(pvar))
1232 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1233 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1234 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1235 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1236 case VT_INT:
1237 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1238 case VT_UINT:
1239 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1240 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1241 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1242 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1243 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1244 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1245 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1246 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1247 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1248 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1249 V_CY(pvar).s.Lo); break;
1250 case VT_DATE:
1251 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1252 TRACE(",<invalid>");
1253 else
1254 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1255 st.wHour, st.wMinute, st.wSecond);
1256 break;
1257 case VT_ERROR:
1258 case VT_VOID:
1259 case VT_USERDEFINED:
1260 case VT_EMPTY:
1261 case VT_NULL: break;
1262 default: TRACE(",?"); break;
1265 TRACE("}\n");
1268 static void dump_DispParms(DISPPARAMS * pdp)
1270 int index = 0;
1272 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1274 while (index < pdp->cArgs)
1276 dump_Variant( &pdp->rgvarg[index] );
1277 ++index;
1281 static void dump_TypeInfo(ITypeInfoImpl * pty)
1283 TRACE("%p ref=%lu\n", pty, pty->ref);
1284 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1285 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1286 TRACE("fct:%u var:%u impl:%u\n",
1287 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1288 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1289 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1290 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1291 dump_TLBFuncDesc(pty->funclist);
1292 dump_TLBVarDesc(pty->varlist);
1293 dump_TLBImplType(pty->impltypelist);
1296 static void dump_VARDESC(VARDESC *v)
1298 MESSAGE("memid %ld\n",v->memid);
1299 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1300 MESSAGE("oInst %ld\n",v->u.oInst);
1301 dump_ELEMDESC(&(v->elemdescVar));
1302 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1303 MESSAGE("varkind %d\n",v->varkind);
1306 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1308 /* VT_LPWSTR is largest type that */
1309 /* may appear in type description*/
1310 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1311 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1312 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1313 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1314 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1315 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1316 {{0},30},{{0},31}
1319 static void TLB_abort(void)
1321 DebugBreak();
1323 static void * TLB_Alloc(unsigned size)
1325 void * ret;
1326 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1327 /* FIXME */
1328 ERR("cannot allocate memory\n");
1330 return ret;
1333 static void TLB_Free(void * ptr)
1335 HeapFree(GetProcessHeap(), 0, ptr);
1338 /* returns the size required for a deep copy of a typedesc into a
1339 * flat buffer */
1340 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1342 SIZE_T size = 0;
1344 if (alloc_initial_space)
1345 size += sizeof(TYPEDESC);
1347 switch (tdesc->vt)
1349 case VT_PTR:
1350 case VT_SAFEARRAY:
1351 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1352 break;
1353 case VT_CARRAY:
1354 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1355 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1356 break;
1358 return size;
1361 /* deep copy a typedesc into a flat buffer */
1362 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1364 if (!dest)
1366 dest = buffer;
1367 buffer = (char *)buffer + sizeof(TYPEDESC);
1370 *dest = *src;
1372 switch (src->vt)
1374 case VT_PTR:
1375 case VT_SAFEARRAY:
1376 dest->u.lptdesc = buffer;
1377 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1378 break;
1379 case VT_CARRAY:
1380 dest->u.lpadesc = buffer;
1381 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1382 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1383 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1384 break;
1386 return buffer;
1389 /**********************************************************************
1391 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1393 /* read function */
1394 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1396 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1397 pcx->pos, count, pcx->oStart, pcx->length, where);
1399 if (where != DO_NOT_SEEK)
1401 where += pcx->oStart;
1402 if (where > pcx->length)
1404 /* FIXME */
1405 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1406 TLB_abort();
1408 pcx->pos = where;
1410 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1411 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1412 pcx->pos += count;
1413 return count;
1416 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1417 long where )
1419 DWORD ret;
1421 ret = MSFT_Read(buffer, count, pcx, where);
1422 FromLEDWords(buffer, ret);
1424 return ret;
1427 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1428 long where )
1430 DWORD ret;
1432 ret = MSFT_Read(buffer, count, pcx, where);
1433 FromLEWords(buffer, ret);
1435 return ret;
1438 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1440 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1441 memset(pGuid,0, sizeof(GUID));
1442 return;
1444 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1445 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1446 pGuid->Data2 = FromLEWord(pGuid->Data2);
1447 pGuid->Data3 = FromLEWord(pGuid->Data3);
1448 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1451 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1453 char * name;
1454 MSFT_NameIntro niName;
1455 int lengthInChars;
1456 WCHAR* pwstring = NULL;
1457 BSTR bstrName = NULL;
1459 if (offset < 0)
1461 ERR_(typelib)("bad offset %d\n", offset);
1462 return NULL;
1464 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1465 pcx->pTblDir->pNametab.offset+offset);
1466 niName.namelen &= 0xFF; /* FIXME: correct ? */
1467 name=TLB_Alloc((niName.namelen & 0xff) +1);
1468 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1469 name[niName.namelen & 0xff]='\0';
1471 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1472 name, -1, NULL, 0);
1474 /* no invalid characters in string */
1475 if (lengthInChars)
1477 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1479 /* don't check for invalid character since this has been done previously */
1480 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1482 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1483 lengthInChars = SysStringLen(bstrName);
1484 HeapFree(GetProcessHeap(), 0, pwstring);
1487 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1488 return bstrName;
1491 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1493 char * string;
1494 INT16 length;
1495 int lengthInChars;
1496 BSTR bstr = NULL;
1498 if(offset<0) return NULL;
1499 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1500 if(length <= 0) return 0;
1501 string=TLB_Alloc(length +1);
1502 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1503 string[length]='\0';
1505 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1506 string, -1, NULL, 0);
1508 /* no invalid characters in string */
1509 if (lengthInChars)
1511 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1513 /* don't check for invalid character since this has been done previously */
1514 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1516 bstr = SysAllocStringLen(pwstring, lengthInChars);
1517 lengthInChars = SysStringLen(bstr);
1518 HeapFree(GetProcessHeap(), 0, pwstring);
1521 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1522 return bstr;
1525 * read a value and fill a VARIANT structure
1527 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1529 int size;
1531 TRACE_(typelib)("\n");
1533 if(offset <0) { /* data are packed in here */
1534 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1535 V_I2(pVar) = offset & 0x3ffffff;
1536 return;
1538 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1539 pcx->pTblDir->pCustData.offset + offset );
1540 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1541 switch (V_VT(pVar)){
1542 case VT_EMPTY: /* FIXME: is this right? */
1543 case VT_NULL: /* FIXME: is this right? */
1544 case VT_I2 : /* this should not happen */
1545 case VT_I4 :
1546 case VT_R4 :
1547 case VT_ERROR :
1548 case VT_BOOL :
1549 case VT_I1 :
1550 case VT_UI1 :
1551 case VT_UI2 :
1552 case VT_UI4 :
1553 case VT_INT :
1554 case VT_UINT :
1555 case VT_VOID : /* FIXME: is this right? */
1556 case VT_HRESULT :
1557 size=4; break;
1558 case VT_R8 :
1559 case VT_CY :
1560 case VT_DATE :
1561 case VT_I8 :
1562 case VT_UI8 :
1563 case VT_DECIMAL : /* FIXME: is this right? */
1564 case VT_FILETIME :
1565 size=8;break;
1566 /* pointer types with known behaviour */
1567 case VT_BSTR :{
1568 char * ptr;
1569 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1570 if(size < 0) {
1571 FIXME("BSTR length = %d?\n", size);
1572 } else {
1573 ptr=TLB_Alloc(size);/* allocate temp buffer */
1574 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1575 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1576 /* FIXME: do we need a AtoW conversion here? */
1577 V_UNION(pVar, bstrVal[size])=L'\0';
1578 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1579 TLB_Free(ptr);
1582 size=-4; break;
1583 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1584 case VT_DISPATCH :
1585 case VT_VARIANT :
1586 case VT_UNKNOWN :
1587 case VT_PTR :
1588 case VT_SAFEARRAY :
1589 case VT_CARRAY :
1590 case VT_USERDEFINED :
1591 case VT_LPSTR :
1592 case VT_LPWSTR :
1593 case VT_BLOB :
1594 case VT_STREAM :
1595 case VT_STORAGE :
1596 case VT_STREAMED_OBJECT :
1597 case VT_STORED_OBJECT :
1598 case VT_BLOB_OBJECT :
1599 case VT_CF :
1600 case VT_CLSID :
1601 default:
1602 size=0;
1603 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1604 V_VT(pVar));
1607 if(size>0) /* (big|small) endian correct? */
1608 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1609 return;
1612 * create a linked list with custom data
1614 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1616 MSFT_CDGuid entry;
1617 TLBCustData* pNew;
1618 int count=0;
1620 TRACE_(typelib)("\n");
1622 while(offset >=0){
1623 count++;
1624 pNew=TLB_Alloc(sizeof(TLBCustData));
1625 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1626 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1627 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1628 /* add new custom data at head of the list */
1629 pNew->next=*ppCustData;
1630 *ppCustData=pNew;
1631 offset = entry.next;
1633 return count;
1636 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1637 ITypeInfoImpl *pTI)
1639 if(type <0)
1640 pTd->vt=type & VT_TYPEMASK;
1641 else
1642 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1644 if(pTd->vt == VT_USERDEFINED)
1645 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1647 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1650 static void
1651 MSFT_DoFuncs(TLBContext* pcx,
1652 ITypeInfoImpl* pTI,
1653 int cFuncs,
1654 int cVars,
1655 int offset,
1656 TLBFuncDesc** pptfd)
1659 * member information is stored in a data structure at offset
1660 * indicated by the memoffset field of the typeinfo structure
1661 * There are several distinctive parts.
1662 * The first part starts with a field that holds the total length
1663 * of this (first) part excluding this field. Then follow the records,
1664 * for each member there is one record.
1666 * The first entry is always the length of the record (including this
1667 * length word).
1668 * The rest of the record depends on the type of the member. If there is
1669 * a field indicating the member type (function, variable, interface, etc)
1670 * I have not found it yet. At this time we depend on the information
1671 * in the type info and the usual order how things are stored.
1673 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1674 * for each member;
1676 * Third is an equal sized array with file offsets to the name entry
1677 * of each member.
1679 * The fourth and last (?) part is an array with offsets to the records
1680 * in the first part of this file segment.
1683 int infolen, nameoffset, reclength, nrattributes, i;
1684 int recoffset = offset + sizeof(INT);
1686 char recbuf[512];
1687 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1689 TRACE_(typelib)("\n");
1691 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1693 for ( i = 0; i < cFuncs ; i++ )
1695 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1697 /* name, eventually add to a hash table */
1698 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1699 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1701 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1703 /* read the function information record */
1704 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1706 reclength &= 0x1ff;
1708 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1710 /* do the attributes */
1711 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1712 / sizeof(int);
1714 if ( nrattributes > 0 )
1716 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1718 if ( nrattributes > 1 )
1720 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1721 pFuncRec->OptAttr[1]) ;
1723 if ( nrattributes > 2 )
1725 if ( pFuncRec->FKCCIC & 0x2000 )
1727 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1729 else
1731 (*pptfd)->Entry = MSFT_ReadString(pcx,
1732 pFuncRec->OptAttr[2]);
1734 if( nrattributes > 5 )
1736 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1738 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1740 MSFT_CustData(pcx,
1741 pFuncRec->OptAttr[6],
1742 &(*pptfd)->pCustData);
1749 /* fill the FuncDesc Structure */
1750 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1751 offset + infolen + ( i + 1) * sizeof(INT));
1753 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1754 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1755 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1756 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1757 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1758 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1759 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1761 MSFT_GetTdesc(pcx,
1762 pFuncRec->DataType,
1763 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1764 pTI);
1766 /* do the parameters/arguments */
1767 if(pFuncRec->nrargs)
1769 int j = 0;
1770 MSFT_ParameterInfo paraminfo;
1772 (*pptfd)->funcdesc.lprgelemdescParam =
1773 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1775 (*pptfd)->pParamDesc =
1776 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1778 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1779 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1781 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1783 TYPEDESC* lpArgTypeDesc = 0;
1785 MSFT_GetTdesc(pcx,
1786 paraminfo.DataType,
1787 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1788 pTI);
1790 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1792 /* name */
1793 if (paraminfo.oName == -1)
1794 /* this occurs for [propput] or [propget] methods, so
1795 * we should just set the name of the parameter to the
1796 * name of the method. */
1797 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1798 else
1799 (*pptfd)->pParamDesc[j].Name =
1800 MSFT_ReadName( pcx, paraminfo.oName );
1801 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1803 /* SEEK value = jump to offset,
1804 * from there jump to the end of record,
1805 * go back by (j-1) arguments
1807 MSFT_ReadLEDWords( &paraminfo ,
1808 sizeof(MSFT_ParameterInfo), pcx,
1809 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1810 * sizeof(MSFT_ParameterInfo)));
1811 lpArgTypeDesc =
1812 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1814 while ( lpArgTypeDesc != NULL )
1816 switch ( lpArgTypeDesc->vt )
1818 case VT_PTR:
1819 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1820 break;
1822 case VT_CARRAY:
1823 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1824 break;
1826 case VT_USERDEFINED:
1827 MSFT_DoRefType(pcx, pTI,
1828 lpArgTypeDesc->u.hreftype);
1830 lpArgTypeDesc = NULL;
1831 break;
1833 default:
1834 lpArgTypeDesc = NULL;
1840 /* parameter is the return value! */
1841 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1843 TYPEDESC* lpArgTypeDesc;
1845 (*pptfd)->funcdesc.elemdescFunc =
1846 (*pptfd)->funcdesc.lprgelemdescParam[j];
1848 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1850 while ( lpArgTypeDesc != NULL )
1852 switch ( lpArgTypeDesc->vt )
1854 case VT_PTR:
1855 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1856 break;
1857 case VT_CARRAY:
1858 lpArgTypeDesc =
1859 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1861 break;
1863 case VT_USERDEFINED:
1864 MSFT_DoRefType(pcx,
1865 pTI,
1866 lpArgTypeDesc->u.hreftype);
1868 lpArgTypeDesc = NULL;
1869 break;
1871 default:
1872 lpArgTypeDesc = NULL;
1877 /* second time around */
1878 for(j=0;j<pFuncRec->nrargs;j++)
1880 /* default value */
1881 if ( (PARAMFLAG_FHASDEFAULT &
1882 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1883 ((pFuncRec->FKCCIC) & 0x1000) )
1885 INT* pInt = (INT *)((char *)pFuncRec +
1886 reclength -
1887 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1889 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1891 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1892 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1894 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1895 pInt[j], pcx);
1897 /* custom info */
1898 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1900 MSFT_CustData(pcx,
1901 pFuncRec->OptAttr[7+j],
1902 &(*pptfd)->pParamDesc[j].pCustData);
1907 /* scode is not used: archaic win16 stuff FIXME: right? */
1908 (*pptfd)->funcdesc.cScodes = 0 ;
1909 (*pptfd)->funcdesc.lprgscode = NULL ;
1911 pptfd = & ((*pptfd)->next);
1912 recoffset += reclength;
1916 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1917 int cVars, int offset, TLBVarDesc ** pptvd)
1919 int infolen, nameoffset, reclength;
1920 char recbuf[256];
1921 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1922 int i;
1923 int recoffset;
1925 TRACE_(typelib)("\n");
1927 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1928 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1929 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1930 recoffset += offset+sizeof(INT);
1931 for(i=0;i<cVars;i++){
1932 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1933 /* name, eventually add to a hash table */
1934 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1935 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1936 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1937 /* read the variable information record */
1938 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1939 reclength &=0xff;
1940 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1941 /* Optional data */
1942 if(reclength >(6*sizeof(INT)) )
1943 (*pptvd)->HelpContext=pVarRec->HelpContext;
1944 if(reclength >(7*sizeof(INT)) )
1945 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1946 if(reclength >(8*sizeof(INT)) )
1947 if(reclength >(9*sizeof(INT)) )
1948 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1949 /* fill the VarDesc Structure */
1950 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1951 offset + infolen + ( i + 1) * sizeof(INT));
1952 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1953 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1954 MSFT_GetTdesc(pcx, pVarRec->DataType,
1955 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1956 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1957 if(pVarRec->VarKind == VAR_CONST ){
1958 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1959 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1960 pVarRec->OffsValue, pcx);
1961 } else
1962 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1963 pptvd=&((*pptvd)->next);
1964 recoffset += reclength;
1967 /* fill in data for a hreftype (offset). When the referenced type is contained
1968 * in the typelib, it's just an (file) offset in the type info base dir.
1969 * If comes from import, it's an offset+1 in the ImpInfo table
1970 * */
1971 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1972 int offset)
1974 int j;
1975 TLBRefType **ppRefType = &pTI->reflist;
1977 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1979 while(*ppRefType) {
1980 if((*ppRefType)->reference == offset)
1981 return;
1982 ppRefType = &(*ppRefType)->next;
1985 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1986 sizeof(**ppRefType));
1988 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1989 /* external typelib */
1990 MSFT_ImpInfo impinfo;
1991 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1993 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1995 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1996 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1997 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1998 if(pImpLib->offset==impinfo.oImpFile) break;
1999 pImpLib=pImpLib->next;
2001 if(pImpLib){
2002 (*ppRefType)->reference=offset;
2003 (*ppRefType)->pImpTLInfo = pImpLib;
2004 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2005 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2006 (*ppRefType)->index = TLB_REF_USE_GUID;
2007 } else
2008 (*ppRefType)->index = impinfo.oGuid;
2009 }else{
2010 ERR("Cannot find a reference\n");
2011 (*ppRefType)->reference=-1;
2012 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2014 }else{
2015 /* in this typelib */
2016 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2017 (*ppRefType)->reference=offset;
2018 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2022 /* process Implemented Interfaces of a com class */
2023 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2024 int offset)
2026 int i;
2027 MSFT_RefRecord refrec;
2028 TLBImplType **ppImpl = &pTI->impltypelist;
2030 TRACE_(typelib)("\n");
2032 for(i=0;i<count;i++){
2033 if(offset<0) break; /* paranoia */
2034 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2035 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2036 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2037 (*ppImpl)->hRef = refrec.reftype;
2038 (*ppImpl)->implflags=refrec.flags;
2039 (*ppImpl)->ctCustData=
2040 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2041 offset=refrec.onext;
2042 ppImpl=&((*ppImpl)->next);
2046 * process a typeinfo record
2048 static ITypeInfoImpl * MSFT_DoTypeInfo(
2049 TLBContext *pcx,
2050 int count,
2051 ITypeLibImpl * pLibInfo)
2053 MSFT_TypeInfoBase tiBase;
2054 ITypeInfoImpl *ptiRet;
2056 TRACE_(typelib)("count=%u\n", count);
2058 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2059 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2060 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2062 /* this is where we are coming from */
2063 ptiRet->pTypeLib = pLibInfo;
2064 ptiRet->index=count;
2065 /* fill in the typeattr fields */
2066 WARN("Assign constructor/destructor memid\n");
2068 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2069 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2070 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2071 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2072 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2073 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2074 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2075 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2076 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2077 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2078 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2079 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2080 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2081 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2082 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2083 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2084 MSFT_GetTdesc(pcx, tiBase.datatype1,
2085 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2087 /* FIXME: */
2088 /* IDLDESC idldescType; *//* never saw this one != zero */
2090 /* name, eventually add to a hash table */
2091 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2092 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2093 /* help info */
2094 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2095 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2096 ptiRet->dwHelpContext=tiBase.helpcontext;
2098 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2099 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2101 /* note: InfoType's Help file and HelpStringDll come from the containing
2102 * library. Further HelpString and Docstring appear to be the same thing :(
2104 /* functions */
2105 if(ptiRet->TypeAttr.cFuncs >0 )
2106 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2107 ptiRet->TypeAttr.cVars,
2108 tiBase.memoffset, & ptiRet->funclist);
2109 /* variables */
2110 if(ptiRet->TypeAttr.cVars >0 )
2111 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2112 ptiRet->TypeAttr.cVars,
2113 tiBase.memoffset, & ptiRet->varlist);
2114 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2115 switch(ptiRet->TypeAttr.typekind)
2117 case TKIND_COCLASS:
2118 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2119 tiBase.datatype1);
2120 break;
2121 case TKIND_DISPATCH:
2122 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2124 if (tiBase.datatype1 != -1)
2126 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2127 ptiRet->impltypelist->hRef = tiBase.datatype1;
2129 else
2130 { /* FIXME: This is a really bad hack to add IDispatch */
2131 const char* szStdOle = "stdole2.tlb\0";
2132 int nStdOleLen = strlen(szStdOle);
2133 TLBRefType **ppRef = &ptiRet->reflist;
2135 while(*ppRef) {
2136 if((*ppRef)->reference == -1)
2137 break;
2138 ppRef = &(*ppRef)->next;
2140 if(!*ppRef) {
2141 *ppRef = TLB_Alloc(sizeof(**ppRef));
2142 (*ppRef)->guid = IID_IDispatch;
2143 (*ppRef)->reference = -1;
2144 (*ppRef)->index = TLB_REF_USE_GUID;
2145 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2146 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2147 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2148 nStdOleLen + 1);
2150 MultiByteToWideChar(CP_ACP,
2151 MB_PRECOMPOSED,
2152 szStdOle,
2154 (*ppRef)->pImpTLInfo->name,
2155 SysStringLen((*ppRef)->pImpTLInfo->name));
2157 (*ppRef)->pImpTLInfo->lcid = 0;
2158 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2159 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2162 break;
2163 default:
2164 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2165 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2166 ptiRet->impltypelist->hRef = tiBase.datatype1;
2167 break;
2170 ptiRet->ctCustData=
2171 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2173 TRACE_(typelib)("%s guid: %s kind:%s\n",
2174 debugstr_w(ptiRet->Name),
2175 debugstr_guid(&ptiRet->TypeAttr.guid),
2176 typekind_desc[ptiRet->TypeAttr.typekind]);
2178 return ptiRet;
2181 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2182 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2183 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2184 * tradeoff here.
2186 static ITypeLibImpl *tlb_cache_first;
2187 static CRITICAL_SECTION cache_section;
2188 static CRITICAL_SECTION_DEBUG cache_section_debug =
2190 0, 0, &cache_section,
2191 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2192 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2194 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2197 /****************************************************************************
2198 * TLB_ReadTypeLib
2200 * find the type of the typelib file and map the typelib resource into
2201 * the memory
2203 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2204 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2205 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2207 ITypeLibImpl *entry;
2208 int ret = TYPE_E_CANTLOADLIBRARY;
2209 DWORD dwSignature = 0;
2210 HANDLE hFile;
2212 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2214 *ppTypeLib = NULL;
2216 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2217 EnterCriticalSection(&cache_section);
2218 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2220 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2222 TRACE("cache hit\n");
2223 *ppTypeLib = (ITypeLib2*)entry;
2224 ITypeLib_AddRef(*ppTypeLib);
2225 LeaveCriticalSection(&cache_section);
2226 return S_OK;
2229 LeaveCriticalSection(&cache_section);
2231 /* check the signature of the file */
2232 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2233 if (INVALID_HANDLE_VALUE != hFile)
2235 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2236 if (hMapping)
2238 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2239 if(pBase)
2241 /* retrieve file size */
2242 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2244 /* first try to load as *.tlb */
2245 dwSignature = FromLEDWord(*((DWORD*) pBase));
2246 if ( dwSignature == MSFT_SIGNATURE)
2248 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2250 else if ( dwSignature == SLTG_SIGNATURE)
2252 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2254 UnmapViewOfFile(pBase);
2256 CloseHandle(hMapping);
2258 CloseHandle(hFile);
2260 else
2262 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2265 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2266 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2268 /* find the typelibrary resource*/
2269 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2270 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2271 if (hinstDLL)
2273 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2274 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2275 if (hrsrc)
2277 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2278 if (hGlobal)
2280 LPVOID pBase = LockResource(hGlobal);
2281 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2283 if (pBase)
2285 /* try to load as incore resource */
2286 dwSignature = FromLEDWord(*((DWORD*) pBase));
2287 if ( dwSignature == MSFT_SIGNATURE)
2289 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2291 else if ( dwSignature == SLTG_SIGNATURE)
2293 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2295 else
2297 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2300 FreeResource( hGlobal );
2303 FreeLibrary(hinstDLL);
2307 if(*ppTypeLib) {
2308 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2310 TRACE("adding to cache\n");
2311 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2312 lstrcpyW(impl->path, pszFileName);
2313 /* We should really canonicalise the path here. */
2314 impl->index = index;
2316 /* FIXME: check if it has added already in the meantime */
2317 EnterCriticalSection(&cache_section);
2318 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2319 impl->prev = NULL;
2320 tlb_cache_first = impl;
2321 LeaveCriticalSection(&cache_section);
2322 ret = S_OK;
2323 } else
2324 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2326 return ret;
2329 /*================== ITypeLib(2) Methods ===================================*/
2331 /****************************************************************************
2332 * ITypeLib2_Constructor_MSFT
2334 * loading an MSFT typelib from an in-memory image
2336 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2338 TLBContext cx;
2339 long lPSegDir;
2340 MSFT_Header tlbHeader;
2341 MSFT_SegDir tlbSegDir;
2342 ITypeLibImpl * pTypeLibImpl;
2344 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2346 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2347 if (!pTypeLibImpl) return NULL;
2349 pTypeLibImpl->lpVtbl = &tlbvt;
2350 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2351 pTypeLibImpl->ref = 1;
2353 /* get pointer to beginning of typelib data */
2354 cx.pos = 0;
2355 cx.oStart=0;
2356 cx.mapping = pLib;
2357 cx.pLibInfo = pTypeLibImpl;
2358 cx.length = dwTLBLength;
2360 /* read header */
2361 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2362 TRACE("header:\n");
2363 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2364 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2365 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2366 return NULL;
2368 /* there is a small amount of information here until the next important
2369 * part:
2370 * the segment directory . Try to calculate the amount of data */
2371 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2373 /* now read the segment directory */
2374 TRACE("read segment directory (at %ld)\n",lPSegDir);
2375 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2376 cx.pTblDir = &tlbSegDir;
2378 /* just check two entries */
2379 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2381 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2382 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2383 return NULL;
2386 /* now fill our internal data */
2387 /* TLIBATTR fields */
2388 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2390 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2391 /* Windows seems to have zero here, is this correct? */
2392 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2393 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2394 else
2395 pTypeLibImpl->LibAttr.lcid = 0;
2397 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2398 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2399 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2400 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2402 /* name, eventually add to a hash table */
2403 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2405 /* help info */
2406 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2407 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2409 if( tlbHeader.varflags & HELPDLLFLAG)
2411 int offset;
2412 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2413 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2416 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2418 /* custom data */
2419 if(tlbHeader.CustomDataOffset >= 0)
2421 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2424 /* fill in typedescriptions */
2425 if(tlbSegDir.pTypdescTab.length > 0)
2427 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2428 INT16 td[4];
2429 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2430 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2431 for(i=0; i<cTD; )
2433 /* FIXME: add several sanity checks here */
2434 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2435 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2437 /* FIXME: check safearray */
2438 if(td[3] < 0)
2439 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2440 else
2441 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2443 else if(td[0] == VT_CARRAY)
2445 /* array descr table here */
2446 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2448 else if(td[0] == VT_USERDEFINED)
2450 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2452 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2455 /* second time around to fill the array subscript info */
2456 for(i=0;i<cTD;i++)
2458 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2459 if(tlbSegDir.pArrayDescriptions.offset>0)
2461 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2462 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2464 if(td[1]<0)
2465 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2466 else
2467 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2469 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2471 for(j = 0; j<td[2]; j++)
2473 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2474 sizeof(INT), &cx, DO_NOT_SEEK);
2475 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2476 sizeof(INT), &cx, DO_NOT_SEEK);
2479 else
2481 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2482 ERR("didn't find array description data\n");
2487 /* imported type libs */
2488 if(tlbSegDir.pImpFiles.offset>0)
2490 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2491 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2492 UINT16 size;
2494 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2496 char *name;
2497 DWORD len;
2499 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2500 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2501 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2503 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2504 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2505 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2506 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2508 size >>= 2;
2509 name = TLB_Alloc(size+1);
2510 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2511 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2512 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2513 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2514 TLB_Free(name);
2516 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2517 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2519 ppImpLib = &(*ppImpLib)->next;
2523 /* type info's */
2524 if(tlbHeader.nrtypeinfos >= 0 )
2526 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2527 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2528 int i;
2530 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2532 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2534 ppTI = &((*ppTI)->next);
2535 (pTypeLibImpl->TypeInfoCount)++;
2539 TRACE("(%p)\n", pTypeLibImpl);
2540 return (ITypeLib2*) pTypeLibImpl;
2544 static BSTR TLB_MultiByteToBSTR(char *ptr)
2546 DWORD len;
2547 WCHAR *nameW;
2548 BSTR ret;
2550 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2551 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2552 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2553 ret = SysAllocString(nameW);
2554 HeapFree(GetProcessHeap(), 0, nameW);
2555 return ret;
2558 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2560 char b[3];
2561 int i;
2562 short s;
2564 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2565 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2566 return FALSE;
2569 guid->Data4[0] = s >> 8;
2570 guid->Data4[1] = s & 0xff;
2572 b[2] = '\0';
2573 for(i = 0; i < 6; i++) {
2574 memcpy(b, str + 24 + 2 * i, 2);
2575 guid->Data4[i + 2] = strtol(b, NULL, 16);
2577 return TRUE;
2580 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2582 WORD bytelen;
2583 DWORD len;
2584 WCHAR *nameW;
2586 *pBstr = NULL;
2587 bytelen = *(WORD*)ptr;
2588 if(bytelen == 0xffff) return 2;
2589 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2590 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2591 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2592 *pBstr = SysAllocStringLen(nameW, len);
2593 HeapFree(GetProcessHeap(), 0, nameW);
2594 return bytelen + 2;
2597 static WORD SLTG_ReadStringA(char *ptr, char **str)
2599 WORD bytelen;
2601 *str = NULL;
2602 bytelen = *(WORD*)ptr;
2603 if(bytelen == 0xffff) return 2;
2604 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2605 memcpy(*str, ptr + 2, bytelen);
2606 (*str)[bytelen] = '\0';
2607 return bytelen + 2;
2610 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2612 char *ptr = pLibBlk;
2613 WORD w;
2615 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2616 FIXME("libblk magic = %04x\n", w);
2617 return 0;
2620 ptr += 6;
2621 if((w = *(WORD*)ptr) != 0xffff) {
2622 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2623 ptr += w;
2625 ptr += 2;
2627 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2629 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2631 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2632 ptr += 4;
2634 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2635 ptr += 2;
2637 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2638 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2639 else
2640 pTypeLibImpl->LibAttr.lcid = 0;
2641 ptr += 2;
2643 ptr += 4; /* skip res12 */
2645 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2646 ptr += 2;
2648 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2649 ptr += 2;
2651 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2652 ptr += 2;
2654 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2655 ptr += sizeof(GUID);
2657 return ptr - (char*)pLibBlk;
2660 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2662 BOOL done = FALSE;
2663 TYPEDESC *pTD = &pElem->tdesc;
2665 /* Handle [in/out] first */
2666 if((*pType & 0xc000) == 0xc000)
2667 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2668 else if(*pType & 0x8000)
2669 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2670 else if(*pType & 0x4000)
2671 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2672 else
2673 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2675 if(*pType & 0x2000)
2676 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2678 if(*pType & 0x80)
2679 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2681 while(!done) {
2682 if((*pType & 0xe00) == 0xe00) {
2683 pTD->vt = VT_PTR;
2684 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2685 sizeof(TYPEDESC));
2686 pTD = pTD->u.lptdesc;
2688 switch(*pType & 0x7f) {
2689 case VT_PTR:
2690 pTD->vt = VT_PTR;
2691 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2692 sizeof(TYPEDESC));
2693 pTD = pTD->u.lptdesc;
2694 break;
2696 case VT_USERDEFINED:
2697 pTD->vt = VT_USERDEFINED;
2698 pTD->u.hreftype = *(++pType) / 4;
2699 done = TRUE;
2700 break;
2702 case VT_CARRAY:
2704 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2705 array */
2707 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2709 pTD->vt = VT_CARRAY;
2710 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2711 sizeof(ARRAYDESC) +
2712 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2713 pTD->u.lpadesc->cDims = pSA->cDims;
2714 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2715 pSA->cDims * sizeof(SAFEARRAYBOUND));
2717 pTD = &pTD->u.lpadesc->tdescElem;
2718 break;
2721 case VT_SAFEARRAY:
2723 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2724 useful? */
2726 pType++;
2727 pTD->vt = VT_SAFEARRAY;
2728 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2729 sizeof(TYPEDESC));
2730 pTD = pTD->u.lptdesc;
2731 break;
2733 default:
2734 pTD->vt = *pType & 0x7f;
2735 done = TRUE;
2736 break;
2738 pType++;
2740 return pType;
2744 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2745 char *pNameTable)
2747 int ref;
2748 char *name;
2749 TLBRefType **ppRefType;
2751 if(pRef->magic != SLTG_REF_MAGIC) {
2752 FIXME("Ref magic = %x\n", pRef->magic);
2753 return;
2755 name = ( (char*)(&pRef->names) + pRef->number);
2757 ppRefType = &pTI->reflist;
2758 for(ref = 0; ref < pRef->number >> 3; ref++) {
2759 char *refname;
2760 unsigned int lib_offs, type_num;
2762 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2763 sizeof(**ppRefType));
2765 name += SLTG_ReadStringA(name, &refname);
2766 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2767 FIXME("Can't sscanf ref\n");
2768 if(lib_offs != 0xffff) {
2769 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2771 while(*import) {
2772 if((*import)->offset == lib_offs)
2773 break;
2774 import = &(*import)->next;
2776 if(!*import) {
2777 char fname[MAX_PATH+1];
2778 int len;
2780 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2781 sizeof(**import));
2782 (*import)->offset = lib_offs;
2783 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2784 &(*import)->guid);
2785 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2786 &(*import)->wVersionMajor,
2787 &(*import)->wVersionMinor,
2788 &(*import)->lcid, fname) != 4) {
2789 FIXME("can't sscanf ref %s\n",
2790 pNameTable + lib_offs + 40);
2792 len = strlen(fname);
2793 if(fname[len-1] != '#')
2794 FIXME("fname = %s\n", fname);
2795 fname[len-1] = '\0';
2796 (*import)->name = TLB_MultiByteToBSTR(fname);
2798 (*ppRefType)->pImpTLInfo = *import;
2799 } else { /* internal ref */
2800 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2802 (*ppRefType)->reference = ref;
2803 (*ppRefType)->index = type_num;
2805 HeapFree(GetProcessHeap(), 0, refname);
2806 ppRefType = &(*ppRefType)->next;
2808 if((BYTE)*name != SLTG_REF_MAGIC)
2809 FIXME("End of ref block magic = %x\n", *name);
2810 dump_TLBRefType(pTI->reflist);
2813 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2814 BOOL OneOnly)
2816 SLTG_ImplInfo *info;
2817 TLBImplType **ppImplType = &pTI->impltypelist;
2818 /* I don't really get this structure, usually it's 0x16 bytes
2819 long, but iuser.tlb contains some that are 0x18 bytes long.
2820 That's ok because we can use the next ptr to jump to the next
2821 one. But how do we know the length of the last one? The WORD
2822 at offs 0x8 might be the clue. For now I'm just assuming that
2823 the last one is the regular 0x16 bytes. */
2825 info = (SLTG_ImplInfo*)pBlk;
2826 while(1) {
2827 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2828 sizeof(**ppImplType));
2829 (*ppImplType)->hRef = info->ref;
2830 (*ppImplType)->implflags = info->impltypeflags;
2831 pTI->TypeAttr.cImplTypes++;
2832 ppImplType = &(*ppImplType)->next;
2834 if(info->next == 0xffff)
2835 break;
2836 if(OneOnly)
2837 FIXME("Interface inheriting more than one interface\n");
2838 info = (SLTG_ImplInfo*)(pBlk + info->next);
2840 info++; /* see comment at top of function */
2841 return (char*)info;
2844 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2845 char *pNameTable)
2847 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2848 SLTG_MemberHeader *pMemHeader;
2849 char *pFirstItem, *pNextItem;
2851 if(pTIHeader->href_table != 0xffffffff) {
2852 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2853 pNameTable);
2857 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2859 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2861 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2862 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2865 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2869 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2870 char *pNameTable)
2872 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2873 SLTG_MemberHeader *pMemHeader;
2874 SLTG_Function *pFunc;
2875 char *pFirstItem, *pNextItem;
2876 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2877 int num = 0;
2879 if(pTIHeader->href_table != 0xffffffff) {
2880 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2881 pNameTable);
2884 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2886 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2888 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2889 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2892 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2893 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2895 int param;
2896 WORD *pType, *pArg;
2898 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2899 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2900 FIXME("func magic = %02x\n", pFunc->magic);
2901 return NULL;
2903 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2904 sizeof(**ppFuncDesc));
2905 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2907 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2908 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2909 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2910 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2911 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2912 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2914 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2915 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2917 if(pFunc->retnextopt & 0x80)
2918 pType = &pFunc->rettype;
2919 else
2920 pType = (WORD*)(pFirstItem + pFunc->rettype);
2923 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2925 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2926 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2927 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2928 (*ppFuncDesc)->pParamDesc =
2929 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2930 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2932 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2934 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2935 char *paramName = pNameTable + *pArg;
2936 BOOL HaveOffs;
2937 /* If arg type follows then paramName points to the 2nd
2938 letter of the name, else the next WORD is an offset to
2939 the arg type and paramName points to the first letter.
2940 So let's take one char off paramName and see if we're
2941 pointing at an alpha-numeric char. However if *pArg is
2942 0xffff or 0xfffe then the param has no name, the former
2943 meaning that the next WORD is the type, the latter
2944 meaning the the next WORD is an offset to the type. */
2946 HaveOffs = FALSE;
2947 if(*pArg == 0xffff)
2948 paramName = NULL;
2949 else if(*pArg == 0xfffe) {
2950 paramName = NULL;
2951 HaveOffs = TRUE;
2953 else if(paramName[-1] && !isalnum(paramName[-1]))
2954 HaveOffs = TRUE;
2956 pArg++;
2958 if(HaveOffs) { /* the next word is an offset to type */
2959 pType = (WORD*)(pFirstItem + *pArg);
2960 SLTG_DoType(pType, pFirstItem,
2961 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2962 pArg++;
2963 } else {
2964 if(paramName)
2965 paramName--;
2966 pArg = SLTG_DoType(pArg, pFirstItem,
2967 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2970 /* Are we an optional param ? */
2971 if((*ppFuncDesc)->funcdesc.cParams - param <=
2972 (*ppFuncDesc)->funcdesc.cParamsOpt)
2973 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2975 if(paramName) {
2976 (*ppFuncDesc)->pParamDesc[param].Name =
2977 TLB_MultiByteToBSTR(paramName);
2981 ppFuncDesc = &((*ppFuncDesc)->next);
2982 if(pFunc->next == 0xffff) break;
2984 pTI->TypeAttr.cFuncs = num;
2985 dump_TLBFuncDesc(pTI->funclist);
2986 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2989 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2990 char *pNameTable)
2992 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2993 SLTG_MemberHeader *pMemHeader;
2994 SLTG_RecordItem *pItem;
2995 char *pFirstItem;
2996 TLBVarDesc **ppVarDesc = &pTI->varlist;
2997 int num = 0;
2998 WORD *pType;
2999 char buf[300];
3001 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3003 pFirstItem = (char*)(pMemHeader + 1);
3004 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
3005 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
3006 if(pItem->magic != SLTG_RECORD_MAGIC) {
3007 FIXME("record magic = %02x\n", pItem->magic);
3008 return NULL;
3010 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3011 sizeof(**ppVarDesc));
3012 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3013 (*ppVarDesc)->vardesc.memid = pItem->memid;
3014 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3015 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3017 if(pItem->typepos == 0x02)
3018 pType = &pItem->type;
3019 else if(pItem->typepos == 0x00)
3020 pType = (WORD*)(pFirstItem + pItem->type);
3021 else {
3022 FIXME("typepos = %02x\n", pItem->typepos);
3023 break;
3026 SLTG_DoType(pType, pFirstItem,
3027 &(*ppVarDesc)->vardesc.elemdescVar);
3029 /* FIXME("helpcontext, helpstring\n"); */
3031 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3033 ppVarDesc = &((*ppVarDesc)->next);
3034 if(pItem->next == 0xffff) break;
3036 pTI->TypeAttr.cVars = num;
3037 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3040 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3041 char *pNameTable)
3043 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3044 SLTG_MemberHeader *pMemHeader;
3045 SLTG_AliasItem *pItem;
3046 int i, mustbelast;
3048 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3049 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3051 mustbelast = 0;
3052 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3053 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3054 if (pItem->vt == 0xffff) {
3055 if (i<(pMemHeader->cbExtra/4-1))
3056 FIXME("Endmarker too early in process alias data!\n");
3057 break;
3059 if (mustbelast) {
3060 FIXME("Chain extends over last entry?\n");
3061 break;
3063 if (pItem->vt == VT_USERDEFINED) {
3064 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3065 /* guessing here ... */
3066 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3067 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3068 mustbelast = 1;
3069 } else {
3070 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3071 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3073 pItem++;
3075 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3078 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3079 char *pNameTable)
3081 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3082 SLTG_MemberHeader *pMemHeader;
3083 SLTG_AliasItem *pItem;
3085 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3086 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3087 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3088 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3089 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3092 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3093 char *pNameTable)
3095 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3096 SLTG_MemberHeader *pMemHeader;
3097 SLTG_EnumItem *pItem;
3098 char *pFirstItem;
3099 TLBVarDesc **ppVarDesc = &pTI->varlist;
3100 int num = 0;
3102 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3104 pFirstItem = (char*)(pMemHeader + 1);
3105 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3106 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3107 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3108 FIXME("enumitem magic = %04x\n", pItem->magic);
3109 return NULL;
3111 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3112 sizeof(**ppVarDesc));
3113 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3114 (*ppVarDesc)->vardesc.memid = pItem->memid;
3115 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3116 sizeof(VARIANT));
3117 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3118 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3119 *(INT*)(pItem->value + pFirstItem);
3120 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3121 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3122 /* FIXME("helpcontext, helpstring\n"); */
3124 ppVarDesc = &((*ppVarDesc)->next);
3125 if(pItem->next == 0xffff) break;
3127 pTI->TypeAttr.cVars = num;
3128 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3131 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3132 managable copy of it into this */
3133 typedef struct {
3134 WORD small_no;
3135 char *index_name;
3136 char *other_name;
3137 WORD res1a;
3138 WORD name_offs;
3139 WORD more_bytes;
3140 char *extra;
3141 WORD res20;
3142 DWORD helpcontext;
3143 WORD res26;
3144 GUID uuid;
3145 } SLTG_InternalOtherTypeInfo;
3147 /****************************************************************************
3148 * ITypeLib2_Constructor_SLTG
3150 * loading a SLTG typelib from an in-memory image
3152 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3154 ITypeLibImpl *pTypeLibImpl;
3155 SLTG_Header *pHeader;
3156 SLTG_BlkEntry *pBlkEntry;
3157 SLTG_Magic *pMagic;
3158 SLTG_Index *pIndex;
3159 SLTG_Pad9 *pPad9;
3160 LPVOID pBlk, pFirstBlk;
3161 SLTG_LibBlk *pLibBlk;
3162 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3163 char *pAfterOTIBlks = NULL;
3164 char *pNameTable, *ptr;
3165 int i;
3166 DWORD len, order;
3167 ITypeInfoImpl **ppTypeInfoImpl;
3169 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3171 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3172 if (!pTypeLibImpl) return NULL;
3174 pTypeLibImpl->lpVtbl = &tlbvt;
3175 pTypeLibImpl->ref = 1;
3177 pHeader = pLib;
3179 TRACE_(typelib)("header:\n");
3180 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3181 pHeader->nrOfFileBlks );
3182 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3183 FIXME("Header type magic 0x%08lx not supported.\n",
3184 pHeader->SLTG_magic);
3185 return NULL;
3188 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3189 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3191 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3192 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3194 /* Next we have a magic block */
3195 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3197 /* Let's see if we're still in sync */
3198 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3199 sizeof(SLTG_COMPOBJ_MAGIC))) {
3200 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3201 return NULL;
3203 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3204 sizeof(SLTG_DIR_MAGIC))) {
3205 FIXME("dir magic = %s\n", pMagic->dir_magic);
3206 return NULL;
3209 pIndex = (SLTG_Index*)(pMagic+1);
3211 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3213 pFirstBlk = (LPVOID)(pPad9 + 1);
3215 /* We'll set up a ptr to the main library block, which is the last one. */
3217 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3218 pBlkEntry[order].next != 0;
3219 order = pBlkEntry[order].next - 1, i++) {
3220 pBlk = (char*)pBlk + pBlkEntry[order].len;
3222 pLibBlk = pBlk;
3224 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3226 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3227 interspersed */
3229 len += 0x40;
3231 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3233 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3234 sizeof(*pOtherTypeInfoBlks) *
3235 pTypeLibImpl->TypeInfoCount);
3238 ptr = (char*)pLibBlk + len;
3240 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3241 WORD w, extra;
3242 len = 0;
3244 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3246 w = *(WORD*)(ptr + 2);
3247 if(w != 0xffff) {
3248 len += w;
3249 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3250 w+1);
3251 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3252 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3254 w = *(WORD*)(ptr + 4 + len);
3255 if(w != 0xffff) {
3256 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3257 len += w;
3258 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3259 w+1);
3260 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3261 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3263 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3264 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3265 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3266 if(extra) {
3267 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3268 extra);
3269 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3270 len += extra;
3272 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3273 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3274 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3275 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3276 len += sizeof(SLTG_OtherTypeInfo);
3277 ptr += len;
3280 pAfterOTIBlks = ptr;
3282 /* Skip this WORD and get the next DWORD */
3283 len = *(DWORD*)(pAfterOTIBlks + 2);
3285 /* Now add this to pLibBLk look at what we're pointing at and
3286 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3287 dust and we should be pointing at the beginning of the name
3288 table */
3290 pNameTable = (char*)pLibBlk + len;
3292 switch(*(WORD*)pNameTable) {
3293 case 0xffff:
3294 break;
3295 case 0x0200:
3296 pNameTable += 0x20;
3297 break;
3298 default:
3299 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3300 break;
3303 pNameTable += 0x216;
3305 pNameTable += 2;
3307 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3309 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3312 /* Hopefully we now have enough ptrs set up to actually read in
3313 some TypeInfos. It's not clear which order to do them in, so
3314 I'll just follow the links along the BlkEntry chain and read
3315 them in in the order in which they're in the file */
3317 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3319 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3320 pBlkEntry[order].next != 0;
3321 order = pBlkEntry[order].next - 1, i++) {
3323 SLTG_TypeInfoHeader *pTIHeader;
3324 SLTG_TypeInfoTail *pTITail;
3326 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3327 pOtherTypeInfoBlks[i].index_name)) {
3328 FIXME("Index strings don't match\n");
3329 return NULL;
3332 pTIHeader = pBlk;
3333 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3334 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3335 return NULL;
3337 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3338 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3339 (*ppTypeInfoImpl)->index = i;
3340 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3341 pOtherTypeInfoBlks[i].name_offs +
3342 pNameTable);
3343 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3344 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3345 sizeof(GUID));
3346 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3347 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3348 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3349 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3350 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3352 if((pTIHeader->typeflags1 & 7) != 2)
3353 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3354 if(pTIHeader->typeflags3 != 2)
3355 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3357 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3358 debugstr_w((*ppTypeInfoImpl)->Name),
3359 typekind_desc[pTIHeader->typekind],
3360 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3361 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3363 switch(pTIHeader->typekind) {
3364 case TKIND_ENUM:
3365 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3366 break;
3368 case TKIND_RECORD:
3369 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3370 break;
3372 case TKIND_INTERFACE:
3373 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3374 break;
3376 case TKIND_COCLASS:
3377 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3378 break;
3380 case TKIND_ALIAS:
3381 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3382 if (pTITail->tdescalias_vt)
3383 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3384 break;
3386 case TKIND_DISPATCH:
3387 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3388 break;
3390 default:
3391 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3392 pTITail = NULL;
3393 break;
3397 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3398 but we've already set those */
3399 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3400 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3401 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3403 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3404 X(06);
3405 X(08);
3406 X(0a);
3407 X(0c);
3408 X(0e);
3409 X(10);
3410 X(12);
3411 X(16);
3412 X(18);
3413 X(1a);
3414 X(1c);
3415 X(1e);
3416 X(24);
3417 X(26);
3418 X(2a);
3419 X(2c);
3420 X(2e);
3421 X(30);
3422 X(32);
3423 X(34);
3425 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3426 pBlk = (char*)pBlk + pBlkEntry[order].len;
3429 if(i != pTypeLibImpl->TypeInfoCount) {
3430 FIXME("Somehow processed %d TypeInfos\n", i);
3431 return NULL;
3434 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3435 return (ITypeLib2*)pTypeLibImpl;
3438 /* ITypeLib::QueryInterface
3440 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3441 ITypeLib2 * iface,
3442 REFIID riid,
3443 VOID **ppvObject)
3445 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3447 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3449 *ppvObject=NULL;
3450 if(IsEqualIID(riid, &IID_IUnknown) ||
3451 IsEqualIID(riid,&IID_ITypeLib)||
3452 IsEqualIID(riid,&IID_ITypeLib2))
3454 *ppvObject = This;
3457 if(*ppvObject)
3459 ITypeLib2_AddRef(iface);
3460 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3461 return S_OK;
3463 TRACE("-- Interface: E_NOINTERFACE\n");
3464 return E_NOINTERFACE;
3467 /* ITypeLib::AddRef
3469 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3471 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3472 ULONG ref = InterlockedIncrement(&This->ref);
3474 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3476 return ref;
3479 /* ITypeLib::Release
3481 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3483 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3484 ULONG ref = InterlockedDecrement(&This->ref);
3486 TRACE("(%p)->(%lu)\n",This, ref);
3488 if (!ref)
3490 /* remove cache entry */
3491 TRACE("removing from cache list\n");
3492 EnterCriticalSection(&cache_section);
3493 if (This->next) This->next->prev = This->prev;
3494 if (This->prev) This->prev->next = This->next;
3495 else tlb_cache_first = This->next;
3496 LeaveCriticalSection(&cache_section);
3498 /* FIXME destroy child objects */
3499 TRACE(" destroying ITypeLib(%p)\n",This);
3501 if (This->Name)
3503 SysFreeString(This->Name);
3504 This->Name = NULL;
3507 if (This->DocString)
3509 SysFreeString(This->DocString);
3510 This->DocString = NULL;
3513 if (This->HelpFile)
3515 SysFreeString(This->HelpFile);
3516 This->HelpFile = NULL;
3519 if (This->HelpStringDll)
3521 SysFreeString(This->HelpStringDll);
3522 This->HelpStringDll = NULL;
3525 if (This->pTypeInfo) /* can be NULL */
3526 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3527 HeapFree(GetProcessHeap(),0,This);
3528 return 0;
3531 return ref;
3534 /* ITypeLib::GetTypeInfoCount
3536 * Returns the number of type descriptions in the type library
3538 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3540 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3541 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3542 return This->TypeInfoCount;
3545 /* ITypeLib::GetTypeInfo
3547 * retrieves the specified type description in the library.
3549 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3550 ITypeLib2 *iface,
3551 UINT index,
3552 ITypeInfo **ppTInfo)
3554 int i;
3556 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3557 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3559 TRACE("(%p)->(index=%d)\n", This, index);
3561 if (!ppTInfo) return E_INVALIDARG;
3563 /* search element n in list */
3564 for(i=0; i < index; i++)
3566 pTypeInfo = pTypeInfo->next;
3567 if (!pTypeInfo)
3569 TRACE("-- element not found\n");
3570 return TYPE_E_ELEMENTNOTFOUND;
3574 *ppTInfo = (ITypeInfo *) pTypeInfo;
3576 ITypeInfo_AddRef(*ppTInfo);
3577 TRACE("-- found (%p)\n",*ppTInfo);
3578 return S_OK;
3582 /* ITypeLibs::GetTypeInfoType
3584 * Retrieves the type of a type description.
3586 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3587 ITypeLib2 *iface,
3588 UINT index,
3589 TYPEKIND *pTKind)
3591 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3592 int i;
3593 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3595 TRACE("(%p) index %d\n", This, index);
3597 if(!pTKind) return E_INVALIDARG;
3599 /* search element n in list */
3600 for(i=0; i < index; i++)
3602 if(!pTInfo)
3604 TRACE("-- element not found\n");
3605 return TYPE_E_ELEMENTNOTFOUND;
3607 pTInfo = pTInfo->next;
3610 *pTKind = pTInfo->TypeAttr.typekind;
3611 TRACE("-- found Type (%d)\n", *pTKind);
3612 return S_OK;
3615 /* ITypeLib::GetTypeInfoOfGuid
3617 * Retrieves the type description that corresponds to the specified GUID.
3620 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3621 ITypeLib2 *iface,
3622 REFGUID guid,
3623 ITypeInfo **ppTInfo)
3625 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3626 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3628 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3630 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3632 /* search linked list for guid */
3633 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3635 pTypeInfo = pTypeInfo->next;
3637 if (!pTypeInfo)
3639 /* end of list reached */
3640 TRACE("-- element not found\n");
3641 return TYPE_E_ELEMENTNOTFOUND;
3645 TRACE("-- found (%p, %s)\n",
3646 pTypeInfo,
3647 debugstr_w(pTypeInfo->Name));
3649 *ppTInfo = (ITypeInfo*)pTypeInfo;
3650 ITypeInfo_AddRef(*ppTInfo);
3651 return S_OK;
3654 /* ITypeLib::GetLibAttr
3656 * Retrieves the structure that contains the library's attributes.
3659 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3660 ITypeLib2 *iface,
3661 LPTLIBATTR *ppTLibAttr)
3663 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3664 TRACE("(%p)\n",This);
3665 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3666 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3667 return S_OK;
3670 /* ITypeLib::GetTypeComp
3672 * Enables a client compiler to bind to a library's types, variables,
3673 * constants, and global functions.
3676 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3677 ITypeLib2 *iface,
3678 ITypeComp **ppTComp)
3680 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3682 TRACE("(%p)->(%p)\n",This,ppTComp);
3683 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3684 ITypeComp_AddRef(*ppTComp);
3686 return S_OK;
3689 /* ITypeLib::GetDocumentation
3691 * Retrieves the library's documentation string, the complete Help file name
3692 * and path, and the context identifier for the library Help topic in the Help
3693 * file.
3695 * On a successful return all non-null BSTR pointers will have been set,
3696 * possibly to NULL.
3698 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3699 ITypeLib2 *iface,
3700 INT index,
3701 BSTR *pBstrName,
3702 BSTR *pBstrDocString,
3703 DWORD *pdwHelpContext,
3704 BSTR *pBstrHelpFile)
3706 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3708 HRESULT result = E_INVALIDARG;
3710 ITypeInfo *pTInfo;
3713 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3714 This, index,
3715 pBstrName, pBstrDocString,
3716 pdwHelpContext, pBstrHelpFile);
3718 if(index<0)
3720 /* documentation for the typelib */
3721 if(pBstrName)
3723 if (This->Name)
3725 if(!(*pBstrName = SysAllocString(This->Name)))
3726 goto memerr1;
3728 else
3729 *pBstrName = NULL;
3731 if(pBstrDocString)
3733 if (This->DocString)
3735 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3736 goto memerr2;
3738 else if (This->Name)
3740 if(!(*pBstrDocString = SysAllocString(This->Name)))
3741 goto memerr2;
3743 else
3744 *pBstrDocString = NULL;
3746 if(pdwHelpContext)
3748 *pdwHelpContext = This->dwHelpContext;
3750 if(pBstrHelpFile)
3752 if (This->HelpFile)
3754 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3755 goto memerr3;
3757 else
3758 *pBstrHelpFile = NULL;
3761 result = S_OK;
3763 else
3765 /* for a typeinfo */
3766 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3768 if(SUCCEEDED(result))
3770 result = ITypeInfo_GetDocumentation(pTInfo,
3771 MEMBERID_NIL,
3772 pBstrName,
3773 pBstrDocString,
3774 pdwHelpContext, pBstrHelpFile);
3776 ITypeInfo_Release(pTInfo);
3779 return result;
3780 memerr3:
3781 if (pBstrDocString) SysFreeString (*pBstrDocString);
3782 memerr2:
3783 if (pBstrName) SysFreeString (*pBstrName);
3784 memerr1:
3785 return STG_E_INSUFFICIENTMEMORY;
3788 /* ITypeLib::IsName
3790 * Indicates whether a passed-in string contains the name of a type or member
3791 * described in the library.
3794 static HRESULT WINAPI ITypeLib2_fnIsName(
3795 ITypeLib2 *iface,
3796 LPOLESTR szNameBuf,
3797 ULONG lHashVal,
3798 BOOL *pfName)
3800 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3801 ITypeInfoImpl *pTInfo;
3802 TLBFuncDesc *pFInfo;
3803 TLBVarDesc *pVInfo;
3804 int i;
3805 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3807 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3808 pfName);
3810 *pfName=TRUE;
3811 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3812 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3813 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3814 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3815 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3816 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3817 goto ITypeLib2_fnIsName_exit;
3819 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3820 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3823 *pfName=FALSE;
3825 ITypeLib2_fnIsName_exit:
3826 TRACE("(%p)slow! search for %s: %s found!\n", This,
3827 debugstr_w(szNameBuf), *pfName?"NOT":"");
3829 return S_OK;
3832 /* ITypeLib::FindName
3834 * Finds occurrences of a type description in a type library. This may be used
3835 * to quickly verify that a name exists in a type library.
3838 static HRESULT WINAPI ITypeLib2_fnFindName(
3839 ITypeLib2 *iface,
3840 LPOLESTR szNameBuf,
3841 ULONG lHashVal,
3842 ITypeInfo **ppTInfo,
3843 MEMBERID *rgMemId,
3844 UINT16 *pcFound)
3846 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3847 ITypeInfoImpl *pTInfo;
3848 TLBFuncDesc *pFInfo;
3849 TLBVarDesc *pVInfo;
3850 int i,j = 0;
3851 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3853 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3854 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3855 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3856 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3857 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3858 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3859 goto ITypeLib2_fnFindName_exit;
3862 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3863 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3864 continue;
3865 ITypeLib2_fnFindName_exit:
3866 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3867 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3868 j++;
3870 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3871 This, *pcFound, debugstr_w(szNameBuf), j);
3873 *pcFound=j;
3875 return S_OK;
3878 /* ITypeLib::ReleaseTLibAttr
3880 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3883 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3884 ITypeLib2 *iface,
3885 TLIBATTR *pTLibAttr)
3887 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3888 TRACE("freeing (%p)\n",This);
3889 HeapFree(GetProcessHeap(),0,pTLibAttr);
3893 /* ITypeLib2::GetCustData
3895 * gets the custom data
3897 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3898 ITypeLib2 * iface,
3899 REFGUID guid,
3900 VARIANT *pVarVal)
3902 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3903 TLBCustData *pCData;
3905 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3907 if( IsEqualIID(guid, &pCData->guid)) break;
3910 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3912 if(pCData)
3914 VariantInit( pVarVal);
3915 VariantCopy( pVarVal, &pCData->data);
3916 return S_OK;
3918 return E_INVALIDARG; /* FIXME: correct? */
3921 /* ITypeLib2::GetLibStatistics
3923 * Returns statistics about a type library that are required for efficient
3924 * sizing of hash tables.
3927 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3928 ITypeLib2 * iface,
3929 ULONG *pcUniqueNames,
3930 ULONG *pcchUniqueNames)
3932 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3934 FIXME("(%p): stub!\n", This);
3936 if(pcUniqueNames) *pcUniqueNames=1;
3937 if(pcchUniqueNames) *pcchUniqueNames=1;
3938 return S_OK;
3941 /* ITypeLib2::GetDocumentation2
3943 * Retrieves the library's documentation string, the complete Help file name
3944 * and path, the localization context to use, and the context ID for the
3945 * library Help topic in the Help file.
3948 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3949 ITypeLib2 * iface,
3950 INT index,
3951 LCID lcid,
3952 BSTR *pbstrHelpString,
3953 DWORD *pdwHelpStringContext,
3954 BSTR *pbstrHelpStringDll)
3956 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3957 HRESULT result;
3958 ITypeInfo *pTInfo;
3960 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3962 /* the help string should be obtained from the helpstringdll,
3963 * using the _DLLGetDocumentation function, based on the supplied
3964 * lcid. Nice to do sometime...
3966 if(index<0)
3968 /* documentation for the typelib */
3969 if(pbstrHelpString)
3970 *pbstrHelpString=SysAllocString(This->DocString);
3971 if(pdwHelpStringContext)
3972 *pdwHelpStringContext=This->dwHelpContext;
3973 if(pbstrHelpStringDll)
3974 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3976 result = S_OK;
3978 else
3980 /* for a typeinfo */
3981 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3983 if(SUCCEEDED(result))
3985 ITypeInfo2 * pTInfo2;
3986 result = ITypeInfo_QueryInterface(pTInfo,
3987 &IID_ITypeInfo2,
3988 (LPVOID*) &pTInfo2);
3990 if(SUCCEEDED(result))
3992 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3993 MEMBERID_NIL,
3994 lcid,
3995 pbstrHelpString,
3996 pdwHelpStringContext,
3997 pbstrHelpStringDll);
3999 ITypeInfo2_Release(pTInfo2);
4002 ITypeInfo_Release(pTInfo);
4005 return result;
4008 /* ITypeLib2::GetAllCustData
4010 * Gets all custom data items for the library.
4013 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4014 ITypeLib2 * iface,
4015 CUSTDATA *pCustData)
4017 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4018 TLBCustData *pCData;
4019 int i;
4020 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4021 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4022 if(pCustData->prgCustData ){
4023 pCustData->cCustData=This->ctCustData;
4024 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4025 pCustData->prgCustData[i].guid=pCData->guid;
4026 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4028 }else{
4029 ERR(" OUT OF MEMORY!\n");
4030 return E_OUTOFMEMORY;
4032 return S_OK;
4035 static const ITypeLib2Vtbl tlbvt = {
4036 ITypeLib2_fnQueryInterface,
4037 ITypeLib2_fnAddRef,
4038 ITypeLib2_fnRelease,
4039 ITypeLib2_fnGetTypeInfoCount,
4040 ITypeLib2_fnGetTypeInfo,
4041 ITypeLib2_fnGetTypeInfoType,
4042 ITypeLib2_fnGetTypeInfoOfGuid,
4043 ITypeLib2_fnGetLibAttr,
4044 ITypeLib2_fnGetTypeComp,
4045 ITypeLib2_fnGetDocumentation,
4046 ITypeLib2_fnIsName,
4047 ITypeLib2_fnFindName,
4048 ITypeLib2_fnReleaseTLibAttr,
4050 ITypeLib2_fnGetCustData,
4051 ITypeLib2_fnGetLibStatistics,
4052 ITypeLib2_fnGetDocumentation2,
4053 ITypeLib2_fnGetAllCustData
4057 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4059 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4061 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4064 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4066 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4068 return ITypeLib2_AddRef((ITypeLib2 *)This);
4071 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4073 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4075 return ITypeLib2_Release((ITypeLib2 *)This);
4078 static HRESULT WINAPI ITypeLibComp_fnBind(
4079 ITypeComp * iface,
4080 OLECHAR * szName,
4081 ULONG lHash,
4082 WORD wFlags,
4083 ITypeInfo ** ppTInfo,
4084 DESCKIND * pDescKind,
4085 BINDPTR * pBindPtr)
4087 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4088 ITypeInfoImpl *pTypeInfo;
4090 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4092 *pDescKind = DESCKIND_NONE;
4093 pBindPtr->lptcomp = NULL;
4094 *ppTInfo = NULL;
4096 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4098 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4100 /* FIXME: check wFlags here? */
4101 /* FIXME: we should use a hash table to look this info up using lHash
4102 * instead of an O(n) search */
4103 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4104 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4106 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4108 *pDescKind = DESCKIND_TYPECOMP;
4109 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4110 ITypeComp_AddRef(pBindPtr->lptcomp);
4111 TRACE("module or enum: %s\n", debugstr_w(szName));
4112 return S_OK;
4116 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4117 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4119 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4120 HRESULT hr;
4122 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4123 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4125 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4126 return S_OK;
4130 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4131 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4133 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4134 HRESULT hr;
4135 ITypeInfo *subtypeinfo;
4136 BINDPTR subbindptr;
4137 DESCKIND subdesckind;
4139 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4140 &subtypeinfo, &subdesckind, &subbindptr);
4141 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4143 TYPEDESC tdesc_appobject =
4146 0 /* FIXME */
4148 VT_USERDEFINED
4150 const VARDESC vardesc_appobject =
4152 -2, /* memid */
4153 NULL, /* lpstrSchema */
4155 0 /* oInst */
4158 /* ELEMDESC */
4160 /* TYPEDESC */
4162 &tdesc_appobject
4164 VT_PTR
4167 0, /* wVarFlags */
4168 VAR_STATIC /* varkind */
4171 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4173 /* cleanup things filled in by Bind call so we can put our
4174 * application object data in there instead */
4175 switch (subdesckind)
4177 case DESCKIND_FUNCDESC:
4178 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4179 break;
4180 case DESCKIND_VARDESC:
4181 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4182 break;
4183 default:
4184 break;
4186 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4188 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4189 if (FAILED(hr))
4190 return hr;
4192 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4193 *ppTInfo = (ITypeInfo *)pTypeInfo;
4194 ITypeInfo_AddRef(*ppTInfo);
4195 return S_OK;
4200 TRACE("name not found %s\n", debugstr_w(szName));
4201 return S_OK;
4204 static HRESULT WINAPI ITypeLibComp_fnBindType(
4205 ITypeComp * iface,
4206 OLECHAR * szName,
4207 ULONG lHash,
4208 ITypeInfo ** ppTInfo,
4209 ITypeComp ** ppTComp)
4211 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4212 return E_NOTIMPL;
4215 static const ITypeCompVtbl tlbtcvt =
4218 ITypeLibComp_fnQueryInterface,
4219 ITypeLibComp_fnAddRef,
4220 ITypeLibComp_fnRelease,
4222 ITypeLibComp_fnBind,
4223 ITypeLibComp_fnBindType
4226 /*================== ITypeInfo(2) Methods ===================================*/
4227 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4229 ITypeInfoImpl * pTypeInfoImpl;
4231 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4232 if (pTypeInfoImpl)
4234 pTypeInfoImpl->lpVtbl = &tinfvt;
4235 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4236 pTypeInfoImpl->ref=1;
4238 TRACE("(%p)\n", pTypeInfoImpl);
4239 return (ITypeInfo2*) pTypeInfoImpl;
4242 /* ITypeInfo::QueryInterface
4244 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4245 ITypeInfo2 *iface,
4246 REFIID riid,
4247 VOID **ppvObject)
4249 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4251 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4253 *ppvObject=NULL;
4254 if(IsEqualIID(riid, &IID_IUnknown) ||
4255 IsEqualIID(riid,&IID_ITypeInfo)||
4256 IsEqualIID(riid,&IID_ITypeInfo2))
4257 *ppvObject = This;
4259 if(*ppvObject){
4260 ITypeInfo_AddRef(iface);
4261 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4262 return S_OK;
4264 TRACE("-- Interface: E_NOINTERFACE\n");
4265 return E_NOINTERFACE;
4268 /* ITypeInfo::AddRef
4270 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4273 ULONG ref = InterlockedIncrement(&This->ref);
4275 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4277 TRACE("(%p)->ref is %lu\n",This, ref);
4278 return ref;
4281 /* ITypeInfo::Release
4283 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4285 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4286 ULONG ref = InterlockedDecrement(&This->ref);
4288 TRACE("(%p)->(%lu)\n",This, ref);
4290 if (ref) {
4291 /* We don't release ITypeLib when ref=0 because
4292 it means that function is called by ITypeLib2_Release */
4293 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4294 } else {
4295 FIXME("destroy child objects\n");
4297 TRACE("destroying ITypeInfo(%p)\n",This);
4298 if (This->Name)
4300 SysFreeString(This->Name);
4301 This->Name = 0;
4304 if (This->DocString)
4306 SysFreeString(This->DocString);
4307 This->DocString = 0;
4310 if (This->DllName)
4312 SysFreeString(This->DllName);
4313 This->DllName = 0;
4316 if (This->next)
4318 ITypeInfo_Release((ITypeInfo*)This->next);
4321 HeapFree(GetProcessHeap(),0,This);
4322 return 0;
4324 return ref;
4327 /* ITypeInfo::GetTypeAttr
4329 * Retrieves a TYPEATTR structure that contains the attributes of the type
4330 * description.
4333 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4334 LPTYPEATTR *ppTypeAttr)
4336 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4337 SIZE_T size;
4339 TRACE("(%p)\n",This);
4341 size = sizeof(**ppTypeAttr);
4342 if (This->TypeAttr.typekind == TKIND_ALIAS)
4343 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4345 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4346 if (!*ppTypeAttr)
4347 return E_OUTOFMEMORY;
4349 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4351 if (This->TypeAttr.typekind == TKIND_ALIAS)
4352 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4353 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4355 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4356 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4357 funcs */
4358 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4359 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4361 return S_OK;
4364 /* ITypeInfo::GetTypeComp
4366 * Retrieves the ITypeComp interface for the type description, which enables a
4367 * client compiler to bind to the type description's members.
4370 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4371 ITypeComp * *ppTComp)
4373 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4375 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4377 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4378 ITypeComp_AddRef(*ppTComp);
4379 return S_OK;
4382 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4384 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4385 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4386 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4387 return size;
4390 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4392 memcpy(dest, src, sizeof(ELEMDESC));
4393 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4394 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4396 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4397 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4398 *buffer += sizeof(PARAMDESCEX);
4399 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4400 VariantInit(&pparamdescex_dest->varDefaultValue);
4401 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4402 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4404 else
4405 dest->u.paramdesc.pparamdescex = NULL;
4406 return S_OK;
4409 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4411 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4412 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4415 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr )
4417 FUNCDESC *dest;
4418 char *buffer;
4419 SIZE_T size = sizeof(*src);
4420 SHORT i;
4421 HRESULT hr;
4423 size += sizeof(*src->lprgscode) * src->cScodes;
4424 size += TLB_SizeElemDesc(&src->elemdescFunc);
4425 for (i = 0; i < src->cParams; i++)
4427 size += sizeof(ELEMDESC);
4428 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4431 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4432 if (!dest) return E_OUTOFMEMORY;
4434 memcpy(dest, src, sizeof(FUNCDESC));
4435 buffer = (char *)(dest + 1);
4437 dest->lprgscode = (SCODE *)buffer;
4438 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4439 buffer += sizeof(*src->lprgscode) * src->cScodes;
4441 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4442 if (FAILED(hr))
4444 SysFreeString((BSTR)dest);
4445 return hr;
4448 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4449 buffer += sizeof(ELEMDESC) * src->cParams;
4450 for (i = 0; i < src->cParams; i++)
4452 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4453 if (FAILED(hr))
4454 break;
4456 if (FAILED(hr))
4458 /* undo the above actions */
4459 for (i = i - 1; i >= 0; i--)
4460 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4461 TLB_FreeElemDesc(&dest->elemdescFunc);
4462 SysFreeString((BSTR)dest);
4463 return hr;
4466 *dest_ptr = dest;
4467 return S_OK;
4470 /* ITypeInfo::GetFuncDesc
4472 * Retrieves the FUNCDESC structure that contains information about a
4473 * specified function.
4476 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4477 LPFUNCDESC *ppFuncDesc)
4479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4480 int i;
4481 const TLBFuncDesc *pFDesc;
4483 TRACE("(%p) index %d\n", This, index);
4485 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4488 if(pFDesc)
4489 return TLB_AllocAndInitFuncDesc(&pFDesc->funcdesc, ppFuncDesc);
4491 return E_INVALIDARG;
4494 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4496 VARDESC *dest;
4497 char *buffer;
4498 SIZE_T size = sizeof(*src);
4499 HRESULT hr;
4501 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4502 if (src->varkind == VAR_CONST)
4503 size += sizeof(VARIANT);
4504 size += TLB_SizeElemDesc(&src->elemdescVar);
4506 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4507 if (!dest) return E_OUTOFMEMORY;
4509 *dest = *src;
4510 buffer = (char *)(dest + 1);
4511 if (src->lpstrSchema)
4513 int len;
4514 dest->lpstrSchema = (LPOLESTR)buffer;
4515 len = strlenW(src->lpstrSchema);
4516 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4517 buffer += (len + 1) * sizeof(WCHAR);
4520 if (src->varkind == VAR_CONST)
4522 HRESULT hr;
4524 dest->u.lpvarValue = (VARIANT *)buffer;
4525 *dest->u.lpvarValue = *src->u.lpvarValue;
4526 buffer += sizeof(VARIANT);
4527 VariantInit(dest->u.lpvarValue);
4528 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4529 if (FAILED(hr))
4531 SysFreeString((BSTR)dest_ptr);
4532 return hr;
4535 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4536 if (FAILED(hr))
4538 if (src->varkind == VAR_CONST)
4539 VariantClear(dest->u.lpvarValue);
4540 SysFreeString((BSTR)dest);
4541 return hr;
4543 *dest_ptr = dest;
4544 return S_OK;
4547 /* ITypeInfo::GetVarDesc
4549 * Retrieves a VARDESC structure that describes the specified variable.
4552 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4553 LPVARDESC *ppVarDesc)
4555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4556 int i;
4557 const TLBVarDesc *pVDesc;
4559 TRACE("(%p) index %d\n", This, index);
4561 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4564 if (pVDesc)
4565 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4567 return E_INVALIDARG;
4570 /* ITypeInfo_GetNames
4572 * Retrieves the variable with the specified member ID (or the name of the
4573 * property or method and its parameters) that correspond to the specified
4574 * function ID.
4576 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4577 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4579 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4580 TLBFuncDesc * pFDesc;
4581 TLBVarDesc * pVDesc;
4582 int i;
4583 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4584 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4585 if(pFDesc)
4587 /* function found, now return function and parameter names */
4588 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4590 if(!i)
4591 *rgBstrNames=SysAllocString(pFDesc->Name);
4592 else
4593 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4595 *pcNames=i;
4597 else
4599 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4600 if(pVDesc)
4602 *rgBstrNames=SysAllocString(pVDesc->Name);
4603 *pcNames=1;
4605 else
4607 if(This->TypeAttr.cImplTypes &&
4608 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4609 /* recursive search */
4610 ITypeInfo *pTInfo;
4611 HRESULT result;
4612 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4613 &pTInfo);
4614 if(SUCCEEDED(result))
4616 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4617 ITypeInfo_Release(pTInfo);
4618 return result;
4620 WARN("Could not search inherited interface!\n");
4622 else
4624 WARN("no names found\n");
4626 *pcNames=0;
4627 return TYPE_E_ELEMENTNOTFOUND;
4630 return S_OK;
4634 /* ITypeInfo::GetRefTypeOfImplType
4636 * If a type description describes a COM class, it retrieves the type
4637 * description of the implemented interface types. For an interface,
4638 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4639 * if any exist.
4642 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4643 ITypeInfo2 *iface,
4644 UINT index,
4645 HREFTYPE *pRefType)
4647 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4648 int i;
4649 HRESULT hr = S_OK;
4650 TLBImplType *pImpl = This->impltypelist;
4652 TRACE("(%p) index %d\n", This, index);
4653 if (TRACE_ON(ole)) dump_TypeInfo(This);
4655 if(index==(UINT)-1)
4657 /* only valid on dual interfaces;
4658 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4660 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4662 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4663 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4665 *pRefType = -1;
4667 else
4669 hr = TYPE_E_ELEMENTNOTFOUND;
4672 else
4674 /* get element n from linked list */
4675 for(i=0; pImpl && i<index; i++)
4677 pImpl = pImpl->next;
4680 if (pImpl)
4681 *pRefType = pImpl->hRef;
4682 else
4683 hr = TYPE_E_ELEMENTNOTFOUND;
4686 if(TRACE_ON(ole))
4688 if(SUCCEEDED(hr))
4689 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4690 else
4691 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4694 return hr;
4697 /* ITypeInfo::GetImplTypeFlags
4699 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4700 * or base interface in a type description.
4702 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4703 UINT index, INT *pImplTypeFlags)
4705 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4706 int i;
4707 TLBImplType *pImpl;
4709 TRACE("(%p) index %d\n", This, index);
4710 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4711 i++, pImpl=pImpl->next)
4713 if(i==index && pImpl){
4714 *pImplTypeFlags=pImpl->implflags;
4715 return S_OK;
4717 *pImplTypeFlags=0;
4718 return TYPE_E_ELEMENTNOTFOUND;
4721 /* GetIDsOfNames
4722 * Maps between member names and member IDs, and parameter names and
4723 * parameter IDs.
4725 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4726 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4728 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4729 TLBFuncDesc * pFDesc;
4730 TLBVarDesc * pVDesc;
4731 HRESULT ret=S_OK;
4733 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4734 cNames);
4735 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4736 int i, j;
4737 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4738 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4739 for(i=1; i < cNames; i++){
4740 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4741 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4742 break;
4743 if( j<pFDesc->funcdesc.cParams)
4744 pMemId[i]=j;
4745 else
4746 ret=DISP_E_UNKNOWNNAME;
4748 return ret;
4751 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4752 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4753 if(cNames) *pMemId=pVDesc->vardesc.memid;
4754 return ret;
4757 /* not found, see if this is and interface with an inheritance */
4758 if(This->TypeAttr.cImplTypes &&
4759 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4760 /* recursive search */
4761 ITypeInfo *pTInfo;
4762 ret=ITypeInfo_GetRefTypeInfo(iface,
4763 This->impltypelist->hRef, &pTInfo);
4764 if(SUCCEEDED(ret)){
4765 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4766 ITypeInfo_Release(pTInfo);
4767 return ret;
4769 WARN("Could not search inherited interface!\n");
4770 } else
4771 WARN("no names found\n");
4772 return DISP_E_UNKNOWNNAME;
4775 /* ITypeInfo::Invoke
4777 * Invokes a method, or accesses a property of an object, that implements the
4778 * interface described by the type description.
4780 DWORD
4781 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4782 DWORD res;
4784 if (TRACE_ON(ole)) {
4785 int i;
4786 TRACE("Calling %p(",func);
4787 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4788 TRACE(")\n");
4791 switch (callconv) {
4792 case CC_STDCALL:
4794 switch (nrargs) {
4795 case 0:
4796 res = func();
4797 break;
4798 case 1:
4799 res = func(args[0]);
4800 break;
4801 case 2:
4802 res = func(args[0],args[1]);
4803 break;
4804 case 3:
4805 res = func(args[0],args[1],args[2]);
4806 break;
4807 case 4:
4808 res = func(args[0],args[1],args[2],args[3]);
4809 break;
4810 case 5:
4811 res = func(args[0],args[1],args[2],args[3],args[4]);
4812 break;
4813 case 6:
4814 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4815 break;
4816 case 7:
4817 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4818 break;
4819 case 8:
4820 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4821 break;
4822 case 9:
4823 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4824 break;
4825 case 10:
4826 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4827 break;
4828 case 11:
4829 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4830 break;
4831 case 12:
4832 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
4833 break;
4834 case 13:
4835 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
4836 break;
4837 case 14:
4838 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
4839 break;
4840 default:
4841 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4842 res = -1;
4843 break;
4845 break;
4846 default:
4847 FIXME("unsupported calling convention %d\n",callconv);
4848 res = -1;
4849 break;
4851 TRACE("returns %08lx\n",res);
4852 return res;
4855 extern int _argsize(DWORD vt);
4857 /****************************************************************************
4858 * Helper functions for Dispcall / Invoke, which copies one variant
4859 * with target type onto the argument stack.
4861 static HRESULT
4862 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4863 DWORD *argpos, VARIANT *arg, VARTYPE vt
4865 UINT arglen = _argsize(vt)*sizeof(DWORD);
4866 VARIANT va;
4868 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4869 memcpy(argpos,&arg,sizeof(void*));
4870 return S_OK;
4873 if (V_VT(arg) == vt) {
4874 memcpy(argpos, &V_I4(arg), arglen);
4875 return S_OK;
4878 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4879 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4880 return S_OK;
4883 if (vt == VT_VARIANT) {
4884 memcpy(argpos, arg, arglen);
4885 return S_OK;
4887 /* Deref BYREF vars if there is need */
4888 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4889 memcpy(argpos,(void*)V_I4(arg), arglen);
4890 return S_OK;
4892 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4893 /* in this context, if the type lib specifies IUnknown*, giving an
4894 IDispatch* is correct; so, don't invoke VariantChangeType */
4895 memcpy(argpos,&V_I4(arg), arglen);
4896 return S_OK;
4898 if ((vt == VT_PTR) && tdesc)
4899 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4901 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4902 ITypeInfo *tinfo2 = NULL;
4903 TYPEATTR *tattr = NULL;
4904 HRESULT hres;
4906 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4907 if (hres) {
4908 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4909 "while coercing from vt 0x%x. Copying 4 byte.\n",
4910 tdesc->u.hreftype,V_VT(arg));
4911 memcpy(argpos, &V_I4(arg), 4);
4912 return S_OK;
4914 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4915 if( hres )
4917 ERR("GetTypeAttr failed\n");
4918 ITypeInfo_Release(tinfo2);
4919 return hres;
4921 switch (tattr->typekind) {
4922 case TKIND_ENUM:
4923 switch ( V_VT( arg ) ) {
4924 case VT_I2:
4925 *argpos = V_I2(arg);
4926 hres = S_OK;
4927 break;
4928 case VT_I4:
4929 memcpy(argpos, &V_I4(arg), 4);
4930 hres = S_OK;
4931 break;
4932 case VT_BYREF|VT_I4:
4933 memcpy(argpos, V_I4REF(arg), 4);
4934 hres = S_OK;
4935 break;
4936 default:
4937 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4938 hres = E_FAIL;
4939 break;
4941 break;
4943 case TKIND_ALIAS:
4944 tdesc = &(tattr->tdescAlias);
4945 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4946 break;
4948 case TKIND_INTERFACE:
4949 if (V_VT(arg) == VT_DISPATCH) {
4950 IDispatch *disp;
4951 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4952 memcpy(argpos, &V_DISPATCH(arg), 4);
4953 hres = S_OK;
4954 break;
4956 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4957 &IID_IDispatch,(LPVOID*)&disp);
4958 if (SUCCEEDED(hres)) {
4959 memcpy(argpos,&disp,4);
4960 IUnknown_Release(V_DISPATCH(arg));
4961 hres = S_OK;
4962 break;
4964 FIXME("Failed to query IDispatch interface from %s while "
4965 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4966 hres = E_FAIL;
4967 break;
4969 if (V_VT(arg) == VT_UNKNOWN) {
4970 memcpy(argpos, &V_UNKNOWN(arg), 4);
4971 hres = S_OK;
4972 break;
4974 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4975 V_VT(arg),debugstr_guid(&(tattr->guid)));
4976 hres = E_FAIL;
4977 break;
4979 case TKIND_DISPATCH:
4980 if (V_VT(arg) == VT_DISPATCH) {
4981 memcpy(argpos, &V_DISPATCH(arg), 4);
4982 hres = S_OK;
4984 else {
4985 hres = E_FAIL;
4986 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4988 break;
4989 case TKIND_RECORD:
4990 FIXME("TKIND_RECORD unhandled.\n");
4991 hres = E_FAIL;
4992 break;
4993 default:
4994 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4995 hres = E_FAIL;
4996 break;
4998 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4999 ITypeInfo_Release(tinfo2);
5000 return hres;
5003 VariantInit(&va);
5004 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
5005 memcpy(argpos,&V_I4(&va), arglen);
5006 FIXME("Should not use VariantChangeType here."
5007 " (conversion from 0x%x -> 0x%x) %08lx\n",
5008 V_VT(arg), vt, *argpos
5010 return S_OK;
5012 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
5013 return E_FAIL;
5016 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
5018 HRESULT hr = S_OK;
5019 ITypeInfo *tinfo2 = NULL;
5020 TYPEATTR *tattr = NULL;
5022 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5023 if (hr)
5025 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
5026 "hr = 0x%08lx\n",
5027 tdesc->u.hreftype, hr);
5028 return hr;
5030 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5031 if (hr)
5033 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
5034 ITypeInfo_Release(tinfo2);
5035 return hr;
5038 switch (tattr->typekind)
5040 case TKIND_ENUM:
5041 *vt |= VT_I4;
5042 break;
5044 case TKIND_ALIAS:
5045 tdesc = &tattr->tdescAlias;
5046 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5047 break;
5049 case TKIND_INTERFACE:
5050 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5051 *vt |= VT_DISPATCH;
5052 else
5053 *vt |= VT_UNKNOWN;
5054 break;
5056 case TKIND_DISPATCH:
5057 *vt |= VT_DISPATCH;
5058 break;
5060 case TKIND_RECORD:
5061 FIXME("TKIND_RECORD unhandled.\n");
5062 hr = E_NOTIMPL;
5063 break;
5065 case TKIND_UNION:
5066 FIXME("TKIND_RECORD unhandled.\n");
5067 hr = E_NOTIMPL;
5068 break;
5070 default:
5071 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5072 hr = E_NOTIMPL;
5073 break;
5075 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5076 ITypeInfo_Release(tinfo2);
5077 return hr;
5080 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
5082 HRESULT hr = S_OK;
5084 /* enforce only one level of pointer indirection */
5085 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
5087 tdesc = tdesc->u.lptdesc;
5089 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5090 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5091 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5092 if ((tdesc->vt == VT_USERDEFINED) ||
5093 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5095 VARTYPE vt_userdefined = 0;
5096 TYPEDESC *tdesc_userdefined = tdesc;
5097 if (tdesc->vt == VT_PTR)
5099 vt_userdefined = VT_BYREF;
5100 tdesc_userdefined = tdesc->u.lptdesc;
5102 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5103 if ((hr == S_OK) &&
5104 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5105 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5107 *vt |= vt_userdefined;
5108 return S_OK;
5111 *vt = VT_BYREF;
5114 switch (tdesc->vt)
5116 case VT_HRESULT:
5117 *vt |= VT_ERROR;
5118 break;
5119 case VT_USERDEFINED:
5120 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5121 break;
5122 case VT_PTR:
5123 ERR("cannot convert VT_PTR into variant VT\n");
5124 hr = E_FAIL;
5125 break;
5126 default:
5127 *vt |= tdesc->vt;
5128 break;
5130 return hr;
5133 /***********************************************************************
5134 * DispCallFunc (OLEAUT32.@)
5136 HRESULT WINAPI
5137 DispCallFunc(
5138 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5139 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5141 int i, argsize, argspos;
5142 DWORD *args;
5143 HRESULT hres;
5145 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5146 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5147 pvargResult, V_VT(pvargResult));
5149 /* DispCallFunc is only used to invoke methods belonging to an
5150 * IDispatch-derived COM interface. So we need to add a first parameter
5151 * to the list of arguments, to supply the interface pointer */
5152 argsize = 1;
5153 for (i=0;i<cActuals;i++)
5155 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5156 dump_Variant(prgpvarg[i]);
5157 argsize += _argsize(prgvt[i]);
5159 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5160 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
5161 argspos = 1;
5162 for (i=0;i<cActuals;i++)
5164 VARIANT *arg = prgpvarg[i];
5165 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5166 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5167 argspos += _argsize(prgvt[i]);
5170 hres = _invoke((*(FARPROC**)pvInstance)[oVft/sizeof(void *)],cc,argsize,args);
5171 if (pvargResult && (vtReturn != VT_EMPTY))
5173 TRACE("Method returned 0x%08lx\n",hres);
5174 V_VT(pvargResult) = vtReturn;
5175 V_UI4(pvargResult) = hres;
5178 HeapFree(GetProcessHeap(),0,args);
5179 return S_OK;
5182 static HRESULT WINAPI ITypeInfo_fnInvoke(
5183 ITypeInfo2 *iface,
5184 VOID *pIUnk,
5185 MEMBERID memid,
5186 UINT16 dwFlags,
5187 DISPPARAMS *pDispParams,
5188 VARIANT *pVarResult,
5189 EXCEPINFO *pExcepInfo,
5190 UINT *pArgErr)
5192 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5193 int i;
5194 unsigned int func_index, var_index;
5195 TYPEKIND type_kind;
5196 HRESULT hres;
5198 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
5199 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5201 dump_DispParms(pDispParams);
5203 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
5204 if (SUCCEEDED(hres)) {
5205 FUNCDESC *func_desc;
5207 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
5208 if(FAILED(hres)) return hres;
5209 if (TRACE_ON(ole))
5211 TRACE("invoking:\n");
5212 dump_FUNCDESC(func_desc);
5215 switch (func_desc->funckind) {
5216 case FUNC_PUREVIRTUAL:
5217 case FUNC_VIRTUAL: {
5218 DWORD res;
5219 int numargs, numargs2, argspos, args2pos;
5220 DWORD *args , *args2;
5221 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
5222 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
5224 hres = S_OK;
5225 numargs = 1; /* sizeof(thisptr) */
5226 numargs2 = 0;
5227 for (i = 0; i < func_desc->cParams; i++) {
5228 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5230 numargs += _argsize(tdesc->vt);
5231 if (i>=pDispParams->cArgs) { /* arguments to return */
5232 if (tdesc->vt == VT_PTR) {
5233 numargs2 += _argsize(tdesc->u.lptdesc->vt);
5234 } else {
5235 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
5236 numargs2 += _argsize(tdesc->vt);
5241 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
5242 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
5244 args[0] = (DWORD)pIUnk;
5245 argspos = 1; args2pos = 0;
5246 for (i = 0; i < func_desc->cParams; i++) {
5247 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
5248 TYPEDESC *tdesc = &(elemdesc->tdesc);
5249 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
5250 int arglen = _argsize(tdesc->vt);
5252 if (i<pDispParams->cArgs) {
5253 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
5255 if (paramFlags & PARAMFLAG_FOPT) {
5256 if(i < func_desc->cParams - func_desc->cParamsOpt)
5257 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5258 if(V_VT(arg) == VT_EMPTY
5259 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
5260 /* FIXME: Documentation says that we do this when parameter is left unspecified.
5261 How to determine it? */
5263 if(paramFlags & PARAMFLAG_FHASDEFAULT)
5264 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5265 V_VT(arg) = VT_ERROR;
5266 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5267 arglen = _argsize(VT_ERROR);
5270 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5271 if (FAILED(hres)) goto func_fail;
5272 argspos += arglen;
5273 } else if (paramFlags & PARAMFLAG_FOPT) {
5274 VARIANT *arg = &rgvarg[i];
5276 if (i < func_desc->cParams - func_desc->cParamsOpt)
5277 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5278 if (paramFlags & PARAMFLAG_FHASDEFAULT)
5279 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5281 V_VT(arg) = VT_ERROR;
5282 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5283 arglen = _argsize(VT_ERROR);
5284 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5285 if (FAILED(hres)) goto func_fail;
5286 argspos += arglen;
5287 } else {
5288 if (tdesc->vt == VT_PTR)
5289 arglen = _argsize(tdesc->u.lptdesc->vt);
5290 else
5291 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5293 /* Supply pointers for the rest, so propertyget works*/
5294 args[argspos] = (DWORD)&args2[args2pos];
5296 /* If pointer to variant, pass reference it. */
5297 if ((tdesc->vt == VT_PTR) &&
5298 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5299 pVarResult
5301 args[argspos]= (DWORD)pVarResult;
5302 argspos += 1;
5303 args2pos += arglen;
5306 if (func_desc->cParamsOpt < 0)
5307 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5309 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5310 func_desc->callconv,
5311 numargs,
5312 args
5315 if (pVarResult) {
5316 for (i = 0; i < func_desc->cParams; i++) {
5317 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5318 if (wParamFlags & PARAMFLAG_FRETVAL) {
5319 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5320 TYPEDESC *tdesc = &elemdesc->tdesc;
5321 VARIANTARG varresult;
5322 V_VT(&varresult) = 0;
5323 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5324 if (hres)
5325 break;
5326 /* FIXME: this is really messy - we should keep the
5327 * args in VARIANTARGs rather than a DWORD array */
5328 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5329 if (TRACE_ON(ole))
5331 TRACE("varresult: ");
5332 dump_Variant(&varresult);
5334 hres = VariantCopyInd(pVarResult, &varresult);
5335 /* free data stored in varresult. Note that
5336 * VariantClear doesn't do what we want because we are
5337 * working with byref types. */
5338 /* FIXME: clear safearrays, bstrs, records and
5339 * variants here too */
5340 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5341 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5343 if(*V_UNKNOWNREF(&varresult))
5344 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5346 break;
5351 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5352 WARN("invoked function failed with error 0x%08lx\n", res);
5353 hres = DISP_E_EXCEPTION;
5354 if (pExcepInfo) pExcepInfo->scode = res;
5356 func_fail:
5357 HeapFree(GetProcessHeap(), 0, rgvarg);
5358 HeapFree(GetProcessHeap(),0,args2);
5359 HeapFree(GetProcessHeap(),0,args);
5360 break;
5362 case FUNC_DISPATCH: {
5363 IDispatch *disp;
5365 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5366 if (SUCCEEDED(hres)) {
5367 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5368 hres = IDispatch_Invoke(
5369 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5370 pVarResult,pExcepInfo,pArgErr
5372 if (FAILED(hres))
5373 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5374 IDispatch_Release(disp);
5375 } else
5376 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5377 break;
5379 default:
5380 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5381 hres = E_FAIL;
5382 break;
5385 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5386 TRACE("-- 0x%08lx\n", hres);
5387 return hres;
5389 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5390 VARDESC *var_desc;
5392 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5393 if(FAILED(hres)) return hres;
5395 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5396 dump_VARDESC(var_desc);
5397 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5398 return E_NOTIMPL;
5401 /* not found, look for it in inherited interfaces */
5402 ITypeInfo2_GetTypeKind(iface, &type_kind);
5403 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5404 HREFTYPE ref_type;
5405 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5406 /* recursive search */
5407 ITypeInfo *pTInfo;
5408 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5409 if(SUCCEEDED(hres)){
5410 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5411 ITypeInfo_Release(pTInfo);
5412 return hres;
5414 WARN("Could not search inherited interface!\n");
5417 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5418 return DISP_E_MEMBERNOTFOUND;
5421 /* ITypeInfo::GetDocumentation
5423 * Retrieves the documentation string, the complete Help file name and path,
5424 * and the context ID for the Help topic for a specified type description.
5426 * (Can be tested by the Visual Basic Editor in Word for instance.)
5428 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5429 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5430 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5432 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5433 TLBFuncDesc * pFDesc;
5434 TLBVarDesc * pVDesc;
5435 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5436 " HelpContext(%p) HelpFile(%p)\n",
5437 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5438 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5439 if(pBstrName)
5440 *pBstrName=SysAllocString(This->Name);
5441 if(pBstrDocString)
5442 *pBstrDocString=SysAllocString(This->DocString);
5443 if(pdwHelpContext)
5444 *pdwHelpContext=This->dwHelpContext;
5445 if(pBstrHelpFile)
5446 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5447 return S_OK;
5448 }else {/* for a member */
5449 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5450 if(pFDesc->funcdesc.memid==memid){
5451 if(pBstrName)
5452 *pBstrName = SysAllocString(pFDesc->Name);
5453 if(pBstrDocString)
5454 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5455 if(pdwHelpContext)
5456 *pdwHelpContext=pFDesc->helpcontext;
5457 return S_OK;
5459 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5460 if(pVDesc->vardesc.memid==memid){
5461 if(pBstrName)
5462 *pBstrName = SysAllocString(pVDesc->Name);
5463 if(pBstrDocString)
5464 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5465 if(pdwHelpContext)
5466 *pdwHelpContext=pVDesc->HelpContext;
5467 return S_OK;
5470 WARN("member %ld not found\n", memid);
5471 return TYPE_E_ELEMENTNOTFOUND;
5474 /* ITypeInfo::GetDllEntry
5476 * Retrieves a description or specification of an entry point for a function
5477 * in a DLL.
5479 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5480 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5481 WORD *pwOrdinal)
5483 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5484 TLBFuncDesc *pFDesc;
5486 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5488 if (pBstrDllName) *pBstrDllName = NULL;
5489 if (pBstrName) *pBstrName = NULL;
5490 if (pwOrdinal) *pwOrdinal = 0;
5492 if (This->TypeAttr.typekind != TKIND_MODULE)
5493 return TYPE_E_BADMODULEKIND;
5495 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5496 if(pFDesc->funcdesc.memid==memid){
5497 dump_TypeInfo(This);
5498 dump_TLBFuncDescOne(pFDesc);
5500 if (pBstrDllName)
5501 *pBstrDllName = SysAllocString(This->DllName);
5503 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5504 if (pBstrName)
5505 *pBstrName = SysAllocString(pFDesc->Entry);
5506 if (pwOrdinal)
5507 *pwOrdinal = -1;
5508 return S_OK;
5510 if (pBstrName)
5511 *pBstrName = NULL;
5512 if (pwOrdinal)
5513 *pwOrdinal = (DWORD)pFDesc->Entry;
5514 return S_OK;
5516 return TYPE_E_ELEMENTNOTFOUND;
5519 /* ITypeInfo::GetRefTypeInfo
5521 * If a type description references other type descriptions, it retrieves
5522 * the referenced type descriptions.
5524 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5525 ITypeInfo2 *iface,
5526 HREFTYPE hRefType,
5527 ITypeInfo **ppTInfo)
5529 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5530 HRESULT result = E_FAIL;
5532 if (hRefType == -1 &&
5533 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5534 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5536 /* when we meet a DUAL dispinterface, we must create the interface
5537 * version of it.
5539 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5542 /* the interface version contains the same information as the dispinterface
5543 * copy the contents of the structs.
5545 *pTypeInfoImpl = *This;
5546 pTypeInfoImpl->ref = 1;
5548 /* change the type to interface */
5549 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5551 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5553 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5555 result = S_OK;
5557 } else {
5558 TLBRefType *pRefType;
5559 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5560 if(pRefType->reference == hRefType)
5561 break;
5563 if(!pRefType)
5564 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5565 if(pRefType && hRefType != -1) {
5566 ITypeLib *pTLib = NULL;
5568 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5569 UINT Index;
5570 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5571 } else {
5572 if(pRefType->pImpTLInfo->pImpTypeLib) {
5573 TRACE("typeinfo in imported typelib that is already loaded\n");
5574 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5575 ITypeLib2_AddRef((ITypeLib*) pTLib);
5576 result = S_OK;
5577 } else {
5578 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5579 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5580 pRefType->pImpTLInfo->wVersionMajor,
5581 pRefType->pImpTLInfo->wVersionMinor,
5582 pRefType->pImpTLInfo->lcid,
5583 &pTLib);
5585 if(!SUCCEEDED(result)) {
5586 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5587 result=LoadTypeLib(libnam, &pTLib);
5588 SysFreeString(libnam);
5590 if(SUCCEEDED(result)) {
5591 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5592 ITypeLib2_AddRef(pTLib);
5596 if(SUCCEEDED(result)) {
5597 if(pRefType->index == TLB_REF_USE_GUID)
5598 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5599 &pRefType->guid,
5600 ppTInfo);
5601 else
5602 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5603 ppTInfo);
5605 if (pTLib != NULL)
5606 ITypeLib2_Release(pTLib);
5610 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5611 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5612 return result;
5615 /* ITypeInfo::AddressOfMember
5617 * Retrieves the addresses of static functions or variables, such as those
5618 * defined in a DLL.
5620 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5621 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5623 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5624 FIXME("(%p) stub!\n", This);
5625 return S_OK;
5628 /* ITypeInfo::CreateInstance
5630 * Creates a new instance of a type that describes a component object class
5631 * (coclass).
5633 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5634 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5636 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5637 FIXME("(%p) stub!\n", This);
5638 return S_OK;
5641 /* ITypeInfo::GetMops
5643 * Retrieves marshalling information.
5645 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5646 BSTR *pBstrMops)
5648 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5649 FIXME("(%p) stub!\n", This);
5650 return S_OK;
5653 /* ITypeInfo::GetContainingTypeLib
5655 * Retrieves the containing type library and the index of the type description
5656 * within that type library.
5658 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5659 ITypeLib * *ppTLib, UINT *pIndex)
5661 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5663 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5664 if (pIndex) {
5665 *pIndex=This->index;
5666 TRACE("returning pIndex=%d\n", *pIndex);
5669 if (ppTLib) {
5670 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5671 ITypeLib2_AddRef(*ppTLib);
5672 TRACE("returning ppTLib=%p\n", *ppTLib);
5675 return S_OK;
5678 /* ITypeInfo::ReleaseTypeAttr
5680 * Releases a TYPEATTR previously returned by GetTypeAttr.
5683 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5684 TYPEATTR* pTypeAttr)
5686 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5687 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5688 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5691 /* ITypeInfo::ReleaseFuncDesc
5693 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5695 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5696 ITypeInfo2 *iface,
5697 FUNCDESC *pFuncDesc)
5699 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5700 SHORT i;
5702 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5704 for (i = 0; i < pFuncDesc->cParams; i++)
5705 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5706 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5708 SysFreeString((BSTR)pFuncDesc);
5711 /* ITypeInfo::ReleaseVarDesc
5713 * Releases a VARDESC previously returned by GetVarDesc.
5715 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5716 VARDESC *pVarDesc)
5718 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5719 TRACE("(%p)->(%p)\n", This, pVarDesc);
5721 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5722 if (pVarDesc->varkind == VAR_CONST)
5723 VariantClear(pVarDesc->u.lpvarValue);
5724 SysFreeString((BSTR)pVarDesc);
5727 /* ITypeInfo2::GetTypeKind
5729 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5732 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5733 TYPEKIND *pTypeKind)
5735 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5736 *pTypeKind=This->TypeAttr.typekind;
5737 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5738 return S_OK;
5741 /* ITypeInfo2::GetTypeFlags
5743 * Returns the type flags without any allocations. This returns a DWORD type
5744 * flag, which expands the type flags without growing the TYPEATTR (type
5745 * attribute).
5748 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5750 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5751 *pTypeFlags=This->TypeAttr.wTypeFlags;
5752 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5753 return S_OK;
5756 /* ITypeInfo2::GetFuncIndexOfMemId
5757 * Binds to a specific member based on a known DISPID, where the member name
5758 * is not known (for example, when binding to a default member).
5761 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5762 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5764 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5765 TLBFuncDesc *pFuncInfo;
5766 int i;
5767 HRESULT result;
5769 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5770 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5771 break;
5772 if(pFuncInfo) {
5773 *pFuncIndex = i;
5774 result = S_OK;
5775 } else
5776 result = TYPE_E_ELEMENTNOTFOUND;
5778 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5779 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5780 return result;
5783 /* TypeInfo2::GetVarIndexOfMemId
5785 * Binds to a specific member based on a known DISPID, where the member name
5786 * is not known (for example, when binding to a default member).
5789 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5790 MEMBERID memid, UINT *pVarIndex)
5792 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5793 TLBVarDesc *pVarInfo;
5794 int i;
5795 HRESULT result;
5796 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5797 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5799 if(pVarInfo) {
5800 *pVarIndex = i;
5801 result = S_OK;
5802 } else
5803 result = TYPE_E_ELEMENTNOTFOUND;
5805 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5806 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5807 return result;
5810 /* ITypeInfo2::GetCustData
5812 * Gets the custom data
5814 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5815 ITypeInfo2 * iface,
5816 REFGUID guid,
5817 VARIANT *pVarVal)
5819 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5820 TLBCustData *pCData;
5822 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5823 if( IsEqualIID(guid, &pCData->guid)) break;
5825 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5827 if(pCData)
5829 VariantInit( pVarVal);
5830 VariantCopy( pVarVal, &pCData->data);
5831 return S_OK;
5833 return E_INVALIDARG; /* FIXME: correct? */
5836 /* ITypeInfo2::GetFuncCustData
5838 * Gets the custom data
5840 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5841 ITypeInfo2 * iface,
5842 UINT index,
5843 REFGUID guid,
5844 VARIANT *pVarVal)
5846 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5847 TLBCustData *pCData=NULL;
5848 TLBFuncDesc * pFDesc;
5849 int i;
5850 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5851 pFDesc=pFDesc->next);
5853 if(pFDesc)
5854 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5855 if( IsEqualIID(guid, &pCData->guid)) break;
5857 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5859 if(pCData){
5860 VariantInit( pVarVal);
5861 VariantCopy( pVarVal, &pCData->data);
5862 return S_OK;
5864 return E_INVALIDARG; /* FIXME: correct? */
5867 /* ITypeInfo2::GetParamCustData
5869 * Gets the custom data
5871 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5872 ITypeInfo2 * iface,
5873 UINT indexFunc,
5874 UINT indexParam,
5875 REFGUID guid,
5876 VARIANT *pVarVal)
5878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5879 TLBCustData *pCData=NULL;
5880 TLBFuncDesc * pFDesc;
5881 int i;
5883 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5885 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5886 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5887 pCData = pCData->next)
5888 if( IsEqualIID(guid, &pCData->guid)) break;
5890 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5892 if(pCData)
5894 VariantInit( pVarVal);
5895 VariantCopy( pVarVal, &pCData->data);
5896 return S_OK;
5898 return E_INVALIDARG; /* FIXME: correct? */
5901 /* ITypeInfo2::GetVarCustData
5903 * Gets the custom data
5905 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5906 ITypeInfo2 * iface,
5907 UINT index,
5908 REFGUID guid,
5909 VARIANT *pVarVal)
5911 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5912 TLBCustData *pCData=NULL;
5913 TLBVarDesc * pVDesc;
5914 int i;
5916 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5918 if(pVDesc)
5920 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5922 if( IsEqualIID(guid, &pCData->guid)) break;
5926 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5928 if(pCData)
5930 VariantInit( pVarVal);
5931 VariantCopy( pVarVal, &pCData->data);
5932 return S_OK;
5934 return E_INVALIDARG; /* FIXME: correct? */
5937 /* ITypeInfo2::GetImplCustData
5939 * Gets the custom data
5941 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5942 ITypeInfo2 * iface,
5943 UINT index,
5944 REFGUID guid,
5945 VARIANT *pVarVal)
5947 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5948 TLBCustData *pCData=NULL;
5949 TLBImplType * pRDesc;
5950 int i;
5952 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5954 if(pRDesc)
5956 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5958 if( IsEqualIID(guid, &pCData->guid)) break;
5962 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5964 if(pCData)
5966 VariantInit( pVarVal);
5967 VariantCopy( pVarVal, &pCData->data);
5968 return S_OK;
5970 return E_INVALIDARG; /* FIXME: correct? */
5973 /* ITypeInfo2::GetDocumentation2
5975 * Retrieves the documentation string, the complete Help file name and path,
5976 * the localization context to use, and the context ID for the library Help
5977 * topic in the Help file.
5980 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5981 ITypeInfo2 * iface,
5982 MEMBERID memid,
5983 LCID lcid,
5984 BSTR *pbstrHelpString,
5985 DWORD *pdwHelpStringContext,
5986 BSTR *pbstrHelpStringDll)
5988 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5989 TLBFuncDesc * pFDesc;
5990 TLBVarDesc * pVDesc;
5991 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5992 "HelpStringContext(%p) HelpStringDll(%p)\n",
5993 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5994 pbstrHelpStringDll );
5995 /* the help string should be obtained from the helpstringdll,
5996 * using the _DLLGetDocumentation function, based on the supplied
5997 * lcid. Nice to do sometime...
5999 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6000 if(pbstrHelpString)
6001 *pbstrHelpString=SysAllocString(This->Name);
6002 if(pdwHelpStringContext)
6003 *pdwHelpStringContext=This->dwHelpStringContext;
6004 if(pbstrHelpStringDll)
6005 *pbstrHelpStringDll=
6006 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6007 return S_OK;
6008 }else {/* for a member */
6009 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6010 if(pFDesc->funcdesc.memid==memid){
6011 if(pbstrHelpString)
6012 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6013 if(pdwHelpStringContext)
6014 *pdwHelpStringContext=pFDesc->HelpStringContext;
6015 if(pbstrHelpStringDll)
6016 *pbstrHelpStringDll=
6017 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6018 return S_OK;
6020 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6021 if(pVDesc->vardesc.memid==memid){
6022 if(pbstrHelpString)
6023 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6024 if(pdwHelpStringContext)
6025 *pdwHelpStringContext=pVDesc->HelpStringContext;
6026 if(pbstrHelpStringDll)
6027 *pbstrHelpStringDll=
6028 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6029 return S_OK;
6032 return TYPE_E_ELEMENTNOTFOUND;
6035 /* ITypeInfo2::GetAllCustData
6037 * Gets all custom data items for the Type info.
6040 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6041 ITypeInfo2 * iface,
6042 CUSTDATA *pCustData)
6044 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6045 TLBCustData *pCData;
6046 int i;
6048 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6050 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6051 if(pCustData->prgCustData ){
6052 pCustData->cCustData=This->ctCustData;
6053 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6054 pCustData->prgCustData[i].guid=pCData->guid;
6055 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6057 }else{
6058 ERR(" OUT OF MEMORY!\n");
6059 return E_OUTOFMEMORY;
6061 return S_OK;
6064 /* ITypeInfo2::GetAllFuncCustData
6066 * Gets all custom data items for the specified Function
6069 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6070 ITypeInfo2 * iface,
6071 UINT index,
6072 CUSTDATA *pCustData)
6074 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6075 TLBCustData *pCData;
6076 TLBFuncDesc * pFDesc;
6077 int i;
6078 TRACE("(%p) index %d\n", This, index);
6079 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6080 pFDesc=pFDesc->next)
6082 if(pFDesc){
6083 pCustData->prgCustData =
6084 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6085 if(pCustData->prgCustData ){
6086 pCustData->cCustData=pFDesc->ctCustData;
6087 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6088 pCData = pCData->next){
6089 pCustData->prgCustData[i].guid=pCData->guid;
6090 VariantCopy(& pCustData->prgCustData[i].varValue,
6091 & pCData->data);
6093 }else{
6094 ERR(" OUT OF MEMORY!\n");
6095 return E_OUTOFMEMORY;
6097 return S_OK;
6099 return TYPE_E_ELEMENTNOTFOUND;
6102 /* ITypeInfo2::GetAllParamCustData
6104 * Gets all custom data items for the Functions
6107 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6108 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6110 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6111 TLBCustData *pCData=NULL;
6112 TLBFuncDesc * pFDesc;
6113 int i;
6114 TRACE("(%p) index %d\n", This, indexFunc);
6115 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6116 pFDesc=pFDesc->next)
6118 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6119 pCustData->prgCustData =
6120 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6121 sizeof(CUSTDATAITEM));
6122 if(pCustData->prgCustData ){
6123 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6124 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6125 pCData; i++, pCData = pCData->next){
6126 pCustData->prgCustData[i].guid=pCData->guid;
6127 VariantCopy(& pCustData->prgCustData[i].varValue,
6128 & pCData->data);
6130 }else{
6131 ERR(" OUT OF MEMORY!\n");
6132 return E_OUTOFMEMORY;
6134 return S_OK;
6136 return TYPE_E_ELEMENTNOTFOUND;
6139 /* ITypeInfo2::GetAllVarCustData
6141 * Gets all custom data items for the specified Variable
6144 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6145 UINT index, CUSTDATA *pCustData)
6147 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6148 TLBCustData *pCData;
6149 TLBVarDesc * pVDesc;
6150 int i;
6151 TRACE("(%p) index %d\n", This, index);
6152 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6153 pVDesc=pVDesc->next)
6155 if(pVDesc){
6156 pCustData->prgCustData =
6157 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6158 if(pCustData->prgCustData ){
6159 pCustData->cCustData=pVDesc->ctCustData;
6160 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6161 pCData = pCData->next){
6162 pCustData->prgCustData[i].guid=pCData->guid;
6163 VariantCopy(& pCustData->prgCustData[i].varValue,
6164 & pCData->data);
6166 }else{
6167 ERR(" OUT OF MEMORY!\n");
6168 return E_OUTOFMEMORY;
6170 return S_OK;
6172 return TYPE_E_ELEMENTNOTFOUND;
6175 /* ITypeInfo2::GetAllImplCustData
6177 * Gets all custom data items for the specified implementation type
6180 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6181 ITypeInfo2 * iface,
6182 UINT index,
6183 CUSTDATA *pCustData)
6185 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6186 TLBCustData *pCData;
6187 TLBImplType * pRDesc;
6188 int i;
6189 TRACE("(%p) index %d\n", This, index);
6190 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6191 pRDesc=pRDesc->next)
6193 if(pRDesc){
6194 pCustData->prgCustData =
6195 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6196 if(pCustData->prgCustData ){
6197 pCustData->cCustData=pRDesc->ctCustData;
6198 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6199 pCData = pCData->next){
6200 pCustData->prgCustData[i].guid=pCData->guid;
6201 VariantCopy(& pCustData->prgCustData[i].varValue,
6202 & pCData->data);
6204 }else{
6205 ERR(" OUT OF MEMORY!\n");
6206 return E_OUTOFMEMORY;
6208 return S_OK;
6210 return TYPE_E_ELEMENTNOTFOUND;
6213 static const ITypeInfo2Vtbl tinfvt =
6216 ITypeInfo_fnQueryInterface,
6217 ITypeInfo_fnAddRef,
6218 ITypeInfo_fnRelease,
6220 ITypeInfo_fnGetTypeAttr,
6221 ITypeInfo_fnGetTypeComp,
6222 ITypeInfo_fnGetFuncDesc,
6223 ITypeInfo_fnGetVarDesc,
6224 ITypeInfo_fnGetNames,
6225 ITypeInfo_fnGetRefTypeOfImplType,
6226 ITypeInfo_fnGetImplTypeFlags,
6227 ITypeInfo_fnGetIDsOfNames,
6228 ITypeInfo_fnInvoke,
6229 ITypeInfo_fnGetDocumentation,
6230 ITypeInfo_fnGetDllEntry,
6231 ITypeInfo_fnGetRefTypeInfo,
6232 ITypeInfo_fnAddressOfMember,
6233 ITypeInfo_fnCreateInstance,
6234 ITypeInfo_fnGetMops,
6235 ITypeInfo_fnGetContainingTypeLib,
6236 ITypeInfo_fnReleaseTypeAttr,
6237 ITypeInfo_fnReleaseFuncDesc,
6238 ITypeInfo_fnReleaseVarDesc,
6240 ITypeInfo2_fnGetTypeKind,
6241 ITypeInfo2_fnGetTypeFlags,
6242 ITypeInfo2_fnGetFuncIndexOfMemId,
6243 ITypeInfo2_fnGetVarIndexOfMemId,
6244 ITypeInfo2_fnGetCustData,
6245 ITypeInfo2_fnGetFuncCustData,
6246 ITypeInfo2_fnGetParamCustData,
6247 ITypeInfo2_fnGetVarCustData,
6248 ITypeInfo2_fnGetImplTypeCustData,
6249 ITypeInfo2_fnGetDocumentation2,
6250 ITypeInfo2_fnGetAllCustData,
6251 ITypeInfo2_fnGetAllFuncCustData,
6252 ITypeInfo2_fnGetAllParamCustData,
6253 ITypeInfo2_fnGetAllVarCustData,
6254 ITypeInfo2_fnGetAllImplTypeCustData,
6257 /******************************************************************************
6258 * CreateDispTypeInfo [OLEAUT32.31]
6260 * Build type information for an object so it can be called through an
6261 * IDispatch interface.
6263 * RETURNS
6264 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6265 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6267 * NOTES
6268 * This call allows an objects methods to be accessed through IDispatch, by
6269 * building an ITypeInfo object that IDispatch can use to call through.
6271 HRESULT WINAPI CreateDispTypeInfo(
6272 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6273 LCID lcid, /* [I] Locale Id */
6274 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6276 ITypeInfoImpl *pTIImpl;
6277 int param, func;
6278 TLBFuncDesc **ppFuncDesc;
6280 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
6281 pTIImpl->pTypeLib = NULL;
6282 pTIImpl->index = 0;
6283 pTIImpl->Name = NULL;
6284 pTIImpl->dwHelpContext = -1;
6285 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
6286 pTIImpl->TypeAttr.lcid = lcid;
6287 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
6288 pTIImpl->TypeAttr.wMajorVerNum = 0;
6289 pTIImpl->TypeAttr.wMinorVerNum = 0;
6290 pTIImpl->TypeAttr.cbAlignment = 2;
6291 pTIImpl->TypeAttr.cbSizeInstance = -1;
6292 pTIImpl->TypeAttr.cbSizeVft = -1;
6293 pTIImpl->TypeAttr.cFuncs = 0;
6294 pTIImpl->TypeAttr.cImplTypes = 1;
6295 pTIImpl->TypeAttr.cVars = 0;
6296 pTIImpl->TypeAttr.wTypeFlags = 0;
6298 ppFuncDesc = &pTIImpl->funclist;
6299 for(func = 0; func < pidata->cMembers; func++) {
6300 METHODDATA *md = pidata->pmethdata + func;
6301 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6302 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6303 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6304 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6305 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6306 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6307 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6308 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6309 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6310 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6311 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6312 md->cArgs * sizeof(ELEMDESC));
6313 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6314 md->cArgs * sizeof(TLBParDesc));
6315 for(param = 0; param < md->cArgs; param++) {
6316 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6317 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6319 ppFuncDesc = &(*ppFuncDesc)->next;
6321 *pptinfo = (ITypeInfo*)pTIImpl;
6322 return S_OK;
6326 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6328 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6330 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6333 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6335 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6337 return ITypeInfo_AddRef((ITypeInfo *)This);
6340 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6342 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6344 return ITypeInfo_Release((ITypeInfo *)This);
6347 static HRESULT WINAPI ITypeComp_fnBind(
6348 ITypeComp * iface,
6349 OLECHAR * szName,
6350 ULONG lHash,
6351 WORD wFlags,
6352 ITypeInfo ** ppTInfo,
6353 DESCKIND * pDescKind,
6354 BINDPTR * pBindPtr)
6356 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6357 TLBFuncDesc * pFDesc;
6358 TLBVarDesc * pVDesc;
6360 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6362 *pDescKind = DESCKIND_NONE;
6363 pBindPtr->lpfuncdesc = NULL;
6364 *ppTInfo = NULL;
6366 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6367 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6368 if (!strcmpW(pFDesc->Name, szName)) {
6369 break;
6372 if (pFDesc)
6374 HRESULT hr = TLB_AllocAndInitFuncDesc(&pFDesc->funcdesc, &pBindPtr->lpfuncdesc);
6375 if (FAILED(hr))
6376 return hr;
6377 *pDescKind = DESCKIND_FUNCDESC;
6378 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6379 ITypeInfo_AddRef(*ppTInfo);
6380 return S_OK;
6381 } else {
6382 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
6384 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6385 if (!strcmpW(pVDesc->Name, szName)) {
6386 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6387 if (FAILED(hr))
6388 return hr;
6389 *pDescKind = DESCKIND_VARDESC;
6390 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6391 ITypeInfo_AddRef(*ppTInfo);
6392 return S_OK;
6397 /* FIXME: search each inherited interface, not just the first */
6398 if (This->TypeAttr.cImplTypes) {
6399 /* recursive search */
6400 ITypeInfo *pTInfo;
6401 ITypeComp *pTComp;
6402 HRESULT hr;
6403 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6404 if (SUCCEEDED(hr))
6406 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6407 ITypeInfo_Release(pTInfo);
6409 if (SUCCEEDED(hr))
6411 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6412 ITypeComp_Release(pTComp);
6413 return hr;
6415 WARN("Could not search inherited interface!\n");
6417 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6418 return DISP_E_MEMBERNOTFOUND;
6421 static HRESULT WINAPI ITypeComp_fnBindType(
6422 ITypeComp * iface,
6423 OLECHAR * szName,
6424 ULONG lHash,
6425 ITypeInfo ** ppTInfo,
6426 ITypeComp ** ppTComp)
6428 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6430 /* strange behaviour (does nothing) but like the
6431 * original */
6433 if (!ppTInfo || !ppTComp)
6434 return E_POINTER;
6436 *ppTInfo = NULL;
6437 *ppTComp = NULL;
6439 return S_OK;
6442 static const ITypeCompVtbl tcompvt =
6445 ITypeComp_fnQueryInterface,
6446 ITypeComp_fnAddRef,
6447 ITypeComp_fnRelease,
6449 ITypeComp_fnBind,
6450 ITypeComp_fnBindType