oleaut: Revert incorrect patch changing the order of parameters passed
[wine/multimedia.git] / dlls / oleaut32 / typelib.c
blob8cface4595a0ef10d682b9102d7adf371bd63969
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, const 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 HREFTYPE hreftype; /* hreftype for app object binding */
980 /* type libs seem to store the doc strings in ascii
981 * so why should we do it in unicode?
983 BSTR Name;
984 BSTR DocString;
985 BSTR DllName;
986 unsigned long dwHelpContext;
987 unsigned long dwHelpStringContext;
989 /* functions */
990 TLBFuncDesc * funclist; /* linked list with function descriptions */
992 /* variables */
993 TLBVarDesc * varlist; /* linked list with variable descriptions */
995 /* Implemented Interfaces */
996 TLBImplType * impltypelist;
998 TLBRefType * reflist;
999 int ctCustData;
1000 TLBCustData * pCustData; /* linked list to cust data; */
1001 struct tagITypeInfoImpl * next;
1002 } ITypeInfoImpl;
1004 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1006 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1009 static const ITypeInfo2Vtbl tinfvt;
1010 static const ITypeCompVtbl tcompvt;
1012 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1014 typedef struct tagTLBContext
1016 unsigned int oStart; /* start of TLB in file */
1017 unsigned int pos; /* current pos */
1018 unsigned int length; /* total length */
1019 void *mapping; /* memory mapping */
1020 MSFT_SegDir * pTblDir;
1021 ITypeLibImpl* pLibInfo;
1022 } TLBContext;
1025 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1028 debug
1030 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1031 if (pTD->vt & VT_RESERVED)
1032 szVarType += strlen(strcpy(szVarType, "reserved | "));
1033 if (pTD->vt & VT_BYREF)
1034 szVarType += strlen(strcpy(szVarType, "ref to "));
1035 if (pTD->vt & VT_ARRAY)
1036 szVarType += strlen(strcpy(szVarType, "array of "));
1037 if (pTD->vt & VT_VECTOR)
1038 szVarType += strlen(strcpy(szVarType, "vector of "));
1039 switch(pTD->vt & VT_TYPEMASK) {
1040 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1041 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1042 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1043 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1044 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1045 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1046 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1047 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1048 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1049 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1050 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1051 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1052 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1053 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1054 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1055 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1056 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1057 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1058 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1059 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1060 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1061 pTD->u.hreftype); break;
1062 case VT_PTR: sprintf(szVarType, "ptr to ");
1063 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1064 break;
1065 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1066 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1067 break;
1068 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1069 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1070 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1071 break;
1073 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1077 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1078 char buf[200];
1079 USHORT flags = edesc->u.paramdesc.wParamFlags;
1080 dump_TypeDesc(&edesc->tdesc,buf);
1081 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1082 MESSAGE("\t\tu.paramdesc.wParamFlags");
1083 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1084 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1085 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1086 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1087 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1088 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1089 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1090 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1091 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1093 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1094 int i;
1095 MESSAGE("memid is %08lx\n",funcdesc->memid);
1096 for (i=0;i<funcdesc->cParams;i++) {
1097 MESSAGE("Param %d:\n",i);
1098 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1100 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1101 switch (funcdesc->funckind) {
1102 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1103 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1104 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1105 case FUNC_STATIC: MESSAGE("static");break;
1106 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1107 default: MESSAGE("unknown");break;
1109 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1110 switch (funcdesc->invkind) {
1111 case INVOKE_FUNC: MESSAGE("func");break;
1112 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1113 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1114 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1116 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1117 switch (funcdesc->callconv) {
1118 case CC_CDECL: MESSAGE("cdecl");break;
1119 case CC_PASCAL: MESSAGE("pascal");break;
1120 case CC_STDCALL: MESSAGE("stdcall");break;
1121 case CC_SYSCALL: MESSAGE("syscall");break;
1122 default:break;
1124 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1125 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1126 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1128 MESSAGE("\telemdescFunc (return value type):\n");
1129 dump_ELEMDESC(&funcdesc->elemdescFunc);
1132 static const char * typekind_desc[] =
1134 "TKIND_ENUM",
1135 "TKIND_RECORD",
1136 "TKIND_MODULE",
1137 "TKIND_INTERFACE",
1138 "TKIND_DISPATCH",
1139 "TKIND_COCLASS",
1140 "TKIND_ALIAS",
1141 "TKIND_UNION",
1142 "TKIND_MAX"
1145 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1147 int i;
1148 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1149 for (i=0;i<pfd->funcdesc.cParams;i++)
1150 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1153 dump_FUNCDESC(&(pfd->funcdesc));
1155 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1156 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1158 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1160 while (pfd)
1162 dump_TLBFuncDescOne(pfd);
1163 pfd = pfd->next;
1166 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1168 while (pvd)
1170 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1171 pvd = pvd->next;
1175 static void dump_TLBImpLib(const TLBImpLib *import)
1177 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1178 debugstr_w(import->name));
1179 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1180 import->wVersionMinor, import->lcid, import->offset);
1183 static void dump_TLBRefType(const TLBRefType * prt)
1185 while (prt)
1187 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1188 if(prt->index == -1)
1189 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1190 else
1191 TRACE_(typelib)("type no: %d\n", prt->index);
1193 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1194 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1195 TRACE_(typelib)("in lib\n");
1196 dump_TLBImpLib(prt->pImpTLInfo);
1198 prt = prt->next;
1202 static void dump_TLBImplType(const TLBImplType * impl)
1204 while (impl) {
1205 TRACE_(typelib)(
1206 "implementing/inheriting interface hRef = %lx implflags %x\n",
1207 impl->hRef, impl->implflags);
1208 impl = impl->next;
1212 void dump_Variant(const VARIANT * pvar)
1214 SYSTEMTIME st;
1216 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1218 if (pvar)
1220 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1221 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1223 TRACE(",%p", V_BYREF(pvar));
1225 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1227 TRACE(",%p", V_ARRAY(pvar));
1229 else switch (V_TYPE(pvar))
1231 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1232 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1233 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1234 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1235 case VT_INT:
1236 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1237 case VT_UINT:
1238 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1239 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1240 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1241 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1242 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1243 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1244 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1245 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1246 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1247 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1248 V_CY(pvar).s.Lo); break;
1249 case VT_DATE:
1250 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1251 TRACE(",<invalid>");
1252 else
1253 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1254 st.wHour, st.wMinute, st.wSecond);
1255 break;
1256 case VT_ERROR:
1257 case VT_VOID:
1258 case VT_USERDEFINED:
1259 case VT_EMPTY:
1260 case VT_NULL: break;
1261 default: TRACE(",?"); break;
1264 TRACE("}\n");
1267 static void dump_DispParms(const DISPPARAMS * pdp)
1269 int index = 0;
1271 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1273 while (index < pdp->cArgs)
1275 dump_Variant( &pdp->rgvarg[index] );
1276 ++index;
1280 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1282 TRACE("%p ref=%lu\n", pty, pty->ref);
1283 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
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("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1289 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1290 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1291 if (TRACE_ON(ole))
1292 dump_TLBFuncDesc(pty->funclist);
1293 dump_TLBVarDesc(pty->varlist);
1294 dump_TLBImplType(pty->impltypelist);
1297 static void dump_VARDESC(const VARDESC *v)
1299 MESSAGE("memid %ld\n",v->memid);
1300 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1301 MESSAGE("oInst %ld\n",v->u.oInst);
1302 dump_ELEMDESC(&(v->elemdescVar));
1303 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1304 MESSAGE("varkind %d\n",v->varkind);
1307 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1309 /* VT_LPWSTR is largest type that */
1310 /* may appear in type description*/
1311 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1312 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1313 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1314 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1315 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1316 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1317 {{0},30},{{0},31}
1320 static void TLB_abort(void)
1322 DebugBreak();
1324 static void * TLB_Alloc(unsigned size)
1326 void * ret;
1327 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1328 /* FIXME */
1329 ERR("cannot allocate memory\n");
1331 return ret;
1334 static void TLB_Free(void * ptr)
1336 HeapFree(GetProcessHeap(), 0, ptr);
1339 /* returns the size required for a deep copy of a typedesc into a
1340 * flat buffer */
1341 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1343 SIZE_T size = 0;
1345 if (alloc_initial_space)
1346 size += sizeof(TYPEDESC);
1348 switch (tdesc->vt)
1350 case VT_PTR:
1351 case VT_SAFEARRAY:
1352 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1353 break;
1354 case VT_CARRAY:
1355 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1356 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1357 break;
1359 return size;
1362 /* deep copy a typedesc into a flat buffer */
1363 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1365 if (!dest)
1367 dest = buffer;
1368 buffer = (char *)buffer + sizeof(TYPEDESC);
1371 *dest = *src;
1373 switch (src->vt)
1375 case VT_PTR:
1376 case VT_SAFEARRAY:
1377 dest->u.lptdesc = buffer;
1378 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1379 break;
1380 case VT_CARRAY:
1381 dest->u.lpadesc = buffer;
1382 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1383 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1384 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1385 break;
1387 return buffer;
1390 /**********************************************************************
1392 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1394 /* read function */
1395 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1397 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1398 pcx->pos, count, pcx->oStart, pcx->length, where);
1400 if (where != DO_NOT_SEEK)
1402 where += pcx->oStart;
1403 if (where > pcx->length)
1405 /* FIXME */
1406 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1407 TLB_abort();
1409 pcx->pos = where;
1411 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1412 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1413 pcx->pos += count;
1414 return count;
1417 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1418 long where )
1420 DWORD ret;
1422 ret = MSFT_Read(buffer, count, pcx, where);
1423 FromLEDWords(buffer, ret);
1425 return ret;
1428 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1429 long where )
1431 DWORD ret;
1433 ret = MSFT_Read(buffer, count, pcx, where);
1434 FromLEWords(buffer, ret);
1436 return ret;
1439 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1441 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1442 memset(pGuid,0, sizeof(GUID));
1443 return;
1445 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1446 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1447 pGuid->Data2 = FromLEWord(pGuid->Data2);
1448 pGuid->Data3 = FromLEWord(pGuid->Data3);
1449 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1452 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1454 MSFT_NameIntro niName;
1456 if (offset < 0)
1458 ERR_(typelib)("bad offset %d\n", offset);
1459 return -1;
1462 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1463 pcx->pTblDir->pNametab.offset+offset);
1465 return niName.hreftype;
1468 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1470 char * name;
1471 MSFT_NameIntro niName;
1472 int lengthInChars;
1473 WCHAR* pwstring = NULL;
1474 BSTR bstrName = NULL;
1476 if (offset < 0)
1478 ERR_(typelib)("bad offset %d\n", offset);
1479 return NULL;
1481 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1482 pcx->pTblDir->pNametab.offset+offset);
1483 niName.namelen &= 0xFF; /* FIXME: correct ? */
1484 name=TLB_Alloc((niName.namelen & 0xff) +1);
1485 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1486 name[niName.namelen & 0xff]='\0';
1488 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1489 name, -1, NULL, 0);
1491 /* no invalid characters in string */
1492 if (lengthInChars)
1494 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1496 /* don't check for invalid character since this has been done previously */
1497 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1499 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1500 lengthInChars = SysStringLen(bstrName);
1501 HeapFree(GetProcessHeap(), 0, pwstring);
1504 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1505 return bstrName;
1508 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1510 char * string;
1511 INT16 length;
1512 int lengthInChars;
1513 BSTR bstr = NULL;
1515 if(offset<0) return NULL;
1516 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1517 if(length <= 0) return 0;
1518 string=TLB_Alloc(length +1);
1519 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1520 string[length]='\0';
1522 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1523 string, -1, NULL, 0);
1525 /* no invalid characters in string */
1526 if (lengthInChars)
1528 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1530 /* don't check for invalid character since this has been done previously */
1531 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1533 bstr = SysAllocStringLen(pwstring, lengthInChars);
1534 lengthInChars = SysStringLen(bstr);
1535 HeapFree(GetProcessHeap(), 0, pwstring);
1538 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1539 return bstr;
1542 * read a value and fill a VARIANT structure
1544 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1546 int size;
1548 TRACE_(typelib)("\n");
1550 if(offset <0) { /* data are packed in here */
1551 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1552 V_I4(pVar) = offset & 0x3ffffff;
1553 return;
1555 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1556 pcx->pTblDir->pCustData.offset + offset );
1557 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1558 switch (V_VT(pVar)){
1559 case VT_EMPTY: /* FIXME: is this right? */
1560 case VT_NULL: /* FIXME: is this right? */
1561 case VT_I2 : /* this should not happen */
1562 case VT_I4 :
1563 case VT_R4 :
1564 case VT_ERROR :
1565 case VT_BOOL :
1566 case VT_I1 :
1567 case VT_UI1 :
1568 case VT_UI2 :
1569 case VT_UI4 :
1570 case VT_INT :
1571 case VT_UINT :
1572 case VT_VOID : /* FIXME: is this right? */
1573 case VT_HRESULT :
1574 size=4; break;
1575 case VT_R8 :
1576 case VT_CY :
1577 case VT_DATE :
1578 case VT_I8 :
1579 case VT_UI8 :
1580 case VT_DECIMAL : /* FIXME: is this right? */
1581 case VT_FILETIME :
1582 size=8;break;
1583 /* pointer types with known behaviour */
1584 case VT_BSTR :{
1585 char * ptr;
1586 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1587 if(size < 0) {
1588 FIXME("BSTR length = %d?\n", size);
1589 } else {
1590 ptr=TLB_Alloc(size);/* allocate temp buffer */
1591 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1592 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1593 /* FIXME: do we need a AtoW conversion here? */
1594 V_UNION(pVar, bstrVal[size])=L'\0';
1595 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1596 TLB_Free(ptr);
1599 size=-4; break;
1600 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1601 case VT_DISPATCH :
1602 case VT_VARIANT :
1603 case VT_UNKNOWN :
1604 case VT_PTR :
1605 case VT_SAFEARRAY :
1606 case VT_CARRAY :
1607 case VT_USERDEFINED :
1608 case VT_LPSTR :
1609 case VT_LPWSTR :
1610 case VT_BLOB :
1611 case VT_STREAM :
1612 case VT_STORAGE :
1613 case VT_STREAMED_OBJECT :
1614 case VT_STORED_OBJECT :
1615 case VT_BLOB_OBJECT :
1616 case VT_CF :
1617 case VT_CLSID :
1618 default:
1619 size=0;
1620 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1621 V_VT(pVar));
1624 if(size>0) /* (big|small) endian correct? */
1625 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1626 return;
1629 * create a linked list with custom data
1631 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1633 MSFT_CDGuid entry;
1634 TLBCustData* pNew;
1635 int count=0;
1637 TRACE_(typelib)("\n");
1639 while(offset >=0){
1640 count++;
1641 pNew=TLB_Alloc(sizeof(TLBCustData));
1642 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1643 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1644 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1645 /* add new custom data at head of the list */
1646 pNew->next=*ppCustData;
1647 *ppCustData=pNew;
1648 offset = entry.next;
1650 return count;
1653 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1654 ITypeInfoImpl *pTI)
1656 if(type <0)
1657 pTd->vt=type & VT_TYPEMASK;
1658 else
1659 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1661 if(pTd->vt == VT_USERDEFINED)
1662 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1664 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1667 static void
1668 MSFT_DoFuncs(TLBContext* pcx,
1669 ITypeInfoImpl* pTI,
1670 int cFuncs,
1671 int cVars,
1672 int offset,
1673 TLBFuncDesc** pptfd)
1676 * member information is stored in a data structure at offset
1677 * indicated by the memoffset field of the typeinfo structure
1678 * There are several distinctive parts.
1679 * The first part starts with a field that holds the total length
1680 * of this (first) part excluding this field. Then follow the records,
1681 * for each member there is one record.
1683 * The first entry is always the length of the record (including this
1684 * length word).
1685 * The rest of the record depends on the type of the member. If there is
1686 * a field indicating the member type (function, variable, interface, etc)
1687 * I have not found it yet. At this time we depend on the information
1688 * in the type info and the usual order how things are stored.
1690 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1691 * for each member;
1693 * Third is an equal sized array with file offsets to the name entry
1694 * of each member.
1696 * The fourth and last (?) part is an array with offsets to the records
1697 * in the first part of this file segment.
1700 int infolen, nameoffset, reclength, nrattributes, i;
1701 int recoffset = offset + sizeof(INT);
1703 char recbuf[512];
1704 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1705 TLBFuncDesc *ptfd_prev = NULL;
1707 TRACE_(typelib)("\n");
1709 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1711 for ( i = 0; i < cFuncs ; i++ )
1713 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1715 /* name, eventually add to a hash table */
1716 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1717 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1719 /* nameoffset is sometimes -1 on the second half of a propget/propput
1720 * pair of functions */
1721 if ((nameoffset == -1) && (i > 0))
1722 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1723 else
1724 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1726 /* read the function information record */
1727 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1729 reclength &= 0x1ff;
1731 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1733 /* do the attributes */
1734 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1735 / sizeof(int);
1737 if ( nrattributes > 0 )
1739 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1741 if ( nrattributes > 1 )
1743 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1744 pFuncRec->OptAttr[1]) ;
1746 if ( nrattributes > 2 )
1748 if ( pFuncRec->FKCCIC & 0x2000 )
1750 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1752 else
1754 (*pptfd)->Entry = MSFT_ReadString(pcx,
1755 pFuncRec->OptAttr[2]);
1757 if( nrattributes > 5 )
1759 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1761 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1763 MSFT_CustData(pcx,
1764 pFuncRec->OptAttr[6],
1765 &(*pptfd)->pCustData);
1772 /* fill the FuncDesc Structure */
1773 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1774 offset + infolen + ( i + 1) * sizeof(INT));
1776 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1777 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1778 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1779 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1780 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1781 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1782 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1784 MSFT_GetTdesc(pcx,
1785 pFuncRec->DataType,
1786 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1787 pTI);
1789 /* do the parameters/arguments */
1790 if(pFuncRec->nrargs)
1792 int j = 0;
1793 MSFT_ParameterInfo paraminfo;
1795 (*pptfd)->funcdesc.lprgelemdescParam =
1796 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1798 (*pptfd)->pParamDesc =
1799 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1801 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1802 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1804 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1806 TYPEDESC *lpArgTypeDesc;
1807 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1809 MSFT_GetTdesc(pcx,
1810 paraminfo.DataType,
1811 &elemdesc->tdesc,
1812 pTI);
1814 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1816 /* name */
1817 if (paraminfo.oName == -1)
1818 /* this occurs for [propput] or [propget] methods, so
1819 * we should just set the name of the parameter to the
1820 * name of the method. */
1821 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1822 else
1823 (*pptfd)->pParamDesc[j].Name =
1824 MSFT_ReadName( pcx, paraminfo.oName );
1825 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1827 lpArgTypeDesc = &elemdesc->tdesc;
1829 /* resolve referenced type if any */
1830 while ( lpArgTypeDesc != NULL )
1832 switch ( lpArgTypeDesc->vt )
1834 case VT_PTR:
1835 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1836 break;
1838 case VT_CARRAY:
1839 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1840 break;
1842 case VT_USERDEFINED:
1843 MSFT_DoRefType(pcx, pTI,
1844 lpArgTypeDesc->u.hreftype);
1846 lpArgTypeDesc = NULL;
1847 break;
1849 default:
1850 lpArgTypeDesc = NULL;
1854 /* default value */
1855 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1856 (pFuncRec->FKCCIC & 0x1000) )
1858 INT* pInt = (INT *)((char *)pFuncRec +
1859 reclength -
1860 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1862 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1864 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1865 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1867 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1868 pInt[j], pcx);
1870 else
1871 elemdesc->u.paramdesc.pparamdescex = NULL;
1872 /* custom info */
1873 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1875 MSFT_CustData(pcx,
1876 pFuncRec->OptAttr[7+j],
1877 &(*pptfd)->pParamDesc[j].pCustData);
1880 /* SEEK value = jump to offset,
1881 * from there jump to the end of record,
1882 * go back by (j-1) arguments
1884 MSFT_ReadLEDWords( &paraminfo ,
1885 sizeof(MSFT_ParameterInfo), pcx,
1886 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1887 * sizeof(MSFT_ParameterInfo)));
1891 /* scode is not used: archaic win16 stuff FIXME: right? */
1892 (*pptfd)->funcdesc.cScodes = 0 ;
1893 (*pptfd)->funcdesc.lprgscode = NULL ;
1895 ptfd_prev = *pptfd;
1896 pptfd = & ((*pptfd)->next);
1897 recoffset += reclength;
1901 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1902 int cVars, int offset, TLBVarDesc ** pptvd)
1904 int infolen, nameoffset, reclength;
1905 char recbuf[256];
1906 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1907 int i;
1908 int recoffset;
1910 TRACE_(typelib)("\n");
1912 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1913 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1914 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1915 recoffset += offset+sizeof(INT);
1916 for(i=0;i<cVars;i++){
1917 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1918 /* name, eventually add to a hash table */
1919 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1920 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1921 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1922 /* read the variable information record */
1923 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1924 reclength &=0xff;
1925 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1926 /* Optional data */
1927 if(reclength >(6*sizeof(INT)) )
1928 (*pptvd)->HelpContext=pVarRec->HelpContext;
1929 if(reclength >(7*sizeof(INT)) )
1930 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1931 if(reclength >(8*sizeof(INT)) )
1932 if(reclength >(9*sizeof(INT)) )
1933 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1934 /* fill the VarDesc Structure */
1935 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1936 offset + infolen + ( i + 1) * sizeof(INT));
1937 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1938 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1939 MSFT_GetTdesc(pcx, pVarRec->DataType,
1940 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1941 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1942 if(pVarRec->VarKind == VAR_CONST ){
1943 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1944 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1945 pVarRec->OffsValue, pcx);
1946 } else
1947 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1948 pptvd=&((*pptvd)->next);
1949 recoffset += reclength;
1952 /* fill in data for a hreftype (offset). When the referenced type is contained
1953 * in the typelib, it's just an (file) offset in the type info base dir.
1954 * If comes from import, it's an offset+1 in the ImpInfo table
1955 * */
1956 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1957 int offset)
1959 int j;
1960 TLBRefType **ppRefType = &pTI->reflist;
1962 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1964 while(*ppRefType) {
1965 if((*ppRefType)->reference == offset)
1966 return;
1967 ppRefType = &(*ppRefType)->next;
1970 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1971 sizeof(**ppRefType));
1973 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1974 /* external typelib */
1975 MSFT_ImpInfo impinfo;
1976 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1978 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1980 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1981 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1982 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1983 if(pImpLib->offset==impinfo.oImpFile) break;
1984 pImpLib=pImpLib->next;
1986 if(pImpLib){
1987 (*ppRefType)->reference=offset;
1988 (*ppRefType)->pImpTLInfo = pImpLib;
1989 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1990 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1991 (*ppRefType)->index = TLB_REF_USE_GUID;
1992 } else
1993 (*ppRefType)->index = impinfo.oGuid;
1994 }else{
1995 ERR("Cannot find a reference\n");
1996 (*ppRefType)->reference=-1;
1997 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1999 }else{
2000 /* in this typelib */
2001 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2002 (*ppRefType)->reference=offset;
2003 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2007 /* process Implemented Interfaces of a com class */
2008 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2009 int offset)
2011 int i;
2012 MSFT_RefRecord refrec;
2013 TLBImplType **ppImpl = &pTI->impltypelist;
2015 TRACE_(typelib)("\n");
2017 for(i=0;i<count;i++){
2018 if(offset<0) break; /* paranoia */
2019 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2020 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2021 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2022 (*ppImpl)->hRef = refrec.reftype;
2023 (*ppImpl)->implflags=refrec.flags;
2024 (*ppImpl)->ctCustData=
2025 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2026 offset=refrec.onext;
2027 ppImpl=&((*ppImpl)->next);
2031 * process a typeinfo record
2033 static ITypeInfoImpl * MSFT_DoTypeInfo(
2034 TLBContext *pcx,
2035 int count,
2036 ITypeLibImpl * pLibInfo)
2038 MSFT_TypeInfoBase tiBase;
2039 ITypeInfoImpl *ptiRet;
2041 TRACE_(typelib)("count=%u\n", count);
2043 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2044 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2045 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2047 /* this is where we are coming from */
2048 ptiRet->pTypeLib = pLibInfo;
2049 ptiRet->index=count;
2050 /* fill in the typeattr fields */
2051 WARN("Assign constructor/destructor memid\n");
2053 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2054 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2055 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2056 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2057 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2058 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2059 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2060 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2061 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2062 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2063 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2064 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2065 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2066 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2067 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2068 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2069 MSFT_GetTdesc(pcx, tiBase.datatype1,
2070 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2072 /* FIXME: */
2073 /* IDLDESC idldescType; *//* never saw this one != zero */
2075 /* name, eventually add to a hash table */
2076 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2077 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2078 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2079 /* help info */
2080 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2081 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2082 ptiRet->dwHelpContext=tiBase.helpcontext;
2084 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2085 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2087 /* note: InfoType's Help file and HelpStringDll come from the containing
2088 * library. Further HelpString and Docstring appear to be the same thing :(
2090 /* functions */
2091 if(ptiRet->TypeAttr.cFuncs >0 )
2092 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2093 ptiRet->TypeAttr.cVars,
2094 tiBase.memoffset, & ptiRet->funclist);
2095 /* variables */
2096 if(ptiRet->TypeAttr.cVars >0 )
2097 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2098 ptiRet->TypeAttr.cVars,
2099 tiBase.memoffset, & ptiRet->varlist);
2100 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2101 switch(ptiRet->TypeAttr.typekind)
2103 case TKIND_COCLASS:
2104 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2105 tiBase.datatype1);
2106 break;
2107 case TKIND_DISPATCH:
2108 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2110 if (tiBase.datatype1 != -1)
2112 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2113 ptiRet->impltypelist->hRef = tiBase.datatype1;
2115 else
2116 { /* FIXME: This is a really bad hack to add IDispatch */
2117 const char* szStdOle = "stdole2.tlb\0";
2118 int nStdOleLen = strlen(szStdOle);
2119 TLBRefType **ppRef = &ptiRet->reflist;
2121 while(*ppRef) {
2122 if((*ppRef)->reference == -1)
2123 break;
2124 ppRef = &(*ppRef)->next;
2126 if(!*ppRef) {
2127 *ppRef = TLB_Alloc(sizeof(**ppRef));
2128 (*ppRef)->guid = IID_IDispatch;
2129 (*ppRef)->reference = -1;
2130 (*ppRef)->index = TLB_REF_USE_GUID;
2131 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2132 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2133 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2134 nStdOleLen + 1);
2136 MultiByteToWideChar(CP_ACP,
2137 MB_PRECOMPOSED,
2138 szStdOle,
2140 (*ppRef)->pImpTLInfo->name,
2141 SysStringLen((*ppRef)->pImpTLInfo->name));
2143 (*ppRef)->pImpTLInfo->lcid = 0;
2144 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2145 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2148 break;
2149 default:
2150 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2151 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2152 ptiRet->impltypelist->hRef = tiBase.datatype1;
2153 break;
2156 ptiRet->ctCustData=
2157 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2159 TRACE_(typelib)("%s guid: %s kind:%s\n",
2160 debugstr_w(ptiRet->Name),
2161 debugstr_guid(&ptiRet->TypeAttr.guid),
2162 typekind_desc[ptiRet->TypeAttr.typekind]);
2164 return ptiRet;
2167 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2168 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2169 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2170 * tradeoff here.
2172 static ITypeLibImpl *tlb_cache_first;
2173 static CRITICAL_SECTION cache_section;
2174 static CRITICAL_SECTION_DEBUG cache_section_debug =
2176 0, 0, &cache_section,
2177 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2178 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2180 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2183 /****************************************************************************
2184 * TLB_ReadTypeLib
2186 * find the type of the typelib file and map the typelib resource into
2187 * the memory
2189 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2190 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2191 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2193 ITypeLibImpl *entry;
2194 int ret = TYPE_E_CANTLOADLIBRARY;
2195 DWORD dwSignature = 0;
2196 HANDLE hFile;
2198 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2200 *ppTypeLib = NULL;
2202 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2203 EnterCriticalSection(&cache_section);
2204 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2206 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2208 TRACE("cache hit\n");
2209 *ppTypeLib = (ITypeLib2*)entry;
2210 ITypeLib_AddRef(*ppTypeLib);
2211 LeaveCriticalSection(&cache_section);
2212 return S_OK;
2215 LeaveCriticalSection(&cache_section);
2217 /* check the signature of the file */
2218 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2219 if (INVALID_HANDLE_VALUE != hFile)
2221 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2222 if (hMapping)
2224 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2225 if(pBase)
2227 /* retrieve file size */
2228 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2230 /* first try to load as *.tlb */
2231 dwSignature = FromLEDWord(*((DWORD*) pBase));
2232 if ( dwSignature == MSFT_SIGNATURE)
2234 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2236 else if ( dwSignature == SLTG_SIGNATURE)
2238 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2240 UnmapViewOfFile(pBase);
2242 CloseHandle(hMapping);
2244 CloseHandle(hFile);
2246 else
2248 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2251 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2252 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2254 /* find the typelibrary resource*/
2255 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2256 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2257 if (hinstDLL)
2259 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2260 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2261 if (hrsrc)
2263 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2264 if (hGlobal)
2266 LPVOID pBase = LockResource(hGlobal);
2267 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2269 if (pBase)
2271 /* try to load as incore resource */
2272 dwSignature = FromLEDWord(*((DWORD*) pBase));
2273 if ( dwSignature == MSFT_SIGNATURE)
2275 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2277 else if ( dwSignature == SLTG_SIGNATURE)
2279 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2281 else
2283 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2286 FreeResource( hGlobal );
2289 FreeLibrary(hinstDLL);
2293 if(*ppTypeLib) {
2294 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2296 TRACE("adding to cache\n");
2297 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2298 lstrcpyW(impl->path, pszFileName);
2299 /* We should really canonicalise the path here. */
2300 impl->index = index;
2302 /* FIXME: check if it has added already in the meantime */
2303 EnterCriticalSection(&cache_section);
2304 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2305 impl->prev = NULL;
2306 tlb_cache_first = impl;
2307 LeaveCriticalSection(&cache_section);
2308 ret = S_OK;
2309 } else
2310 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2312 return ret;
2315 /*================== ITypeLib(2) Methods ===================================*/
2317 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2319 ITypeLibImpl* pTypeLibImpl;
2321 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2322 if (!pTypeLibImpl) return NULL;
2324 pTypeLibImpl->lpVtbl = &tlbvt;
2325 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2326 pTypeLibImpl->ref = 1;
2328 return pTypeLibImpl;
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 = TypeLibImpl_Constructor();
2347 if (!pTypeLibImpl) return NULL;
2349 /* get pointer to beginning of typelib data */
2350 cx.pos = 0;
2351 cx.oStart=0;
2352 cx.mapping = pLib;
2353 cx.pLibInfo = pTypeLibImpl;
2354 cx.length = dwTLBLength;
2356 /* read header */
2357 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2358 TRACE("header:\n");
2359 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2360 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2361 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2362 return NULL;
2364 /* there is a small amount of information here until the next important
2365 * part:
2366 * the segment directory . Try to calculate the amount of data */
2367 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2369 /* now read the segment directory */
2370 TRACE("read segment directory (at %ld)\n",lPSegDir);
2371 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2372 cx.pTblDir = &tlbSegDir;
2374 /* just check two entries */
2375 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2377 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2378 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2379 return NULL;
2382 /* now fill our internal data */
2383 /* TLIBATTR fields */
2384 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2386 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2387 /* Windows seems to have zero here, is this correct? */
2388 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2389 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2390 else
2391 pTypeLibImpl->LibAttr.lcid = 0;
2393 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2394 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2395 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2396 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2398 /* name, eventually add to a hash table */
2399 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2401 /* help info */
2402 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2403 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2405 if( tlbHeader.varflags & HELPDLLFLAG)
2407 int offset;
2408 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2409 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2412 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2414 /* custom data */
2415 if(tlbHeader.CustomDataOffset >= 0)
2417 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2420 /* fill in typedescriptions */
2421 if(tlbSegDir.pTypdescTab.length > 0)
2423 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2424 INT16 td[4];
2425 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2426 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2427 for(i=0; i<cTD; )
2429 /* FIXME: add several sanity checks here */
2430 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2431 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2433 /* FIXME: check safearray */
2434 if(td[3] < 0)
2435 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2436 else
2437 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2439 else if(td[0] == VT_CARRAY)
2441 /* array descr table here */
2442 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2444 else if(td[0] == VT_USERDEFINED)
2446 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2448 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2451 /* second time around to fill the array subscript info */
2452 for(i=0;i<cTD;i++)
2454 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2455 if(tlbSegDir.pArrayDescriptions.offset>0)
2457 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2458 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2460 if(td[1]<0)
2461 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2462 else
2463 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2465 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2467 for(j = 0; j<td[2]; j++)
2469 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2470 sizeof(INT), &cx, DO_NOT_SEEK);
2471 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2472 sizeof(INT), &cx, DO_NOT_SEEK);
2475 else
2477 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2478 ERR("didn't find array description data\n");
2483 /* imported type libs */
2484 if(tlbSegDir.pImpFiles.offset>0)
2486 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2487 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2488 UINT16 size;
2490 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2492 char *name;
2493 DWORD len;
2495 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2496 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2497 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2499 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2500 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2501 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2502 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2504 size >>= 2;
2505 name = TLB_Alloc(size+1);
2506 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2507 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2508 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2509 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2510 TLB_Free(name);
2512 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2513 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2515 ppImpLib = &(*ppImpLib)->next;
2519 /* type info's */
2520 if(tlbHeader.nrtypeinfos >= 0 )
2522 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2523 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2524 int i;
2526 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2528 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2530 ppTI = &((*ppTI)->next);
2531 (pTypeLibImpl->TypeInfoCount)++;
2535 TRACE("(%p)\n", pTypeLibImpl);
2536 return (ITypeLib2*) pTypeLibImpl;
2540 static BSTR TLB_MultiByteToBSTR(char *ptr)
2542 DWORD len;
2543 WCHAR *nameW;
2544 BSTR ret;
2546 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2547 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2548 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2549 ret = SysAllocString(nameW);
2550 HeapFree(GetProcessHeap(), 0, nameW);
2551 return ret;
2554 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2556 char b[3];
2557 int i;
2558 short s;
2560 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2561 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2562 return FALSE;
2565 guid->Data4[0] = s >> 8;
2566 guid->Data4[1] = s & 0xff;
2568 b[2] = '\0';
2569 for(i = 0; i < 6; i++) {
2570 memcpy(b, str + 24 + 2 * i, 2);
2571 guid->Data4[i + 2] = strtol(b, NULL, 16);
2573 return TRUE;
2576 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2578 WORD bytelen;
2579 DWORD len;
2580 WCHAR *nameW;
2582 *pBstr = NULL;
2583 bytelen = *(WORD*)ptr;
2584 if(bytelen == 0xffff) return 2;
2585 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2586 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2587 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2588 *pBstr = SysAllocStringLen(nameW, len);
2589 HeapFree(GetProcessHeap(), 0, nameW);
2590 return bytelen + 2;
2593 static WORD SLTG_ReadStringA(char *ptr, char **str)
2595 WORD bytelen;
2597 *str = NULL;
2598 bytelen = *(WORD*)ptr;
2599 if(bytelen == 0xffff) return 2;
2600 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2601 memcpy(*str, ptr + 2, bytelen);
2602 (*str)[bytelen] = '\0';
2603 return bytelen + 2;
2606 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2608 char *ptr = pLibBlk;
2609 WORD w;
2611 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2612 FIXME("libblk magic = %04x\n", w);
2613 return 0;
2616 ptr += 6;
2617 if((w = *(WORD*)ptr) != 0xffff) {
2618 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2619 ptr += w;
2621 ptr += 2;
2623 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2625 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2627 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2628 ptr += 4;
2630 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2631 ptr += 2;
2633 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2634 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2635 else
2636 pTypeLibImpl->LibAttr.lcid = 0;
2637 ptr += 2;
2639 ptr += 4; /* skip res12 */
2641 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2642 ptr += 2;
2644 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2645 ptr += 2;
2647 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2648 ptr += 2;
2650 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2651 ptr += sizeof(GUID);
2653 return ptr - (char*)pLibBlk;
2656 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2658 BOOL done = FALSE;
2659 TYPEDESC *pTD = &pElem->tdesc;
2661 /* Handle [in/out] first */
2662 if((*pType & 0xc000) == 0xc000)
2663 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2664 else if(*pType & 0x8000)
2665 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2666 else if(*pType & 0x4000)
2667 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2668 else
2669 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2671 if(*pType & 0x2000)
2672 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2674 if(*pType & 0x80)
2675 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2677 while(!done) {
2678 if((*pType & 0xe00) == 0xe00) {
2679 pTD->vt = VT_PTR;
2680 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2681 sizeof(TYPEDESC));
2682 pTD = pTD->u.lptdesc;
2684 switch(*pType & 0x7f) {
2685 case VT_PTR:
2686 pTD->vt = VT_PTR;
2687 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2688 sizeof(TYPEDESC));
2689 pTD = pTD->u.lptdesc;
2690 break;
2692 case VT_USERDEFINED:
2693 pTD->vt = VT_USERDEFINED;
2694 pTD->u.hreftype = *(++pType) / 4;
2695 done = TRUE;
2696 break;
2698 case VT_CARRAY:
2700 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2701 array */
2703 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2705 pTD->vt = VT_CARRAY;
2706 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2707 sizeof(ARRAYDESC) +
2708 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2709 pTD->u.lpadesc->cDims = pSA->cDims;
2710 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2711 pSA->cDims * sizeof(SAFEARRAYBOUND));
2713 pTD = &pTD->u.lpadesc->tdescElem;
2714 break;
2717 case VT_SAFEARRAY:
2719 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2720 useful? */
2722 pType++;
2723 pTD->vt = VT_SAFEARRAY;
2724 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2725 sizeof(TYPEDESC));
2726 pTD = pTD->u.lptdesc;
2727 break;
2729 default:
2730 pTD->vt = *pType & 0x7f;
2731 done = TRUE;
2732 break;
2734 pType++;
2736 return pType;
2740 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2741 char *pNameTable)
2743 int ref;
2744 char *name;
2745 TLBRefType **ppRefType;
2747 if(pRef->magic != SLTG_REF_MAGIC) {
2748 FIXME("Ref magic = %x\n", pRef->magic);
2749 return;
2751 name = ( (char*)(&pRef->names) + pRef->number);
2753 ppRefType = &pTI->reflist;
2754 for(ref = 0; ref < pRef->number >> 3; ref++) {
2755 char *refname;
2756 unsigned int lib_offs, type_num;
2758 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2759 sizeof(**ppRefType));
2761 name += SLTG_ReadStringA(name, &refname);
2762 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2763 FIXME("Can't sscanf ref\n");
2764 if(lib_offs != 0xffff) {
2765 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2767 while(*import) {
2768 if((*import)->offset == lib_offs)
2769 break;
2770 import = &(*import)->next;
2772 if(!*import) {
2773 char fname[MAX_PATH+1];
2774 int len;
2776 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2777 sizeof(**import));
2778 (*import)->offset = lib_offs;
2779 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2780 &(*import)->guid);
2781 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2782 &(*import)->wVersionMajor,
2783 &(*import)->wVersionMinor,
2784 &(*import)->lcid, fname) != 4) {
2785 FIXME("can't sscanf ref %s\n",
2786 pNameTable + lib_offs + 40);
2788 len = strlen(fname);
2789 if(fname[len-1] != '#')
2790 FIXME("fname = %s\n", fname);
2791 fname[len-1] = '\0';
2792 (*import)->name = TLB_MultiByteToBSTR(fname);
2794 (*ppRefType)->pImpTLInfo = *import;
2795 } else { /* internal ref */
2796 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2798 (*ppRefType)->reference = ref;
2799 (*ppRefType)->index = type_num;
2801 HeapFree(GetProcessHeap(), 0, refname);
2802 ppRefType = &(*ppRefType)->next;
2804 if((BYTE)*name != SLTG_REF_MAGIC)
2805 FIXME("End of ref block magic = %x\n", *name);
2806 dump_TLBRefType(pTI->reflist);
2809 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2810 BOOL OneOnly)
2812 SLTG_ImplInfo *info;
2813 TLBImplType **ppImplType = &pTI->impltypelist;
2814 /* I don't really get this structure, usually it's 0x16 bytes
2815 long, but iuser.tlb contains some that are 0x18 bytes long.
2816 That's ok because we can use the next ptr to jump to the next
2817 one. But how do we know the length of the last one? The WORD
2818 at offs 0x8 might be the clue. For now I'm just assuming that
2819 the last one is the regular 0x16 bytes. */
2821 info = (SLTG_ImplInfo*)pBlk;
2822 while(1) {
2823 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2824 sizeof(**ppImplType));
2825 (*ppImplType)->hRef = info->ref;
2826 (*ppImplType)->implflags = info->impltypeflags;
2827 pTI->TypeAttr.cImplTypes++;
2828 ppImplType = &(*ppImplType)->next;
2830 if(info->next == 0xffff)
2831 break;
2832 if(OneOnly)
2833 FIXME("Interface inheriting more than one interface\n");
2834 info = (SLTG_ImplInfo*)(pBlk + info->next);
2836 info++; /* see comment at top of function */
2837 return (char*)info;
2840 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2841 char *pNameTable)
2843 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2844 SLTG_MemberHeader *pMemHeader;
2845 char *pFirstItem, *pNextItem;
2847 if(pTIHeader->href_table != 0xffffffff) {
2848 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2849 pNameTable);
2853 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2855 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2857 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2858 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2861 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2865 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2866 char *pNameTable)
2868 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2869 SLTG_MemberHeader *pMemHeader;
2870 SLTG_Function *pFunc;
2871 char *pFirstItem, *pNextItem;
2872 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2873 int num = 0;
2875 if(pTIHeader->href_table != 0xffffffff) {
2876 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2877 pNameTable);
2880 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2882 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2884 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2885 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2888 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2889 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2891 int param;
2892 WORD *pType, *pArg;
2894 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2895 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2896 FIXME("func magic = %02x\n", pFunc->magic);
2897 return NULL;
2899 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2900 sizeof(**ppFuncDesc));
2901 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2903 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2904 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2905 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2906 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2907 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2908 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2910 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2911 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2913 if(pFunc->retnextopt & 0x80)
2914 pType = &pFunc->rettype;
2915 else
2916 pType = (WORD*)(pFirstItem + pFunc->rettype);
2919 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2921 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2922 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2923 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2924 (*ppFuncDesc)->pParamDesc =
2925 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2926 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2928 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2930 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2931 char *paramName = pNameTable + *pArg;
2932 BOOL HaveOffs;
2933 /* If arg type follows then paramName points to the 2nd
2934 letter of the name, else the next WORD is an offset to
2935 the arg type and paramName points to the first letter.
2936 So let's take one char off paramName and see if we're
2937 pointing at an alpha-numeric char. However if *pArg is
2938 0xffff or 0xfffe then the param has no name, the former
2939 meaning that the next WORD is the type, the latter
2940 meaning the the next WORD is an offset to the type. */
2942 HaveOffs = FALSE;
2943 if(*pArg == 0xffff)
2944 paramName = NULL;
2945 else if(*pArg == 0xfffe) {
2946 paramName = NULL;
2947 HaveOffs = TRUE;
2949 else if(paramName[-1] && !isalnum(paramName[-1]))
2950 HaveOffs = TRUE;
2952 pArg++;
2954 if(HaveOffs) { /* the next word is an offset to type */
2955 pType = (WORD*)(pFirstItem + *pArg);
2956 SLTG_DoType(pType, pFirstItem,
2957 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2958 pArg++;
2959 } else {
2960 if(paramName)
2961 paramName--;
2962 pArg = SLTG_DoType(pArg, pFirstItem,
2963 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2966 /* Are we an optional param ? */
2967 if((*ppFuncDesc)->funcdesc.cParams - param <=
2968 (*ppFuncDesc)->funcdesc.cParamsOpt)
2969 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2971 if(paramName) {
2972 (*ppFuncDesc)->pParamDesc[param].Name =
2973 TLB_MultiByteToBSTR(paramName);
2977 ppFuncDesc = &((*ppFuncDesc)->next);
2978 if(pFunc->next == 0xffff) break;
2980 pTI->TypeAttr.cFuncs = num;
2981 if (TRACE_ON(typelib))
2982 dump_TLBFuncDesc(pTI->funclist);
2983 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2986 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2987 char *pNameTable)
2989 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2990 SLTG_MemberHeader *pMemHeader;
2991 SLTG_RecordItem *pItem;
2992 char *pFirstItem;
2993 TLBVarDesc **ppVarDesc = &pTI->varlist;
2994 int num = 0;
2995 WORD *pType;
2996 char buf[300];
2998 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3000 pFirstItem = (char*)(pMemHeader + 1);
3001 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
3002 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
3003 if(pItem->magic != SLTG_RECORD_MAGIC) {
3004 FIXME("record magic = %02x\n", pItem->magic);
3005 return NULL;
3007 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3008 sizeof(**ppVarDesc));
3009 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3010 (*ppVarDesc)->vardesc.memid = pItem->memid;
3011 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3012 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3014 if(pItem->typepos == 0x02)
3015 pType = &pItem->type;
3016 else if(pItem->typepos == 0x00)
3017 pType = (WORD*)(pFirstItem + pItem->type);
3018 else {
3019 FIXME("typepos = %02x\n", pItem->typepos);
3020 break;
3023 SLTG_DoType(pType, pFirstItem,
3024 &(*ppVarDesc)->vardesc.elemdescVar);
3026 /* FIXME("helpcontext, helpstring\n"); */
3028 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3030 ppVarDesc = &((*ppVarDesc)->next);
3031 if(pItem->next == 0xffff) break;
3033 pTI->TypeAttr.cVars = num;
3034 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3037 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3038 char *pNameTable)
3040 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3041 SLTG_MemberHeader *pMemHeader;
3042 SLTG_AliasItem *pItem;
3043 int i, mustbelast;
3045 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3046 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3048 mustbelast = 0;
3049 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3050 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3051 if (pItem->vt == 0xffff) {
3052 if (i<(pMemHeader->cbExtra/4-1))
3053 FIXME("Endmarker too early in process alias data!\n");
3054 break;
3056 if (mustbelast) {
3057 FIXME("Chain extends over last entry?\n");
3058 break;
3060 if (pItem->vt == VT_USERDEFINED) {
3061 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3062 /* guessing here ... */
3063 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3064 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3065 mustbelast = 1;
3066 } else {
3067 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3068 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3070 pItem++;
3072 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3075 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3076 char *pNameTable)
3078 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3079 SLTG_MemberHeader *pMemHeader;
3080 SLTG_AliasItem *pItem;
3082 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3083 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3084 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3085 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3086 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3089 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3090 char *pNameTable)
3092 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3093 SLTG_MemberHeader *pMemHeader;
3094 SLTG_EnumItem *pItem;
3095 char *pFirstItem;
3096 TLBVarDesc **ppVarDesc = &pTI->varlist;
3097 int num = 0;
3099 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3101 pFirstItem = (char*)(pMemHeader + 1);
3102 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3103 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3104 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3105 FIXME("enumitem magic = %04x\n", pItem->magic);
3106 return NULL;
3108 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3109 sizeof(**ppVarDesc));
3110 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3111 (*ppVarDesc)->vardesc.memid = pItem->memid;
3112 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3113 sizeof(VARIANT));
3114 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3115 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3116 *(INT*)(pItem->value + pFirstItem);
3117 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3118 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3119 /* FIXME("helpcontext, helpstring\n"); */
3121 ppVarDesc = &((*ppVarDesc)->next);
3122 if(pItem->next == 0xffff) break;
3124 pTI->TypeAttr.cVars = num;
3125 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3128 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3129 managable copy of it into this */
3130 typedef struct {
3131 WORD small_no;
3132 char *index_name;
3133 char *other_name;
3134 WORD res1a;
3135 WORD name_offs;
3136 WORD more_bytes;
3137 char *extra;
3138 WORD res20;
3139 DWORD helpcontext;
3140 WORD res26;
3141 GUID uuid;
3142 } SLTG_InternalOtherTypeInfo;
3144 /****************************************************************************
3145 * ITypeLib2_Constructor_SLTG
3147 * loading a SLTG typelib from an in-memory image
3149 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3151 ITypeLibImpl *pTypeLibImpl;
3152 SLTG_Header *pHeader;
3153 SLTG_BlkEntry *pBlkEntry;
3154 SLTG_Magic *pMagic;
3155 SLTG_Index *pIndex;
3156 SLTG_Pad9 *pPad9;
3157 LPVOID pBlk, pFirstBlk;
3158 SLTG_LibBlk *pLibBlk;
3159 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3160 char *pAfterOTIBlks = NULL;
3161 char *pNameTable, *ptr;
3162 int i;
3163 DWORD len, order;
3164 ITypeInfoImpl **ppTypeInfoImpl;
3166 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3169 pTypeLibImpl = TypeLibImpl_Constructor();
3170 if (!pTypeLibImpl) return NULL;
3172 pHeader = pLib;
3174 TRACE_(typelib)("header:\n");
3175 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3176 pHeader->nrOfFileBlks );
3177 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3178 FIXME("Header type magic 0x%08lx not supported.\n",
3179 pHeader->SLTG_magic);
3180 return NULL;
3183 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3184 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3186 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3187 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3189 /* Next we have a magic block */
3190 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3192 /* Let's see if we're still in sync */
3193 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3194 sizeof(SLTG_COMPOBJ_MAGIC))) {
3195 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3196 return NULL;
3198 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3199 sizeof(SLTG_DIR_MAGIC))) {
3200 FIXME("dir magic = %s\n", pMagic->dir_magic);
3201 return NULL;
3204 pIndex = (SLTG_Index*)(pMagic+1);
3206 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3208 pFirstBlk = (LPVOID)(pPad9 + 1);
3210 /* We'll set up a ptr to the main library block, which is the last one. */
3212 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3213 pBlkEntry[order].next != 0;
3214 order = pBlkEntry[order].next - 1, i++) {
3215 pBlk = (char*)pBlk + pBlkEntry[order].len;
3217 pLibBlk = pBlk;
3219 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3221 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3222 interspersed */
3224 len += 0x40;
3226 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3228 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3229 sizeof(*pOtherTypeInfoBlks) *
3230 pTypeLibImpl->TypeInfoCount);
3233 ptr = (char*)pLibBlk + len;
3235 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3236 WORD w, extra;
3237 len = 0;
3239 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3241 w = *(WORD*)(ptr + 2);
3242 if(w != 0xffff) {
3243 len += w;
3244 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3245 w+1);
3246 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3247 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3249 w = *(WORD*)(ptr + 4 + len);
3250 if(w != 0xffff) {
3251 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3252 len += w;
3253 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3254 w+1);
3255 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3256 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3258 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3259 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3260 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3261 if(extra) {
3262 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3263 extra);
3264 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3265 len += extra;
3267 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3268 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3269 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3270 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3271 len += sizeof(SLTG_OtherTypeInfo);
3272 ptr += len;
3275 pAfterOTIBlks = ptr;
3277 /* Skip this WORD and get the next DWORD */
3278 len = *(DWORD*)(pAfterOTIBlks + 2);
3280 /* Now add this to pLibBLk look at what we're pointing at and
3281 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3282 dust and we should be pointing at the beginning of the name
3283 table */
3285 pNameTable = (char*)pLibBlk + len;
3287 switch(*(WORD*)pNameTable) {
3288 case 0xffff:
3289 break;
3290 case 0x0200:
3291 pNameTable += 0x20;
3292 break;
3293 default:
3294 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3295 break;
3298 pNameTable += 0x216;
3300 pNameTable += 2;
3302 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3304 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3307 /* Hopefully we now have enough ptrs set up to actually read in
3308 some TypeInfos. It's not clear which order to do them in, so
3309 I'll just follow the links along the BlkEntry chain and read
3310 them in in the order in which they're in the file */
3312 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3314 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3315 pBlkEntry[order].next != 0;
3316 order = pBlkEntry[order].next - 1, i++) {
3318 SLTG_TypeInfoHeader *pTIHeader;
3319 SLTG_TypeInfoTail *pTITail;
3321 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3322 pOtherTypeInfoBlks[i].index_name)) {
3323 FIXME("Index strings don't match\n");
3324 return NULL;
3327 pTIHeader = pBlk;
3328 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3329 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3330 return NULL;
3332 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3333 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3334 (*ppTypeInfoImpl)->index = i;
3335 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3336 pOtherTypeInfoBlks[i].name_offs +
3337 pNameTable);
3338 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3339 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3340 sizeof(GUID));
3341 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3342 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3343 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3344 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3345 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3347 if((pTIHeader->typeflags1 & 7) != 2)
3348 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3349 if(pTIHeader->typeflags3 != 2)
3350 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3352 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3353 debugstr_w((*ppTypeInfoImpl)->Name),
3354 typekind_desc[pTIHeader->typekind],
3355 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3356 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3358 switch(pTIHeader->typekind) {
3359 case TKIND_ENUM:
3360 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3361 break;
3363 case TKIND_RECORD:
3364 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3365 break;
3367 case TKIND_INTERFACE:
3368 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3369 break;
3371 case TKIND_COCLASS:
3372 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3373 break;
3375 case TKIND_ALIAS:
3376 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3377 if (pTITail->tdescalias_vt)
3378 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3379 break;
3381 case TKIND_DISPATCH:
3382 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3383 break;
3385 default:
3386 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3387 pTITail = NULL;
3388 break;
3392 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3393 but we've already set those */
3394 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3395 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3396 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3398 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3399 X(06);
3400 X(08);
3401 X(0a);
3402 X(0c);
3403 X(0e);
3404 X(10);
3405 X(12);
3406 X(16);
3407 X(18);
3408 X(1a);
3409 X(1c);
3410 X(1e);
3411 X(24);
3412 X(26);
3413 X(2a);
3414 X(2c);
3415 X(2e);
3416 X(30);
3417 X(32);
3418 X(34);
3420 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3421 pBlk = (char*)pBlk + pBlkEntry[order].len;
3424 if(i != pTypeLibImpl->TypeInfoCount) {
3425 FIXME("Somehow processed %d TypeInfos\n", i);
3426 return NULL;
3429 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3430 return (ITypeLib2*)pTypeLibImpl;
3433 /* ITypeLib::QueryInterface
3435 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3436 ITypeLib2 * iface,
3437 REFIID riid,
3438 VOID **ppvObject)
3440 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3442 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3444 *ppvObject=NULL;
3445 if(IsEqualIID(riid, &IID_IUnknown) ||
3446 IsEqualIID(riid,&IID_ITypeLib)||
3447 IsEqualIID(riid,&IID_ITypeLib2))
3449 *ppvObject = This;
3452 if(*ppvObject)
3454 ITypeLib2_AddRef(iface);
3455 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3456 return S_OK;
3458 TRACE("-- Interface: E_NOINTERFACE\n");
3459 return E_NOINTERFACE;
3462 /* ITypeLib::AddRef
3464 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3466 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3467 ULONG ref = InterlockedIncrement(&This->ref);
3469 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3471 return ref;
3474 /* ITypeLib::Release
3476 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3478 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3479 ULONG ref = InterlockedDecrement(&This->ref);
3481 TRACE("(%p)->(%lu)\n",This, ref);
3483 if (!ref)
3485 /* remove cache entry */
3486 if(This->path)
3488 TRACE("removing from cache list\n");
3489 EnterCriticalSection(&cache_section);
3490 if (This->next) This->next->prev = This->prev;
3491 if (This->prev) This->prev->next = This->next;
3492 else tlb_cache_first = This->next;
3493 LeaveCriticalSection(&cache_section);
3494 HeapFree(GetProcessHeap(), 0, This->path);
3496 /* FIXME destroy child objects */
3497 TRACE(" destroying ITypeLib(%p)\n",This);
3499 if (This->Name)
3501 SysFreeString(This->Name);
3502 This->Name = NULL;
3505 if (This->DocString)
3507 SysFreeString(This->DocString);
3508 This->DocString = NULL;
3511 if (This->HelpFile)
3513 SysFreeString(This->HelpFile);
3514 This->HelpFile = NULL;
3517 if (This->HelpStringDll)
3519 SysFreeString(This->HelpStringDll);
3520 This->HelpStringDll = NULL;
3523 if (This->pTypeInfo) /* can be NULL */
3524 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3525 HeapFree(GetProcessHeap(),0,This);
3526 return 0;
3529 return ref;
3532 /* ITypeLib::GetTypeInfoCount
3534 * Returns the number of type descriptions in the type library
3536 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3538 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3539 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3540 return This->TypeInfoCount;
3543 /* ITypeLib::GetTypeInfo
3545 * retrieves the specified type description in the library.
3547 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3548 ITypeLib2 *iface,
3549 UINT index,
3550 ITypeInfo **ppTInfo)
3552 int i;
3554 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3555 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3557 TRACE("(%p)->(index=%d)\n", This, index);
3559 if (!ppTInfo) return E_INVALIDARG;
3561 /* search element n in list */
3562 for(i=0; i < index; i++)
3564 pTypeInfo = pTypeInfo->next;
3565 if (!pTypeInfo)
3567 TRACE("-- element not found\n");
3568 return TYPE_E_ELEMENTNOTFOUND;
3572 *ppTInfo = (ITypeInfo *) pTypeInfo;
3574 ITypeInfo_AddRef(*ppTInfo);
3575 TRACE("-- found (%p)\n",*ppTInfo);
3576 return S_OK;
3580 /* ITypeLibs::GetTypeInfoType
3582 * Retrieves the type of a type description.
3584 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3585 ITypeLib2 *iface,
3586 UINT index,
3587 TYPEKIND *pTKind)
3589 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3590 int i;
3591 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3593 TRACE("(%p) index %d\n", This, index);
3595 if(!pTKind) return E_INVALIDARG;
3597 /* search element n in list */
3598 for(i=0; i < index; i++)
3600 if(!pTInfo)
3602 TRACE("-- element not found\n");
3603 return TYPE_E_ELEMENTNOTFOUND;
3605 pTInfo = pTInfo->next;
3608 *pTKind = pTInfo->TypeAttr.typekind;
3609 TRACE("-- found Type (%d)\n", *pTKind);
3610 return S_OK;
3613 /* ITypeLib::GetTypeInfoOfGuid
3615 * Retrieves the type description that corresponds to the specified GUID.
3618 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3619 ITypeLib2 *iface,
3620 REFGUID guid,
3621 ITypeInfo **ppTInfo)
3623 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3624 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3626 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3628 if (!pTypeInfo)
3630 WARN("-- element not found\n");
3631 return TYPE_E_ELEMENTNOTFOUND;
3634 /* search linked list for guid */
3635 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3637 pTypeInfo = pTypeInfo->next;
3639 if (!pTypeInfo)
3641 /* end of list reached */
3642 WARN("-- element not found\n");
3643 return TYPE_E_ELEMENTNOTFOUND;
3647 TRACE("-- found (%p, %s)\n",
3648 pTypeInfo,
3649 debugstr_w(pTypeInfo->Name));
3651 *ppTInfo = (ITypeInfo*)pTypeInfo;
3652 ITypeInfo_AddRef(*ppTInfo);
3653 return S_OK;
3656 /* ITypeLib::GetLibAttr
3658 * Retrieves the structure that contains the library's attributes.
3661 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3662 ITypeLib2 *iface,
3663 LPTLIBATTR *ppTLibAttr)
3665 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3666 TRACE("(%p)\n",This);
3667 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3668 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3669 return S_OK;
3672 /* ITypeLib::GetTypeComp
3674 * Enables a client compiler to bind to a library's types, variables,
3675 * constants, and global functions.
3678 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3679 ITypeLib2 *iface,
3680 ITypeComp **ppTComp)
3682 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3684 TRACE("(%p)->(%p)\n",This,ppTComp);
3685 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3686 ITypeComp_AddRef(*ppTComp);
3688 return S_OK;
3691 /* ITypeLib::GetDocumentation
3693 * Retrieves the library's documentation string, the complete Help file name
3694 * and path, and the context identifier for the library Help topic in the Help
3695 * file.
3697 * On a successful return all non-null BSTR pointers will have been set,
3698 * possibly to NULL.
3700 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3701 ITypeLib2 *iface,
3702 INT index,
3703 BSTR *pBstrName,
3704 BSTR *pBstrDocString,
3705 DWORD *pdwHelpContext,
3706 BSTR *pBstrHelpFile)
3708 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3710 HRESULT result = E_INVALIDARG;
3712 ITypeInfo *pTInfo;
3715 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3716 This, index,
3717 pBstrName, pBstrDocString,
3718 pdwHelpContext, pBstrHelpFile);
3720 if(index<0)
3722 /* documentation for the typelib */
3723 if(pBstrName)
3725 if (This->Name)
3727 if(!(*pBstrName = SysAllocString(This->Name)))
3728 goto memerr1;
3730 else
3731 *pBstrName = NULL;
3733 if(pBstrDocString)
3735 if (This->DocString)
3737 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3738 goto memerr2;
3740 else if (This->Name)
3742 if(!(*pBstrDocString = SysAllocString(This->Name)))
3743 goto memerr2;
3745 else
3746 *pBstrDocString = NULL;
3748 if(pdwHelpContext)
3750 *pdwHelpContext = This->dwHelpContext;
3752 if(pBstrHelpFile)
3754 if (This->HelpFile)
3756 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3757 goto memerr3;
3759 else
3760 *pBstrHelpFile = NULL;
3763 result = S_OK;
3765 else
3767 /* for a typeinfo */
3768 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3770 if(SUCCEEDED(result))
3772 result = ITypeInfo_GetDocumentation(pTInfo,
3773 MEMBERID_NIL,
3774 pBstrName,
3775 pBstrDocString,
3776 pdwHelpContext, pBstrHelpFile);
3778 ITypeInfo_Release(pTInfo);
3781 return result;
3782 memerr3:
3783 if (pBstrDocString) SysFreeString (*pBstrDocString);
3784 memerr2:
3785 if (pBstrName) SysFreeString (*pBstrName);
3786 memerr1:
3787 return STG_E_INSUFFICIENTMEMORY;
3790 /* ITypeLib::IsName
3792 * Indicates whether a passed-in string contains the name of a type or member
3793 * described in the library.
3796 static HRESULT WINAPI ITypeLib2_fnIsName(
3797 ITypeLib2 *iface,
3798 LPOLESTR szNameBuf,
3799 ULONG lHashVal,
3800 BOOL *pfName)
3802 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3803 ITypeInfoImpl *pTInfo;
3804 TLBFuncDesc *pFInfo;
3805 TLBVarDesc *pVInfo;
3806 int i;
3807 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3809 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3810 pfName);
3812 *pfName=TRUE;
3813 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3814 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3815 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3816 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3817 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3818 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3819 goto ITypeLib2_fnIsName_exit;
3821 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3822 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3825 *pfName=FALSE;
3827 ITypeLib2_fnIsName_exit:
3828 TRACE("(%p)slow! search for %s: %s found!\n", This,
3829 debugstr_w(szNameBuf), *pfName?"NOT":"");
3831 return S_OK;
3834 /* ITypeLib::FindName
3836 * Finds occurrences of a type description in a type library. This may be used
3837 * to quickly verify that a name exists in a type library.
3840 static HRESULT WINAPI ITypeLib2_fnFindName(
3841 ITypeLib2 *iface,
3842 LPOLESTR szNameBuf,
3843 ULONG lHashVal,
3844 ITypeInfo **ppTInfo,
3845 MEMBERID *rgMemId,
3846 UINT16 *pcFound)
3848 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3849 ITypeInfoImpl *pTInfo;
3850 TLBFuncDesc *pFInfo;
3851 TLBVarDesc *pVInfo;
3852 int i,j = 0;
3853 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3855 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3856 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3857 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3858 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3859 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3860 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3861 goto ITypeLib2_fnFindName_exit;
3864 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3865 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3866 continue;
3867 ITypeLib2_fnFindName_exit:
3868 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3869 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3870 j++;
3872 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3873 This, *pcFound, debugstr_w(szNameBuf), j);
3875 *pcFound=j;
3877 return S_OK;
3880 /* ITypeLib::ReleaseTLibAttr
3882 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3885 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3886 ITypeLib2 *iface,
3887 TLIBATTR *pTLibAttr)
3889 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3890 TRACE("freeing (%p)\n",This);
3891 HeapFree(GetProcessHeap(),0,pTLibAttr);
3895 /* ITypeLib2::GetCustData
3897 * gets the custom data
3899 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3900 ITypeLib2 * iface,
3901 REFGUID guid,
3902 VARIANT *pVarVal)
3904 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3905 TLBCustData *pCData;
3907 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3909 if( IsEqualIID(guid, &pCData->guid)) break;
3912 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3914 if(pCData)
3916 VariantInit( pVarVal);
3917 VariantCopy( pVarVal, &pCData->data);
3918 return S_OK;
3920 return E_INVALIDARG; /* FIXME: correct? */
3923 /* ITypeLib2::GetLibStatistics
3925 * Returns statistics about a type library that are required for efficient
3926 * sizing of hash tables.
3929 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3930 ITypeLib2 * iface,
3931 ULONG *pcUniqueNames,
3932 ULONG *pcchUniqueNames)
3934 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3936 FIXME("(%p): stub!\n", This);
3938 if(pcUniqueNames) *pcUniqueNames=1;
3939 if(pcchUniqueNames) *pcchUniqueNames=1;
3940 return S_OK;
3943 /* ITypeLib2::GetDocumentation2
3945 * Retrieves the library's documentation string, the complete Help file name
3946 * and path, the localization context to use, and the context ID for the
3947 * library Help topic in the Help file.
3950 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3951 ITypeLib2 * iface,
3952 INT index,
3953 LCID lcid,
3954 BSTR *pbstrHelpString,
3955 DWORD *pdwHelpStringContext,
3956 BSTR *pbstrHelpStringDll)
3958 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3959 HRESULT result;
3960 ITypeInfo *pTInfo;
3962 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3964 /* the help string should be obtained from the helpstringdll,
3965 * using the _DLLGetDocumentation function, based on the supplied
3966 * lcid. Nice to do sometime...
3968 if(index<0)
3970 /* documentation for the typelib */
3971 if(pbstrHelpString)
3972 *pbstrHelpString=SysAllocString(This->DocString);
3973 if(pdwHelpStringContext)
3974 *pdwHelpStringContext=This->dwHelpContext;
3975 if(pbstrHelpStringDll)
3976 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3978 result = S_OK;
3980 else
3982 /* for a typeinfo */
3983 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3985 if(SUCCEEDED(result))
3987 ITypeInfo2 * pTInfo2;
3988 result = ITypeInfo_QueryInterface(pTInfo,
3989 &IID_ITypeInfo2,
3990 (LPVOID*) &pTInfo2);
3992 if(SUCCEEDED(result))
3994 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3995 MEMBERID_NIL,
3996 lcid,
3997 pbstrHelpString,
3998 pdwHelpStringContext,
3999 pbstrHelpStringDll);
4001 ITypeInfo2_Release(pTInfo2);
4004 ITypeInfo_Release(pTInfo);
4007 return result;
4010 /* ITypeLib2::GetAllCustData
4012 * Gets all custom data items for the library.
4015 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4016 ITypeLib2 * iface,
4017 CUSTDATA *pCustData)
4019 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4020 TLBCustData *pCData;
4021 int i;
4022 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4023 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4024 if(pCustData->prgCustData ){
4025 pCustData->cCustData=This->ctCustData;
4026 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4027 pCustData->prgCustData[i].guid=pCData->guid;
4028 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4030 }else{
4031 ERR(" OUT OF MEMORY!\n");
4032 return E_OUTOFMEMORY;
4034 return S_OK;
4037 static const ITypeLib2Vtbl tlbvt = {
4038 ITypeLib2_fnQueryInterface,
4039 ITypeLib2_fnAddRef,
4040 ITypeLib2_fnRelease,
4041 ITypeLib2_fnGetTypeInfoCount,
4042 ITypeLib2_fnGetTypeInfo,
4043 ITypeLib2_fnGetTypeInfoType,
4044 ITypeLib2_fnGetTypeInfoOfGuid,
4045 ITypeLib2_fnGetLibAttr,
4046 ITypeLib2_fnGetTypeComp,
4047 ITypeLib2_fnGetDocumentation,
4048 ITypeLib2_fnIsName,
4049 ITypeLib2_fnFindName,
4050 ITypeLib2_fnReleaseTLibAttr,
4052 ITypeLib2_fnGetCustData,
4053 ITypeLib2_fnGetLibStatistics,
4054 ITypeLib2_fnGetDocumentation2,
4055 ITypeLib2_fnGetAllCustData
4059 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4061 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4063 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4066 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4068 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4070 return ITypeLib2_AddRef((ITypeLib2 *)This);
4073 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4075 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4077 return ITypeLib2_Release((ITypeLib2 *)This);
4080 static HRESULT WINAPI ITypeLibComp_fnBind(
4081 ITypeComp * iface,
4082 OLECHAR * szName,
4083 ULONG lHash,
4084 WORD wFlags,
4085 ITypeInfo ** ppTInfo,
4086 DESCKIND * pDescKind,
4087 BINDPTR * pBindPtr)
4089 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4090 ITypeInfoImpl *pTypeInfo;
4092 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4094 *pDescKind = DESCKIND_NONE;
4095 pBindPtr->lptcomp = NULL;
4096 *ppTInfo = NULL;
4098 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4100 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4102 /* FIXME: check wFlags here? */
4103 /* FIXME: we should use a hash table to look this info up using lHash
4104 * instead of an O(n) search */
4105 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4106 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4108 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4110 *pDescKind = DESCKIND_TYPECOMP;
4111 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4112 ITypeComp_AddRef(pBindPtr->lptcomp);
4113 TRACE("module or enum: %s\n", debugstr_w(szName));
4114 return S_OK;
4118 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4119 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4121 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4122 HRESULT hr;
4124 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4125 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4127 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4128 return S_OK;
4132 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4133 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4135 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4136 HRESULT hr;
4137 ITypeInfo *subtypeinfo;
4138 BINDPTR subbindptr;
4139 DESCKIND subdesckind;
4141 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4142 &subtypeinfo, &subdesckind, &subbindptr);
4143 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4145 TYPEDESC tdesc_appobject =
4148 (TYPEDESC *)pTypeInfo->hreftype
4150 VT_USERDEFINED
4152 const VARDESC vardesc_appobject =
4154 -2, /* memid */
4155 NULL, /* lpstrSchema */
4157 0 /* oInst */
4160 /* ELEMDESC */
4162 /* TYPEDESC */
4164 &tdesc_appobject
4166 VT_PTR
4169 0, /* wVarFlags */
4170 VAR_STATIC /* varkind */
4173 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4175 /* cleanup things filled in by Bind call so we can put our
4176 * application object data in there instead */
4177 switch (subdesckind)
4179 case DESCKIND_FUNCDESC:
4180 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4181 break;
4182 case DESCKIND_VARDESC:
4183 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4184 break;
4185 default:
4186 break;
4188 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4190 if (pTypeInfo->hreftype == -1)
4191 FIXME("no hreftype for interface %p\n", pTypeInfo);
4193 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4194 if (FAILED(hr))
4195 return hr;
4197 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4198 *ppTInfo = (ITypeInfo *)pTypeInfo;
4199 ITypeInfo_AddRef(*ppTInfo);
4200 return S_OK;
4205 TRACE("name not found %s\n", debugstr_w(szName));
4206 return S_OK;
4209 static HRESULT WINAPI ITypeLibComp_fnBindType(
4210 ITypeComp * iface,
4211 OLECHAR * szName,
4212 ULONG lHash,
4213 ITypeInfo ** ppTInfo,
4214 ITypeComp ** ppTComp)
4216 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4217 return E_NOTIMPL;
4220 static const ITypeCompVtbl tlbtcvt =
4223 ITypeLibComp_fnQueryInterface,
4224 ITypeLibComp_fnAddRef,
4225 ITypeLibComp_fnRelease,
4227 ITypeLibComp_fnBind,
4228 ITypeLibComp_fnBindType
4231 /*================== ITypeInfo(2) Methods ===================================*/
4232 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4234 ITypeInfoImpl * pTypeInfoImpl;
4236 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4237 if (pTypeInfoImpl)
4239 pTypeInfoImpl->lpVtbl = &tinfvt;
4240 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4241 pTypeInfoImpl->ref=1;
4242 pTypeInfoImpl->hreftype = -1;
4244 TRACE("(%p)\n", pTypeInfoImpl);
4245 return (ITypeInfo2*) pTypeInfoImpl;
4248 /* ITypeInfo::QueryInterface
4250 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4251 ITypeInfo2 *iface,
4252 REFIID riid,
4253 VOID **ppvObject)
4255 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4257 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4259 *ppvObject=NULL;
4260 if(IsEqualIID(riid, &IID_IUnknown) ||
4261 IsEqualIID(riid,&IID_ITypeInfo)||
4262 IsEqualIID(riid,&IID_ITypeInfo2))
4263 *ppvObject = This;
4265 if(*ppvObject){
4266 ITypeInfo_AddRef(iface);
4267 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4268 return S_OK;
4270 TRACE("-- Interface: E_NOINTERFACE\n");
4271 return E_NOINTERFACE;
4274 /* ITypeInfo::AddRef
4276 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4278 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4279 ULONG ref = InterlockedIncrement(&This->ref);
4281 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4283 TRACE("(%p)->ref is %lu\n",This, ref);
4284 return ref;
4287 /* ITypeInfo::Release
4289 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4291 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4292 ULONG ref = InterlockedDecrement(&This->ref);
4294 TRACE("(%p)->(%lu)\n",This, ref);
4296 if (ref) {
4297 /* We don't release ITypeLib when ref=0 because
4298 it means that function is called by ITypeLib2_Release */
4299 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4300 } else {
4301 static int once = 0;
4302 if (!once)
4304 once = 1;
4305 FIXME("destroy child objects\n");
4308 TRACE("destroying ITypeInfo(%p)\n",This);
4309 if (This->Name)
4311 SysFreeString(This->Name);
4312 This->Name = 0;
4315 if (This->DocString)
4317 SysFreeString(This->DocString);
4318 This->DocString = 0;
4321 if (This->DllName)
4323 SysFreeString(This->DllName);
4324 This->DllName = 0;
4327 if (This->next)
4329 ITypeInfo_Release((ITypeInfo*)This->next);
4332 HeapFree(GetProcessHeap(),0,This);
4333 return 0;
4335 return ref;
4338 /* ITypeInfo::GetTypeAttr
4340 * Retrieves a TYPEATTR structure that contains the attributes of the type
4341 * description.
4344 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4345 LPTYPEATTR *ppTypeAttr)
4347 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4348 SIZE_T size;
4350 TRACE("(%p)\n",This);
4352 size = sizeof(**ppTypeAttr);
4353 if (This->TypeAttr.typekind == TKIND_ALIAS)
4354 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4356 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4357 if (!*ppTypeAttr)
4358 return E_OUTOFMEMORY;
4360 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4362 if (This->TypeAttr.typekind == TKIND_ALIAS)
4363 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4364 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4366 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4367 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4368 funcs */
4369 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4370 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4372 return S_OK;
4375 /* ITypeInfo::GetTypeComp
4377 * Retrieves the ITypeComp interface for the type description, which enables a
4378 * client compiler to bind to the type description's members.
4381 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4382 ITypeComp * *ppTComp)
4384 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4386 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4388 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4389 ITypeComp_AddRef(*ppTComp);
4390 return S_OK;
4393 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4395 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4396 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4397 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4398 return size;
4401 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4403 memcpy(dest, src, sizeof(ELEMDESC));
4404 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4405 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4407 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4408 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4409 *buffer += sizeof(PARAMDESCEX);
4410 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4411 VariantInit(&pparamdescex_dest->varDefaultValue);
4412 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4413 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4415 else
4416 dest->u.paramdesc.pparamdescex = NULL;
4417 return S_OK;
4420 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4422 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4423 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4426 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4428 FUNCDESC *dest;
4429 char *buffer;
4430 SIZE_T size = sizeof(*src);
4431 SHORT i;
4432 HRESULT hr;
4434 size += sizeof(*src->lprgscode) * src->cScodes;
4435 size += TLB_SizeElemDesc(&src->elemdescFunc);
4436 for (i = 0; i < src->cParams; i++)
4438 size += sizeof(ELEMDESC);
4439 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4442 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4443 if (!dest) return E_OUTOFMEMORY;
4445 memcpy(dest, src, sizeof(FUNCDESC));
4446 buffer = (char *)(dest + 1);
4448 dest->lprgscode = (SCODE *)buffer;
4449 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4450 buffer += sizeof(*src->lprgscode) * src->cScodes;
4452 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4453 if (FAILED(hr))
4455 SysFreeString((BSTR)dest);
4456 return hr;
4459 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4460 buffer += sizeof(ELEMDESC) * src->cParams;
4461 for (i = 0; i < src->cParams; i++)
4463 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4464 if (FAILED(hr))
4465 break;
4467 if (FAILED(hr))
4469 /* undo the above actions */
4470 for (i = i - 1; i >= 0; i--)
4471 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4472 TLB_FreeElemDesc(&dest->elemdescFunc);
4473 SysFreeString((BSTR)dest);
4474 return hr;
4477 /* special treatment for dispinterfaces: this makes functions appear
4478 * to return their [retval] value when it is really returning an
4479 * HRESULT */
4480 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4482 if (dest->cParams &&
4483 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4485 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4486 if (elemdesc->tdesc.vt != VT_PTR)
4488 ERR("elemdesc should have started with VT_PTR instead of:\n");
4489 if (ERR_ON(ole))
4490 dump_ELEMDESC(elemdesc);
4491 return E_UNEXPECTED;
4494 /* copy last parameter to the return value. we are using a flat
4495 * buffer so there is no danger of leaking memory in
4496 * elemdescFunc */
4497 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4499 /* remove the last parameter */
4500 dest->cParams--;
4502 else
4503 /* otherwise this function is made to appear to have no return
4504 * value */
4505 dest->elemdescFunc.tdesc.vt = VT_VOID;
4509 *dest_ptr = dest;
4510 return S_OK;
4513 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4516 const TLBFuncDesc *pFDesc;
4517 int i;
4519 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4522 if (pFDesc)
4524 *ppFuncDesc = &pFDesc->funcdesc;
4525 return S_OK;
4528 return E_INVALIDARG;
4531 /* ITypeInfo::GetFuncDesc
4533 * Retrieves the FUNCDESC structure that contains information about a
4534 * specified function.
4537 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4538 LPFUNCDESC *ppFuncDesc)
4540 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4541 const FUNCDESC *internal_funcdesc;
4542 HRESULT hr;
4544 TRACE("(%p) index %d\n", This, index);
4546 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4547 if (FAILED(hr))
4548 return hr;
4550 return TLB_AllocAndInitFuncDesc(
4551 internal_funcdesc,
4552 ppFuncDesc,
4553 This->TypeAttr.typekind == TKIND_DISPATCH);
4556 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4558 VARDESC *dest;
4559 char *buffer;
4560 SIZE_T size = sizeof(*src);
4561 HRESULT hr;
4563 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4564 if (src->varkind == VAR_CONST)
4565 size += sizeof(VARIANT);
4566 size += TLB_SizeElemDesc(&src->elemdescVar);
4568 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4569 if (!dest) return E_OUTOFMEMORY;
4571 *dest = *src;
4572 buffer = (char *)(dest + 1);
4573 if (src->lpstrSchema)
4575 int len;
4576 dest->lpstrSchema = (LPOLESTR)buffer;
4577 len = strlenW(src->lpstrSchema);
4578 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4579 buffer += (len + 1) * sizeof(WCHAR);
4582 if (src->varkind == VAR_CONST)
4584 HRESULT hr;
4586 dest->u.lpvarValue = (VARIANT *)buffer;
4587 *dest->u.lpvarValue = *src->u.lpvarValue;
4588 buffer += sizeof(VARIANT);
4589 VariantInit(dest->u.lpvarValue);
4590 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4591 if (FAILED(hr))
4593 SysFreeString((BSTR)dest_ptr);
4594 return hr;
4597 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4598 if (FAILED(hr))
4600 if (src->varkind == VAR_CONST)
4601 VariantClear(dest->u.lpvarValue);
4602 SysFreeString((BSTR)dest);
4603 return hr;
4605 *dest_ptr = dest;
4606 return S_OK;
4609 /* ITypeInfo::GetVarDesc
4611 * Retrieves a VARDESC structure that describes the specified variable.
4614 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4615 LPVARDESC *ppVarDesc)
4617 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4618 int i;
4619 const TLBVarDesc *pVDesc;
4621 TRACE("(%p) index %d\n", This, index);
4623 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4626 if (pVDesc)
4627 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4629 return E_INVALIDARG;
4632 /* ITypeInfo_GetNames
4634 * Retrieves the variable with the specified member ID (or the name of the
4635 * property or method and its parameters) that correspond to the specified
4636 * function ID.
4638 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4639 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4641 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4642 const TLBFuncDesc *pFDesc;
4643 const TLBVarDesc *pVDesc;
4644 int i;
4645 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4646 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4647 if(pFDesc)
4649 /* function found, now return function and parameter names */
4650 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4652 if(!i)
4653 *rgBstrNames=SysAllocString(pFDesc->Name);
4654 else
4655 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4657 *pcNames=i;
4659 else
4661 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4662 if(pVDesc)
4664 *rgBstrNames=SysAllocString(pVDesc->Name);
4665 *pcNames=1;
4667 else
4669 if(This->TypeAttr.cImplTypes &&
4670 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4671 /* recursive search */
4672 ITypeInfo *pTInfo;
4673 HRESULT result;
4674 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4675 &pTInfo);
4676 if(SUCCEEDED(result))
4678 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4679 ITypeInfo_Release(pTInfo);
4680 return result;
4682 WARN("Could not search inherited interface!\n");
4684 else
4686 WARN("no names found\n");
4688 *pcNames=0;
4689 return TYPE_E_ELEMENTNOTFOUND;
4692 return S_OK;
4696 /* ITypeInfo::GetRefTypeOfImplType
4698 * If a type description describes a COM class, it retrieves the type
4699 * description of the implemented interface types. For an interface,
4700 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4701 * if any exist.
4704 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4705 ITypeInfo2 *iface,
4706 UINT index,
4707 HREFTYPE *pRefType)
4709 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4710 int i;
4711 HRESULT hr = S_OK;
4712 const TLBImplType *pImpl = This->impltypelist;
4714 TRACE("(%p) index %d\n", This, index);
4715 if (TRACE_ON(ole)) dump_TypeInfo(This);
4717 if(index==(UINT)-1)
4719 /* only valid on dual interfaces;
4720 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4722 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4724 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4725 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4727 *pRefType = -1;
4729 else
4731 hr = TYPE_E_ELEMENTNOTFOUND;
4734 else
4736 /* get element n from linked list */
4737 for(i=0; pImpl && i<index; i++)
4739 pImpl = pImpl->next;
4742 if (pImpl)
4743 *pRefType = pImpl->hRef;
4744 else
4745 hr = TYPE_E_ELEMENTNOTFOUND;
4748 if(TRACE_ON(ole))
4750 if(SUCCEEDED(hr))
4751 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4752 else
4753 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4756 return hr;
4759 /* ITypeInfo::GetImplTypeFlags
4761 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4762 * or base interface in a type description.
4764 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4765 UINT index, INT *pImplTypeFlags)
4767 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4768 int i;
4769 TLBImplType *pImpl;
4771 TRACE("(%p) index %d\n", This, index);
4772 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4773 i++, pImpl=pImpl->next)
4775 if(i==index && pImpl){
4776 *pImplTypeFlags=pImpl->implflags;
4777 return S_OK;
4779 *pImplTypeFlags=0;
4780 return TYPE_E_ELEMENTNOTFOUND;
4783 /* GetIDsOfNames
4784 * Maps between member names and member IDs, and parameter names and
4785 * parameter IDs.
4787 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4788 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4790 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4791 const TLBFuncDesc *pFDesc;
4792 const TLBVarDesc *pVDesc;
4793 HRESULT ret=S_OK;
4794 int i;
4796 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4797 cNames);
4799 /* init out parameters in case of failure */
4800 for (i = 0; i < cNames; i++)
4801 pMemId[i] = MEMBERID_NIL;
4803 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4804 int j;
4805 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4806 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4807 for(i=1; i < cNames; i++){
4808 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4809 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4810 break;
4811 if( j<pFDesc->funcdesc.cParams)
4812 pMemId[i]=j;
4813 else
4814 ret=DISP_E_UNKNOWNNAME;
4816 TRACE("-- 0x%08lx\n", ret);
4817 return ret;
4820 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4821 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4822 if(cNames) *pMemId=pVDesc->vardesc.memid;
4823 return ret;
4826 /* not found, see if this is and interface with an inheritance */
4827 if(This->TypeAttr.cImplTypes &&
4828 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4829 /* recursive search */
4830 ITypeInfo *pTInfo;
4831 ret=ITypeInfo_GetRefTypeInfo(iface,
4832 This->impltypelist->hRef, &pTInfo);
4833 if(SUCCEEDED(ret)){
4834 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4835 ITypeInfo_Release(pTInfo);
4836 return ret;
4838 WARN("Could not search inherited interface!\n");
4839 } else
4840 WARN("no names found\n");
4841 return DISP_E_UNKNOWNNAME;
4844 /* ITypeInfo::Invoke
4846 * Invokes a method, or accesses a property of an object, that implements the
4847 * interface described by the type description.
4849 DWORD
4850 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4851 DWORD res;
4853 if (TRACE_ON(ole)) {
4854 int i;
4855 TRACE("Calling %p(",func);
4856 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4857 TRACE(")\n");
4860 switch (callconv) {
4861 case CC_STDCALL:
4863 switch (nrargs) {
4864 case 0:
4865 res = func();
4866 break;
4867 case 1:
4868 res = func(args[0]);
4869 break;
4870 case 2:
4871 res = func(args[0],args[1]);
4872 break;
4873 case 3:
4874 res = func(args[0],args[1],args[2]);
4875 break;
4876 case 4:
4877 res = func(args[0],args[1],args[2],args[3]);
4878 break;
4879 case 5:
4880 res = func(args[0],args[1],args[2],args[3],args[4]);
4881 break;
4882 case 6:
4883 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4884 break;
4885 case 7:
4886 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4887 break;
4888 case 8:
4889 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4890 break;
4891 case 9:
4892 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4893 break;
4894 case 10:
4895 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4896 break;
4897 case 11:
4898 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4899 break;
4900 case 12:
4901 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]);
4902 break;
4903 case 13:
4904 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]);
4905 break;
4906 case 14:
4907 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]);
4908 break;
4909 case 15:
4910 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],args[14]);
4911 break;
4912 case 16:
4913 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],args[14],args[15]);
4914 break;
4915 case 17:
4916 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],args[14],args[15],args[16]);
4917 break;
4918 case 18:
4919 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],args[14],args[15],args[16],args[17]);
4920 break;
4921 case 19:
4922 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],args[14],args[15],args[16],args[17],args[18]);
4923 break;
4924 case 20:
4925 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],args[14],args[15],args[16],args[17],args[18],args[19]);
4926 break;
4927 case 21:
4928 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],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
4929 break;
4930 case 22:
4931 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],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
4932 break;
4933 case 23:
4934 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],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
4935 break;
4936 default:
4937 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4938 res = -1;
4939 break;
4941 break;
4942 default:
4943 FIXME("unsupported calling convention %d\n",callconv);
4944 res = -1;
4945 break;
4947 TRACE("returns %08lx\n",res);
4948 return res;
4951 extern int _argsize(DWORD vt);
4953 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4955 HRESULT hr = S_OK;
4956 ITypeInfo *tinfo2 = NULL;
4957 TYPEATTR *tattr = NULL;
4959 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4960 if (hr)
4962 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4963 "hr = 0x%08lx\n",
4964 tdesc->u.hreftype, hr);
4965 return hr;
4967 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4968 if (hr)
4970 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4971 ITypeInfo_Release(tinfo2);
4972 return hr;
4975 switch (tattr->typekind)
4977 case TKIND_ENUM:
4978 *vt |= VT_I4;
4979 break;
4981 case TKIND_ALIAS:
4982 tdesc = &tattr->tdescAlias;
4983 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4984 break;
4986 case TKIND_INTERFACE:
4987 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4988 *vt |= VT_DISPATCH;
4989 else
4990 *vt |= VT_UNKNOWN;
4991 break;
4993 case TKIND_DISPATCH:
4994 *vt |= VT_DISPATCH;
4995 break;
4997 case TKIND_RECORD:
4998 FIXME("TKIND_RECORD unhandled.\n");
4999 hr = E_NOTIMPL;
5000 break;
5002 case TKIND_UNION:
5003 FIXME("TKIND_RECORD unhandled.\n");
5004 hr = E_NOTIMPL;
5005 break;
5007 default:
5008 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5009 hr = E_NOTIMPL;
5010 break;
5012 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5013 ITypeInfo_Release(tinfo2);
5014 return hr;
5017 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5019 HRESULT hr = S_OK;
5021 /* enforce only one level of pointer indirection */
5022 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5024 tdesc = tdesc->u.lptdesc;
5026 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5027 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5028 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5029 if ((tdesc->vt == VT_USERDEFINED) ||
5030 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5032 VARTYPE vt_userdefined = 0;
5033 const TYPEDESC *tdesc_userdefined = tdesc;
5034 if (tdesc->vt == VT_PTR)
5036 vt_userdefined = VT_BYREF;
5037 tdesc_userdefined = tdesc->u.lptdesc;
5039 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5040 if ((hr == S_OK) &&
5041 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5042 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5044 *vt |= vt_userdefined;
5045 return S_OK;
5048 *vt = VT_BYREF;
5051 switch (tdesc->vt)
5053 case VT_HRESULT:
5054 *vt |= VT_ERROR;
5055 break;
5056 case VT_USERDEFINED:
5057 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5058 break;
5059 case VT_VOID:
5060 case VT_CARRAY:
5061 case VT_PTR:
5062 case VT_LPSTR:
5063 case VT_LPWSTR:
5064 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5065 hr = DISP_E_BADVARTYPE;
5066 break;
5067 case VT_SAFEARRAY:
5068 *vt |= VT_ARRAY;
5069 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5070 break;
5071 default:
5072 *vt |= tdesc->vt;
5073 break;
5075 return hr;
5078 /***********************************************************************
5079 * DispCallFunc (OLEAUT32.@)
5081 * Invokes a function of the specifed calling convention, passing the
5082 * specified arguments and returns the result.
5084 * PARAMS
5085 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5086 * oVft [I] The offset in the vtable. See notes.
5087 * cc [I] Calling convention of the function to call.
5088 * vtReturn [I] The return type of the function.
5089 * cActuals [I] Number of parameters.
5090 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5091 * prgpvarg [I] The arguments to pass.
5092 * pvargResult [O] The return value of the function. Can be NULL.
5094 * RETURNS
5095 * Success: S_OK.
5096 * Failure: HRESULT code.
5098 * NOTES
5099 * The HRESULT return value of this function is not affected by the return
5100 * value of the user supplied function, which is returned in pvargResult.
5102 * If pvInstance is NULL then a non-object function is to be called and oVft
5103 * is the address of the function to call.
5105 * The cc parameter can be one of the following values:
5106 *|CC_FASTCALL
5107 *|CC_CDECL
5108 *|CC_PASCAL
5109 *|CC_STDCALL
5110 *|CC_FPFASTCALL
5111 *|CC_SYSCALL
5112 *|CC_MPWCDECL
5113 *|CC_MPWPASCAL
5116 HRESULT WINAPI
5117 DispCallFunc(
5118 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5119 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5121 int i, argsize, argspos;
5122 DWORD *args;
5123 HRESULT hres;
5125 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5126 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5127 pvargResult, V_VT(pvargResult));
5129 argsize = 0;
5130 if (pvInstance)
5131 argsize++; /* for This pointer */
5133 for (i=0;i<cActuals;i++)
5135 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5136 dump_Variant(prgpvarg[i]);
5137 argsize += _argsize(prgvt[i]);
5139 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5141 argspos = 0;
5142 if (pvInstance)
5144 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5145 argspos++;
5148 for (i=0;i<cActuals;i++)
5150 VARIANT *arg = prgpvarg[i];
5151 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5152 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5153 argspos += _argsize(prgvt[i]);
5156 if (pvInstance)
5158 FARPROC *vtable = *(FARPROC**)pvInstance;
5159 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5161 else
5162 /* if we aren't invoking an object then the function pointer is stored
5163 * in oVft */
5164 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5166 if (pvargResult && (vtReturn != VT_EMPTY))
5168 TRACE("Method returned 0x%08lx\n",hres);
5169 V_VT(pvargResult) = vtReturn;
5170 V_UI4(pvargResult) = hres;
5173 HeapFree(GetProcessHeap(),0,args);
5174 return S_OK;
5177 #define INVBUF_ELEMENT_SIZE \
5178 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5179 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5180 ((VARIANTARG *)(buffer))
5181 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5182 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5183 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5184 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5185 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5186 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5188 static HRESULT WINAPI ITypeInfo_fnInvoke(
5189 ITypeInfo2 *iface,
5190 VOID *pIUnk,
5191 MEMBERID memid,
5192 UINT16 wFlags,
5193 DISPPARAMS *pDispParams,
5194 VARIANT *pVarResult,
5195 EXCEPINFO *pExcepInfo,
5196 UINT *pArgErr)
5198 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5199 int i;
5200 unsigned int var_index;
5201 TYPEKIND type_kind;
5202 HRESULT hres;
5203 const TLBFuncDesc *pFuncInfo;
5205 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5206 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5208 dump_DispParms(pDispParams);
5210 /* we do this instead of using GetFuncDesc since it will return a fake
5211 * FUNCDESC for dispinterfaces and we want the real function description */
5212 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5213 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5214 break;
5216 if (pFuncInfo) {
5217 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5219 if (TRACE_ON(ole))
5221 TRACE("invoking:\n");
5222 dump_TLBFuncDescOne(pFuncInfo);
5225 switch (func_desc->funckind) {
5226 case FUNC_PUREVIRTUAL:
5227 case FUNC_VIRTUAL: {
5228 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5229 VARIANT varresult;
5230 VARIANT retval; /* pointer for storing byref retvals in */
5231 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5232 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5233 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5235 hres = S_OK;
5236 for (i = 0; i < func_desc->cParams; i++)
5238 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5239 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5240 if (FAILED(hres))
5241 goto func_fail;
5244 TRACE("changing args\n");
5245 for (i = 0; i < func_desc->cParams; i++)
5247 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5249 if (wParamFlags & PARAMFLAG_FRETVAL)
5251 /* note: this check is placed so that if the caller passes
5252 * in a VARIANTARG for the retval we just ignore it, like
5253 * native does */
5254 if (i == func_desc->cParams - 1)
5256 VARIANTARG *arg;
5257 arg = prgpvarg[i] = &rgvarg[i];
5258 memset(arg, 0, sizeof(*arg));
5259 V_VT(arg) = rgvt[i];
5260 memset(&retval, 0, sizeof(retval));
5261 V_BYREF(arg) = &retval;
5263 else
5265 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5266 hres = E_UNEXPECTED;
5267 break;
5270 else if (i < pDispParams->cArgs)
5272 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5273 V_VT(&rgvarg[i]) = V_VT(src_arg);
5274 dump_Variant(src_arg);
5276 /* FIXME: this doesn't work for VT_BYREF arguments if
5277 * they are not the same type as in the paramdesc */
5278 if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5280 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5281 V_VT(&missing_arg[i]) = V_VT(src_arg);
5282 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5283 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5285 else
5286 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5288 if (FAILED(hres))
5290 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5291 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5292 debugstr_VT(src_arg), debugstr_VF(src_arg));
5293 break;
5295 V_VT(&rgvarg[i]) = rgvt[i];
5296 prgpvarg[i] = &rgvarg[i];
5298 else if (wParamFlags & PARAMFLAG_FOPT)
5300 VARIANTARG *arg;
5301 arg = prgpvarg[i] = &rgvarg[i];
5302 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5304 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5305 if (FAILED(hres))
5306 break;
5308 else
5310 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5311 V_VT(arg) = VT_VARIANT | VT_BYREF;
5312 V_VARIANTREF(arg) = &missing_arg[i];
5313 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5314 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5317 else
5319 hres = DISP_E_BADPARAMCOUNT;
5320 break;
5323 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5324 if (func_desc->cParamsOpt < 0)
5326 FIXME("Does not support safearray optional parameters\n");
5327 hres = DISP_E_BADPARAMCOUNT;
5328 goto func_fail; /* FIXME: we don't free changed types here */
5331 V_VT(&varresult) = 0;
5332 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5333 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5335 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5336 V_VT(&varresult), func_desc->cParams, rgvt,
5337 prgpvarg, &varresult);
5339 for (i = 0; i < func_desc->cParams; i++)
5341 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5342 if (wParamFlags & PARAMFLAG_FRETVAL)
5344 if (TRACE_ON(ole))
5346 TRACE("[retval] value: ");
5347 dump_Variant(prgpvarg[i]);
5350 if (pVarResult)
5351 /* deref return value */
5352 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5354 /* free data stored in varresult. Note that
5355 * VariantClear doesn't do what we want because we are
5356 * working with byref types. */
5357 /* FIXME: clear safearrays, bstrs, records and
5358 * variants here too */
5359 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5360 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5362 if(*V_UNKNOWNREF(prgpvarg[i]))
5363 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5365 break;
5367 else if (i < pDispParams->cArgs)
5369 if (wParamFlags & PARAMFLAG_FOUT)
5371 hres = VariantChangeType(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i],
5372 &rgvarg[i], 0,
5373 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5374 if (FAILED(hres))
5376 ERR("failed to convert param %d to vt %d\n", i,
5377 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5378 break;
5381 VariantClear(&rgvarg[i]);
5383 else if (wParamFlags & PARAMFLAG_FOPT)
5385 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5386 VariantClear(&rgvarg[i]);
5390 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5392 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5393 hres = DISP_E_EXCEPTION;
5394 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5397 func_fail:
5398 HeapFree(GetProcessHeap(), 0, buffer);
5399 break;
5401 case FUNC_DISPATCH: {
5402 IDispatch *disp;
5404 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5405 if (SUCCEEDED(hres)) {
5406 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5407 hres = IDispatch_Invoke(
5408 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5409 pVarResult,pExcepInfo,pArgErr
5411 if (FAILED(hres))
5412 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5413 IDispatch_Release(disp);
5414 } else
5415 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5416 break;
5418 default:
5419 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5420 hres = E_FAIL;
5421 break;
5424 TRACE("-- 0x%08lx\n", hres);
5425 return hres;
5427 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5428 VARDESC *var_desc;
5430 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5431 if(FAILED(hres)) return hres;
5433 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5434 dump_VARDESC(var_desc);
5435 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5436 return E_NOTIMPL;
5439 /* not found, look for it in inherited interfaces */
5440 ITypeInfo2_GetTypeKind(iface, &type_kind);
5441 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5442 HREFTYPE ref_type;
5443 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5444 /* recursive search */
5445 ITypeInfo *pTInfo;
5446 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5447 if(SUCCEEDED(hres)){
5448 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5449 ITypeInfo_Release(pTInfo);
5450 return hres;
5452 WARN("Could not search inherited interface!\n");
5455 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5456 return DISP_E_MEMBERNOTFOUND;
5459 /* ITypeInfo::GetDocumentation
5461 * Retrieves the documentation string, the complete Help file name and path,
5462 * and the context ID for the Help topic for a specified type description.
5464 * (Can be tested by the Visual Basic Editor in Word for instance.)
5466 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5467 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5468 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5470 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5471 const TLBFuncDesc *pFDesc;
5472 const TLBVarDesc *pVDesc;
5473 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5474 " HelpContext(%p) HelpFile(%p)\n",
5475 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5476 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5477 if(pBstrName)
5478 *pBstrName=SysAllocString(This->Name);
5479 if(pBstrDocString)
5480 *pBstrDocString=SysAllocString(This->DocString);
5481 if(pdwHelpContext)
5482 *pdwHelpContext=This->dwHelpContext;
5483 if(pBstrHelpFile)
5484 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5485 return S_OK;
5486 }else {/* for a member */
5487 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5488 if(pFDesc->funcdesc.memid==memid){
5489 if(pBstrName)
5490 *pBstrName = SysAllocString(pFDesc->Name);
5491 if(pBstrDocString)
5492 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5493 if(pdwHelpContext)
5494 *pdwHelpContext=pFDesc->helpcontext;
5495 return S_OK;
5497 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5498 if(pVDesc->vardesc.memid==memid){
5499 if(pBstrName)
5500 *pBstrName = SysAllocString(pVDesc->Name);
5501 if(pBstrDocString)
5502 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5503 if(pdwHelpContext)
5504 *pdwHelpContext=pVDesc->HelpContext;
5505 return S_OK;
5508 WARN("member %ld not found\n", memid);
5509 return TYPE_E_ELEMENTNOTFOUND;
5512 /* ITypeInfo::GetDllEntry
5514 * Retrieves a description or specification of an entry point for a function
5515 * in a DLL.
5517 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5518 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5519 WORD *pwOrdinal)
5521 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5522 const TLBFuncDesc *pFDesc;
5524 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5526 if (pBstrDllName) *pBstrDllName = NULL;
5527 if (pBstrName) *pBstrName = NULL;
5528 if (pwOrdinal) *pwOrdinal = 0;
5530 if (This->TypeAttr.typekind != TKIND_MODULE)
5531 return TYPE_E_BADMODULEKIND;
5533 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5534 if(pFDesc->funcdesc.memid==memid){
5535 dump_TypeInfo(This);
5536 if (TRACE_ON(ole))
5537 dump_TLBFuncDescOne(pFDesc);
5539 if (pBstrDllName)
5540 *pBstrDllName = SysAllocString(This->DllName);
5542 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5543 if (pBstrName)
5544 *pBstrName = SysAllocString(pFDesc->Entry);
5545 if (pwOrdinal)
5546 *pwOrdinal = -1;
5547 return S_OK;
5549 if (pBstrName)
5550 *pBstrName = NULL;
5551 if (pwOrdinal)
5552 *pwOrdinal = (DWORD)pFDesc->Entry;
5553 return S_OK;
5555 return TYPE_E_ELEMENTNOTFOUND;
5558 /* ITypeInfo::GetRefTypeInfo
5560 * If a type description references other type descriptions, it retrieves
5561 * the referenced type descriptions.
5563 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5564 ITypeInfo2 *iface,
5565 HREFTYPE hRefType,
5566 ITypeInfo **ppTInfo)
5568 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5569 HRESULT result = E_FAIL;
5571 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5573 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5574 ITypeInfo_AddRef(*ppTInfo);
5575 result = S_OK;
5577 else if (hRefType == -1 &&
5578 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5579 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5581 /* when we meet a DUAL dispinterface, we must create the interface
5582 * version of it.
5584 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5587 /* the interface version contains the same information as the dispinterface
5588 * copy the contents of the structs.
5590 *pTypeInfoImpl = *This;
5591 pTypeInfoImpl->ref = 1;
5593 /* change the type to interface */
5594 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5596 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5598 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5600 result = S_OK;
5602 } else {
5603 TLBRefType *pRefType;
5604 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5605 if(pRefType->reference == hRefType)
5606 break;
5608 if(!pRefType)
5609 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5610 if(pRefType && hRefType != -1) {
5611 ITypeLib *pTLib = NULL;
5613 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5614 UINT Index;
5615 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5616 } else {
5617 if(pRefType->pImpTLInfo->pImpTypeLib) {
5618 TRACE("typeinfo in imported typelib that is already loaded\n");
5619 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5620 ITypeLib2_AddRef((ITypeLib*) pTLib);
5621 result = S_OK;
5622 } else {
5623 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5624 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5625 pRefType->pImpTLInfo->wVersionMajor,
5626 pRefType->pImpTLInfo->wVersionMinor,
5627 pRefType->pImpTLInfo->lcid,
5628 &pTLib);
5630 if(!SUCCEEDED(result)) {
5631 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5632 result=LoadTypeLib(libnam, &pTLib);
5633 SysFreeString(libnam);
5635 if(SUCCEEDED(result)) {
5636 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5637 ITypeLib2_AddRef(pTLib);
5641 if(SUCCEEDED(result)) {
5642 if(pRefType->index == TLB_REF_USE_GUID)
5643 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5644 &pRefType->guid,
5645 ppTInfo);
5646 else
5647 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5648 ppTInfo);
5650 if (pTLib != NULL)
5651 ITypeLib2_Release(pTLib);
5655 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5656 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5657 return result;
5660 /* ITypeInfo::AddressOfMember
5662 * Retrieves the addresses of static functions or variables, such as those
5663 * defined in a DLL.
5665 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5666 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5668 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5669 HRESULT hr;
5670 BSTR dll, entry;
5671 WORD ordinal;
5672 HMODULE module;
5674 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5676 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5677 if (FAILED(hr))
5678 return hr;
5680 module = LoadLibraryW(dll);
5681 if (!module)
5683 ERR("couldn't load %s\n", debugstr_w(dll));
5684 SysFreeString(dll);
5685 if (entry) SysFreeString(entry);
5686 return STG_E_FILENOTFOUND;
5688 /* FIXME: store library somewhere where we can free it */
5690 if (entry)
5692 LPSTR entryA;
5693 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5694 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5695 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5697 *ppv = GetProcAddress(module, entryA);
5698 if (!*ppv)
5699 ERR("function not found %s\n", debugstr_a(entryA));
5701 HeapFree(GetProcessHeap(), 0, entryA);
5703 else
5705 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5706 if (!*ppv)
5707 ERR("function not found %d\n", ordinal);
5710 SysFreeString(dll);
5711 if (entry) SysFreeString(entry);
5713 if (!*ppv)
5714 return TYPE_E_DLLFUNCTIONNOTFOUND;
5716 return S_OK;
5719 /* ITypeInfo::CreateInstance
5721 * Creates a new instance of a type that describes a component object class
5722 * (coclass).
5724 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5725 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5727 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5728 FIXME("(%p) stub!\n", This);
5729 return S_OK;
5732 /* ITypeInfo::GetMops
5734 * Retrieves marshalling information.
5736 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5737 BSTR *pBstrMops)
5739 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5740 FIXME("(%p) stub!\n", This);
5741 return S_OK;
5744 /* ITypeInfo::GetContainingTypeLib
5746 * Retrieves the containing type library and the index of the type description
5747 * within that type library.
5749 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5750 ITypeLib * *ppTLib, UINT *pIndex)
5752 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5754 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5755 if (pIndex) {
5756 *pIndex=This->index;
5757 TRACE("returning pIndex=%d\n", *pIndex);
5760 if (ppTLib) {
5761 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5762 ITypeLib2_AddRef(*ppTLib);
5763 TRACE("returning ppTLib=%p\n", *ppTLib);
5766 return S_OK;
5769 /* ITypeInfo::ReleaseTypeAttr
5771 * Releases a TYPEATTR previously returned by GetTypeAttr.
5774 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5775 TYPEATTR* pTypeAttr)
5777 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5778 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5779 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5782 /* ITypeInfo::ReleaseFuncDesc
5784 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5786 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5787 ITypeInfo2 *iface,
5788 FUNCDESC *pFuncDesc)
5790 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5791 SHORT i;
5793 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5795 for (i = 0; i < pFuncDesc->cParams; i++)
5796 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5797 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5799 SysFreeString((BSTR)pFuncDesc);
5802 /* ITypeInfo::ReleaseVarDesc
5804 * Releases a VARDESC previously returned by GetVarDesc.
5806 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5807 VARDESC *pVarDesc)
5809 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5810 TRACE("(%p)->(%p)\n", This, pVarDesc);
5812 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5813 if (pVarDesc->varkind == VAR_CONST)
5814 VariantClear(pVarDesc->u.lpvarValue);
5815 SysFreeString((BSTR)pVarDesc);
5818 /* ITypeInfo2::GetTypeKind
5820 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5823 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5824 TYPEKIND *pTypeKind)
5826 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5827 *pTypeKind=This->TypeAttr.typekind;
5828 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5829 return S_OK;
5832 /* ITypeInfo2::GetTypeFlags
5834 * Returns the type flags without any allocations. This returns a DWORD type
5835 * flag, which expands the type flags without growing the TYPEATTR (type
5836 * attribute).
5839 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5841 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5842 *pTypeFlags=This->TypeAttr.wTypeFlags;
5843 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5844 return S_OK;
5847 /* ITypeInfo2::GetFuncIndexOfMemId
5848 * Binds to a specific member based on a known DISPID, where the member name
5849 * is not known (for example, when binding to a default member).
5852 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5853 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5855 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5856 const TLBFuncDesc *pFuncInfo;
5857 int i;
5858 HRESULT result;
5860 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5861 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5862 break;
5863 if(pFuncInfo) {
5864 *pFuncIndex = i;
5865 result = S_OK;
5866 } else
5867 result = TYPE_E_ELEMENTNOTFOUND;
5869 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5870 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5871 return result;
5874 /* TypeInfo2::GetVarIndexOfMemId
5876 * Binds to a specific member based on a known DISPID, where the member name
5877 * is not known (for example, when binding to a default member).
5880 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5881 MEMBERID memid, UINT *pVarIndex)
5883 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5884 TLBVarDesc *pVarInfo;
5885 int i;
5886 HRESULT result;
5887 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5888 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5890 if(pVarInfo) {
5891 *pVarIndex = i;
5892 result = S_OK;
5893 } else
5894 result = TYPE_E_ELEMENTNOTFOUND;
5896 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5897 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5898 return result;
5901 /* ITypeInfo2::GetCustData
5903 * Gets the custom data
5905 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5906 ITypeInfo2 * iface,
5907 REFGUID guid,
5908 VARIANT *pVarVal)
5910 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5911 TLBCustData *pCData;
5913 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5914 if( IsEqualIID(guid, &pCData->guid)) break;
5916 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5918 if(pCData)
5920 VariantInit( pVarVal);
5921 VariantCopy( pVarVal, &pCData->data);
5922 return S_OK;
5924 return E_INVALIDARG; /* FIXME: correct? */
5927 /* ITypeInfo2::GetFuncCustData
5929 * Gets the custom data
5931 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5932 ITypeInfo2 * iface,
5933 UINT index,
5934 REFGUID guid,
5935 VARIANT *pVarVal)
5937 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5938 TLBCustData *pCData=NULL;
5939 TLBFuncDesc * pFDesc;
5940 int i;
5941 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5942 pFDesc=pFDesc->next);
5944 if(pFDesc)
5945 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5946 if( IsEqualIID(guid, &pCData->guid)) break;
5948 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5950 if(pCData){
5951 VariantInit( pVarVal);
5952 VariantCopy( pVarVal, &pCData->data);
5953 return S_OK;
5955 return E_INVALIDARG; /* FIXME: correct? */
5958 /* ITypeInfo2::GetParamCustData
5960 * Gets the custom data
5962 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5963 ITypeInfo2 * iface,
5964 UINT indexFunc,
5965 UINT indexParam,
5966 REFGUID guid,
5967 VARIANT *pVarVal)
5969 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5970 TLBCustData *pCData=NULL;
5971 TLBFuncDesc * pFDesc;
5972 int i;
5974 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5976 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5977 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5978 pCData = pCData->next)
5979 if( IsEqualIID(guid, &pCData->guid)) break;
5981 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5983 if(pCData)
5985 VariantInit( pVarVal);
5986 VariantCopy( pVarVal, &pCData->data);
5987 return S_OK;
5989 return E_INVALIDARG; /* FIXME: correct? */
5992 /* ITypeInfo2::GetVarCustData
5994 * Gets the custom data
5996 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5997 ITypeInfo2 * iface,
5998 UINT index,
5999 REFGUID guid,
6000 VARIANT *pVarVal)
6002 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6003 TLBCustData *pCData=NULL;
6004 TLBVarDesc * pVDesc;
6005 int i;
6007 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6009 if(pVDesc)
6011 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6013 if( IsEqualIID(guid, &pCData->guid)) break;
6017 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6019 if(pCData)
6021 VariantInit( pVarVal);
6022 VariantCopy( pVarVal, &pCData->data);
6023 return S_OK;
6025 return E_INVALIDARG; /* FIXME: correct? */
6028 /* ITypeInfo2::GetImplCustData
6030 * Gets the custom data
6032 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6033 ITypeInfo2 * iface,
6034 UINT index,
6035 REFGUID guid,
6036 VARIANT *pVarVal)
6038 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6039 TLBCustData *pCData=NULL;
6040 TLBImplType * pRDesc;
6041 int i;
6043 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6045 if(pRDesc)
6047 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6049 if( IsEqualIID(guid, &pCData->guid)) break;
6053 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6055 if(pCData)
6057 VariantInit( pVarVal);
6058 VariantCopy( pVarVal, &pCData->data);
6059 return S_OK;
6061 return E_INVALIDARG; /* FIXME: correct? */
6064 /* ITypeInfo2::GetDocumentation2
6066 * Retrieves the documentation string, the complete Help file name and path,
6067 * the localization context to use, and the context ID for the library Help
6068 * topic in the Help file.
6071 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6072 ITypeInfo2 * iface,
6073 MEMBERID memid,
6074 LCID lcid,
6075 BSTR *pbstrHelpString,
6076 DWORD *pdwHelpStringContext,
6077 BSTR *pbstrHelpStringDll)
6079 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6080 const TLBFuncDesc *pFDesc;
6081 const TLBVarDesc *pVDesc;
6082 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6083 "HelpStringContext(%p) HelpStringDll(%p)\n",
6084 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6085 pbstrHelpStringDll );
6086 /* the help string should be obtained from the helpstringdll,
6087 * using the _DLLGetDocumentation function, based on the supplied
6088 * lcid. Nice to do sometime...
6090 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6091 if(pbstrHelpString)
6092 *pbstrHelpString=SysAllocString(This->Name);
6093 if(pdwHelpStringContext)
6094 *pdwHelpStringContext=This->dwHelpStringContext;
6095 if(pbstrHelpStringDll)
6096 *pbstrHelpStringDll=
6097 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6098 return S_OK;
6099 }else {/* for a member */
6100 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6101 if(pFDesc->funcdesc.memid==memid){
6102 if(pbstrHelpString)
6103 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6104 if(pdwHelpStringContext)
6105 *pdwHelpStringContext=pFDesc->HelpStringContext;
6106 if(pbstrHelpStringDll)
6107 *pbstrHelpStringDll=
6108 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6109 return S_OK;
6111 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6112 if(pVDesc->vardesc.memid==memid){
6113 if(pbstrHelpString)
6114 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6115 if(pdwHelpStringContext)
6116 *pdwHelpStringContext=pVDesc->HelpStringContext;
6117 if(pbstrHelpStringDll)
6118 *pbstrHelpStringDll=
6119 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6120 return S_OK;
6123 return TYPE_E_ELEMENTNOTFOUND;
6126 /* ITypeInfo2::GetAllCustData
6128 * Gets all custom data items for the Type info.
6131 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6132 ITypeInfo2 * iface,
6133 CUSTDATA *pCustData)
6135 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6136 TLBCustData *pCData;
6137 int i;
6139 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6141 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6142 if(pCustData->prgCustData ){
6143 pCustData->cCustData=This->ctCustData;
6144 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6145 pCustData->prgCustData[i].guid=pCData->guid;
6146 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6148 }else{
6149 ERR(" OUT OF MEMORY!\n");
6150 return E_OUTOFMEMORY;
6152 return S_OK;
6155 /* ITypeInfo2::GetAllFuncCustData
6157 * Gets all custom data items for the specified Function
6160 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6161 ITypeInfo2 * iface,
6162 UINT index,
6163 CUSTDATA *pCustData)
6165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6166 TLBCustData *pCData;
6167 TLBFuncDesc * pFDesc;
6168 int i;
6169 TRACE("(%p) index %d\n", This, index);
6170 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6171 pFDesc=pFDesc->next)
6173 if(pFDesc){
6174 pCustData->prgCustData =
6175 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6176 if(pCustData->prgCustData ){
6177 pCustData->cCustData=pFDesc->ctCustData;
6178 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6179 pCData = pCData->next){
6180 pCustData->prgCustData[i].guid=pCData->guid;
6181 VariantCopy(& pCustData->prgCustData[i].varValue,
6182 & pCData->data);
6184 }else{
6185 ERR(" OUT OF MEMORY!\n");
6186 return E_OUTOFMEMORY;
6188 return S_OK;
6190 return TYPE_E_ELEMENTNOTFOUND;
6193 /* ITypeInfo2::GetAllParamCustData
6195 * Gets all custom data items for the Functions
6198 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6199 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6201 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6202 TLBCustData *pCData=NULL;
6203 TLBFuncDesc * pFDesc;
6204 int i;
6205 TRACE("(%p) index %d\n", This, indexFunc);
6206 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6207 pFDesc=pFDesc->next)
6209 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6210 pCustData->prgCustData =
6211 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6212 sizeof(CUSTDATAITEM));
6213 if(pCustData->prgCustData ){
6214 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6215 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6216 pCData; i++, pCData = pCData->next){
6217 pCustData->prgCustData[i].guid=pCData->guid;
6218 VariantCopy(& pCustData->prgCustData[i].varValue,
6219 & pCData->data);
6221 }else{
6222 ERR(" OUT OF MEMORY!\n");
6223 return E_OUTOFMEMORY;
6225 return S_OK;
6227 return TYPE_E_ELEMENTNOTFOUND;
6230 /* ITypeInfo2::GetAllVarCustData
6232 * Gets all custom data items for the specified Variable
6235 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6236 UINT index, CUSTDATA *pCustData)
6238 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6239 TLBCustData *pCData;
6240 TLBVarDesc * pVDesc;
6241 int i;
6242 TRACE("(%p) index %d\n", This, index);
6243 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6244 pVDesc=pVDesc->next)
6246 if(pVDesc){
6247 pCustData->prgCustData =
6248 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6249 if(pCustData->prgCustData ){
6250 pCustData->cCustData=pVDesc->ctCustData;
6251 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6252 pCData = pCData->next){
6253 pCustData->prgCustData[i].guid=pCData->guid;
6254 VariantCopy(& pCustData->prgCustData[i].varValue,
6255 & pCData->data);
6257 }else{
6258 ERR(" OUT OF MEMORY!\n");
6259 return E_OUTOFMEMORY;
6261 return S_OK;
6263 return TYPE_E_ELEMENTNOTFOUND;
6266 /* ITypeInfo2::GetAllImplCustData
6268 * Gets all custom data items for the specified implementation type
6271 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6272 ITypeInfo2 * iface,
6273 UINT index,
6274 CUSTDATA *pCustData)
6276 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6277 TLBCustData *pCData;
6278 TLBImplType * pRDesc;
6279 int i;
6280 TRACE("(%p) index %d\n", This, index);
6281 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6282 pRDesc=pRDesc->next)
6284 if(pRDesc){
6285 pCustData->prgCustData =
6286 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6287 if(pCustData->prgCustData ){
6288 pCustData->cCustData=pRDesc->ctCustData;
6289 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6290 pCData = pCData->next){
6291 pCustData->prgCustData[i].guid=pCData->guid;
6292 VariantCopy(& pCustData->prgCustData[i].varValue,
6293 & pCData->data);
6295 }else{
6296 ERR(" OUT OF MEMORY!\n");
6297 return E_OUTOFMEMORY;
6299 return S_OK;
6301 return TYPE_E_ELEMENTNOTFOUND;
6304 static const ITypeInfo2Vtbl tinfvt =
6307 ITypeInfo_fnQueryInterface,
6308 ITypeInfo_fnAddRef,
6309 ITypeInfo_fnRelease,
6311 ITypeInfo_fnGetTypeAttr,
6312 ITypeInfo_fnGetTypeComp,
6313 ITypeInfo_fnGetFuncDesc,
6314 ITypeInfo_fnGetVarDesc,
6315 ITypeInfo_fnGetNames,
6316 ITypeInfo_fnGetRefTypeOfImplType,
6317 ITypeInfo_fnGetImplTypeFlags,
6318 ITypeInfo_fnGetIDsOfNames,
6319 ITypeInfo_fnInvoke,
6320 ITypeInfo_fnGetDocumentation,
6321 ITypeInfo_fnGetDllEntry,
6322 ITypeInfo_fnGetRefTypeInfo,
6323 ITypeInfo_fnAddressOfMember,
6324 ITypeInfo_fnCreateInstance,
6325 ITypeInfo_fnGetMops,
6326 ITypeInfo_fnGetContainingTypeLib,
6327 ITypeInfo_fnReleaseTypeAttr,
6328 ITypeInfo_fnReleaseFuncDesc,
6329 ITypeInfo_fnReleaseVarDesc,
6331 ITypeInfo2_fnGetTypeKind,
6332 ITypeInfo2_fnGetTypeFlags,
6333 ITypeInfo2_fnGetFuncIndexOfMemId,
6334 ITypeInfo2_fnGetVarIndexOfMemId,
6335 ITypeInfo2_fnGetCustData,
6336 ITypeInfo2_fnGetFuncCustData,
6337 ITypeInfo2_fnGetParamCustData,
6338 ITypeInfo2_fnGetVarCustData,
6339 ITypeInfo2_fnGetImplTypeCustData,
6340 ITypeInfo2_fnGetDocumentation2,
6341 ITypeInfo2_fnGetAllCustData,
6342 ITypeInfo2_fnGetAllFuncCustData,
6343 ITypeInfo2_fnGetAllParamCustData,
6344 ITypeInfo2_fnGetAllVarCustData,
6345 ITypeInfo2_fnGetAllImplTypeCustData,
6348 /******************************************************************************
6349 * CreateDispTypeInfo [OLEAUT32.31]
6351 * Build type information for an object so it can be called through an
6352 * IDispatch interface.
6354 * RETURNS
6355 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6356 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6358 * NOTES
6359 * This call allows an objects methods to be accessed through IDispatch, by
6360 * building an ITypeInfo object that IDispatch can use to call through.
6362 HRESULT WINAPI CreateDispTypeInfo(
6363 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6364 LCID lcid, /* [I] Locale Id */
6365 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6367 ITypeInfoImpl *pTIClass, *pTIIface;
6368 ITypeLibImpl *pTypeLibImpl;
6369 int param, func;
6370 TLBFuncDesc **ppFuncDesc;
6372 TRACE_(typelib)("\n");
6373 pTypeLibImpl = TypeLibImpl_Constructor();
6374 if (!pTypeLibImpl) return E_FAIL;
6376 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6377 pTIIface->pTypeLib = pTypeLibImpl;
6378 pTIIface->index = 0;
6379 pTIIface->Name = NULL;
6380 pTIIface->dwHelpContext = -1;
6381 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6382 pTIIface->TypeAttr.lcid = lcid;
6383 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6384 pTIIface->TypeAttr.wMajorVerNum = 0;
6385 pTIIface->TypeAttr.wMinorVerNum = 0;
6386 pTIIface->TypeAttr.cbAlignment = 2;
6387 pTIIface->TypeAttr.cbSizeInstance = -1;
6388 pTIIface->TypeAttr.cbSizeVft = -1;
6389 pTIIface->TypeAttr.cFuncs = 0;
6390 pTIIface->TypeAttr.cImplTypes = 0;
6391 pTIIface->TypeAttr.cVars = 0;
6392 pTIIface->TypeAttr.wTypeFlags = 0;
6394 ppFuncDesc = &pTIIface->funclist;
6395 for(func = 0; func < pidata->cMembers; func++) {
6396 METHODDATA *md = pidata->pmethdata + func;
6397 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6398 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6399 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6400 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6401 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6402 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6403 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6404 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6405 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6406 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6407 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6408 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6409 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6410 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6411 md->cArgs * sizeof(ELEMDESC));
6412 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6413 md->cArgs * sizeof(TLBParDesc));
6414 for(param = 0; param < md->cArgs; param++) {
6415 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6416 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6418 (*ppFuncDesc)->helpcontext = 0;
6419 (*ppFuncDesc)->HelpStringContext = 0;
6420 (*ppFuncDesc)->HelpString = NULL;
6421 (*ppFuncDesc)->Entry = NULL;
6422 (*ppFuncDesc)->ctCustData = 0;
6423 (*ppFuncDesc)->pCustData = NULL;
6424 (*ppFuncDesc)->next = NULL;
6425 ppFuncDesc = &(*ppFuncDesc)->next;
6428 pTypeLibImpl->pTypeInfo = pTIIface;
6429 pTypeLibImpl->TypeInfoCount++;
6431 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6432 pTIClass->pTypeLib = pTypeLibImpl;
6433 pTIClass->index = 1;
6434 pTIClass->Name = NULL;
6435 pTIClass->dwHelpContext = -1;
6436 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6437 pTIClass->TypeAttr.lcid = lcid;
6438 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6439 pTIClass->TypeAttr.wMajorVerNum = 0;
6440 pTIClass->TypeAttr.wMinorVerNum = 0;
6441 pTIClass->TypeAttr.cbAlignment = 2;
6442 pTIClass->TypeAttr.cbSizeInstance = -1;
6443 pTIClass->TypeAttr.cbSizeVft = -1;
6444 pTIClass->TypeAttr.cFuncs = 0;
6445 pTIClass->TypeAttr.cImplTypes = 1;
6446 pTIClass->TypeAttr.cVars = 0;
6447 pTIClass->TypeAttr.wTypeFlags = 0;
6449 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6450 pTIClass->impltypelist->hRef = 1;
6452 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6453 pTIClass->reflist->index = 0;
6454 pTIClass->reflist->reference = 1;
6455 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6457 pTIIface->next = pTIClass;
6458 pTypeLibImpl->TypeInfoCount++;
6460 *pptinfo = (ITypeInfo*)pTIClass;
6461 return S_OK;
6465 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6467 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6469 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6472 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6474 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6476 return ITypeInfo_AddRef((ITypeInfo *)This);
6479 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6481 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6483 return ITypeInfo_Release((ITypeInfo *)This);
6486 static HRESULT WINAPI ITypeComp_fnBind(
6487 ITypeComp * iface,
6488 OLECHAR * szName,
6489 ULONG lHash,
6490 WORD wFlags,
6491 ITypeInfo ** ppTInfo,
6492 DESCKIND * pDescKind,
6493 BINDPTR * pBindPtr)
6495 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6496 const TLBFuncDesc *pFDesc;
6497 const TLBVarDesc *pVDesc;
6499 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6501 *pDescKind = DESCKIND_NONE;
6502 pBindPtr->lpfuncdesc = NULL;
6503 *ppTInfo = NULL;
6505 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6506 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6507 if (!strcmpW(pFDesc->Name, szName)) {
6508 break;
6511 if (pFDesc)
6513 HRESULT hr = TLB_AllocAndInitFuncDesc(
6514 &pFDesc->funcdesc,
6515 &pBindPtr->lpfuncdesc,
6516 This->TypeAttr.typekind == TKIND_DISPATCH);
6517 if (FAILED(hr))
6518 return hr;
6519 *pDescKind = DESCKIND_FUNCDESC;
6520 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6521 ITypeInfo_AddRef(*ppTInfo);
6522 return S_OK;
6523 } else {
6524 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6525 if (!strcmpW(pVDesc->Name, szName)) {
6526 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6527 if (FAILED(hr))
6528 return hr;
6529 *pDescKind = DESCKIND_VARDESC;
6530 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6531 ITypeInfo_AddRef(*ppTInfo);
6532 return S_OK;
6536 /* FIXME: search each inherited interface, not just the first */
6537 if (This->TypeAttr.cImplTypes) {
6538 /* recursive search */
6539 ITypeInfo *pTInfo;
6540 ITypeComp *pTComp;
6541 HRESULT hr;
6542 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6543 if (SUCCEEDED(hr))
6545 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6546 ITypeInfo_Release(pTInfo);
6548 if (SUCCEEDED(hr))
6550 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6551 ITypeComp_Release(pTComp);
6552 return hr;
6554 WARN("Could not search inherited interface!\n");
6556 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6557 return DISP_E_MEMBERNOTFOUND;
6560 static HRESULT WINAPI ITypeComp_fnBindType(
6561 ITypeComp * iface,
6562 OLECHAR * szName,
6563 ULONG lHash,
6564 ITypeInfo ** ppTInfo,
6565 ITypeComp ** ppTComp)
6567 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6569 /* strange behaviour (does nothing) but like the
6570 * original */
6572 if (!ppTInfo || !ppTComp)
6573 return E_POINTER;
6575 *ppTInfo = NULL;
6576 *ppTComp = NULL;
6578 return S_OK;
6581 static const ITypeCompVtbl tcompvt =
6584 ITypeComp_fnQueryInterface,
6585 ITypeComp_fnAddRef,
6586 ITypeComp_fnRelease,
6588 ITypeComp_fnBind,
6589 ITypeComp_fnBindType