ole32: Register a few more clipboard formats and make them have global scope.
[wine/hacks.git] / dlls / oleaut32 / typelib.c
bloba0af8473c4e63fe3f85ae660e006c6c18cab8ffb
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
269 sprintfW( buffer, LcidFormatW, lcid );
270 switch(syskind)
272 case SYS_WIN16: strcatW( buffer, win16W ); break;
273 case SYS_WIN32: strcatW( buffer, win32W ); break;
274 default:
275 TRACE("Typelib is for unsupported syskind %i\n", syskind);
276 return NULL;
278 return buffer;
281 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
284 /****************************************************************************
285 * QueryPathOfRegTypeLib [OLEAUT32.164]
287 * Gets the path to a registered type library.
289 * PARAMS
290 * guid [I] referenced guid
291 * wMaj [I] major version
292 * wMin [I] minor version
293 * lcid [I] locale id
294 * path [O] path of typelib
296 * RETURNS
297 * Success: S_OK.
298 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
299 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
300 * opened.
302 HRESULT WINAPI QueryPathOfRegTypeLib(
303 REFGUID guid,
304 WORD wMaj,
305 WORD wMin,
306 LCID lcid,
307 LPBSTR path )
309 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
310 LCID myLCID = lcid;
311 HKEY hkey;
312 WCHAR buffer[60];
313 WCHAR Path[MAX_PATH];
314 LONG res;
316 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
318 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
319 get_typelib_key( guid, wMaj, wMin, buffer );
321 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
322 if (res == ERROR_FILE_NOT_FOUND)
324 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
325 return TYPE_E_LIBNOTREGISTERED;
327 else if (res != ERROR_SUCCESS)
329 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
330 return TYPE_E_REGISTRYACCESS;
333 while (hr != S_OK)
335 LONG dwPathLen = sizeof(Path);
337 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
339 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
341 if (!lcid)
342 break;
343 else if (myLCID == lcid)
345 /* try with sub-langid */
346 myLCID = SUBLANGID(lcid);
348 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
350 /* try with system langid */
351 myLCID = 0;
353 else
355 break;
358 else
360 *path = SysAllocString( Path );
361 hr = S_OK;
364 RegCloseKey( hkey );
365 TRACE_(typelib)("-- 0x%08x\n", hr);
366 return hr;
369 /******************************************************************************
370 * CreateTypeLib [OLEAUT32.160] creates a typelib
372 * RETURNS
373 * Success: S_OK
374 * Failure: Status
376 HRESULT WINAPI CreateTypeLib(
377 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
379 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
380 return E_FAIL;
383 /******************************************************************************
384 * LoadTypeLib [OLEAUT32.161]
386 * Loads a type library
388 * PARAMS
389 * szFile [I] Name of file to load from.
390 * pptLib [O] Pointer that receives ITypeLib object on success.
392 * RETURNS
393 * Success: S_OK
394 * Failure: Status
396 * SEE
397 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
399 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
401 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
402 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
405 /******************************************************************************
406 * LoadTypeLibEx [OLEAUT32.183]
408 * Loads and optionally registers a type library
410 * RETURNS
411 * Success: S_OK
412 * Failure: Status
414 HRESULT WINAPI LoadTypeLibEx(
415 LPCOLESTR szFile, /* [in] Name of file to load from */
416 REGKIND regkind, /* [in] Specify kind of registration */
417 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
419 WCHAR szPath[MAX_PATH+1];
420 HRESULT res;
422 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
424 *pptLib = NULL;
426 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
428 if (SUCCEEDED(res))
429 switch(regkind)
431 case REGKIND_DEFAULT:
432 /* don't register typelibs supplied with full path. Experimentation confirms the following */
433 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
434 (szFile[0] && (szFile[1] == ':'))) break;
435 /* else fall-through */
437 case REGKIND_REGISTER:
438 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
440 IUnknown_Release(*pptLib);
441 *pptLib = 0;
443 break;
444 case REGKIND_NONE:
445 break;
448 TRACE(" returns %08x\n",res);
449 return res;
452 /******************************************************************************
453 * LoadRegTypeLib [OLEAUT32.162]
455 * Loads a registered type library.
457 * PARAMS
458 * rguid [I] GUID of the registered type library.
459 * wVerMajor [I] major version.
460 * wVerMinor [I] minor version.
461 * lcid [I] locale ID.
462 * ppTLib [O] pointer that receives an ITypeLib object on success.
464 * RETURNS
465 * Success: S_OK.
466 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
467 * LoadTypeLib.
469 HRESULT WINAPI LoadRegTypeLib(
470 REFGUID rguid,
471 WORD wVerMajor,
472 WORD wVerMinor,
473 LCID lcid,
474 ITypeLib **ppTLib)
476 BSTR bstr=NULL;
477 HRESULT res;
479 *ppTLib = NULL;
481 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
483 if(SUCCEEDED(res))
485 res= LoadTypeLib(bstr, ppTLib);
486 SysFreeString(bstr);
489 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
491 return res;
495 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
496 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
497 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
498 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
499 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
500 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
502 /******************************************************************************
503 * RegisterTypeLib [OLEAUT32.163]
504 * Adds information about a type library to the System Registry
505 * NOTES
506 * Docs: ITypeLib FAR * ptlib
507 * Docs: OLECHAR FAR* szFullPath
508 * Docs: OLECHAR FAR* szHelpDir
510 * RETURNS
511 * Success: S_OK
512 * Failure: Status
514 HRESULT WINAPI RegisterTypeLib(
515 ITypeLib * ptlib, /* [in] Pointer to the library*/
516 OLECHAR * szFullPath, /* [in] full Path of the library*/
517 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
518 may be NULL*/
520 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
521 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
522 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
523 HRESULT res;
524 TLIBATTR *attr;
525 WCHAR keyName[60];
526 WCHAR tmp[16];
527 HKEY key, subKey;
528 UINT types, tidx;
529 TYPEKIND kind;
530 DWORD disposition;
532 if (ptlib == NULL || szFullPath == NULL)
533 return E_INVALIDARG;
535 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
536 return E_FAIL;
538 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
540 res = S_OK;
541 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
542 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
544 LPOLESTR doc;
546 /* Set the human-readable name of the typelib */
547 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
549 if (RegSetValueExW(key, NULL, 0, REG_SZ,
550 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
551 res = E_FAIL;
553 SysFreeString(doc);
555 else
556 res = E_FAIL;
558 /* Make up the name of the typelib path subkey */
559 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
561 /* Create the typelib path subkey */
562 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
563 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
565 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
566 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
567 res = E_FAIL;
569 RegCloseKey(subKey);
571 else
572 res = E_FAIL;
574 /* Create the flags subkey */
575 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
576 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
578 /* FIXME: is %u correct? */
579 static const WCHAR formatW[] = {'%','u',0};
580 WCHAR buf[20];
581 sprintfW(buf, formatW, attr->wLibFlags);
582 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
583 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
584 res = E_FAIL;
586 RegCloseKey(subKey);
588 else
589 res = E_FAIL;
591 /* create the helpdir subkey */
592 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
593 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
595 BOOL freeHelpDir = FALSE;
596 OLECHAR* pIndexStr;
598 /* if we created a new key, and helpDir was null, set the helpdir
599 to the directory which contains the typelib. However,
600 if we just opened an existing key, we leave the helpdir alone */
601 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
602 szHelpDir = SysAllocString(szFullPath);
603 pIndexStr = strrchrW(szHelpDir, '\\');
604 if (pIndexStr) {
605 *pIndexStr = 0;
607 freeHelpDir = TRUE;
610 /* if we have an szHelpDir, set it! */
611 if (szHelpDir != NULL) {
612 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
613 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
614 res = E_FAIL;
618 /* tidy up */
619 if (freeHelpDir) SysFreeString(szHelpDir);
620 RegCloseKey(subKey);
622 } else {
623 res = E_FAIL;
626 RegCloseKey(key);
628 else
629 res = E_FAIL;
631 /* register OLE Automation-compatible interfaces for this typelib */
632 types = ITypeLib_GetTypeInfoCount(ptlib);
633 for (tidx=0; tidx<types; tidx++) {
634 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
635 LPOLESTR name = NULL;
636 ITypeInfo *tinfo = NULL;
638 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
640 switch (kind) {
641 case TKIND_INTERFACE:
642 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
643 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
644 break;
646 case TKIND_DISPATCH:
647 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
648 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
649 break;
651 default:
652 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
653 break;
656 if (tinfo) {
657 TYPEATTR *tattr = NULL;
658 ITypeInfo_GetTypeAttr(tinfo, &tattr);
660 if (tattr) {
661 TRACE_(typelib)("guid=%s, flags=%04x (",
662 debugstr_guid(&tattr->guid),
663 tattr->wTypeFlags);
665 if (TRACE_ON(typelib)) {
666 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
667 XX(FAPPOBJECT);
668 XX(FCANCREATE);
669 XX(FLICENSED);
670 XX(FPREDECLID);
671 XX(FHIDDEN);
672 XX(FCONTROL);
673 XX(FDUAL);
674 XX(FNONEXTENSIBLE);
675 XX(FOLEAUTOMATION);
676 XX(FRESTRICTED);
677 XX(FAGGREGATABLE);
678 XX(FREPLACEABLE);
679 XX(FDISPATCHABLE);
680 XX(FREVERSEBIND);
681 XX(FPROXY);
682 #undef XX
683 MESSAGE("\n");
686 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
688 /* register interface<->typelib coupling */
689 get_interface_key( &tattr->guid, keyName );
690 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
691 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
693 if (name)
694 RegSetValueExW(key, NULL, 0, REG_SZ,
695 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
697 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
698 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
699 RegSetValueExW(subKey, NULL, 0, REG_SZ,
700 (const BYTE *)PSOA, sizeof PSOA);
701 RegCloseKey(subKey);
704 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
705 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
706 RegSetValueExW(subKey, NULL, 0, REG_SZ,
707 (const BYTE *)PSOA, sizeof PSOA);
708 RegCloseKey(subKey);
711 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
712 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
714 WCHAR buffer[40];
715 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
716 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
718 StringFromGUID2(&attr->guid, buffer, 40);
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
721 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
722 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
723 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
724 RegCloseKey(subKey);
727 RegCloseKey(key);
731 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
734 ITypeInfo_Release(tinfo);
737 SysFreeString(name);
741 ITypeLib_ReleaseTLibAttr(ptlib, attr);
743 return res;
747 /******************************************************************************
748 * UnRegisterTypeLib [OLEAUT32.186]
749 * Removes information about a type library from the System Registry
750 * NOTES
752 * RETURNS
753 * Success: S_OK
754 * Failure: Status
756 HRESULT WINAPI UnRegisterTypeLib(
757 REFGUID libid, /* [in] Guid of the library */
758 WORD wVerMajor, /* [in] major version */
759 WORD wVerMinor, /* [in] minor version */
760 LCID lcid, /* [in] locale id */
761 SYSKIND syskind)
763 BSTR tlibPath = NULL;
764 DWORD tmpLength;
765 WCHAR keyName[60];
766 WCHAR subKeyName[50];
767 int result = S_OK;
768 DWORD i = 0;
769 BOOL deleteOtherStuff;
770 HKEY key = NULL;
771 HKEY subKey = NULL;
772 TYPEATTR* typeAttr = NULL;
773 TYPEKIND kind;
774 ITypeInfo* typeInfo = NULL;
775 ITypeLib* typeLib = NULL;
776 int numTypes;
778 TRACE("(IID: %s)\n",debugstr_guid(libid));
780 /* Create the path to the key */
781 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
783 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
785 TRACE("Unsupported syskind %i\n", syskind);
786 result = E_INVALIDARG;
787 goto end;
790 /* get the path to the typelib on disk */
791 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
792 result = E_INVALIDARG;
793 goto end;
796 /* Try and open the key to the type library. */
797 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
798 result = E_INVALIDARG;
799 goto end;
802 /* Try and load the type library */
803 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
804 result = TYPE_E_INVALIDSTATE;
805 goto end;
808 /* remove any types registered with this typelib */
809 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
810 for (i=0; i<numTypes; i++) {
811 /* get the kind of type */
812 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
813 goto enddeleteloop;
816 /* skip non-interfaces, and get type info for the type */
817 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
818 goto enddeleteloop;
820 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
821 goto enddeleteloop;
823 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
824 goto enddeleteloop;
827 /* the path to the type */
828 get_interface_key( &typeAttr->guid, subKeyName );
830 /* Delete its bits */
831 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
832 goto enddeleteloop;
834 RegDeleteKeyW(subKey, ProxyStubClsidW);
835 RegDeleteKeyW(subKey, ProxyStubClsid32W);
836 RegDeleteKeyW(subKey, TypeLibW);
837 RegCloseKey(subKey);
838 subKey = NULL;
839 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
841 enddeleteloop:
842 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
843 typeAttr = NULL;
844 if (typeInfo) ITypeInfo_Release(typeInfo);
845 typeInfo = NULL;
848 /* Now, delete the type library path subkey */
849 get_lcid_subkey( lcid, syskind, subKeyName );
850 RegDeleteKeyW(key, subKeyName);
851 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
852 RegDeleteKeyW(key, subKeyName);
854 /* check if there is anything besides the FLAGS/HELPDIR keys.
855 If there is, we don't delete them */
856 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
857 deleteOtherStuff = TRUE;
858 i = 0;
859 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
860 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
862 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
863 if (!strcmpW(subKeyName, FLAGSW)) continue;
864 if (!strcmpW(subKeyName, HELPDIRW)) continue;
865 deleteOtherStuff = FALSE;
866 break;
869 /* only delete the other parts of the key if we're absolutely sure */
870 if (deleteOtherStuff) {
871 RegDeleteKeyW(key, FLAGSW);
872 RegDeleteKeyW(key, HELPDIRW);
873 RegCloseKey(key);
874 key = NULL;
876 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
877 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
878 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
881 end:
882 SysFreeString(tlibPath);
883 if (typeLib) ITypeLib_Release(typeLib);
884 if (subKey) RegCloseKey(subKey);
885 if (key) RegCloseKey(key);
886 return result;
889 /*======================= ITypeLib implementation =======================*/
891 typedef struct tagTLBCustData
893 GUID guid;
894 VARIANT data;
895 struct tagTLBCustData* next;
896 } TLBCustData;
898 /* data structure for import typelibs */
899 typedef struct tagTLBImpLib
901 int offset; /* offset in the file (MSFT)
902 offset in nametable (SLTG)
903 just used to identify library while reading
904 data from file */
905 GUID guid; /* libid */
906 BSTR name; /* name */
908 LCID lcid; /* lcid of imported typelib */
910 WORD wVersionMajor; /* major version number */
911 WORD wVersionMinor; /* minor version number */
913 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
914 NULL if not yet loaded */
915 struct tagTLBImpLib * next;
916 } TLBImpLib;
918 /* internal ITypeLib data */
919 typedef struct tagITypeLibImpl
921 const ITypeLib2Vtbl *lpVtbl;
922 const ITypeCompVtbl *lpVtblTypeComp;
923 LONG ref;
924 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
926 /* strings can be stored in tlb as multibyte strings BUT they are *always*
927 * exported to the application as a UNICODE string.
929 BSTR Name;
930 BSTR DocString;
931 BSTR HelpFile;
932 BSTR HelpStringDll;
933 unsigned long dwHelpContext;
934 int TypeInfoCount; /* nr of typeinfo's in librarry */
935 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
936 int ctCustData; /* number of items in cust data list */
937 TLBCustData * pCustData; /* linked list to cust data */
938 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
939 int ctTypeDesc; /* number of items in type desc array */
940 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
941 library. Only used while reading MSFT
942 typelibs */
943 struct list ref_list; /* list of ref types in this typelib */
944 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
947 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
948 struct tagITypeLibImpl *next, *prev;
949 WCHAR *path;
950 INT index;
951 } ITypeLibImpl;
953 static const ITypeLib2Vtbl tlbvt;
954 static const ITypeCompVtbl tlbtcvt;
956 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
958 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
961 /* ITypeLib methods */
962 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
963 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
965 /*======================= ITypeInfo implementation =======================*/
967 /* data for referenced types */
968 typedef struct tagTLBRefType
970 INT index; /* Type index for internal ref or for external ref
971 it the format is SLTG. -2 indicates to
972 use guid */
974 GUID guid; /* guid of the referenced type */
975 /* if index == TLB_REF_USE_GUID */
977 HREFTYPE reference; /* The href of this ref */
978 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
979 TLB_REF_INTERNAL for internal refs
980 TLB_REF_NOT_FOUND for broken refs */
982 struct list entry;
983 } TLBRefType;
985 #define TLB_REF_USE_GUID -2
987 #define TLB_REF_INTERNAL (void*)-2
988 #define TLB_REF_NOT_FOUND (void*)-1
990 /* internal Parameter data */
991 typedef struct tagTLBParDesc
993 BSTR Name;
994 int ctCustData;
995 TLBCustData * pCustData; /* linked list to cust data */
996 } TLBParDesc;
998 /* internal Function data */
999 typedef struct tagTLBFuncDesc
1001 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1002 BSTR Name; /* the name of this function */
1003 TLBParDesc *pParamDesc; /* array with param names and custom data */
1004 int helpcontext;
1005 int HelpStringContext;
1006 BSTR HelpString;
1007 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
1008 int ctCustData;
1009 TLBCustData * pCustData; /* linked list to cust data; */
1010 struct tagTLBFuncDesc * next;
1011 } TLBFuncDesc;
1013 /* internal Variable data */
1014 typedef struct tagTLBVarDesc
1016 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1017 BSTR Name; /* the name of this variable */
1018 int HelpContext;
1019 int HelpStringContext; /* FIXME: where? */
1020 BSTR HelpString;
1021 int ctCustData;
1022 TLBCustData * pCustData;/* linked list to cust data; */
1023 struct tagTLBVarDesc * next;
1024 } TLBVarDesc;
1026 /* internal implemented interface data */
1027 typedef struct tagTLBImplType
1029 HREFTYPE hRef; /* hRef of interface */
1030 int implflags; /* IMPLFLAG_*s */
1031 int ctCustData;
1032 TLBCustData * pCustData;/* linked list to custom data; */
1033 struct tagTLBImplType *next;
1034 } TLBImplType;
1036 /* internal TypeInfo data */
1037 typedef struct tagITypeInfoImpl
1039 const ITypeInfo2Vtbl *lpVtbl;
1040 const ITypeCompVtbl *lpVtblTypeComp;
1041 LONG ref;
1042 BOOL no_free_data; /* don't free data structures */
1043 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1044 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1045 int index; /* index in this typelib; */
1046 HREFTYPE hreftype; /* hreftype for app object binding */
1047 /* type libs seem to store the doc strings in ascii
1048 * so why should we do it in unicode?
1050 BSTR Name;
1051 BSTR DocString;
1052 BSTR DllName;
1053 unsigned long dwHelpContext;
1054 unsigned long dwHelpStringContext;
1056 /* functions */
1057 TLBFuncDesc * funclist; /* linked list with function descriptions */
1059 /* variables */
1060 TLBVarDesc * varlist; /* linked list with variable descriptions */
1062 /* Implemented Interfaces */
1063 TLBImplType * impltypelist;
1065 int ctCustData;
1066 TLBCustData * pCustData; /* linked list to cust data; */
1067 struct tagITypeInfoImpl * next;
1068 } ITypeInfoImpl;
1070 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1072 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1075 static const ITypeInfo2Vtbl tinfvt;
1076 static const ITypeCompVtbl tcompvt;
1078 static ITypeInfo2 * ITypeInfo_Constructor(void);
1080 typedef struct tagTLBContext
1082 unsigned int oStart; /* start of TLB in file */
1083 unsigned int pos; /* current pos */
1084 unsigned int length; /* total length */
1085 void *mapping; /* memory mapping */
1086 MSFT_SegDir * pTblDir;
1087 ITypeLibImpl* pLibInfo;
1088 } TLBContext;
1091 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1094 debug
1096 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1097 if (pTD->vt & VT_RESERVED)
1098 szVarType += strlen(strcpy(szVarType, "reserved | "));
1099 if (pTD->vt & VT_BYREF)
1100 szVarType += strlen(strcpy(szVarType, "ref to "));
1101 if (pTD->vt & VT_ARRAY)
1102 szVarType += strlen(strcpy(szVarType, "array of "));
1103 if (pTD->vt & VT_VECTOR)
1104 szVarType += strlen(strcpy(szVarType, "vector of "));
1105 switch(pTD->vt & VT_TYPEMASK) {
1106 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1107 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1108 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1109 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1110 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1111 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1112 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1113 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1114 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1115 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1116 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1117 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1118 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1119 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1120 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1121 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1122 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1123 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1124 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1125 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1126 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1127 pTD->u.hreftype); break;
1128 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1129 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1130 case VT_PTR: sprintf(szVarType, "ptr to ");
1131 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1132 break;
1133 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1134 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1135 break;
1136 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1137 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1138 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1139 break;
1141 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1145 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1146 char buf[200];
1147 USHORT flags = edesc->u.paramdesc.wParamFlags;
1148 dump_TypeDesc(&edesc->tdesc,buf);
1149 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1150 MESSAGE("\t\tu.paramdesc.wParamFlags");
1151 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1152 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1153 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1154 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1155 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1156 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1157 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1158 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1159 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1161 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1162 int i;
1163 MESSAGE("memid is %08x\n",funcdesc->memid);
1164 for (i=0;i<funcdesc->cParams;i++) {
1165 MESSAGE("Param %d:\n",i);
1166 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1168 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1169 switch (funcdesc->funckind) {
1170 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1171 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1172 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1173 case FUNC_STATIC: MESSAGE("static");break;
1174 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1175 default: MESSAGE("unknown");break;
1177 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1178 switch (funcdesc->invkind) {
1179 case INVOKE_FUNC: MESSAGE("func");break;
1180 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1181 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1182 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1184 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1185 switch (funcdesc->callconv) {
1186 case CC_CDECL: MESSAGE("cdecl");break;
1187 case CC_PASCAL: MESSAGE("pascal");break;
1188 case CC_STDCALL: MESSAGE("stdcall");break;
1189 case CC_SYSCALL: MESSAGE("syscall");break;
1190 default:break;
1192 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1193 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1194 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1196 MESSAGE("\telemdescFunc (return value type):\n");
1197 dump_ELEMDESC(&funcdesc->elemdescFunc);
1200 static const char * const typekind_desc[] =
1202 "TKIND_ENUM",
1203 "TKIND_RECORD",
1204 "TKIND_MODULE",
1205 "TKIND_INTERFACE",
1206 "TKIND_DISPATCH",
1207 "TKIND_COCLASS",
1208 "TKIND_ALIAS",
1209 "TKIND_UNION",
1210 "TKIND_MAX"
1213 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1215 int i;
1216 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1217 for (i=0;i<pfd->funcdesc.cParams;i++)
1218 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1221 dump_FUNCDESC(&(pfd->funcdesc));
1223 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1224 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1226 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1228 while (pfd)
1230 dump_TLBFuncDescOne(pfd);
1231 pfd = pfd->next;
1234 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1236 while (pvd)
1238 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1239 pvd = pvd->next;
1243 static void dump_TLBImpLib(const TLBImpLib *import)
1245 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1246 debugstr_w(import->name));
1247 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1248 import->wVersionMinor, import->lcid, import->offset);
1251 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1253 TLBRefType *ref;
1255 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1257 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1258 if(ref->index == -1)
1259 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1260 else
1261 TRACE_(typelib)("type no: %d\n", ref->index);
1263 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1265 TRACE_(typelib)("in lib\n");
1266 dump_TLBImpLib(ref->pImpTLInfo);
1271 static void dump_TLBImplType(const TLBImplType * impl)
1273 while (impl) {
1274 TRACE_(typelib)(
1275 "implementing/inheriting interface hRef = %x implflags %x\n",
1276 impl->hRef, impl->implflags);
1277 impl = impl->next;
1281 static void dump_Variant(const VARIANT * pvar)
1283 SYSTEMTIME st;
1285 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1287 if (pvar)
1289 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1290 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1292 TRACE(",%p", V_BYREF(pvar));
1294 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1296 TRACE(",%p", V_ARRAY(pvar));
1298 else switch (V_TYPE(pvar))
1300 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1301 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1302 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1303 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1304 case VT_INT:
1305 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1306 case VT_UINT:
1307 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1308 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1309 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1310 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1311 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1312 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1313 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1314 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1315 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1316 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1317 V_CY(pvar).s.Lo); break;
1318 case VT_DATE:
1319 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1320 TRACE(",<invalid>");
1321 else
1322 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1323 st.wHour, st.wMinute, st.wSecond);
1324 break;
1325 case VT_ERROR:
1326 case VT_VOID:
1327 case VT_USERDEFINED:
1328 case VT_EMPTY:
1329 case VT_NULL: break;
1330 default: TRACE(",?"); break;
1333 TRACE("}\n");
1336 static void dump_DispParms(const DISPPARAMS * pdp)
1338 unsigned int index;
1340 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1342 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1344 TRACE("named args:\n");
1345 for (index = 0; index < pdp->cNamedArgs; index++)
1346 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1349 if (pdp->cArgs && pdp->rgvarg)
1351 TRACE("args:\n");
1352 for (index = 0; index < pdp->cArgs; index++)
1353 dump_Variant( &pdp->rgvarg[index] );
1357 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1359 TRACE("%p ref=%u\n", pty, pty->ref);
1360 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1361 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1362 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1363 TRACE("fct:%u var:%u impl:%u\n",
1364 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1365 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1366 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1367 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1368 if (TRACE_ON(ole))
1369 dump_TLBFuncDesc(pty->funclist);
1370 dump_TLBVarDesc(pty->varlist);
1371 dump_TLBImplType(pty->impltypelist);
1374 static void dump_VARDESC(const VARDESC *v)
1376 MESSAGE("memid %d\n",v->memid);
1377 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1378 MESSAGE("oInst %d\n",v->u.oInst);
1379 dump_ELEMDESC(&(v->elemdescVar));
1380 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1381 MESSAGE("varkind %d\n",v->varkind);
1384 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1386 /* VT_LPWSTR is largest type that */
1387 /* may appear in type description*/
1388 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1389 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1390 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1391 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1392 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1393 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1394 {{0},30},{{0},31}
1397 static void TLB_abort(void)
1399 DebugBreak();
1402 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1403 static void * TLB_Alloc(unsigned size)
1405 void * ret;
1406 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1407 /* FIXME */
1408 ERR("cannot allocate memory\n");
1410 return ret;
1413 static void TLB_Free(void * ptr)
1415 HeapFree(GetProcessHeap(), 0, ptr);
1418 /* returns the size required for a deep copy of a typedesc into a
1419 * flat buffer */
1420 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1422 SIZE_T size = 0;
1424 if (alloc_initial_space)
1425 size += sizeof(TYPEDESC);
1427 switch (tdesc->vt)
1429 case VT_PTR:
1430 case VT_SAFEARRAY:
1431 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1432 break;
1433 case VT_CARRAY:
1434 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1435 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1436 break;
1438 return size;
1441 /* deep copy a typedesc into a flat buffer */
1442 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1444 if (!dest)
1446 dest = buffer;
1447 buffer = (char *)buffer + sizeof(TYPEDESC);
1450 *dest = *src;
1452 switch (src->vt)
1454 case VT_PTR:
1455 case VT_SAFEARRAY:
1456 dest->u.lptdesc = buffer;
1457 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1458 break;
1459 case VT_CARRAY:
1460 dest->u.lpadesc = buffer;
1461 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1462 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1463 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1464 break;
1466 return buffer;
1469 /* free custom data allocated by MSFT_CustData */
1470 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1472 TLBCustData *pCustDataNext;
1473 for (; pCustData; pCustData = pCustDataNext)
1475 VariantClear(&pCustData->data);
1477 pCustDataNext = pCustData->next;
1478 TLB_Free(pCustData);
1482 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1484 DWORD len;
1485 BSTR ret;
1487 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1488 ret = SysAllocStringLen(NULL, len - 1);
1489 if (!ret) return ret;
1490 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1491 return ret;
1494 /**********************************************************************
1496 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1498 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1500 return pcx->pos;
1503 static inline void MSFT_Seek(TLBContext *pcx, long where)
1505 if (where != DO_NOT_SEEK)
1507 where += pcx->oStart;
1508 if (where > pcx->length)
1510 /* FIXME */
1511 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1512 TLB_abort();
1514 pcx->pos = where;
1518 /* read function */
1519 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1521 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1522 pcx->pos, count, pcx->oStart, pcx->length, where);
1524 MSFT_Seek(pcx, where);
1525 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1526 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1527 pcx->pos += count;
1528 return count;
1531 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1532 long where )
1534 DWORD ret;
1536 ret = MSFT_Read(buffer, count, pcx, where);
1537 FromLEDWords(buffer, ret);
1539 return ret;
1542 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1543 long where )
1545 DWORD ret;
1547 ret = MSFT_Read(buffer, count, pcx, where);
1548 FromLEWords(buffer, ret);
1550 return ret;
1553 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1555 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1556 memset(pGuid,0, sizeof(GUID));
1557 return;
1559 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1560 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1561 pGuid->Data2 = FromLEWord(pGuid->Data2);
1562 pGuid->Data3 = FromLEWord(pGuid->Data3);
1563 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1566 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1568 MSFT_NameIntro niName;
1570 if (offset < 0)
1572 ERR_(typelib)("bad offset %d\n", offset);
1573 return -1;
1576 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1577 pcx->pTblDir->pNametab.offset+offset);
1579 return niName.hreftype;
1582 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1584 char * name;
1585 MSFT_NameIntro niName;
1586 int lengthInChars;
1587 BSTR bstrName = NULL;
1589 if (offset < 0)
1591 ERR_(typelib)("bad offset %d\n", offset);
1592 return NULL;
1594 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1595 pcx->pTblDir->pNametab.offset+offset);
1596 niName.namelen &= 0xFF; /* FIXME: correct ? */
1597 name=TLB_Alloc((niName.namelen & 0xff) +1);
1598 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1599 name[niName.namelen & 0xff]='\0';
1601 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1602 name, -1, NULL, 0);
1604 /* no invalid characters in string */
1605 if (lengthInChars)
1607 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1609 /* don't check for invalid character since this has been done previously */
1610 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1612 TLB_Free(name);
1614 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1615 return bstrName;
1618 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1620 char * string;
1621 INT16 length;
1622 int lengthInChars;
1623 BSTR bstr = NULL;
1625 if(offset<0) return NULL;
1626 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1627 if(length <= 0) return 0;
1628 string=TLB_Alloc(length +1);
1629 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1630 string[length]='\0';
1632 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1633 string, -1, NULL, 0);
1635 /* no invalid characters in string */
1636 if (lengthInChars)
1638 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1640 /* don't check for invalid character since this has been done previously */
1641 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1643 TLB_Free(string);
1645 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1646 return bstr;
1649 * read a value and fill a VARIANT structure
1651 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1653 int size;
1655 TRACE_(typelib)("\n");
1657 if(offset <0) { /* data are packed in here */
1658 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1659 V_I4(pVar) = offset & 0x3ffffff;
1660 return;
1662 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1663 pcx->pTblDir->pCustData.offset + offset );
1664 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1665 switch (V_VT(pVar)){
1666 case VT_EMPTY: /* FIXME: is this right? */
1667 case VT_NULL: /* FIXME: is this right? */
1668 case VT_I2 : /* this should not happen */
1669 case VT_I4 :
1670 case VT_R4 :
1671 case VT_ERROR :
1672 case VT_BOOL :
1673 case VT_I1 :
1674 case VT_UI1 :
1675 case VT_UI2 :
1676 case VT_UI4 :
1677 case VT_INT :
1678 case VT_UINT :
1679 case VT_VOID : /* FIXME: is this right? */
1680 case VT_HRESULT :
1681 size=4; break;
1682 case VT_R8 :
1683 case VT_CY :
1684 case VT_DATE :
1685 case VT_I8 :
1686 case VT_UI8 :
1687 case VT_DECIMAL : /* FIXME: is this right? */
1688 case VT_FILETIME :
1689 size=8;break;
1690 /* pointer types with known behaviour */
1691 case VT_BSTR :{
1692 char * ptr;
1693 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1694 if(size < 0) {
1695 char next;
1696 DWORD origPos = MSFT_Tell(pcx), nullPos;
1698 do {
1699 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1700 } while (next);
1701 nullPos = MSFT_Tell(pcx);
1702 size = nullPos - origPos;
1703 MSFT_Seek(pcx, origPos);
1705 ptr=TLB_Alloc(size);/* allocate temp buffer */
1706 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1707 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1708 /* FIXME: do we need a AtoW conversion here? */
1709 V_UNION(pVar, bstrVal[size])='\0';
1710 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1711 TLB_Free(ptr);
1713 size=-4; break;
1714 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1715 case VT_DISPATCH :
1716 case VT_VARIANT :
1717 case VT_UNKNOWN :
1718 case VT_PTR :
1719 case VT_SAFEARRAY :
1720 case VT_CARRAY :
1721 case VT_USERDEFINED :
1722 case VT_LPSTR :
1723 case VT_LPWSTR :
1724 case VT_BLOB :
1725 case VT_STREAM :
1726 case VT_STORAGE :
1727 case VT_STREAMED_OBJECT :
1728 case VT_STORED_OBJECT :
1729 case VT_BLOB_OBJECT :
1730 case VT_CF :
1731 case VT_CLSID :
1732 default:
1733 size=0;
1734 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1735 V_VT(pVar));
1738 if(size>0) /* (big|small) endian correct? */
1739 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1740 return;
1743 * create a linked list with custom data
1745 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1747 MSFT_CDGuid entry;
1748 TLBCustData* pNew;
1749 int count=0;
1751 TRACE_(typelib)("\n");
1753 while(offset >=0){
1754 count++;
1755 pNew=TLB_Alloc(sizeof(TLBCustData));
1756 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1757 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1758 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1759 /* add new custom data at head of the list */
1760 pNew->next=*ppCustData;
1761 *ppCustData=pNew;
1762 offset = entry.next;
1764 return count;
1767 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1768 ITypeInfoImpl *pTI)
1770 if(type <0)
1771 pTd->vt=type & VT_TYPEMASK;
1772 else
1773 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1775 if(pTd->vt == VT_USERDEFINED)
1776 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1778 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1781 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1783 /* resolve referenced type if any */
1784 while (lpTypeDesc)
1786 switch (lpTypeDesc->vt)
1788 case VT_PTR:
1789 lpTypeDesc = lpTypeDesc->u.lptdesc;
1790 break;
1792 case VT_CARRAY:
1793 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1794 break;
1796 case VT_USERDEFINED:
1797 MSFT_DoRefType(pcx, pTI->pTypeLib,
1798 lpTypeDesc->u.hreftype);
1800 lpTypeDesc = NULL;
1801 break;
1803 default:
1804 lpTypeDesc = NULL;
1809 static void
1810 MSFT_DoFuncs(TLBContext* pcx,
1811 ITypeInfoImpl* pTI,
1812 int cFuncs,
1813 int cVars,
1814 int offset,
1815 TLBFuncDesc** pptfd)
1818 * member information is stored in a data structure at offset
1819 * indicated by the memoffset field of the typeinfo structure
1820 * There are several distinctive parts.
1821 * The first part starts with a field that holds the total length
1822 * of this (first) part excluding this field. Then follow the records,
1823 * for each member there is one record.
1825 * The first entry is always the length of the record (including this
1826 * length word).
1827 * The rest of the record depends on the type of the member. If there is
1828 * a field indicating the member type (function, variable, interface, etc)
1829 * I have not found it yet. At this time we depend on the information
1830 * in the type info and the usual order how things are stored.
1832 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1833 * for each member;
1835 * Third is an equal sized array with file offsets to the name entry
1836 * of each member.
1838 * The fourth and last (?) part is an array with offsets to the records
1839 * in the first part of this file segment.
1842 int infolen, nameoffset, reclength, nrattributes, i;
1843 int recoffset = offset + sizeof(INT);
1845 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1846 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1847 TLBFuncDesc *ptfd_prev = NULL;
1849 TRACE_(typelib)("\n");
1851 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1853 for ( i = 0; i < cFuncs ; i++ )
1855 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1857 /* name, eventually add to a hash table */
1858 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1859 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1861 /* nameoffset is sometimes -1 on the second half of a propget/propput
1862 * pair of functions */
1863 if ((nameoffset == -1) && (i > 0))
1864 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1865 else
1866 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1868 /* read the function information record */
1869 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1871 reclength &= 0xffff;
1873 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1875 /* do the attributes */
1876 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1877 / sizeof(int);
1879 if ( nrattributes > 0 )
1881 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1883 if ( nrattributes > 1 )
1885 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1886 pFuncRec->OptAttr[1]) ;
1888 if ( nrattributes > 2 )
1890 if ( pFuncRec->FKCCIC & 0x2000 )
1892 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1893 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1894 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1896 else
1898 (*pptfd)->Entry = MSFT_ReadString(pcx,
1899 pFuncRec->OptAttr[2]);
1901 if( nrattributes > 5 )
1903 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1905 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1907 MSFT_CustData(pcx,
1908 pFuncRec->OptAttr[6],
1909 &(*pptfd)->pCustData);
1913 else
1915 (*pptfd)->Entry = (BSTR)-1;
1920 /* fill the FuncDesc Structure */
1921 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1922 offset + infolen + ( i + 1) * sizeof(INT));
1924 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1925 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1926 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1927 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1928 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1929 (*pptfd)->funcdesc.oVft = (pFuncRec->VtableOffset * sizeof(void *))/4;
1930 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1932 MSFT_GetTdesc(pcx,
1933 pFuncRec->DataType,
1934 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1935 pTI);
1936 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1938 /* do the parameters/arguments */
1939 if(pFuncRec->nrargs)
1941 int j = 0;
1942 MSFT_ParameterInfo paraminfo;
1944 (*pptfd)->funcdesc.lprgelemdescParam =
1945 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1947 (*pptfd)->pParamDesc =
1948 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1950 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1951 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1953 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1955 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1957 MSFT_GetTdesc(pcx,
1958 paraminfo.DataType,
1959 &elemdesc->tdesc,
1960 pTI);
1962 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1964 /* name */
1965 if (paraminfo.oName == -1)
1966 /* this occurs for [propput] or [propget] methods, so
1967 * we should just set the name of the parameter to the
1968 * name of the method. */
1969 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1970 else
1971 (*pptfd)->pParamDesc[j].Name =
1972 MSFT_ReadName( pcx, paraminfo.oName );
1973 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1975 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1977 /* default value */
1978 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1979 (pFuncRec->FKCCIC & 0x1000) )
1981 INT* pInt = (INT *)((char *)pFuncRec +
1982 reclength -
1983 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1985 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1987 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1988 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1990 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1991 pInt[j], pcx);
1993 else
1994 elemdesc->u.paramdesc.pparamdescex = NULL;
1995 /* custom info */
1996 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1998 MSFT_CustData(pcx,
1999 pFuncRec->OptAttr[7+j],
2000 &(*pptfd)->pParamDesc[j].pCustData);
2003 /* SEEK value = jump to offset,
2004 * from there jump to the end of record,
2005 * go back by (j-1) arguments
2007 MSFT_ReadLEDWords( &paraminfo ,
2008 sizeof(MSFT_ParameterInfo), pcx,
2009 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2010 * sizeof(MSFT_ParameterInfo)));
2014 /* scode is not used: archaic win16 stuff FIXME: right? */
2015 (*pptfd)->funcdesc.cScodes = 0 ;
2016 (*pptfd)->funcdesc.lprgscode = NULL ;
2018 ptfd_prev = *pptfd;
2019 pptfd = & ((*pptfd)->next);
2020 recoffset += reclength;
2022 HeapFree(GetProcessHeap(), 0, recbuf);
2025 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2026 int cVars, int offset, TLBVarDesc ** pptvd)
2028 int infolen, nameoffset, reclength;
2029 char recbuf[256];
2030 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2031 int i;
2032 int recoffset;
2034 TRACE_(typelib)("\n");
2036 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2037 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2038 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2039 recoffset += offset+sizeof(INT);
2040 for(i=0;i<cVars;i++){
2041 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2042 /* name, eventually add to a hash table */
2043 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2044 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2045 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2046 /* read the variable information record */
2047 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2048 reclength &=0xff;
2049 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2050 /* Optional data */
2051 if(reclength >(6*sizeof(INT)) )
2052 (*pptvd)->HelpContext=pVarRec->HelpContext;
2053 if(reclength >(7*sizeof(INT)) )
2054 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2055 if(reclength >(8*sizeof(INT)) )
2056 if(reclength >(9*sizeof(INT)) )
2057 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2058 /* fill the VarDesc Structure */
2059 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2060 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2061 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2062 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2063 MSFT_GetTdesc(pcx, pVarRec->DataType,
2064 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2065 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2066 if(pVarRec->VarKind == VAR_CONST ){
2067 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2068 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2069 pVarRec->OffsValue, pcx);
2070 } else
2071 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2072 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2073 pptvd=&((*pptvd)->next);
2074 recoffset += reclength;
2077 /* fill in data for a hreftype (offset). When the referenced type is contained
2078 * in the typelib, it's just an (file) offset in the type info base dir.
2079 * If comes from import, it's an offset+1 in the ImpInfo table
2080 * */
2081 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2082 int offset)
2084 TLBRefType *ref;
2086 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2088 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2090 if(ref->reference == offset) return;
2093 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2094 list_add_tail(&pTL->ref_list, &ref->entry);
2096 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2097 /* external typelib */
2098 MSFT_ImpInfo impinfo;
2099 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2101 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2103 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2104 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2105 while (pImpLib){ /* search the known offsets of all import libraries */
2106 if(pImpLib->offset==impinfo.oImpFile) break;
2107 pImpLib=pImpLib->next;
2109 if(pImpLib){
2110 ref->reference = offset;
2111 ref->pImpTLInfo = pImpLib;
2112 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2113 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2114 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2115 ref->index = TLB_REF_USE_GUID;
2116 } else
2117 ref->index = impinfo.oGuid;
2118 }else{
2119 ERR("Cannot find a reference\n");
2120 ref->reference = -1;
2121 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2123 }else{
2124 /* in this typelib */
2125 ref->index = MSFT_HREFTYPE_INDEX(offset);
2126 ref->reference = offset;
2127 ref->pImpTLInfo = TLB_REF_INTERNAL;
2131 /* process Implemented Interfaces of a com class */
2132 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2133 int offset)
2135 int i;
2136 MSFT_RefRecord refrec;
2137 TLBImplType **ppImpl = &pTI->impltypelist;
2139 TRACE_(typelib)("\n");
2141 for(i=0;i<count;i++){
2142 if(offset<0) break; /* paranoia */
2143 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2144 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2145 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2146 (*ppImpl)->hRef = refrec.reftype;
2147 (*ppImpl)->implflags=refrec.flags;
2148 (*ppImpl)->ctCustData=
2149 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2150 offset=refrec.onext;
2151 ppImpl=&((*ppImpl)->next);
2155 * process a typeinfo record
2157 static ITypeInfoImpl * MSFT_DoTypeInfo(
2158 TLBContext *pcx,
2159 int count,
2160 ITypeLibImpl * pLibInfo)
2162 MSFT_TypeInfoBase tiBase;
2163 ITypeInfoImpl *ptiRet;
2165 TRACE_(typelib)("count=%u\n", count);
2167 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2168 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2169 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2171 /* this is where we are coming from */
2172 ptiRet->pTypeLib = pLibInfo;
2173 ptiRet->index=count;
2174 /* fill in the typeattr fields */
2176 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2177 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2178 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2179 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2180 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2181 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2182 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2183 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2184 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2185 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2186 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2187 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2188 ptiRet->TypeAttr.cbSizeVft=(tiBase.cbSizeVft * sizeof(void *))/4; /* FIXME: this is only the non inherited part */
2189 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2190 MSFT_GetTdesc(pcx, tiBase.datatype1,
2191 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2193 /* FIXME: */
2194 /* IDLDESC idldescType; *//* never saw this one != zero */
2196 /* name, eventually add to a hash table */
2197 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2198 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2199 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2200 /* help info */
2201 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2202 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2203 ptiRet->dwHelpContext=tiBase.helpcontext;
2205 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2206 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2208 /* note: InfoType's Help file and HelpStringDll come from the containing
2209 * library. Further HelpString and Docstring appear to be the same thing :(
2211 /* functions */
2212 if(ptiRet->TypeAttr.cFuncs >0 )
2213 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2214 ptiRet->TypeAttr.cVars,
2215 tiBase.memoffset, & ptiRet->funclist);
2216 /* variables */
2217 if(ptiRet->TypeAttr.cVars >0 )
2218 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2219 ptiRet->TypeAttr.cVars,
2220 tiBase.memoffset, & ptiRet->varlist);
2221 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2222 switch(ptiRet->TypeAttr.typekind)
2224 case TKIND_COCLASS:
2225 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2226 tiBase.datatype1);
2227 break;
2228 case TKIND_DISPATCH:
2229 /* This is not -1 when the interface is a non-base dual interface or
2230 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2231 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2232 not this interface.
2235 if (tiBase.datatype1 != -1)
2237 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2238 ptiRet->impltypelist->hRef = tiBase.datatype1;
2239 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2241 break;
2242 default:
2243 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2244 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2245 ptiRet->impltypelist->hRef = tiBase.datatype1;
2246 break;
2249 ptiRet->ctCustData=
2250 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2252 TRACE_(typelib)("%s guid: %s kind:%s\n",
2253 debugstr_w(ptiRet->Name),
2254 debugstr_guid(&ptiRet->TypeAttr.guid),
2255 typekind_desc[ptiRet->TypeAttr.typekind]);
2256 if (TRACE_ON(typelib))
2257 dump_TypeInfo(ptiRet);
2259 return ptiRet;
2262 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2263 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2264 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2265 * tradeoff here.
2267 static ITypeLibImpl *tlb_cache_first;
2268 static CRITICAL_SECTION cache_section;
2269 static CRITICAL_SECTION_DEBUG cache_section_debug =
2271 0, 0, &cache_section,
2272 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2273 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2275 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2278 typedef struct TLB_PEFile
2280 const IUnknownVtbl *lpvtbl;
2281 LONG refs;
2282 HMODULE dll;
2283 HRSRC typelib_resource;
2284 HGLOBAL typelib_global;
2285 LPVOID typelib_base;
2286 } TLB_PEFile;
2288 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2290 if (IsEqualIID(riid, &IID_IUnknown))
2292 *ppv = iface;
2293 IUnknown_AddRef(iface);
2294 return S_OK;
2296 *ppv = NULL;
2297 return E_NOINTERFACE;
2300 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2302 TLB_PEFile *This = (TLB_PEFile *)iface;
2303 return InterlockedIncrement(&This->refs);
2306 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2308 TLB_PEFile *This = (TLB_PEFile *)iface;
2309 ULONG refs = InterlockedDecrement(&This->refs);
2310 if (!refs)
2312 if (This->typelib_global)
2313 FreeResource(This->typelib_global);
2314 if (This->dll)
2315 FreeLibrary(This->dll);
2316 HeapFree(GetProcessHeap(), 0, This);
2318 return refs;
2321 static const IUnknownVtbl TLB_PEFile_Vtable =
2323 TLB_PEFile_QueryInterface,
2324 TLB_PEFile_AddRef,
2325 TLB_PEFile_Release
2328 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2330 TLB_PEFile *This;
2332 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2333 if (!This)
2334 return E_OUTOFMEMORY;
2336 This->lpvtbl = &TLB_PEFile_Vtable;
2337 This->refs = 1;
2338 This->dll = NULL;
2339 This->typelib_resource = NULL;
2340 This->typelib_global = NULL;
2341 This->typelib_base = NULL;
2343 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2344 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2346 if (This->dll)
2348 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2349 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2350 if (This->typelib_resource)
2352 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2353 if (This->typelib_global)
2355 This->typelib_base = LockResource(This->typelib_global);
2357 if (This->typelib_base)
2359 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2360 *ppBase = This->typelib_base;
2361 *ppFile = (IUnknown *)&This->lpvtbl;
2362 return S_OK;
2368 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2369 return TYPE_E_CANTLOADLIBRARY;
2372 typedef struct TLB_NEFile
2374 const IUnknownVtbl *lpvtbl;
2375 LONG refs;
2376 LPVOID typelib_base;
2377 } TLB_NEFile;
2379 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2381 if (IsEqualIID(riid, &IID_IUnknown))
2383 *ppv = iface;
2384 IUnknown_AddRef(iface);
2385 return S_OK;
2387 *ppv = NULL;
2388 return E_NOINTERFACE;
2391 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2393 TLB_NEFile *This = (TLB_NEFile *)iface;
2394 return InterlockedIncrement(&This->refs);
2397 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2399 TLB_NEFile *This = (TLB_NEFile *)iface;
2400 ULONG refs = InterlockedDecrement(&This->refs);
2401 if (!refs)
2403 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2404 HeapFree(GetProcessHeap(), 0, This);
2406 return refs;
2409 static const IUnknownVtbl TLB_NEFile_Vtable =
2411 TLB_NEFile_QueryInterface,
2412 TLB_NEFile_AddRef,
2413 TLB_NEFile_Release
2416 /***********************************************************************
2417 * read_xx_header [internal]
2419 static int read_xx_header( HFILE lzfd )
2421 IMAGE_DOS_HEADER mzh;
2422 char magic[3];
2424 LZSeek( lzfd, 0, SEEK_SET );
2425 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2426 return 0;
2427 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2428 return 0;
2430 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2431 if ( 2 != LZRead( lzfd, magic, 2 ) )
2432 return 0;
2434 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2436 if ( magic[0] == 'N' && magic[1] == 'E' )
2437 return IMAGE_OS2_SIGNATURE;
2438 if ( magic[0] == 'P' && magic[1] == 'E' )
2439 return IMAGE_NT_SIGNATURE;
2441 magic[2] = '\0';
2442 WARN("Can't handle %s files.\n", magic );
2443 return 0;
2447 /***********************************************************************
2448 * find_ne_resource [internal]
2450 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2451 DWORD *resLen, DWORD *resOff )
2453 IMAGE_OS2_HEADER nehd;
2454 NE_TYPEINFO *typeInfo;
2455 NE_NAMEINFO *nameInfo;
2456 DWORD nehdoffset;
2457 LPBYTE resTab;
2458 DWORD resTabSize;
2459 int count;
2461 /* Read in NE header */
2462 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2463 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2465 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2466 if ( !resTabSize )
2468 TRACE("No resources in NE dll\n" );
2469 return FALSE;
2472 /* Read in resource table */
2473 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2474 if ( !resTab ) return FALSE;
2476 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2477 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2479 HeapFree( GetProcessHeap(), 0, resTab );
2480 return FALSE;
2483 /* Find resource */
2484 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2486 if (HIWORD(typeid) != 0) /* named type */
2488 BYTE len = strlen( typeid );
2489 while (typeInfo->type_id)
2491 if (!(typeInfo->type_id & 0x8000))
2493 BYTE *p = resTab + typeInfo->type_id;
2494 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2496 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2497 typeInfo->count * sizeof(NE_NAMEINFO));
2500 else /* numeric type id */
2502 WORD id = LOWORD(typeid) | 0x8000;
2503 while (typeInfo->type_id)
2505 if (typeInfo->type_id == id) goto found_type;
2506 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2507 typeInfo->count * sizeof(NE_NAMEINFO));
2510 TRACE("No typeid entry found for %p\n", typeid );
2511 HeapFree( GetProcessHeap(), 0, resTab );
2512 return FALSE;
2514 found_type:
2515 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2517 if (HIWORD(resid) != 0) /* named resource */
2519 BYTE len = strlen( resid );
2520 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2522 BYTE *p = resTab + nameInfo->id;
2523 if (nameInfo->id & 0x8000) continue;
2524 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2527 else /* numeric resource id */
2529 WORD id = LOWORD(resid) | 0x8000;
2530 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2531 if (nameInfo->id == id) goto found_name;
2533 TRACE("No resid entry found for %p\n", typeid );
2534 HeapFree( GetProcessHeap(), 0, resTab );
2535 return FALSE;
2537 found_name:
2538 /* Return resource data */
2539 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2540 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2542 HeapFree( GetProcessHeap(), 0, resTab );
2543 return TRUE;
2546 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2548 HFILE lzfd = -1;
2549 OFSTRUCT ofs;
2550 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2551 TLB_NEFile *This = NULL;
2553 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2554 if (!This) return E_OUTOFMEMORY;
2556 This->lpvtbl = &TLB_NEFile_Vtable;
2557 This->refs = 1;
2558 This->typelib_base = NULL;
2560 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2561 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2563 DWORD reslen, offset;
2564 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2566 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2567 if( !This->typelib_base )
2568 hr = E_OUTOFMEMORY;
2569 else
2571 LZSeek( lzfd, offset, SEEK_SET );
2572 reslen = LZRead( lzfd, This->typelib_base, reslen );
2573 LZClose( lzfd );
2574 *ppBase = This->typelib_base;
2575 *pdwTLBLength = reslen;
2576 *ppFile = (IUnknown *)&This->lpvtbl;
2577 return S_OK;
2582 if( lzfd >= 0) LZClose( lzfd );
2583 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2584 return hr;
2587 typedef struct TLB_Mapping
2589 const IUnknownVtbl *lpvtbl;
2590 LONG refs;
2591 HANDLE file;
2592 HANDLE mapping;
2593 LPVOID typelib_base;
2594 } TLB_Mapping;
2596 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2598 if (IsEqualIID(riid, &IID_IUnknown))
2600 *ppv = iface;
2601 IUnknown_AddRef(iface);
2602 return S_OK;
2604 *ppv = NULL;
2605 return E_NOINTERFACE;
2608 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2610 TLB_Mapping *This = (TLB_Mapping *)iface;
2611 return InterlockedIncrement(&This->refs);
2614 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2616 TLB_Mapping *This = (TLB_Mapping *)iface;
2617 ULONG refs = InterlockedDecrement(&This->refs);
2618 if (!refs)
2620 if (This->typelib_base)
2621 UnmapViewOfFile(This->typelib_base);
2622 if (This->mapping)
2623 CloseHandle(This->mapping);
2624 if (This->file != INVALID_HANDLE_VALUE)
2625 CloseHandle(This->file);
2626 HeapFree(GetProcessHeap(), 0, This);
2628 return refs;
2631 static const IUnknownVtbl TLB_Mapping_Vtable =
2633 TLB_Mapping_QueryInterface,
2634 TLB_Mapping_AddRef,
2635 TLB_Mapping_Release
2638 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2640 TLB_Mapping *This;
2642 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2643 if (!This)
2644 return E_OUTOFMEMORY;
2646 This->lpvtbl = &TLB_Mapping_Vtable;
2647 This->refs = 1;
2648 This->file = INVALID_HANDLE_VALUE;
2649 This->mapping = NULL;
2650 This->typelib_base = NULL;
2652 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2653 if (INVALID_HANDLE_VALUE != This->file)
2655 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2656 if (This->mapping)
2658 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2659 if(This->typelib_base)
2661 /* retrieve file size */
2662 *pdwTLBLength = GetFileSize(This->file, NULL);
2663 *ppBase = This->typelib_base;
2664 *ppFile = (IUnknown *)&This->lpvtbl;
2665 return S_OK;
2670 IUnknown_Release((IUnknown *)&This->lpvtbl);
2671 return TYPE_E_CANTLOADLIBRARY;
2674 /****************************************************************************
2675 * TLB_ReadTypeLib
2677 * find the type of the typelib file and map the typelib resource into
2678 * the memory
2680 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2681 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2682 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2684 ITypeLibImpl *entry;
2685 HRESULT ret;
2686 INT index = 1;
2687 LPWSTR index_str, file = (LPWSTR)pszFileName;
2688 LPVOID pBase = NULL;
2689 DWORD dwTLBLength = 0;
2690 IUnknown *pFile = NULL;
2692 *ppTypeLib = NULL;
2694 index_str = strrchrW(pszFileName, '\\');
2695 if(index_str && *++index_str != '\0')
2697 LPWSTR end_ptr;
2698 long idx = strtolW(index_str, &end_ptr, 10);
2699 if(*end_ptr == '\0')
2701 int str_len = index_str - pszFileName - 1;
2702 index = idx;
2703 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2704 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2705 file[str_len] = 0;
2709 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2711 if(strchrW(file, '\\'))
2713 lstrcpyW(pszPath, file);
2715 else
2717 int len = GetSystemDirectoryW(pszPath, cchPath);
2718 pszPath[len] = '\\';
2719 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2723 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2725 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2727 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2728 EnterCriticalSection(&cache_section);
2729 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2731 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2733 TRACE("cache hit\n");
2734 *ppTypeLib = (ITypeLib2*)entry;
2735 ITypeLib_AddRef(*ppTypeLib);
2736 LeaveCriticalSection(&cache_section);
2737 return S_OK;
2740 LeaveCriticalSection(&cache_section);
2742 /* now actually load and parse the typelib */
2744 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2745 if (ret == TYPE_E_CANTLOADLIBRARY)
2746 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2747 if (ret == TYPE_E_CANTLOADLIBRARY)
2748 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2749 if (SUCCEEDED(ret))
2751 if (dwTLBLength >= 4)
2753 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2754 if (dwSignature == MSFT_SIGNATURE)
2755 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2756 else if (dwSignature == SLTG_SIGNATURE)
2757 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2758 else
2760 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2761 ret = TYPE_E_CANTLOADLIBRARY;
2764 else
2765 ret = TYPE_E_CANTLOADLIBRARY;
2766 IUnknown_Release(pFile);
2769 if(*ppTypeLib) {
2770 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2772 TRACE("adding to cache\n");
2773 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2774 lstrcpyW(impl->path, pszPath);
2775 /* We should really canonicalise the path here. */
2776 impl->index = index;
2778 /* FIXME: check if it has added already in the meantime */
2779 EnterCriticalSection(&cache_section);
2780 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2781 impl->prev = NULL;
2782 tlb_cache_first = impl;
2783 LeaveCriticalSection(&cache_section);
2784 ret = S_OK;
2785 } else
2786 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2788 return ret;
2791 /*================== ITypeLib(2) Methods ===================================*/
2793 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2795 ITypeLibImpl* pTypeLibImpl;
2797 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2798 if (!pTypeLibImpl) return NULL;
2800 pTypeLibImpl->lpVtbl = &tlbvt;
2801 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2802 pTypeLibImpl->ref = 1;
2804 list_init(&pTypeLibImpl->ref_list);
2805 pTypeLibImpl->dispatch_href = -1;
2807 return pTypeLibImpl;
2810 /****************************************************************************
2811 * ITypeLib2_Constructor_MSFT
2813 * loading an MSFT typelib from an in-memory image
2815 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2817 TLBContext cx;
2818 long lPSegDir;
2819 MSFT_Header tlbHeader;
2820 MSFT_SegDir tlbSegDir;
2821 ITypeLibImpl * pTypeLibImpl;
2823 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2825 pTypeLibImpl = TypeLibImpl_Constructor();
2826 if (!pTypeLibImpl) return NULL;
2828 /* get pointer to beginning of typelib data */
2829 cx.pos = 0;
2830 cx.oStart=0;
2831 cx.mapping = pLib;
2832 cx.pLibInfo = pTypeLibImpl;
2833 cx.length = dwTLBLength;
2835 /* read header */
2836 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2837 TRACE_(typelib)("header:\n");
2838 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2839 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2840 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2841 return NULL;
2843 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2845 /* there is a small amount of information here until the next important
2846 * part:
2847 * the segment directory . Try to calculate the amount of data */
2848 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2850 /* now read the segment directory */
2851 TRACE("read segment directory (at %ld)\n",lPSegDir);
2852 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2853 cx.pTblDir = &tlbSegDir;
2855 /* just check two entries */
2856 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2858 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2859 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2860 return NULL;
2863 /* now fill our internal data */
2864 /* TLIBATTR fields */
2865 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2867 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2868 /* Windows seems to have zero here, is this correct? */
2869 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2870 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2871 else
2872 pTypeLibImpl->LibAttr.lcid = 0;
2874 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2875 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2876 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2877 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2879 /* name, eventually add to a hash table */
2880 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2882 /* help info */
2883 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2884 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2886 if( tlbHeader.varflags & HELPDLLFLAG)
2888 int offset;
2889 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2890 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2893 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2895 /* custom data */
2896 if(tlbHeader.CustomDataOffset >= 0)
2898 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2901 /* fill in type descriptions */
2902 if(tlbSegDir.pTypdescTab.length > 0)
2904 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2905 INT16 td[4];
2906 pTypeLibImpl->ctTypeDesc = cTD;
2907 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2908 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2909 for(i=0; i<cTD; )
2911 /* FIXME: add several sanity checks here */
2912 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2913 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2915 /* FIXME: check safearray */
2916 if(td[3] < 0)
2917 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2918 else
2919 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2921 else if(td[0] == VT_CARRAY)
2923 /* array descr table here */
2924 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2926 else if(td[0] == VT_USERDEFINED)
2928 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2930 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2933 /* second time around to fill the array subscript info */
2934 for(i=0;i<cTD;i++)
2936 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2937 if(tlbSegDir.pArrayDescriptions.offset>0)
2939 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2940 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2942 if(td[1]<0)
2943 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2944 else
2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2947 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2949 for(j = 0; j<td[2]; j++)
2951 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2952 sizeof(INT), &cx, DO_NOT_SEEK);
2953 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2954 sizeof(INT), &cx, DO_NOT_SEEK);
2957 else
2959 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2960 ERR("didn't find array description data\n");
2965 /* imported type libs */
2966 if(tlbSegDir.pImpFiles.offset>0)
2968 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2969 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2970 UINT16 size;
2972 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2974 char *name;
2976 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2977 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2978 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2980 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2981 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2982 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2983 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2985 size >>= 2;
2986 name = TLB_Alloc(size+1);
2987 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2988 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2990 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2991 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2993 ppImpLib = &(*ppImpLib)->next;
2997 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2998 if(pTypeLibImpl->dispatch_href != -1)
2999 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3001 /* type info's */
3002 if(tlbHeader.nrtypeinfos >= 0 )
3004 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3005 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3006 int i;
3008 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3010 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3012 ppTI = &((*ppTI)->next);
3013 (pTypeLibImpl->TypeInfoCount)++;
3017 TRACE("(%p)\n", pTypeLibImpl);
3018 return (ITypeLib2*) pTypeLibImpl;
3022 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3024 char b[3];
3025 int i;
3026 short s;
3028 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3029 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3030 return FALSE;
3033 guid->Data4[0] = s >> 8;
3034 guid->Data4[1] = s & 0xff;
3036 b[2] = '\0';
3037 for(i = 0; i < 6; i++) {
3038 memcpy(b, str + 24 + 2 * i, 2);
3039 guid->Data4[i + 2] = strtol(b, NULL, 16);
3041 return TRUE;
3044 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3046 WORD bytelen;
3047 DWORD len;
3049 *pBstr = NULL;
3050 bytelen = *(const WORD*)ptr;
3051 if(bytelen == 0xffff) return 2;
3052 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3053 *pBstr = SysAllocStringLen(NULL, len - 1);
3054 if (*pBstr)
3055 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3056 return bytelen + 2;
3059 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3061 WORD bytelen;
3063 *str = NULL;
3064 bytelen = *(const WORD*)ptr;
3065 if(bytelen == 0xffff) return 2;
3066 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3067 memcpy(*str, ptr + 2, bytelen);
3068 (*str)[bytelen] = '\0';
3069 return bytelen + 2;
3072 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3074 char *ptr = pLibBlk;
3075 WORD w;
3077 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3078 FIXME("libblk magic = %04x\n", w);
3079 return 0;
3082 ptr += 6;
3083 if((w = *(WORD*)ptr) != 0xffff) {
3084 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3085 ptr += w;
3087 ptr += 2;
3089 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3091 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3093 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3094 ptr += 4;
3096 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3097 ptr += 2;
3099 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3100 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3101 else
3102 pTypeLibImpl->LibAttr.lcid = 0;
3103 ptr += 2;
3105 ptr += 4; /* skip res12 */
3107 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3108 ptr += 2;
3110 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3111 ptr += 2;
3113 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3114 ptr += 2;
3116 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3117 ptr += sizeof(GUID);
3119 return ptr - (char*)pLibBlk;
3122 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3123 typedef struct
3125 unsigned int num;
3126 HREFTYPE refs[1];
3127 } sltg_ref_lookup_t;
3129 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3130 HREFTYPE *typelib_ref)
3132 if(typeinfo_ref < table->num)
3134 *typelib_ref = table->refs[typeinfo_ref];
3135 return S_OK;
3138 ERR_(typelib)("Unable to find reference\n");
3139 *typelib_ref = -1;
3140 return E_FAIL;
3143 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3145 BOOL done = FALSE;
3147 while(!done) {
3148 if((*pType & 0xe00) == 0xe00) {
3149 pTD->vt = VT_PTR;
3150 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3151 sizeof(TYPEDESC));
3152 pTD = pTD->u.lptdesc;
3154 switch(*pType & 0x3f) {
3155 case VT_PTR:
3156 pTD->vt = VT_PTR;
3157 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3158 sizeof(TYPEDESC));
3159 pTD = pTD->u.lptdesc;
3160 break;
3162 case VT_USERDEFINED:
3163 pTD->vt = VT_USERDEFINED;
3164 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3165 done = TRUE;
3166 break;
3168 case VT_CARRAY:
3170 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3171 array */
3173 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3175 pTD->vt = VT_CARRAY;
3176 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3177 sizeof(ARRAYDESC) +
3178 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3179 pTD->u.lpadesc->cDims = pSA->cDims;
3180 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3181 pSA->cDims * sizeof(SAFEARRAYBOUND));
3183 pTD = &pTD->u.lpadesc->tdescElem;
3184 break;
3187 case VT_SAFEARRAY:
3189 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3190 useful? */
3192 pType++;
3193 pTD->vt = VT_SAFEARRAY;
3194 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3195 sizeof(TYPEDESC));
3196 pTD = pTD->u.lptdesc;
3197 break;
3199 default:
3200 pTD->vt = *pType & 0x3f;
3201 done = TRUE;
3202 break;
3204 pType++;
3206 return pType;
3209 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3210 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3212 /* Handle [in/out] first */
3213 if((*pType & 0xc000) == 0xc000)
3214 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3215 else if(*pType & 0x8000)
3216 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3217 else if(*pType & 0x4000)
3218 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3219 else
3220 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3222 if(*pType & 0x2000)
3223 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3225 if(*pType & 0x80)
3226 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3228 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3232 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3233 char *pNameTable)
3235 unsigned int ref;
3236 char *name;
3237 TLBRefType *ref_type;
3238 sltg_ref_lookup_t *table;
3239 HREFTYPE typelib_ref;
3241 if(pRef->magic != SLTG_REF_MAGIC) {
3242 FIXME("Ref magic = %x\n", pRef->magic);
3243 return NULL;
3245 name = ( (char*)pRef->names + pRef->number);
3247 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3248 table->num = pRef->number >> 3;
3250 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3252 /* We don't want the first href to be 0 */
3253 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3255 for(ref = 0; ref < pRef->number >> 3; ref++) {
3256 char *refname;
3257 unsigned int lib_offs, type_num;
3259 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3261 name += SLTG_ReadStringA(name, &refname);
3262 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3263 FIXME_(typelib)("Can't sscanf ref\n");
3264 if(lib_offs != 0xffff) {
3265 TLBImpLib **import = &pTL->pImpLibs;
3267 while(*import) {
3268 if((*import)->offset == lib_offs)
3269 break;
3270 import = &(*import)->next;
3272 if(!*import) {
3273 char fname[MAX_PATH+1];
3274 int len;
3276 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3277 sizeof(**import));
3278 (*import)->offset = lib_offs;
3279 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3280 &(*import)->guid);
3281 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3282 &(*import)->wVersionMajor,
3283 &(*import)->wVersionMinor,
3284 &(*import)->lcid, fname) != 4) {
3285 FIXME_(typelib)("can't sscanf ref %s\n",
3286 pNameTable + lib_offs + 40);
3288 len = strlen(fname);
3289 if(fname[len-1] != '#')
3290 FIXME("fname = %s\n", fname);
3291 fname[len-1] = '\0';
3292 (*import)->name = TLB_MultiByteToBSTR(fname);
3294 ref_type->pImpTLInfo = *import;
3296 /* Store a reference to IDispatch */
3297 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3298 pTL->dispatch_href = typelib_ref;
3300 } else { /* internal ref */
3301 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3303 ref_type->reference = typelib_ref;
3304 ref_type->index = type_num;
3306 HeapFree(GetProcessHeap(), 0, refname);
3307 list_add_tail(&pTL->ref_list, &ref_type->entry);
3309 table->refs[ref] = typelib_ref;
3310 typelib_ref += 4;
3312 if((BYTE)*name != SLTG_REF_MAGIC)
3313 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3314 dump_TLBRefType(pTL);
3315 return table;
3318 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3319 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3321 SLTG_ImplInfo *info;
3322 TLBImplType **ppImplType = &pTI->impltypelist;
3323 /* I don't really get this structure, usually it's 0x16 bytes
3324 long, but iuser.tlb contains some that are 0x18 bytes long.
3325 That's ok because we can use the next ptr to jump to the next
3326 one. But how do we know the length of the last one? The WORD
3327 at offs 0x8 might be the clue. For now I'm just assuming that
3328 the last one is the regular 0x16 bytes. */
3330 info = (SLTG_ImplInfo*)pBlk;
3331 while(1) {
3332 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3333 sizeof(**ppImplType));
3334 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3335 (*ppImplType)->implflags = info->impltypeflags;
3336 pTI->TypeAttr.cImplTypes++;
3337 ppImplType = &(*ppImplType)->next;
3339 if(info->next == 0xffff)
3340 break;
3341 if(OneOnly)
3342 FIXME_(typelib)("Interface inheriting more than one interface\n");
3343 info = (SLTG_ImplInfo*)(pBlk + info->next);
3345 info++; /* see comment at top of function */
3346 return (char*)info;
3349 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3350 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3352 TLBVarDesc **ppVarDesc = &pTI->varlist;
3353 BSTR bstrPrevName = NULL;
3354 SLTG_Variable *pItem;
3355 unsigned short i;
3356 WORD *pType;
3358 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3359 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3361 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3362 sizeof(**ppVarDesc));
3363 (*ppVarDesc)->vardesc.memid = pItem->memid;
3365 if (pItem->magic != SLTG_VAR_MAGIC &&
3366 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3367 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3368 return;
3371 if (pItem->name == 0xfffe)
3372 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3373 else
3374 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3376 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3377 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3378 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3380 if(pItem->flags & 0x02)
3381 pType = &pItem->type;
3382 else
3383 pType = (WORD*)(pBlk + pItem->type);
3385 if (pItem->flags & ~0xda)
3386 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3388 SLTG_DoElem(pType, pBlk,
3389 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3391 if (TRACE_ON(typelib)) {
3392 char buf[300];
3393 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3394 TRACE_(typelib)("elemdescVar: %s\n", buf);
3397 if (pItem->flags & 0x40) {
3398 TRACE_(typelib)("VAR_DISPATCH\n");
3399 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3401 else if (pItem->flags & 0x10) {
3402 TRACE_(typelib)("VAR_CONST\n");
3403 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3404 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3405 sizeof(VARIANT));
3406 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3407 if (pItem->flags & 0x08)
3408 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3409 else {
3410 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3412 case VT_LPSTR:
3413 case VT_LPWSTR:
3414 case VT_BSTR:
3416 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3417 BSTR str;
3418 TRACE_(typelib)("len = %u\n", len);
3419 if (len == 0xffff) {
3420 str = NULL;
3421 } else {
3422 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3423 str = SysAllocStringLen(NULL, alloc_len);
3424 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3426 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3427 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3428 break;
3430 case VT_I2:
3431 case VT_UI2:
3432 case VT_I4:
3433 case VT_UI4:
3434 case VT_INT:
3435 case VT_UINT:
3436 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3437 *(INT*)(pBlk + pItem->byte_offs);
3438 break;
3439 default:
3440 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3444 else {
3445 TRACE_(typelib)("VAR_PERINSTANCE\n");
3446 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3447 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3450 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3451 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3453 if (pItem->flags & 0x80)
3454 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3456 bstrPrevName = (*ppVarDesc)->Name;
3457 ppVarDesc = &((*ppVarDesc)->next);
3459 pTI->TypeAttr.cVars = cVars;
3462 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3463 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3465 SLTG_Function *pFunc;
3466 unsigned short i;
3467 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3469 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3470 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3472 int param;
3473 WORD *pType, *pArg;
3475 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3476 sizeof(**ppFuncDesc));
3478 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3479 case SLTG_FUNCTION_MAGIC:
3480 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3481 break;
3482 case SLTG_DISPATCH_FUNCTION_MAGIC:
3483 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3484 break;
3485 case SLTG_STATIC_FUNCTION_MAGIC:
3486 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3487 break;
3488 default:
3489 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3490 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3491 *ppFuncDesc = NULL;
3492 return;
3494 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3496 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3497 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3498 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3499 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3500 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3501 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3503 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3504 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3506 if(pFunc->retnextopt & 0x80)
3507 pType = &pFunc->rettype;
3508 else
3509 pType = (WORD*)(pBlk + pFunc->rettype);
3511 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3513 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3514 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3515 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3516 (*ppFuncDesc)->pParamDesc =
3517 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3518 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3520 pArg = (WORD*)(pBlk + pFunc->arg_off);
3522 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3523 char *paramName = pNameTable + *pArg;
3524 BOOL HaveOffs;
3525 /* If arg type follows then paramName points to the 2nd
3526 letter of the name, else the next WORD is an offset to
3527 the arg type and paramName points to the first letter.
3528 So let's take one char off paramName and see if we're
3529 pointing at an alpha-numeric char. However if *pArg is
3530 0xffff or 0xfffe then the param has no name, the former
3531 meaning that the next WORD is the type, the latter
3532 meaning that the next WORD is an offset to the type. */
3534 HaveOffs = FALSE;
3535 if(*pArg == 0xffff)
3536 paramName = NULL;
3537 else if(*pArg == 0xfffe) {
3538 paramName = NULL;
3539 HaveOffs = TRUE;
3541 else if(paramName[-1] && !isalnum(paramName[-1]))
3542 HaveOffs = TRUE;
3544 pArg++;
3546 if(HaveOffs) { /* the next word is an offset to type */
3547 pType = (WORD*)(pBlk + *pArg);
3548 SLTG_DoElem(pType, pBlk,
3549 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3550 pArg++;
3551 } else {
3552 if(paramName)
3553 paramName--;
3554 pArg = SLTG_DoElem(pArg, pBlk,
3555 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3558 /* Are we an optional param ? */
3559 if((*ppFuncDesc)->funcdesc.cParams - param <=
3560 (*ppFuncDesc)->funcdesc.cParamsOpt)
3561 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3563 if(paramName) {
3564 (*ppFuncDesc)->pParamDesc[param].Name =
3565 TLB_MultiByteToBSTR(paramName);
3566 } else {
3567 (*ppFuncDesc)->pParamDesc[param].Name =
3568 SysAllocString((*ppFuncDesc)->Name);
3572 ppFuncDesc = &((*ppFuncDesc)->next);
3573 if(pFunc->next == 0xffff) break;
3575 pTI->TypeAttr.cFuncs = cFuncs;
3578 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3579 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3580 SLTG_TypeInfoTail *pTITail)
3582 char *pFirstItem;
3583 sltg_ref_lookup_t *ref_lookup = NULL;
3585 if(pTIHeader->href_table != 0xffffffff) {
3586 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3587 pNameTable);
3590 pFirstItem = pBlk;
3592 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3593 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3595 HeapFree(GetProcessHeap(), 0, ref_lookup);
3599 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3600 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3601 const SLTG_TypeInfoTail *pTITail)
3603 char *pFirstItem;
3604 sltg_ref_lookup_t *ref_lookup = NULL;
3606 if(pTIHeader->href_table != 0xffffffff) {
3607 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3608 pNameTable);
3611 pFirstItem = pBlk;
3613 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3614 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3617 if (pTITail->funcs_off != 0xffff)
3618 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3620 HeapFree(GetProcessHeap(), 0, ref_lookup);
3622 if (TRACE_ON(typelib))
3623 dump_TLBFuncDesc(pTI->funclist);
3626 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3627 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3628 const SLTG_TypeInfoTail *pTITail)
3630 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3633 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3634 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3635 const SLTG_TypeInfoTail *pTITail)
3637 WORD *pType;
3638 sltg_ref_lookup_t *ref_lookup = NULL;
3640 if (pTITail->simple_alias) {
3641 /* if simple alias, no more processing required */
3642 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3643 return;
3646 if(pTIHeader->href_table != 0xffffffff) {
3647 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3648 pNameTable);
3651 /* otherwise it is an offset to a type */
3652 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3654 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3656 HeapFree(GetProcessHeap(), 0, ref_lookup);
3659 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3660 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3661 const SLTG_TypeInfoTail *pTITail)
3663 sltg_ref_lookup_t *ref_lookup = NULL;
3664 if (pTIHeader->href_table != 0xffffffff)
3665 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3666 pNameTable);
3668 if (pTITail->vars_off != 0xffff)
3669 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3671 if (pTITail->funcs_off != 0xffff)
3672 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3674 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3675 * of dispinterface functions including the IDispatch ones, so
3676 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3677 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3679 HeapFree(GetProcessHeap(), 0, ref_lookup);
3680 if (TRACE_ON(typelib))
3681 dump_TLBFuncDesc(pTI->funclist);
3684 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3685 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3686 const SLTG_TypeInfoTail *pTITail)
3688 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3691 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3692 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3693 const SLTG_TypeInfoTail *pTITail)
3695 sltg_ref_lookup_t *ref_lookup = NULL;
3696 if (pTIHeader->href_table != 0xffffffff)
3697 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3698 pNameTable);
3700 if (pTITail->vars_off != 0xffff)
3701 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3703 if (pTITail->funcs_off != 0xffff)
3704 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3705 HeapFree(GetProcessHeap(), 0, ref_lookup);
3706 if (TRACE_ON(typelib))
3707 dump_TypeInfo(pTI);
3710 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3711 managable copy of it into this */
3712 typedef struct {
3713 WORD small_no;
3714 char *index_name;
3715 char *other_name;
3716 WORD res1a;
3717 WORD name_offs;
3718 WORD more_bytes;
3719 char *extra;
3720 WORD res20;
3721 DWORD helpcontext;
3722 WORD res26;
3723 GUID uuid;
3724 } SLTG_InternalOtherTypeInfo;
3726 /****************************************************************************
3727 * ITypeLib2_Constructor_SLTG
3729 * loading a SLTG typelib from an in-memory image
3731 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3733 ITypeLibImpl *pTypeLibImpl;
3734 SLTG_Header *pHeader;
3735 SLTG_BlkEntry *pBlkEntry;
3736 SLTG_Magic *pMagic;
3737 SLTG_Index *pIndex;
3738 SLTG_Pad9 *pPad9;
3739 LPVOID pBlk, pFirstBlk;
3740 SLTG_LibBlk *pLibBlk;
3741 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3742 char *pAfterOTIBlks = NULL;
3743 char *pNameTable, *ptr;
3744 int i;
3745 DWORD len, order;
3746 ITypeInfoImpl **ppTypeInfoImpl;
3748 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3751 pTypeLibImpl = TypeLibImpl_Constructor();
3752 if (!pTypeLibImpl) return NULL;
3754 pHeader = pLib;
3756 TRACE_(typelib)("header:\n");
3757 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3758 pHeader->nrOfFileBlks );
3759 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3760 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3761 pHeader->SLTG_magic);
3762 return NULL;
3765 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3766 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3768 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3769 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3771 /* Next we have a magic block */
3772 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3774 /* Let's see if we're still in sync */
3775 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3776 sizeof(SLTG_COMPOBJ_MAGIC))) {
3777 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3778 return NULL;
3780 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3781 sizeof(SLTG_DIR_MAGIC))) {
3782 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3783 return NULL;
3786 pIndex = (SLTG_Index*)(pMagic+1);
3788 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3790 pFirstBlk = pPad9 + 1;
3792 /* We'll set up a ptr to the main library block, which is the last one. */
3794 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3795 pBlkEntry[order].next != 0;
3796 order = pBlkEntry[order].next - 1, i++) {
3797 pBlk = (char*)pBlk + pBlkEntry[order].len;
3799 pLibBlk = pBlk;
3801 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3803 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3804 interspersed */
3806 len += 0x40;
3808 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3810 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3811 sizeof(*pOtherTypeInfoBlks) *
3812 pTypeLibImpl->TypeInfoCount);
3815 ptr = (char*)pLibBlk + len;
3817 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3818 WORD w, extra;
3819 len = 0;
3821 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3823 w = *(WORD*)(ptr + 2);
3824 if(w != 0xffff) {
3825 len += w;
3826 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3827 w+1);
3828 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3829 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3831 w = *(WORD*)(ptr + 4 + len);
3832 if(w != 0xffff) {
3833 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3834 len += w;
3835 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3836 w+1);
3837 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3838 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3840 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3841 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3842 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3843 if(extra) {
3844 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3845 extra);
3846 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3847 len += extra;
3849 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3850 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3851 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3852 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3853 len += sizeof(SLTG_OtherTypeInfo);
3854 ptr += len;
3857 pAfterOTIBlks = ptr;
3859 /* Skip this WORD and get the next DWORD */
3860 len = *(DWORD*)(pAfterOTIBlks + 2);
3862 /* Now add this to pLibBLk look at what we're pointing at and
3863 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3864 dust and we should be pointing at the beginning of the name
3865 table */
3867 pNameTable = (char*)pLibBlk + len;
3869 switch(*(WORD*)pNameTable) {
3870 case 0xffff:
3871 break;
3872 case 0x0200:
3873 pNameTable += 0x20;
3874 break;
3875 default:
3876 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3877 break;
3880 pNameTable += 0x216;
3882 pNameTable += 2;
3884 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3886 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3889 /* Hopefully we now have enough ptrs set up to actually read in
3890 some TypeInfos. It's not clear which order to do them in, so
3891 I'll just follow the links along the BlkEntry chain and read
3892 them in the order in which they are in the file */
3894 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3896 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3897 pBlkEntry[order].next != 0;
3898 order = pBlkEntry[order].next - 1, i++) {
3900 SLTG_TypeInfoHeader *pTIHeader;
3901 SLTG_TypeInfoTail *pTITail;
3902 SLTG_MemberHeader *pMemHeader;
3904 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3905 pOtherTypeInfoBlks[i].index_name)) {
3906 FIXME_(typelib)("Index strings don't match\n");
3907 return NULL;
3910 pTIHeader = pBlk;
3911 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3912 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3913 return NULL;
3915 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3916 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3917 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3919 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3920 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3921 (*ppTypeInfoImpl)->index = i;
3922 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3923 pOtherTypeInfoBlks[i].name_offs +
3924 pNameTable);
3925 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3926 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3927 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3928 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3929 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3930 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3931 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3933 if((pTIHeader->typeflags1 & 7) != 2)
3934 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3935 if(pTIHeader->typeflags3 != 2)
3936 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3938 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3939 debugstr_w((*ppTypeInfoImpl)->Name),
3940 typekind_desc[pTIHeader->typekind],
3941 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3942 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3944 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3946 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3948 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3949 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3950 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = (pTITail->cbSizeVft * sizeof(void *))/4;
3952 switch(pTIHeader->typekind) {
3953 case TKIND_ENUM:
3954 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3955 pTIHeader, pTITail);
3956 break;
3958 case TKIND_RECORD:
3959 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3960 pTIHeader, pTITail);
3961 break;
3963 case TKIND_INTERFACE:
3964 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3965 pTIHeader, pTITail);
3966 break;
3968 case TKIND_COCLASS:
3969 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3970 pTIHeader, pTITail);
3971 break;
3973 case TKIND_ALIAS:
3974 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3975 pTIHeader, pTITail);
3976 break;
3978 case TKIND_DISPATCH:
3979 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3980 pTIHeader, pTITail);
3981 break;
3983 case TKIND_MODULE:
3984 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3985 pTIHeader, pTITail);
3986 break;
3988 default:
3989 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3990 break;
3994 /* could get cFuncs, cVars and cImplTypes from here
3995 but we've already set those */
3996 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3997 X(06);
3998 X(16);
3999 X(18);
4000 X(1a);
4001 X(1e);
4002 X(24);
4003 X(26);
4004 X(2a);
4005 X(2c);
4006 X(2e);
4007 X(30);
4008 X(32);
4009 X(34);
4010 #undef X
4011 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4012 pBlk = (char*)pBlk + pBlkEntry[order].len;
4015 if(i != pTypeLibImpl->TypeInfoCount) {
4016 FIXME("Somehow processed %d TypeInfos\n", i);
4017 return NULL;
4020 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4021 return (ITypeLib2*)pTypeLibImpl;
4024 /* ITypeLib::QueryInterface
4026 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4027 ITypeLib2 * iface,
4028 REFIID riid,
4029 VOID **ppvObject)
4031 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4033 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4035 *ppvObject=NULL;
4036 if(IsEqualIID(riid, &IID_IUnknown) ||
4037 IsEqualIID(riid,&IID_ITypeLib)||
4038 IsEqualIID(riid,&IID_ITypeLib2))
4040 *ppvObject = This;
4043 if(*ppvObject)
4045 ITypeLib2_AddRef(iface);
4046 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4047 return S_OK;
4049 TRACE("-- Interface: E_NOINTERFACE\n");
4050 return E_NOINTERFACE;
4053 /* ITypeLib::AddRef
4055 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4057 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4058 ULONG ref = InterlockedIncrement(&This->ref);
4060 TRACE("(%p)->ref was %u\n",This, ref - 1);
4062 return ref;
4065 /* ITypeLib::Release
4067 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4069 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4070 ULONG ref = InterlockedDecrement(&This->ref);
4072 TRACE("(%p)->(%u)\n",This, ref);
4074 if (!ref)
4076 TLBImpLib *pImpLib, *pImpLibNext;
4077 TLBCustData *pCustData, *pCustDataNext;
4078 TLBRefType *ref_type;
4079 void *cursor2;
4080 int i;
4082 /* remove cache entry */
4083 if(This->path)
4085 TRACE("removing from cache list\n");
4086 EnterCriticalSection(&cache_section);
4087 if (This->next) This->next->prev = This->prev;
4088 if (This->prev) This->prev->next = This->next;
4089 else tlb_cache_first = This->next;
4090 LeaveCriticalSection(&cache_section);
4091 HeapFree(GetProcessHeap(), 0, This->path);
4093 TRACE(" destroying ITypeLib(%p)\n",This);
4095 SysFreeString(This->Name);
4096 This->Name = NULL;
4098 SysFreeString(This->DocString);
4099 This->DocString = NULL;
4101 SysFreeString(This->HelpFile);
4102 This->HelpFile = NULL;
4104 SysFreeString(This->HelpStringDll);
4105 This->HelpStringDll = NULL;
4107 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4109 VariantClear(&pCustData->data);
4111 pCustDataNext = pCustData->next;
4112 TLB_Free(pCustData);
4115 for (i = 0; i < This->ctTypeDesc; i++)
4116 if (This->pTypeDesc[i].vt == VT_CARRAY)
4117 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4119 TLB_Free(This->pTypeDesc);
4121 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4123 if (pImpLib->pImpTypeLib)
4124 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4125 SysFreeString(pImpLib->name);
4127 pImpLibNext = pImpLib->next;
4128 TLB_Free(pImpLib);
4131 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4133 list_remove(&ref_type->entry);
4134 TLB_Free(ref_type);
4137 if (This->pTypeInfo) /* can be NULL */
4138 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4139 HeapFree(GetProcessHeap(),0,This);
4140 return 0;
4143 return ref;
4146 /* ITypeLib::GetTypeInfoCount
4148 * Returns the number of type descriptions in the type library
4150 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4152 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4153 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4154 return This->TypeInfoCount;
4157 /* ITypeLib::GetTypeInfo
4159 * retrieves the specified type description in the library.
4161 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4162 ITypeLib2 *iface,
4163 UINT index,
4164 ITypeInfo **ppTInfo)
4166 UINT i;
4168 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4169 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4171 TRACE("(%p)->(index=%d)\n", This, index);
4173 if (!ppTInfo) return E_INVALIDARG;
4175 /* search element n in list */
4176 for(i=0; i < index; i++)
4178 pTypeInfo = pTypeInfo->next;
4179 if (!pTypeInfo)
4181 TRACE("-- element not found\n");
4182 return TYPE_E_ELEMENTNOTFOUND;
4186 *ppTInfo = (ITypeInfo *) pTypeInfo;
4188 ITypeInfo_AddRef(*ppTInfo);
4189 TRACE("-- found (%p)\n",*ppTInfo);
4190 return S_OK;
4194 /* ITypeLibs::GetTypeInfoType
4196 * Retrieves the type of a type description.
4198 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4199 ITypeLib2 *iface,
4200 UINT index,
4201 TYPEKIND *pTKind)
4203 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4204 UINT i;
4205 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4207 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4208 return TYPE_E_ELEMENTNOTFOUND;
4210 TRACE("(%p) index %d\n", This, index);
4212 if(!pTKind) return E_INVALIDARG;
4214 /* search element n in list */
4215 for(i=0; i < index; i++)
4217 if(!pTInfo)
4219 TRACE("-- element not found\n");
4220 return TYPE_E_ELEMENTNOTFOUND;
4222 pTInfo = pTInfo->next;
4225 *pTKind = pTInfo->TypeAttr.typekind;
4226 TRACE("-- found Type (%d)\n", *pTKind);
4227 return S_OK;
4230 /* ITypeLib::GetTypeInfoOfGuid
4232 * Retrieves the type description that corresponds to the specified GUID.
4235 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4236 ITypeLib2 *iface,
4237 REFGUID guid,
4238 ITypeInfo **ppTInfo)
4240 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4241 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4243 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4245 if (!pTypeInfo)
4247 WARN("-- element not found\n");
4248 return TYPE_E_ELEMENTNOTFOUND;
4251 /* search linked list for guid */
4252 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4254 pTypeInfo = pTypeInfo->next;
4256 if (!pTypeInfo)
4258 /* end of list reached */
4259 WARN("-- element not found\n");
4260 return TYPE_E_ELEMENTNOTFOUND;
4264 TRACE("-- found (%p, %s)\n",
4265 pTypeInfo,
4266 debugstr_w(pTypeInfo->Name));
4268 *ppTInfo = (ITypeInfo*)pTypeInfo;
4269 ITypeInfo_AddRef(*ppTInfo);
4270 return S_OK;
4273 /* ITypeLib::GetLibAttr
4275 * Retrieves the structure that contains the library's attributes.
4278 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4279 ITypeLib2 *iface,
4280 LPTLIBATTR *ppTLibAttr)
4282 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4283 TRACE("(%p)\n",This);
4284 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4285 **ppTLibAttr = This->LibAttr;
4286 return S_OK;
4289 /* ITypeLib::GetTypeComp
4291 * Enables a client compiler to bind to a library's types, variables,
4292 * constants, and global functions.
4295 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4296 ITypeLib2 *iface,
4297 ITypeComp **ppTComp)
4299 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4301 TRACE("(%p)->(%p)\n",This,ppTComp);
4302 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4303 ITypeComp_AddRef(*ppTComp);
4305 return S_OK;
4308 /* ITypeLib::GetDocumentation
4310 * Retrieves the library's documentation string, the complete Help file name
4311 * and path, and the context identifier for the library Help topic in the Help
4312 * file.
4314 * On a successful return all non-null BSTR pointers will have been set,
4315 * possibly to NULL.
4317 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4318 ITypeLib2 *iface,
4319 INT index,
4320 BSTR *pBstrName,
4321 BSTR *pBstrDocString,
4322 DWORD *pdwHelpContext,
4323 BSTR *pBstrHelpFile)
4325 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4327 HRESULT result = E_INVALIDARG;
4329 ITypeInfo *pTInfo;
4332 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4333 This, index,
4334 pBstrName, pBstrDocString,
4335 pdwHelpContext, pBstrHelpFile);
4337 if(index<0)
4339 /* documentation for the typelib */
4340 if(pBstrName)
4342 if (This->Name)
4344 if(!(*pBstrName = SysAllocString(This->Name)))
4345 goto memerr1;
4347 else
4348 *pBstrName = NULL;
4350 if(pBstrDocString)
4352 if (This->DocString)
4354 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4355 goto memerr2;
4357 else if (This->Name)
4359 if(!(*pBstrDocString = SysAllocString(This->Name)))
4360 goto memerr2;
4362 else
4363 *pBstrDocString = NULL;
4365 if(pdwHelpContext)
4367 *pdwHelpContext = This->dwHelpContext;
4369 if(pBstrHelpFile)
4371 if (This->HelpFile)
4373 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4374 goto memerr3;
4376 else
4377 *pBstrHelpFile = NULL;
4380 result = S_OK;
4382 else
4384 /* for a typeinfo */
4385 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4387 if(SUCCEEDED(result))
4389 result = ITypeInfo_GetDocumentation(pTInfo,
4390 MEMBERID_NIL,
4391 pBstrName,
4392 pBstrDocString,
4393 pdwHelpContext, pBstrHelpFile);
4395 ITypeInfo_Release(pTInfo);
4398 return result;
4399 memerr3:
4400 if (pBstrDocString) SysFreeString (*pBstrDocString);
4401 memerr2:
4402 if (pBstrName) SysFreeString (*pBstrName);
4403 memerr1:
4404 return STG_E_INSUFFICIENTMEMORY;
4407 /* ITypeLib::IsName
4409 * Indicates whether a passed-in string contains the name of a type or member
4410 * described in the library.
4413 static HRESULT WINAPI ITypeLib2_fnIsName(
4414 ITypeLib2 *iface,
4415 LPOLESTR szNameBuf,
4416 ULONG lHashVal,
4417 BOOL *pfName)
4419 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4420 ITypeInfoImpl *pTInfo;
4421 TLBFuncDesc *pFInfo;
4422 TLBVarDesc *pVInfo;
4423 int i;
4424 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4426 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4427 pfName);
4429 *pfName=TRUE;
4430 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4431 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4432 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4433 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4434 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4435 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4436 goto ITypeLib2_fnIsName_exit;
4438 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4439 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4442 *pfName=FALSE;
4444 ITypeLib2_fnIsName_exit:
4445 TRACE("(%p)slow! search for %s: %s found!\n", This,
4446 debugstr_w(szNameBuf), *pfName?"NOT":"");
4448 return S_OK;
4451 /* ITypeLib::FindName
4453 * Finds occurrences of a type description in a type library. This may be used
4454 * to quickly verify that a name exists in a type library.
4457 static HRESULT WINAPI ITypeLib2_fnFindName(
4458 ITypeLib2 *iface,
4459 LPOLESTR szNameBuf,
4460 ULONG lHashVal,
4461 ITypeInfo **ppTInfo,
4462 MEMBERID *rgMemId,
4463 UINT16 *pcFound)
4465 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4466 ITypeInfoImpl *pTInfo;
4467 TLBFuncDesc *pFInfo;
4468 TLBVarDesc *pVInfo;
4469 int i,j = 0;
4470 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4472 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4473 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4474 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4475 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4476 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4477 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4478 goto ITypeLib2_fnFindName_exit;
4481 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4482 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4483 continue;
4484 ITypeLib2_fnFindName_exit:
4485 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4486 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4487 j++;
4489 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4490 This, *pcFound, debugstr_w(szNameBuf), j);
4492 *pcFound=j;
4494 return S_OK;
4497 /* ITypeLib::ReleaseTLibAttr
4499 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4502 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4503 ITypeLib2 *iface,
4504 TLIBATTR *pTLibAttr)
4506 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4507 TRACE("freeing (%p)\n",This);
4508 HeapFree(GetProcessHeap(),0,pTLibAttr);
4512 /* ITypeLib2::GetCustData
4514 * gets the custom data
4516 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4517 ITypeLib2 * iface,
4518 REFGUID guid,
4519 VARIANT *pVarVal)
4521 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4522 TLBCustData *pCData;
4524 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4526 if( IsEqualIID(guid, &pCData->guid)) break;
4529 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4531 if(pCData)
4533 VariantInit( pVarVal);
4534 VariantCopy( pVarVal, &pCData->data);
4535 return S_OK;
4537 return E_INVALIDARG; /* FIXME: correct? */
4540 /* ITypeLib2::GetLibStatistics
4542 * Returns statistics about a type library that are required for efficient
4543 * sizing of hash tables.
4546 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4547 ITypeLib2 * iface,
4548 ULONG *pcUniqueNames,
4549 ULONG *pcchUniqueNames)
4551 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4553 FIXME("(%p): stub!\n", This);
4555 if(pcUniqueNames) *pcUniqueNames=1;
4556 if(pcchUniqueNames) *pcchUniqueNames=1;
4557 return S_OK;
4560 /* ITypeLib2::GetDocumentation2
4562 * Retrieves the library's documentation string, the complete Help file name
4563 * and path, the localization context to use, and the context ID for the
4564 * library Help topic in the Help file.
4567 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4568 ITypeLib2 * iface,
4569 INT index,
4570 LCID lcid,
4571 BSTR *pbstrHelpString,
4572 DWORD *pdwHelpStringContext,
4573 BSTR *pbstrHelpStringDll)
4575 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4576 HRESULT result;
4577 ITypeInfo *pTInfo;
4579 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4581 /* the help string should be obtained from the helpstringdll,
4582 * using the _DLLGetDocumentation function, based on the supplied
4583 * lcid. Nice to do sometime...
4585 if(index<0)
4587 /* documentation for the typelib */
4588 if(pbstrHelpString)
4589 *pbstrHelpString=SysAllocString(This->DocString);
4590 if(pdwHelpStringContext)
4591 *pdwHelpStringContext=This->dwHelpContext;
4592 if(pbstrHelpStringDll)
4593 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4595 result = S_OK;
4597 else
4599 /* for a typeinfo */
4600 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4602 if(SUCCEEDED(result))
4604 ITypeInfo2 * pTInfo2;
4605 result = ITypeInfo_QueryInterface(pTInfo,
4606 &IID_ITypeInfo2,
4607 (LPVOID*) &pTInfo2);
4609 if(SUCCEEDED(result))
4611 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4612 MEMBERID_NIL,
4613 lcid,
4614 pbstrHelpString,
4615 pdwHelpStringContext,
4616 pbstrHelpStringDll);
4618 ITypeInfo2_Release(pTInfo2);
4621 ITypeInfo_Release(pTInfo);
4624 return result;
4627 /* ITypeLib2::GetAllCustData
4629 * Gets all custom data items for the library.
4632 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4633 ITypeLib2 * iface,
4634 CUSTDATA *pCustData)
4636 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4637 TLBCustData *pCData;
4638 int i;
4639 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4640 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4641 if(pCustData->prgCustData ){
4642 pCustData->cCustData=This->ctCustData;
4643 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4644 pCustData->prgCustData[i].guid=pCData->guid;
4645 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4647 }else{
4648 ERR(" OUT OF MEMORY!\n");
4649 return E_OUTOFMEMORY;
4651 return S_OK;
4654 static const ITypeLib2Vtbl tlbvt = {
4655 ITypeLib2_fnQueryInterface,
4656 ITypeLib2_fnAddRef,
4657 ITypeLib2_fnRelease,
4658 ITypeLib2_fnGetTypeInfoCount,
4659 ITypeLib2_fnGetTypeInfo,
4660 ITypeLib2_fnGetTypeInfoType,
4661 ITypeLib2_fnGetTypeInfoOfGuid,
4662 ITypeLib2_fnGetLibAttr,
4663 ITypeLib2_fnGetTypeComp,
4664 ITypeLib2_fnGetDocumentation,
4665 ITypeLib2_fnIsName,
4666 ITypeLib2_fnFindName,
4667 ITypeLib2_fnReleaseTLibAttr,
4669 ITypeLib2_fnGetCustData,
4670 ITypeLib2_fnGetLibStatistics,
4671 ITypeLib2_fnGetDocumentation2,
4672 ITypeLib2_fnGetAllCustData
4676 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4678 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4680 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4683 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4685 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4687 return ITypeLib2_AddRef((ITypeLib2 *)This);
4690 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4692 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4694 return ITypeLib2_Release((ITypeLib2 *)This);
4697 static HRESULT WINAPI ITypeLibComp_fnBind(
4698 ITypeComp * iface,
4699 OLECHAR * szName,
4700 ULONG lHash,
4701 WORD wFlags,
4702 ITypeInfo ** ppTInfo,
4703 DESCKIND * pDescKind,
4704 BINDPTR * pBindPtr)
4706 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4707 ITypeInfoImpl *pTypeInfo;
4709 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4711 *pDescKind = DESCKIND_NONE;
4712 pBindPtr->lptcomp = NULL;
4713 *ppTInfo = NULL;
4715 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4717 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4719 /* FIXME: check wFlags here? */
4720 /* FIXME: we should use a hash table to look this info up using lHash
4721 * instead of an O(n) search */
4722 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4723 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4725 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4727 *pDescKind = DESCKIND_TYPECOMP;
4728 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4729 ITypeComp_AddRef(pBindPtr->lptcomp);
4730 TRACE("module or enum: %s\n", debugstr_w(szName));
4731 return S_OK;
4735 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4736 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4738 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4739 HRESULT hr;
4741 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4742 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4744 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4745 return S_OK;
4749 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4750 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4752 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4753 HRESULT hr;
4754 ITypeInfo *subtypeinfo;
4755 BINDPTR subbindptr;
4756 DESCKIND subdesckind;
4758 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4759 &subtypeinfo, &subdesckind, &subbindptr);
4760 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4762 TYPEDESC tdesc_appobject =
4765 (TYPEDESC *)pTypeInfo->hreftype
4767 VT_USERDEFINED
4769 const VARDESC vardesc_appobject =
4771 -2, /* memid */
4772 NULL, /* lpstrSchema */
4774 0 /* oInst */
4777 /* ELEMDESC */
4779 /* TYPEDESC */
4781 &tdesc_appobject
4783 VT_PTR
4786 0, /* wVarFlags */
4787 VAR_STATIC /* varkind */
4790 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4792 /* cleanup things filled in by Bind call so we can put our
4793 * application object data in there instead */
4794 switch (subdesckind)
4796 case DESCKIND_FUNCDESC:
4797 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4798 break;
4799 case DESCKIND_VARDESC:
4800 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4801 break;
4802 default:
4803 break;
4805 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4807 if (pTypeInfo->hreftype == -1)
4808 FIXME("no hreftype for interface %p\n", pTypeInfo);
4810 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4811 if (FAILED(hr))
4812 return hr;
4814 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4815 *ppTInfo = (ITypeInfo *)pTypeInfo;
4816 ITypeInfo_AddRef(*ppTInfo);
4817 return S_OK;
4822 TRACE("name not found %s\n", debugstr_w(szName));
4823 return S_OK;
4826 static HRESULT WINAPI ITypeLibComp_fnBindType(
4827 ITypeComp * iface,
4828 OLECHAR * szName,
4829 ULONG lHash,
4830 ITypeInfo ** ppTInfo,
4831 ITypeComp ** ppTComp)
4833 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4834 return E_NOTIMPL;
4837 static const ITypeCompVtbl tlbtcvt =
4840 ITypeLibComp_fnQueryInterface,
4841 ITypeLibComp_fnAddRef,
4842 ITypeLibComp_fnRelease,
4844 ITypeLibComp_fnBind,
4845 ITypeLibComp_fnBindType
4848 /*================== ITypeInfo(2) Methods ===================================*/
4849 static ITypeInfo2 * ITypeInfo_Constructor(void)
4851 ITypeInfoImpl * pTypeInfoImpl;
4853 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4854 if (pTypeInfoImpl)
4856 pTypeInfoImpl->lpVtbl = &tinfvt;
4857 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4858 pTypeInfoImpl->ref=1;
4859 pTypeInfoImpl->hreftype = -1;
4860 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4861 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4863 TRACE("(%p)\n", pTypeInfoImpl);
4864 return (ITypeInfo2*) pTypeInfoImpl;
4867 /* ITypeInfo::QueryInterface
4869 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4870 ITypeInfo2 *iface,
4871 REFIID riid,
4872 VOID **ppvObject)
4874 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4876 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4878 *ppvObject=NULL;
4879 if(IsEqualIID(riid, &IID_IUnknown) ||
4880 IsEqualIID(riid,&IID_ITypeInfo)||
4881 IsEqualIID(riid,&IID_ITypeInfo2))
4882 *ppvObject = This;
4884 if(*ppvObject){
4885 ITypeInfo_AddRef(iface);
4886 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4887 return S_OK;
4889 TRACE("-- Interface: E_NOINTERFACE\n");
4890 return E_NOINTERFACE;
4893 /* ITypeInfo::AddRef
4895 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4897 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4898 ULONG ref = InterlockedIncrement(&This->ref);
4900 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4902 TRACE("(%p)->ref is %u\n",This, ref);
4903 return ref;
4906 /* ITypeInfo::Release
4908 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4910 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4911 ULONG ref = InterlockedDecrement(&This->ref);
4913 TRACE("(%p)->(%u)\n",This, ref);
4915 if (ref) {
4916 /* We don't release ITypeLib when ref=0 because
4917 it means that function is called by ITypeLib2_Release */
4918 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4919 } else {
4920 TLBFuncDesc *pFInfo, *pFInfoNext;
4921 TLBVarDesc *pVInfo, *pVInfoNext;
4922 TLBImplType *pImpl, *pImplNext;
4924 TRACE("destroying ITypeInfo(%p)\n",This);
4926 if (This->no_free_data)
4927 goto finish_free;
4929 SysFreeString(This->Name);
4930 This->Name = NULL;
4932 SysFreeString(This->DocString);
4933 This->DocString = NULL;
4935 SysFreeString(This->DllName);
4936 This->DllName = NULL;
4938 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4940 INT i;
4941 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4943 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4944 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4946 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4947 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4949 SysFreeString(pFInfo->pParamDesc[i].Name);
4951 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4952 TLB_Free(pFInfo->pParamDesc);
4953 TLB_FreeCustData(pFInfo->pCustData);
4954 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4955 SysFreeString(pFInfo->Entry);
4956 SysFreeString(pFInfo->HelpString);
4957 SysFreeString(pFInfo->Name);
4959 pFInfoNext = pFInfo->next;
4960 TLB_Free(pFInfo);
4962 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4964 if (pVInfo->vardesc.varkind == VAR_CONST)
4966 VariantClear(pVInfo->vardesc.u.lpvarValue);
4967 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4969 TLB_FreeCustData(pVInfo->pCustData);
4970 SysFreeString(pVInfo->Name);
4971 pVInfoNext = pVInfo->next;
4972 TLB_Free(pVInfo);
4974 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4976 TLB_FreeCustData(pImpl->pCustData);
4977 pImplNext = pImpl->next;
4978 TLB_Free(pImpl);
4980 TLB_FreeCustData(This->pCustData);
4982 finish_free:
4983 if (This->next)
4985 ITypeInfo_Release((ITypeInfo*)This->next);
4988 HeapFree(GetProcessHeap(),0,This);
4989 return 0;
4991 return ref;
4994 /* ITypeInfo::GetTypeAttr
4996 * Retrieves a TYPEATTR structure that contains the attributes of the type
4997 * description.
5000 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5001 LPTYPEATTR *ppTypeAttr)
5003 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5004 SIZE_T size;
5006 TRACE("(%p)\n",This);
5008 size = sizeof(**ppTypeAttr);
5009 if (This->TypeAttr.typekind == TKIND_ALIAS)
5010 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5012 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5013 if (!*ppTypeAttr)
5014 return E_OUTOFMEMORY;
5016 **ppTypeAttr = This->TypeAttr;
5018 if (This->TypeAttr.typekind == TKIND_ALIAS)
5019 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5020 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5022 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5023 /* This should include all the inherited funcs */
5024 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5025 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5026 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5028 return S_OK;
5031 /* ITypeInfo::GetTypeComp
5033 * Retrieves the ITypeComp interface for the type description, which enables a
5034 * client compiler to bind to the type description's members.
5037 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5038 ITypeComp * *ppTComp)
5040 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5042 TRACE("(%p)->(%p)\n", This, ppTComp);
5044 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5045 ITypeComp_AddRef(*ppTComp);
5046 return S_OK;
5049 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5051 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5052 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5053 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5054 return size;
5057 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5059 *dest = *src;
5060 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5061 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5063 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5064 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5065 *buffer += sizeof(PARAMDESCEX);
5066 *pparamdescex_dest = *pparamdescex_src;
5067 VariantInit(&pparamdescex_dest->varDefaultValue);
5068 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5069 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5071 else
5072 dest->u.paramdesc.pparamdescex = NULL;
5073 return S_OK;
5076 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5078 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5079 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5082 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5084 FUNCDESC *dest;
5085 char *buffer;
5086 SIZE_T size = sizeof(*src);
5087 SHORT i;
5088 HRESULT hr;
5090 size += sizeof(*src->lprgscode) * src->cScodes;
5091 size += TLB_SizeElemDesc(&src->elemdescFunc);
5092 for (i = 0; i < src->cParams; i++)
5094 size += sizeof(ELEMDESC);
5095 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5098 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5099 if (!dest) return E_OUTOFMEMORY;
5101 *dest = *src;
5102 if (dispinterface) /* overwrite funckind */
5103 dest->funckind = FUNC_DISPATCH;
5104 buffer = (char *)(dest + 1);
5106 dest->lprgscode = (SCODE *)buffer;
5107 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5108 buffer += sizeof(*src->lprgscode) * src->cScodes;
5110 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5111 if (FAILED(hr))
5113 SysFreeString((BSTR)dest);
5114 return hr;
5117 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5118 buffer += sizeof(ELEMDESC) * src->cParams;
5119 for (i = 0; i < src->cParams; i++)
5121 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5122 if (FAILED(hr))
5123 break;
5125 if (FAILED(hr))
5127 /* undo the above actions */
5128 for (i = i - 1; i >= 0; i--)
5129 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5130 TLB_FreeElemDesc(&dest->elemdescFunc);
5131 SysFreeString((BSTR)dest);
5132 return hr;
5135 /* special treatment for dispinterfaces: this makes functions appear
5136 * to return their [retval] value when it is really returning an
5137 * HRESULT */
5138 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5140 if (dest->cParams &&
5141 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5143 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5144 if (elemdesc->tdesc.vt != VT_PTR)
5146 ERR("elemdesc should have started with VT_PTR instead of:\n");
5147 if (ERR_ON(ole))
5148 dump_ELEMDESC(elemdesc);
5149 return E_UNEXPECTED;
5152 /* copy last parameter to the return value. we are using a flat
5153 * buffer so there is no danger of leaking memory in
5154 * elemdescFunc */
5155 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5157 /* remove the last parameter */
5158 dest->cParams--;
5160 else
5161 /* otherwise this function is made to appear to have no return
5162 * value */
5163 dest->elemdescFunc.tdesc.vt = VT_VOID;
5167 *dest_ptr = dest;
5168 return S_OK;
5171 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5173 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5174 const TLBFuncDesc *pFDesc;
5175 UINT i;
5177 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5180 if (pFDesc)
5182 *ppFuncDesc = &pFDesc->funcdesc;
5183 return S_OK;
5186 return TYPE_E_ELEMENTNOTFOUND;
5189 /* internal function to make the inherited interfaces' methods appear
5190 * part of the interface */
5191 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5192 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5194 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5195 HRESULT hr;
5196 UINT implemented_funcs = 0;
5198 if (funcs)
5199 *funcs = 0;
5200 else
5201 *hrefoffset = DISPATCH_HREF_OFFSET;
5203 if(This->impltypelist)
5205 ITypeInfo *pSubTypeInfo;
5206 UINT sub_funcs;
5208 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5209 if (FAILED(hr))
5210 return hr;
5212 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5213 index,
5214 ppFuncDesc,
5215 &sub_funcs, hrefoffset);
5216 implemented_funcs += sub_funcs;
5217 ITypeInfo_Release(pSubTypeInfo);
5218 if (SUCCEEDED(hr))
5219 return hr;
5220 *hrefoffset += DISPATCH_HREF_OFFSET;
5223 if (funcs)
5224 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5225 else
5226 *hrefoffset = 0;
5228 if (index < implemented_funcs)
5229 return E_INVALIDARG;
5230 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5231 ppFuncDesc);
5234 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5236 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5237 while (TRUE)
5239 switch (pTypeDesc->vt)
5241 case VT_USERDEFINED:
5242 pTypeDesc->u.hreftype += hrefoffset;
5243 return;
5244 case VT_PTR:
5245 case VT_SAFEARRAY:
5246 pTypeDesc = pTypeDesc->u.lptdesc;
5247 break;
5248 case VT_CARRAY:
5249 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5250 break;
5251 default:
5252 return;
5257 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5259 SHORT i;
5260 for (i = 0; i < pFuncDesc->cParams; i++)
5261 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5262 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5265 /* ITypeInfo::GetFuncDesc
5267 * Retrieves the FUNCDESC structure that contains information about a
5268 * specified function.
5271 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5272 LPFUNCDESC *ppFuncDesc)
5274 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5275 const FUNCDESC *internal_funcdesc;
5276 HRESULT hr;
5277 UINT hrefoffset = 0;
5279 TRACE("(%p) index %d\n", This, index);
5281 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5282 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5283 &internal_funcdesc, NULL,
5284 &hrefoffset);
5285 else
5286 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5287 &internal_funcdesc);
5288 if (FAILED(hr))
5290 WARN("description for function %d not found\n", index);
5291 return hr;
5294 hr = TLB_AllocAndInitFuncDesc(
5295 internal_funcdesc,
5296 ppFuncDesc,
5297 This->TypeAttr.typekind == TKIND_DISPATCH);
5299 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5300 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5302 TRACE("-- 0x%08x\n", hr);
5303 return hr;
5306 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5308 VARDESC *dest;
5309 char *buffer;
5310 SIZE_T size = sizeof(*src);
5311 HRESULT hr;
5313 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5314 if (src->varkind == VAR_CONST)
5315 size += sizeof(VARIANT);
5316 size += TLB_SizeElemDesc(&src->elemdescVar);
5318 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5319 if (!dest) return E_OUTOFMEMORY;
5321 *dest = *src;
5322 buffer = (char *)(dest + 1);
5323 if (src->lpstrSchema)
5325 int len;
5326 dest->lpstrSchema = (LPOLESTR)buffer;
5327 len = strlenW(src->lpstrSchema);
5328 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5329 buffer += (len + 1) * sizeof(WCHAR);
5332 if (src->varkind == VAR_CONST)
5334 HRESULT hr;
5336 dest->u.lpvarValue = (VARIANT *)buffer;
5337 *dest->u.lpvarValue = *src->u.lpvarValue;
5338 buffer += sizeof(VARIANT);
5339 VariantInit(dest->u.lpvarValue);
5340 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5341 if (FAILED(hr))
5343 SysFreeString((BSTR)dest_ptr);
5344 return hr;
5347 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5348 if (FAILED(hr))
5350 if (src->varkind == VAR_CONST)
5351 VariantClear(dest->u.lpvarValue);
5352 SysFreeString((BSTR)dest);
5353 return hr;
5355 *dest_ptr = dest;
5356 return S_OK;
5359 /* ITypeInfo::GetVarDesc
5361 * Retrieves a VARDESC structure that describes the specified variable.
5364 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5365 LPVARDESC *ppVarDesc)
5367 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5368 UINT i;
5369 const TLBVarDesc *pVDesc;
5371 TRACE("(%p) index %d\n", This, index);
5373 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5376 if (pVDesc)
5377 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5379 return E_INVALIDARG;
5382 /* ITypeInfo_GetNames
5384 * Retrieves the variable with the specified member ID (or the name of the
5385 * property or method and its parameters) that correspond to the specified
5386 * function ID.
5388 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5389 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5391 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5392 const TLBFuncDesc *pFDesc;
5393 const TLBVarDesc *pVDesc;
5394 int i;
5395 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5396 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5397 if(pFDesc)
5399 /* function found, now return function and parameter names */
5400 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5402 if(!i)
5403 *rgBstrNames=SysAllocString(pFDesc->Name);
5404 else
5405 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5407 *pcNames=i;
5409 else
5411 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5412 if(pVDesc)
5414 *rgBstrNames=SysAllocString(pVDesc->Name);
5415 *pcNames=1;
5417 else
5419 if(This->impltypelist &&
5420 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5421 /* recursive search */
5422 ITypeInfo *pTInfo;
5423 HRESULT result;
5424 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5425 &pTInfo);
5426 if(SUCCEEDED(result))
5428 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5429 ITypeInfo_Release(pTInfo);
5430 return result;
5432 WARN("Could not search inherited interface!\n");
5434 else
5436 WARN("no names found\n");
5438 *pcNames=0;
5439 return TYPE_E_ELEMENTNOTFOUND;
5442 return S_OK;
5446 /* ITypeInfo::GetRefTypeOfImplType
5448 * If a type description describes a COM class, it retrieves the type
5449 * description of the implemented interface types. For an interface,
5450 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5451 * if any exist.
5454 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5455 ITypeInfo2 *iface,
5456 UINT index,
5457 HREFTYPE *pRefType)
5459 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5460 UINT i;
5461 HRESULT hr = S_OK;
5462 const TLBImplType *pImpl = This->impltypelist;
5464 TRACE("(%p) index %d\n", This, index);
5465 if (TRACE_ON(ole)) dump_TypeInfo(This);
5467 if(index==(UINT)-1)
5469 /* only valid on dual interfaces;
5470 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5472 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5474 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5475 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5477 *pRefType = -1;
5479 else
5481 hr = TYPE_E_ELEMENTNOTFOUND;
5484 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5486 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5487 *pRefType = This->pTypeLib->dispatch_href;
5489 else
5491 /* get element n from linked list */
5492 for(i=0; pImpl && i<index; i++)
5494 pImpl = pImpl->next;
5497 if (pImpl)
5498 *pRefType = pImpl->hRef;
5499 else
5500 hr = TYPE_E_ELEMENTNOTFOUND;
5503 if(TRACE_ON(ole))
5505 if(SUCCEEDED(hr))
5506 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5507 else
5508 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5511 return hr;
5514 /* ITypeInfo::GetImplTypeFlags
5516 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5517 * or base interface in a type description.
5519 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5520 UINT index, INT *pImplTypeFlags)
5522 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5523 UINT i;
5524 TLBImplType *pImpl;
5526 TRACE("(%p) index %d\n", This, index);
5527 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5528 i++, pImpl=pImpl->next)
5530 if(i==index && pImpl){
5531 *pImplTypeFlags=pImpl->implflags;
5532 return S_OK;
5534 *pImplTypeFlags=0;
5535 return TYPE_E_ELEMENTNOTFOUND;
5538 /* GetIDsOfNames
5539 * Maps between member names and member IDs, and parameter names and
5540 * parameter IDs.
5542 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5543 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5545 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5546 const TLBFuncDesc *pFDesc;
5547 const TLBVarDesc *pVDesc;
5548 HRESULT ret=S_OK;
5549 UINT i;
5551 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5552 cNames);
5554 /* init out parameters in case of failure */
5555 for (i = 0; i < cNames; i++)
5556 pMemId[i] = MEMBERID_NIL;
5558 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5559 int j;
5560 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5561 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5562 for(i=1; i < cNames; i++){
5563 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5564 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5565 break;
5566 if( j<pFDesc->funcdesc.cParams)
5567 pMemId[i]=j;
5568 else
5569 ret=DISP_E_UNKNOWNNAME;
5571 TRACE("-- 0x%08x\n", ret);
5572 return ret;
5575 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5576 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5577 if(cNames) *pMemId=pVDesc->vardesc.memid;
5578 return ret;
5581 /* not found, see if it can be found in an inherited interface */
5582 if(This->impltypelist) {
5583 /* recursive search */
5584 ITypeInfo *pTInfo;
5585 ret=ITypeInfo_GetRefTypeInfo(iface,
5586 This->impltypelist->hRef, &pTInfo);
5587 if(SUCCEEDED(ret)){
5588 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5589 ITypeInfo_Release(pTInfo);
5590 return ret;
5592 WARN("Could not search inherited interface!\n");
5593 } else
5594 WARN("no names found\n");
5595 return DISP_E_UNKNOWNNAME;
5598 /* ITypeInfo::Invoke
5600 * Invokes a method, or accesses a property of an object, that implements the
5601 * interface described by the type description.
5603 DWORD
5604 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5605 DWORD res;
5607 if (TRACE_ON(ole)) {
5608 int i;
5609 TRACE("Calling %p(",func);
5610 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5611 TRACE(")\n");
5614 switch (callconv) {
5615 case CC_STDCALL:
5617 switch (nrargs) {
5618 case 0:
5619 res = func();
5620 break;
5621 case 1:
5622 res = func(args[0]);
5623 break;
5624 case 2:
5625 res = func(args[0],args[1]);
5626 break;
5627 case 3:
5628 res = func(args[0],args[1],args[2]);
5629 break;
5630 case 4:
5631 res = func(args[0],args[1],args[2],args[3]);
5632 break;
5633 case 5:
5634 res = func(args[0],args[1],args[2],args[3],args[4]);
5635 break;
5636 case 6:
5637 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5638 break;
5639 case 7:
5640 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5641 break;
5642 case 8:
5643 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5644 break;
5645 case 9:
5646 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5647 break;
5648 case 10:
5649 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5650 break;
5651 case 11:
5652 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5653 break;
5654 case 12:
5655 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]);
5656 break;
5657 case 13:
5658 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]);
5659 break;
5660 case 14:
5661 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]);
5662 break;
5663 case 15:
5664 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]);
5665 break;
5666 case 16:
5667 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]);
5668 break;
5669 case 17:
5670 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]);
5671 break;
5672 case 18:
5673 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]);
5674 break;
5675 case 19:
5676 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]);
5677 break;
5678 case 20:
5679 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]);
5680 break;
5681 case 21:
5682 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]);
5683 break;
5684 case 22:
5685 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]);
5686 break;
5687 case 23:
5688 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]);
5689 break;
5690 case 24:
5691 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],args[23]);
5692 break;
5693 case 25:
5694 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],args[23],args[24]);
5695 break;
5696 case 26:
5697 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],args[23],args[24],args[25]);
5698 break;
5699 case 27:
5700 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],args[23],args[24],args[25],args[26]);
5701 break;
5702 case 28:
5703 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],args[23],args[24],args[25],args[26],args[27]);
5704 break;
5705 case 29:
5706 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],args[23],args[24],args[25],args[26],args[27],args[28]);
5707 break;
5708 case 30:
5709 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],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5710 break;
5711 default:
5712 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5713 res = -1;
5714 break;
5716 break;
5717 default:
5718 FIXME("unsupported calling convention %d\n",callconv);
5719 res = -1;
5720 break;
5722 TRACE("returns %08x\n",res);
5723 return res;
5726 /* The size of the argument on the stack in DWORD units (in all x86 call
5727 * convetions the arguments on the stack are DWORD-aligned)
5729 static int _dispargsize(VARTYPE vt)
5731 switch (vt) {
5732 case VT_I8:
5733 case VT_UI8:
5734 return 8/sizeof(DWORD);
5735 case VT_R8:
5736 return sizeof(double)/sizeof(DWORD);
5737 case VT_DECIMAL:
5738 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5739 case VT_CY:
5740 return sizeof(CY)/sizeof(DWORD);
5741 case VT_DATE:
5742 return sizeof(DATE)/sizeof(DWORD);
5743 case VT_VARIANT:
5744 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5745 case VT_RECORD:
5746 FIXME("VT_RECORD not implemented\n");
5747 return 1;
5748 default:
5749 return 1;
5753 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5755 HRESULT hr = S_OK;
5756 ITypeInfo *tinfo2 = NULL;
5757 TYPEATTR *tattr = NULL;
5759 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5760 if (hr)
5762 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5763 "hr = 0x%08x\n",
5764 tdesc->u.hreftype, hr);
5765 return hr;
5767 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5768 if (hr)
5770 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5771 ITypeInfo_Release(tinfo2);
5772 return hr;
5775 switch (tattr->typekind)
5777 case TKIND_ENUM:
5778 *vt |= VT_I4;
5779 break;
5781 case TKIND_ALIAS:
5782 tdesc = &tattr->tdescAlias;
5783 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5784 break;
5786 case TKIND_INTERFACE:
5787 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5788 *vt |= VT_DISPATCH;
5789 else
5790 *vt |= VT_UNKNOWN;
5791 break;
5793 case TKIND_DISPATCH:
5794 *vt |= VT_DISPATCH;
5795 break;
5797 case TKIND_COCLASS:
5798 *vt |= VT_DISPATCH;
5799 break;
5801 case TKIND_RECORD:
5802 FIXME("TKIND_RECORD unhandled.\n");
5803 hr = E_NOTIMPL;
5804 break;
5806 case TKIND_UNION:
5807 FIXME("TKIND_UNION unhandled.\n");
5808 hr = E_NOTIMPL;
5809 break;
5811 default:
5812 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5813 hr = E_NOTIMPL;
5814 break;
5816 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5817 ITypeInfo_Release(tinfo2);
5818 return hr;
5821 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5823 HRESULT hr = S_OK;
5825 /* enforce only one level of pointer indirection */
5826 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5828 tdesc = tdesc->u.lptdesc;
5830 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5831 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5832 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5833 if ((tdesc->vt == VT_USERDEFINED) ||
5834 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5836 VARTYPE vt_userdefined = 0;
5837 const TYPEDESC *tdesc_userdefined = tdesc;
5838 if (tdesc->vt == VT_PTR)
5840 vt_userdefined = VT_BYREF;
5841 tdesc_userdefined = tdesc->u.lptdesc;
5843 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5844 if ((hr == S_OK) &&
5845 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5846 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5848 *vt |= vt_userdefined;
5849 return S_OK;
5852 *vt = VT_BYREF;
5855 switch (tdesc->vt)
5857 case VT_HRESULT:
5858 *vt |= VT_ERROR;
5859 break;
5860 case VT_USERDEFINED:
5861 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5862 break;
5863 case VT_VOID:
5864 case VT_CARRAY:
5865 case VT_PTR:
5866 case VT_LPSTR:
5867 case VT_LPWSTR:
5868 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5869 hr = DISP_E_BADVARTYPE;
5870 break;
5871 case VT_SAFEARRAY:
5872 *vt |= VT_ARRAY;
5873 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5874 break;
5875 default:
5876 *vt |= tdesc->vt;
5877 break;
5879 return hr;
5882 /***********************************************************************
5883 * DispCallFunc (OLEAUT32.@)
5885 * Invokes a function of the specified calling convention, passing the
5886 * specified arguments and returns the result.
5888 * PARAMS
5889 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5890 * oVft [I] The offset in the vtable. See notes.
5891 * cc [I] Calling convention of the function to call.
5892 * vtReturn [I] The return type of the function.
5893 * cActuals [I] Number of parameters.
5894 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5895 * prgpvarg [I] The arguments to pass.
5896 * pvargResult [O] The return value of the function. Can be NULL.
5898 * RETURNS
5899 * Success: S_OK.
5900 * Failure: HRESULT code.
5902 * NOTES
5903 * The HRESULT return value of this function is not affected by the return
5904 * value of the user supplied function, which is returned in pvargResult.
5906 * If pvInstance is NULL then a non-object function is to be called and oVft
5907 * is the address of the function to call.
5909 * The cc parameter can be one of the following values:
5910 *|CC_FASTCALL
5911 *|CC_CDECL
5912 *|CC_PASCAL
5913 *|CC_STDCALL
5914 *|CC_FPFASTCALL
5915 *|CC_SYSCALL
5916 *|CC_MPWCDECL
5917 *|CC_MPWPASCAL
5920 HRESULT WINAPI
5921 DispCallFunc(
5922 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5923 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5925 int argsize, argspos;
5926 UINT i;
5927 DWORD *args;
5928 HRESULT hres;
5930 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5931 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5932 pvargResult, V_VT(pvargResult));
5934 argsize = 0;
5935 if (pvInstance)
5936 argsize++; /* for This pointer */
5938 for (i=0;i<cActuals;i++)
5940 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5941 dump_Variant(prgpvarg[i]);
5942 argsize += _dispargsize(prgvt[i]);
5944 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5946 argspos = 0;
5947 if (pvInstance)
5949 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5950 argspos++;
5953 for (i=0;i<cActuals;i++)
5955 VARIANT *arg = prgpvarg[i];
5956 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5957 if (prgvt[i] == VT_VARIANT)
5958 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5959 else
5960 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5961 argspos += _dispargsize(prgvt[i]);
5964 if (pvInstance)
5966 FARPROC *vtable = *(FARPROC**)pvInstance;
5967 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5969 else
5970 /* if we aren't invoking an object then the function pointer is stored
5971 * in oVft */
5972 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5974 if (pvargResult && (vtReturn != VT_EMPTY))
5976 TRACE("Method returned 0x%08x\n",hres);
5977 V_VT(pvargResult) = vtReturn;
5978 V_UI4(pvargResult) = hres;
5981 HeapFree(GetProcessHeap(),0,args);
5982 return S_OK;
5985 #define INVBUF_ELEMENT_SIZE \
5986 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5987 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5988 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5989 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5990 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5991 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5992 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5993 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5995 static HRESULT WINAPI ITypeInfo_fnInvoke(
5996 ITypeInfo2 *iface,
5997 VOID *pIUnk,
5998 MEMBERID memid,
5999 UINT16 wFlags,
6000 DISPPARAMS *pDispParams,
6001 VARIANT *pVarResult,
6002 EXCEPINFO *pExcepInfo,
6003 UINT *pArgErr)
6005 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6006 int i;
6007 unsigned int var_index;
6008 TYPEKIND type_kind;
6009 HRESULT hres;
6010 const TLBFuncDesc *pFuncInfo;
6012 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6013 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6016 if (!pDispParams)
6018 ERR("NULL pDispParams not allowed\n");
6019 return E_INVALIDARG;
6022 dump_DispParms(pDispParams);
6024 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6026 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6027 pDispParams->cNamedArgs, pDispParams->cArgs);
6028 return E_INVALIDARG;
6031 /* we do this instead of using GetFuncDesc since it will return a fake
6032 * FUNCDESC for dispinterfaces and we want the real function description */
6033 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6034 if ((memid == pFuncInfo->funcdesc.memid) &&
6035 (wFlags & pFuncInfo->funcdesc.invkind))
6036 break;
6038 if (pFuncInfo) {
6039 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6041 if (TRACE_ON(ole))
6043 TRACE("invoking:\n");
6044 dump_TLBFuncDescOne(pFuncInfo);
6047 switch (func_desc->funckind) {
6048 case FUNC_PUREVIRTUAL:
6049 case FUNC_VIRTUAL: {
6050 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6051 VARIANT varresult;
6052 VARIANT retval; /* pointer for storing byref retvals in */
6053 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6054 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6055 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6056 UINT cNamedArgs = pDispParams->cNamedArgs;
6057 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6059 hres = S_OK;
6061 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6063 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6065 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6066 hres = DISP_E_PARAMNOTFOUND;
6067 goto func_fail;
6069 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6070 cNamedArgs--;
6071 rgdispidNamedArgs++;
6074 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6076 ERR("functions with the vararg attribute do not support named arguments\n");
6077 hres = DISP_E_NONAMEDARGS;
6078 goto func_fail;
6081 for (i = 0; i < func_desc->cParams; i++)
6083 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6084 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6085 if (FAILED(hres))
6086 goto func_fail;
6089 TRACE("changing args\n");
6090 for (i = 0; i < func_desc->cParams; i++)
6092 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6093 VARIANTARG *src_arg;
6095 if (cNamedArgs)
6097 USHORT j;
6098 src_arg = NULL;
6099 for (j = 0; j < cNamedArgs; j++)
6100 if (rgdispidNamedArgs[j] == i)
6102 src_arg = &pDispParams->rgvarg[j];
6103 break;
6106 else
6107 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6109 if (wParamFlags & PARAMFLAG_FRETVAL)
6111 /* under most conditions the caller is not allowed to
6112 * pass in a dispparam arg in the index of what would be
6113 * the retval parameter. however, there is an exception
6114 * where the extra parameter is used in an extra
6115 * IDispatch::Invoke below */
6116 if ((i < pDispParams->cArgs) &&
6117 ((func_desc->cParams != 1) || !pVarResult ||
6118 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6120 hres = DISP_E_BADPARAMCOUNT;
6121 break;
6124 /* note: this check is placed so that if the caller passes
6125 * in a VARIANTARG for the retval we just ignore it, like
6126 * native does */
6127 if (i == func_desc->cParams - 1)
6129 VARIANTARG *arg;
6130 arg = prgpvarg[i] = &rgvarg[i];
6131 memset(arg, 0, sizeof(*arg));
6132 V_VT(arg) = rgvt[i];
6133 memset(&retval, 0, sizeof(retval));
6134 V_BYREF(arg) = &retval;
6136 else
6138 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6139 hres = E_UNEXPECTED;
6140 break;
6143 else if (src_arg)
6145 dump_Variant(src_arg);
6147 if (rgvt[i] == VT_VARIANT)
6148 hres = VariantCopy(&rgvarg[i], src_arg);
6149 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6151 if (rgvt[i] == V_VT(src_arg))
6152 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6153 else
6155 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6156 hres = VariantCopy(&missing_arg[i], src_arg);
6157 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6159 V_VT(&rgvarg[i]) = rgvt[i];
6161 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6163 SAFEARRAY *a;
6164 SAFEARRAYBOUND bound;
6165 VARIANT *v;
6166 LONG j;
6167 bound.lLbound = 0;
6168 bound.cElements = pDispParams->cArgs-i;
6169 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6171 ERR("SafeArrayCreate failed\n");
6172 break;
6174 hres = SafeArrayAccessData(a, (LPVOID)&v);
6175 if (hres != S_OK)
6177 ERR("SafeArrayAccessData failed with %x\n", hres);
6178 break;
6180 for (j = 0; j < bound.cElements; j++)
6181 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6182 hres = SafeArrayUnaccessData(a);
6183 if (hres != S_OK)
6185 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6186 break;
6188 V_ARRAY(&rgvarg[i]) = a;
6189 V_VT(&rgvarg[i]) = rgvt[i];
6191 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6193 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6194 V_VT(&missing_arg[i]) = V_VT(src_arg);
6195 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6196 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6197 V_VT(&rgvarg[i]) = rgvt[i];
6199 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6201 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6202 V_VT(&rgvarg[i]) = rgvt[i];
6204 else
6206 /* FIXME: this doesn't work for VT_BYREF arguments if
6207 * they are not the same type as in the paramdesc */
6208 V_VT(&rgvarg[i]) = V_VT(src_arg);
6209 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6210 V_VT(&rgvarg[i]) = rgvt[i];
6213 if (FAILED(hres))
6215 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6216 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6217 debugstr_VT(src_arg), debugstr_VF(src_arg));
6218 break;
6220 prgpvarg[i] = &rgvarg[i];
6222 else if (wParamFlags & PARAMFLAG_FOPT)
6224 VARIANTARG *arg;
6225 arg = prgpvarg[i] = &rgvarg[i];
6226 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6228 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6229 if (FAILED(hres))
6230 break;
6232 else
6234 VARIANTARG *missing_arg;
6235 /* if the function wants a pointer to a variant then
6236 * set that up, otherwise just pass the VT_ERROR in
6237 * the argument by value */
6238 if (rgvt[i] & VT_BYREF)
6240 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6241 V_VT(arg) = VT_VARIANT | VT_BYREF;
6242 V_VARIANTREF(arg) = missing_arg;
6244 else
6245 missing_arg = arg;
6246 V_VT(missing_arg) = VT_ERROR;
6247 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6250 else
6252 hres = DISP_E_BADPARAMCOUNT;
6253 break;
6256 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6258 /* VT_VOID is a special case for return types, so it is not
6259 * handled in the general function */
6260 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6261 V_VT(&varresult) = VT_EMPTY;
6262 else
6264 V_VT(&varresult) = 0;
6265 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6266 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6269 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6270 V_VT(&varresult), func_desc->cParams, rgvt,
6271 prgpvarg, &varresult);
6273 for (i = 0; i < func_desc->cParams; i++)
6275 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6276 if (wParamFlags & PARAMFLAG_FRETVAL)
6278 if (TRACE_ON(ole))
6280 TRACE("[retval] value: ");
6281 dump_Variant(prgpvarg[i]);
6284 if (pVarResult)
6286 VariantInit(pVarResult);
6287 /* deref return value */
6288 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6291 /* free data stored in varresult. Note that
6292 * VariantClear doesn't do what we want because we are
6293 * working with byref types. */
6294 /* FIXME: clear safearrays, bstrs, records and
6295 * variants here too */
6296 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6297 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6299 if(*V_UNKNOWNREF(prgpvarg[i]))
6300 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6302 break;
6304 else if (i < pDispParams->cArgs)
6306 if (wParamFlags & PARAMFLAG_FOUT)
6308 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6310 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6311 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6313 if (FAILED(hres))
6315 ERR("failed to convert param %d to vt %d\n", i,
6316 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6317 break;
6320 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6321 func_desc->cParamsOpt < 0 &&
6322 i == func_desc->cParams-1)
6324 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6325 LONG j, ubound;
6326 VARIANT *v;
6327 hres = SafeArrayGetUBound(a, 1, &ubound);
6328 if (hres != S_OK)
6330 ERR("SafeArrayGetUBound failed with %x\n", hres);
6331 break;
6333 hres = SafeArrayAccessData(a, (LPVOID)&v);
6334 if (hres != S_OK)
6336 ERR("SafeArrayAccessData failed with %x\n", hres);
6337 break;
6339 for (j = 0; j <= ubound; j++)
6340 VariantClear(&v[j]);
6341 hres = SafeArrayUnaccessData(a);
6342 if (hres != S_OK)
6344 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6345 break;
6348 VariantClear(&rgvarg[i]);
6350 else if (wParamFlags & PARAMFLAG_FOPT)
6352 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6353 VariantClear(&rgvarg[i]);
6357 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6359 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6360 hres = DISP_E_EXCEPTION;
6361 if (pExcepInfo)
6363 IErrorInfo *pErrorInfo;
6364 pExcepInfo->scode = V_ERROR(&varresult);
6365 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6367 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6368 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6369 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6370 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6372 IErrorInfo_Release(pErrorInfo);
6376 if (V_VT(&varresult) != VT_ERROR)
6378 TRACE("varresult value: ");
6379 dump_Variant(&varresult);
6381 if (pVarResult)
6383 VariantClear(pVarResult);
6384 *pVarResult = varresult;
6386 else
6387 VariantClear(&varresult);
6390 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6391 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6392 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6393 (pDispParams->cArgs != 0))
6395 if (V_VT(pVarResult) == VT_DISPATCH)
6397 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6398 /* Note: not VariantClear; we still need the dispatch
6399 * pointer to be valid */
6400 VariantInit(pVarResult);
6401 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6402 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6403 pDispParams, pVarResult, pExcepInfo, pArgErr);
6404 IDispatch_Release(pDispatch);
6406 else
6408 VariantClear(pVarResult);
6409 hres = DISP_E_NOTACOLLECTION;
6413 func_fail:
6414 HeapFree(GetProcessHeap(), 0, buffer);
6415 break;
6417 case FUNC_DISPATCH: {
6418 IDispatch *disp;
6420 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6421 if (SUCCEEDED(hres)) {
6422 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6423 hres = IDispatch_Invoke(
6424 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6425 pVarResult,pExcepInfo,pArgErr
6427 if (FAILED(hres))
6428 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6429 IDispatch_Release(disp);
6430 } else
6431 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6432 break;
6434 default:
6435 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6436 hres = E_FAIL;
6437 break;
6440 TRACE("-- 0x%08x\n", hres);
6441 return hres;
6443 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6444 VARDESC *var_desc;
6446 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6447 if(FAILED(hres)) return hres;
6449 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6450 dump_VARDESC(var_desc);
6451 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6452 return E_NOTIMPL;
6455 /* not found, look for it in inherited interfaces */
6456 ITypeInfo2_GetTypeKind(iface, &type_kind);
6457 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6458 if(This->impltypelist) {
6459 /* recursive search */
6460 ITypeInfo *pTInfo;
6461 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6462 if(SUCCEEDED(hres)){
6463 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6464 ITypeInfo_Release(pTInfo);
6465 return hres;
6467 WARN("Could not search inherited interface!\n");
6470 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6471 return DISP_E_MEMBERNOTFOUND;
6474 /* ITypeInfo::GetDocumentation
6476 * Retrieves the documentation string, the complete Help file name and path,
6477 * and the context ID for the Help topic for a specified type description.
6479 * (Can be tested by the Visual Basic Editor in Word for instance.)
6481 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6482 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6483 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6485 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6486 const TLBFuncDesc *pFDesc;
6487 const TLBVarDesc *pVDesc;
6488 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6489 " HelpContext(%p) HelpFile(%p)\n",
6490 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6491 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6492 if(pBstrName)
6493 *pBstrName=SysAllocString(This->Name);
6494 if(pBstrDocString)
6495 *pBstrDocString=SysAllocString(This->DocString);
6496 if(pdwHelpContext)
6497 *pdwHelpContext=This->dwHelpContext;
6498 if(pBstrHelpFile)
6499 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6500 return S_OK;
6501 }else {/* for a member */
6502 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6503 if(pFDesc->funcdesc.memid==memid){
6504 if(pBstrName)
6505 *pBstrName = SysAllocString(pFDesc->Name);
6506 if(pBstrDocString)
6507 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6508 if(pdwHelpContext)
6509 *pdwHelpContext=pFDesc->helpcontext;
6510 return S_OK;
6512 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6513 if(pVDesc->vardesc.memid==memid){
6514 if(pBstrName)
6515 *pBstrName = SysAllocString(pVDesc->Name);
6516 if(pBstrDocString)
6517 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6518 if(pdwHelpContext)
6519 *pdwHelpContext=pVDesc->HelpContext;
6520 return S_OK;
6524 if(This->impltypelist &&
6525 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6526 /* recursive search */
6527 ITypeInfo *pTInfo;
6528 HRESULT result;
6529 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6530 &pTInfo);
6531 if(SUCCEEDED(result)) {
6532 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6533 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6534 ITypeInfo_Release(pTInfo);
6535 return result;
6537 WARN("Could not search inherited interface!\n");
6540 WARN("member %d not found\n", memid);
6541 return TYPE_E_ELEMENTNOTFOUND;
6544 /* ITypeInfo::GetDllEntry
6546 * Retrieves a description or specification of an entry point for a function
6547 * in a DLL.
6549 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6550 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6551 WORD *pwOrdinal)
6553 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6554 const TLBFuncDesc *pFDesc;
6556 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6558 if (pBstrDllName) *pBstrDllName = NULL;
6559 if (pBstrName) *pBstrName = NULL;
6560 if (pwOrdinal) *pwOrdinal = 0;
6562 if (This->TypeAttr.typekind != TKIND_MODULE)
6563 return TYPE_E_BADMODULEKIND;
6565 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6566 if(pFDesc->funcdesc.memid==memid){
6567 dump_TypeInfo(This);
6568 if (TRACE_ON(ole))
6569 dump_TLBFuncDescOne(pFDesc);
6571 if (pBstrDllName)
6572 *pBstrDllName = SysAllocString(This->DllName);
6574 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6575 if (pBstrName)
6576 *pBstrName = SysAllocString(pFDesc->Entry);
6577 if (pwOrdinal)
6578 *pwOrdinal = -1;
6579 return S_OK;
6581 if (pBstrName)
6582 *pBstrName = NULL;
6583 if (pwOrdinal)
6584 *pwOrdinal = (DWORD)pFDesc->Entry;
6585 return S_OK;
6587 return TYPE_E_ELEMENTNOTFOUND;
6590 /* internal function to make the inherited interfaces' methods appear
6591 * part of the interface */
6592 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6593 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6595 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6596 HRESULT hr;
6598 TRACE("%p, 0x%x\n", iface, *hRefType);
6600 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6602 ITypeInfo *pSubTypeInfo;
6604 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6605 if (FAILED(hr))
6606 return hr;
6608 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6609 hRefType, ppTInfo);
6610 ITypeInfo_Release(pSubTypeInfo);
6611 if (SUCCEEDED(hr))
6612 return hr;
6614 *hRefType -= DISPATCH_HREF_OFFSET;
6616 if (!(*hRefType & DISPATCH_HREF_MASK))
6617 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6618 else
6619 return E_FAIL;
6622 /* ITypeInfo::GetRefTypeInfo
6624 * If a type description references other type descriptions, it retrieves
6625 * the referenced type descriptions.
6627 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6628 ITypeInfo2 *iface,
6629 HREFTYPE hRefType,
6630 ITypeInfo **ppTInfo)
6632 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6633 HRESULT result = E_FAIL;
6635 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6637 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6638 ITypeInfo_AddRef(*ppTInfo);
6639 result = S_OK;
6641 else if (hRefType == -1 &&
6642 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6643 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6645 /* when we meet a DUAL dispinterface, we must create the interface
6646 * version of it.
6648 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6651 /* the interface version contains the same information as the dispinterface
6652 * copy the contents of the structs.
6654 *pTypeInfoImpl = *This;
6655 pTypeInfoImpl->ref = 0;
6657 /* change the type to interface */
6658 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6660 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6662 /* we use data structures from This, so we need to keep a reference
6663 * to it to stop it being destroyed and signal to the new instance to
6664 * not free its data structures when it is destroyed */
6665 pTypeInfoImpl->no_free_data = TRUE;
6666 pTypeInfoImpl->next = This;
6667 ITypeInfo_AddRef((ITypeInfo*) This);
6669 ITypeInfo_AddRef(*ppTInfo);
6671 result = S_OK;
6673 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6674 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6675 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6677 HREFTYPE href_dispatch = hRefType;
6678 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6679 } else {
6680 TLBRefType *ref_type;
6681 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6683 if(ref_type->reference == hRefType)
6684 break;
6686 if(&ref_type->entry == &This->pTypeLib->ref_list)
6688 FIXME("Can't find pRefType for ref %x\n", hRefType);
6689 goto end;
6691 if(hRefType != -1) {
6692 ITypeLib *pTLib = NULL;
6694 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6695 UINT Index;
6696 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6697 } else {
6698 if(ref_type->pImpTLInfo->pImpTypeLib) {
6699 TRACE("typeinfo in imported typelib that is already loaded\n");
6700 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6701 ITypeLib2_AddRef(pTLib);
6702 result = S_OK;
6703 } else {
6704 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6705 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6706 ref_type->pImpTLInfo->wVersionMajor,
6707 ref_type->pImpTLInfo->wVersionMinor,
6708 ref_type->pImpTLInfo->lcid,
6709 &pTLib);
6711 if(FAILED(result)) {
6712 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6713 result=LoadTypeLib(libnam, &pTLib);
6714 SysFreeString(libnam);
6716 if(SUCCEEDED(result)) {
6717 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6718 ITypeLib2_AddRef(pTLib);
6722 if(SUCCEEDED(result)) {
6723 if(ref_type->index == TLB_REF_USE_GUID)
6724 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6725 &ref_type->guid,
6726 ppTInfo);
6727 else
6728 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6729 ppTInfo);
6731 if (pTLib != NULL)
6732 ITypeLib2_Release(pTLib);
6736 end:
6737 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6738 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6739 return result;
6742 /* ITypeInfo::AddressOfMember
6744 * Retrieves the addresses of static functions or variables, such as those
6745 * defined in a DLL.
6747 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6748 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6750 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6751 HRESULT hr;
6752 BSTR dll, entry;
6753 WORD ordinal;
6754 HMODULE module;
6756 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6758 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6759 if (FAILED(hr))
6760 return hr;
6762 module = LoadLibraryW(dll);
6763 if (!module)
6765 ERR("couldn't load %s\n", debugstr_w(dll));
6766 SysFreeString(dll);
6767 SysFreeString(entry);
6768 return STG_E_FILENOTFOUND;
6770 /* FIXME: store library somewhere where we can free it */
6772 if (entry)
6774 LPSTR entryA;
6775 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6776 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6777 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6779 *ppv = GetProcAddress(module, entryA);
6780 if (!*ppv)
6781 ERR("function not found %s\n", debugstr_a(entryA));
6783 HeapFree(GetProcessHeap(), 0, entryA);
6785 else
6787 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6788 if (!*ppv)
6789 ERR("function not found %d\n", ordinal);
6792 SysFreeString(dll);
6793 SysFreeString(entry);
6795 if (!*ppv)
6796 return TYPE_E_DLLFUNCTIONNOTFOUND;
6798 return S_OK;
6801 /* ITypeInfo::CreateInstance
6803 * Creates a new instance of a type that describes a component object class
6804 * (coclass).
6806 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6807 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6809 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6810 HRESULT hr;
6811 TYPEATTR *pTA;
6813 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6815 *ppvObj = NULL;
6817 if(pOuterUnk)
6819 WARN("Not able to aggregate\n");
6820 return CLASS_E_NOAGGREGATION;
6823 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6824 if(FAILED(hr)) return hr;
6826 if(pTA->typekind != TKIND_COCLASS)
6828 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6829 hr = E_INVALIDARG;
6830 goto end;
6833 hr = S_FALSE;
6834 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6836 IUnknown *pUnk;
6837 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6838 TRACE("GetActiveObject rets %08x\n", hr);
6839 if(hr == S_OK)
6841 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6842 IUnknown_Release(pUnk);
6846 if(hr != S_OK)
6847 hr = CoCreateInstance(&pTA->guid, NULL,
6848 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6849 riid, ppvObj);
6851 end:
6852 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6853 return hr;
6856 /* ITypeInfo::GetMops
6858 * Retrieves marshalling information.
6860 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6861 BSTR *pBstrMops)
6863 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6864 FIXME("(%p) stub!\n", This);
6865 return S_OK;
6868 /* ITypeInfo::GetContainingTypeLib
6870 * Retrieves the containing type library and the index of the type description
6871 * within that type library.
6873 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6874 ITypeLib * *ppTLib, UINT *pIndex)
6876 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6878 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6879 if (pIndex) {
6880 *pIndex=This->index;
6881 TRACE("returning pIndex=%d\n", *pIndex);
6884 if (ppTLib) {
6885 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6886 ITypeLib2_AddRef(*ppTLib);
6887 TRACE("returning ppTLib=%p\n", *ppTLib);
6890 return S_OK;
6893 /* ITypeInfo::ReleaseTypeAttr
6895 * Releases a TYPEATTR previously returned by GetTypeAttr.
6898 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6899 TYPEATTR* pTypeAttr)
6901 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6902 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6903 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6906 /* ITypeInfo::ReleaseFuncDesc
6908 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6910 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6911 ITypeInfo2 *iface,
6912 FUNCDESC *pFuncDesc)
6914 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6915 SHORT i;
6917 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6919 for (i = 0; i < pFuncDesc->cParams; i++)
6920 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6921 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6923 SysFreeString((BSTR)pFuncDesc);
6926 /* ITypeInfo::ReleaseVarDesc
6928 * Releases a VARDESC previously returned by GetVarDesc.
6930 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6931 VARDESC *pVarDesc)
6933 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6934 TRACE("(%p)->(%p)\n", This, pVarDesc);
6936 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6937 if (pVarDesc->varkind == VAR_CONST)
6938 VariantClear(pVarDesc->u.lpvarValue);
6939 SysFreeString((BSTR)pVarDesc);
6942 /* ITypeInfo2::GetTypeKind
6944 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6947 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6948 TYPEKIND *pTypeKind)
6950 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6951 *pTypeKind=This->TypeAttr.typekind;
6952 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6953 return S_OK;
6956 /* ITypeInfo2::GetTypeFlags
6958 * Returns the type flags without any allocations. This returns a DWORD type
6959 * flag, which expands the type flags without growing the TYPEATTR (type
6960 * attribute).
6963 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6965 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6966 *pTypeFlags=This->TypeAttr.wTypeFlags;
6967 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6968 return S_OK;
6971 /* ITypeInfo2::GetFuncIndexOfMemId
6972 * Binds to a specific member based on a known DISPID, where the member name
6973 * is not known (for example, when binding to a default member).
6976 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6977 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6979 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6980 const TLBFuncDesc *pFuncInfo;
6981 int i;
6982 HRESULT result;
6984 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6985 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6986 break;
6987 if(pFuncInfo) {
6988 *pFuncIndex = i;
6989 result = S_OK;
6990 } else
6991 result = TYPE_E_ELEMENTNOTFOUND;
6993 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6994 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6995 return result;
6998 /* TypeInfo2::GetVarIndexOfMemId
7000 * Binds to a specific member based on a known DISPID, where the member name
7001 * is not known (for example, when binding to a default member).
7004 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7005 MEMBERID memid, UINT *pVarIndex)
7007 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7008 TLBVarDesc *pVarInfo;
7009 int i;
7010 HRESULT result;
7011 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7012 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7014 if(pVarInfo) {
7015 *pVarIndex = i;
7016 result = S_OK;
7017 } else
7018 result = TYPE_E_ELEMENTNOTFOUND;
7020 TRACE("(%p) memid 0x%08x -> %s\n", This,
7021 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7022 return result;
7025 /* ITypeInfo2::GetCustData
7027 * Gets the custom data
7029 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7030 ITypeInfo2 * iface,
7031 REFGUID guid,
7032 VARIANT *pVarVal)
7034 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7035 TLBCustData *pCData;
7037 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7038 if( IsEqualIID(guid, &pCData->guid)) break;
7040 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7042 if(pCData)
7044 VariantInit( pVarVal);
7045 VariantCopy( pVarVal, &pCData->data);
7046 return S_OK;
7048 return E_INVALIDARG; /* FIXME: correct? */
7051 /* ITypeInfo2::GetFuncCustData
7053 * Gets the custom data
7055 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7056 ITypeInfo2 * iface,
7057 UINT index,
7058 REFGUID guid,
7059 VARIANT *pVarVal)
7061 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7062 TLBCustData *pCData=NULL;
7063 TLBFuncDesc * pFDesc;
7064 UINT i;
7065 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7066 pFDesc=pFDesc->next);
7068 if(pFDesc)
7069 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7070 if( IsEqualIID(guid, &pCData->guid)) break;
7072 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7074 if(pCData){
7075 VariantInit( pVarVal);
7076 VariantCopy( pVarVal, &pCData->data);
7077 return S_OK;
7079 return E_INVALIDARG; /* FIXME: correct? */
7082 /* ITypeInfo2::GetParamCustData
7084 * Gets the custom data
7086 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7087 ITypeInfo2 * iface,
7088 UINT indexFunc,
7089 UINT indexParam,
7090 REFGUID guid,
7091 VARIANT *pVarVal)
7093 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7094 TLBCustData *pCData=NULL;
7095 TLBFuncDesc * pFDesc;
7096 UINT i;
7098 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7100 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7101 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7102 pCData = pCData->next)
7103 if( IsEqualIID(guid, &pCData->guid)) break;
7105 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7107 if(pCData)
7109 VariantInit( pVarVal);
7110 VariantCopy( pVarVal, &pCData->data);
7111 return S_OK;
7113 return E_INVALIDARG; /* FIXME: correct? */
7116 /* ITypeInfo2::GetVarCustData
7118 * Gets the custom data
7120 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7121 ITypeInfo2 * iface,
7122 UINT index,
7123 REFGUID guid,
7124 VARIANT *pVarVal)
7126 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7127 TLBCustData *pCData=NULL;
7128 TLBVarDesc * pVDesc;
7129 UINT i;
7131 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7133 if(pVDesc)
7135 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7137 if( IsEqualIID(guid, &pCData->guid)) break;
7141 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7143 if(pCData)
7145 VariantInit( pVarVal);
7146 VariantCopy( pVarVal, &pCData->data);
7147 return S_OK;
7149 return E_INVALIDARG; /* FIXME: correct? */
7152 /* ITypeInfo2::GetImplCustData
7154 * Gets the custom data
7156 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7157 ITypeInfo2 * iface,
7158 UINT index,
7159 REFGUID guid,
7160 VARIANT *pVarVal)
7162 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7163 TLBCustData *pCData=NULL;
7164 TLBImplType * pRDesc;
7165 UINT i;
7167 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7169 if(pRDesc)
7171 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7173 if( IsEqualIID(guid, &pCData->guid)) break;
7177 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7179 if(pCData)
7181 VariantInit( pVarVal);
7182 VariantCopy( pVarVal, &pCData->data);
7183 return S_OK;
7185 return E_INVALIDARG; /* FIXME: correct? */
7188 /* ITypeInfo2::GetDocumentation2
7190 * Retrieves the documentation string, the complete Help file name and path,
7191 * the localization context to use, and the context ID for the library Help
7192 * topic in the Help file.
7195 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7196 ITypeInfo2 * iface,
7197 MEMBERID memid,
7198 LCID lcid,
7199 BSTR *pbstrHelpString,
7200 DWORD *pdwHelpStringContext,
7201 BSTR *pbstrHelpStringDll)
7203 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7204 const TLBFuncDesc *pFDesc;
7205 const TLBVarDesc *pVDesc;
7206 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7207 "HelpStringContext(%p) HelpStringDll(%p)\n",
7208 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7209 pbstrHelpStringDll );
7210 /* the help string should be obtained from the helpstringdll,
7211 * using the _DLLGetDocumentation function, based on the supplied
7212 * lcid. Nice to do sometime...
7214 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7215 if(pbstrHelpString)
7216 *pbstrHelpString=SysAllocString(This->Name);
7217 if(pdwHelpStringContext)
7218 *pdwHelpStringContext=This->dwHelpStringContext;
7219 if(pbstrHelpStringDll)
7220 *pbstrHelpStringDll=
7221 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7222 return S_OK;
7223 }else {/* for a member */
7224 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7225 if(pFDesc->funcdesc.memid==memid){
7226 if(pbstrHelpString)
7227 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7228 if(pdwHelpStringContext)
7229 *pdwHelpStringContext=pFDesc->HelpStringContext;
7230 if(pbstrHelpStringDll)
7231 *pbstrHelpStringDll=
7232 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7233 return S_OK;
7235 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7236 if(pVDesc->vardesc.memid==memid){
7237 if(pbstrHelpString)
7238 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7239 if(pdwHelpStringContext)
7240 *pdwHelpStringContext=pVDesc->HelpStringContext;
7241 if(pbstrHelpStringDll)
7242 *pbstrHelpStringDll=
7243 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7244 return S_OK;
7247 return TYPE_E_ELEMENTNOTFOUND;
7250 /* ITypeInfo2::GetAllCustData
7252 * Gets all custom data items for the Type info.
7255 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7256 ITypeInfo2 * iface,
7257 CUSTDATA *pCustData)
7259 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7260 TLBCustData *pCData;
7261 int i;
7263 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7265 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7266 if(pCustData->prgCustData ){
7267 pCustData->cCustData=This->ctCustData;
7268 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7269 pCustData->prgCustData[i].guid=pCData->guid;
7270 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7272 }else{
7273 ERR(" OUT OF MEMORY!\n");
7274 return E_OUTOFMEMORY;
7276 return S_OK;
7279 /* ITypeInfo2::GetAllFuncCustData
7281 * Gets all custom data items for the specified Function
7284 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7285 ITypeInfo2 * iface,
7286 UINT index,
7287 CUSTDATA *pCustData)
7289 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7290 TLBCustData *pCData;
7291 TLBFuncDesc * pFDesc;
7292 UINT i;
7293 TRACE("(%p) index %d\n", This, index);
7294 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7295 pFDesc=pFDesc->next)
7297 if(pFDesc){
7298 pCustData->prgCustData =
7299 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7300 if(pCustData->prgCustData ){
7301 pCustData->cCustData=pFDesc->ctCustData;
7302 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7303 pCData = pCData->next){
7304 pCustData->prgCustData[i].guid=pCData->guid;
7305 VariantCopy(& pCustData->prgCustData[i].varValue,
7306 & pCData->data);
7308 }else{
7309 ERR(" OUT OF MEMORY!\n");
7310 return E_OUTOFMEMORY;
7312 return S_OK;
7314 return TYPE_E_ELEMENTNOTFOUND;
7317 /* ITypeInfo2::GetAllParamCustData
7319 * Gets all custom data items for the Functions
7322 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7323 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7325 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7326 TLBCustData *pCData=NULL;
7327 TLBFuncDesc * pFDesc;
7328 UINT i;
7329 TRACE("(%p) index %d\n", This, indexFunc);
7330 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7331 pFDesc=pFDesc->next)
7333 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7334 pCustData->prgCustData =
7335 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7336 sizeof(CUSTDATAITEM));
7337 if(pCustData->prgCustData ){
7338 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7339 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7340 pCData; i++, pCData = pCData->next){
7341 pCustData->prgCustData[i].guid=pCData->guid;
7342 VariantCopy(& pCustData->prgCustData[i].varValue,
7343 & pCData->data);
7345 }else{
7346 ERR(" OUT OF MEMORY!\n");
7347 return E_OUTOFMEMORY;
7349 return S_OK;
7351 return TYPE_E_ELEMENTNOTFOUND;
7354 /* ITypeInfo2::GetAllVarCustData
7356 * Gets all custom data items for the specified Variable
7359 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7360 UINT index, CUSTDATA *pCustData)
7362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7363 TLBCustData *pCData;
7364 TLBVarDesc * pVDesc;
7365 UINT i;
7366 TRACE("(%p) index %d\n", This, index);
7367 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7368 pVDesc=pVDesc->next)
7370 if(pVDesc){
7371 pCustData->prgCustData =
7372 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7373 if(pCustData->prgCustData ){
7374 pCustData->cCustData=pVDesc->ctCustData;
7375 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7376 pCData = pCData->next){
7377 pCustData->prgCustData[i].guid=pCData->guid;
7378 VariantCopy(& pCustData->prgCustData[i].varValue,
7379 & pCData->data);
7381 }else{
7382 ERR(" OUT OF MEMORY!\n");
7383 return E_OUTOFMEMORY;
7385 return S_OK;
7387 return TYPE_E_ELEMENTNOTFOUND;
7390 /* ITypeInfo2::GetAllImplCustData
7392 * Gets all custom data items for the specified implementation type
7395 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7396 ITypeInfo2 * iface,
7397 UINT index,
7398 CUSTDATA *pCustData)
7400 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7401 TLBCustData *pCData;
7402 TLBImplType * pRDesc;
7403 UINT i;
7404 TRACE("(%p) index %d\n", This, index);
7405 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7406 pRDesc=pRDesc->next)
7408 if(pRDesc){
7409 pCustData->prgCustData =
7410 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7411 if(pCustData->prgCustData ){
7412 pCustData->cCustData=pRDesc->ctCustData;
7413 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7414 pCData = pCData->next){
7415 pCustData->prgCustData[i].guid=pCData->guid;
7416 VariantCopy(& pCustData->prgCustData[i].varValue,
7417 & pCData->data);
7419 }else{
7420 ERR(" OUT OF MEMORY!\n");
7421 return E_OUTOFMEMORY;
7423 return S_OK;
7425 return TYPE_E_ELEMENTNOTFOUND;
7428 static const ITypeInfo2Vtbl tinfvt =
7431 ITypeInfo_fnQueryInterface,
7432 ITypeInfo_fnAddRef,
7433 ITypeInfo_fnRelease,
7435 ITypeInfo_fnGetTypeAttr,
7436 ITypeInfo_fnGetTypeComp,
7437 ITypeInfo_fnGetFuncDesc,
7438 ITypeInfo_fnGetVarDesc,
7439 ITypeInfo_fnGetNames,
7440 ITypeInfo_fnGetRefTypeOfImplType,
7441 ITypeInfo_fnGetImplTypeFlags,
7442 ITypeInfo_fnGetIDsOfNames,
7443 ITypeInfo_fnInvoke,
7444 ITypeInfo_fnGetDocumentation,
7445 ITypeInfo_fnGetDllEntry,
7446 ITypeInfo_fnGetRefTypeInfo,
7447 ITypeInfo_fnAddressOfMember,
7448 ITypeInfo_fnCreateInstance,
7449 ITypeInfo_fnGetMops,
7450 ITypeInfo_fnGetContainingTypeLib,
7451 ITypeInfo_fnReleaseTypeAttr,
7452 ITypeInfo_fnReleaseFuncDesc,
7453 ITypeInfo_fnReleaseVarDesc,
7455 ITypeInfo2_fnGetTypeKind,
7456 ITypeInfo2_fnGetTypeFlags,
7457 ITypeInfo2_fnGetFuncIndexOfMemId,
7458 ITypeInfo2_fnGetVarIndexOfMemId,
7459 ITypeInfo2_fnGetCustData,
7460 ITypeInfo2_fnGetFuncCustData,
7461 ITypeInfo2_fnGetParamCustData,
7462 ITypeInfo2_fnGetVarCustData,
7463 ITypeInfo2_fnGetImplTypeCustData,
7464 ITypeInfo2_fnGetDocumentation2,
7465 ITypeInfo2_fnGetAllCustData,
7466 ITypeInfo2_fnGetAllFuncCustData,
7467 ITypeInfo2_fnGetAllParamCustData,
7468 ITypeInfo2_fnGetAllVarCustData,
7469 ITypeInfo2_fnGetAllImplTypeCustData,
7472 /******************************************************************************
7473 * CreateDispTypeInfo [OLEAUT32.31]
7475 * Build type information for an object so it can be called through an
7476 * IDispatch interface.
7478 * RETURNS
7479 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7480 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7482 * NOTES
7483 * This call allows an objects methods to be accessed through IDispatch, by
7484 * building an ITypeInfo object that IDispatch can use to call through.
7486 HRESULT WINAPI CreateDispTypeInfo(
7487 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7488 LCID lcid, /* [I] Locale Id */
7489 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7491 ITypeInfoImpl *pTIClass, *pTIIface;
7492 ITypeLibImpl *pTypeLibImpl;
7493 unsigned int param, func;
7494 TLBFuncDesc **ppFuncDesc;
7495 TLBRefType *ref;
7497 TRACE("\n");
7498 pTypeLibImpl = TypeLibImpl_Constructor();
7499 if (!pTypeLibImpl) return E_FAIL;
7501 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7502 pTIIface->pTypeLib = pTypeLibImpl;
7503 pTIIface->index = 0;
7504 pTIIface->Name = NULL;
7505 pTIIface->dwHelpContext = -1;
7506 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7507 pTIIface->TypeAttr.lcid = lcid;
7508 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7509 pTIIface->TypeAttr.wMajorVerNum = 0;
7510 pTIIface->TypeAttr.wMinorVerNum = 0;
7511 pTIIface->TypeAttr.cbAlignment = 2;
7512 pTIIface->TypeAttr.cbSizeInstance = -1;
7513 pTIIface->TypeAttr.cbSizeVft = -1;
7514 pTIIface->TypeAttr.cFuncs = 0;
7515 pTIIface->TypeAttr.cImplTypes = 0;
7516 pTIIface->TypeAttr.cVars = 0;
7517 pTIIface->TypeAttr.wTypeFlags = 0;
7519 ppFuncDesc = &pTIIface->funclist;
7520 for(func = 0; func < pidata->cMembers; func++) {
7521 METHODDATA *md = pidata->pmethdata + func;
7522 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7523 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7524 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7525 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7526 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7527 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7528 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7529 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7530 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7531 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7532 (*ppFuncDesc)->funcdesc.cScodes = 0;
7533 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7534 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7535 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7536 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7537 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7538 md->cArgs * sizeof(ELEMDESC));
7539 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7540 md->cArgs * sizeof(TLBParDesc));
7541 for(param = 0; param < md->cArgs; param++) {
7542 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7543 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7545 (*ppFuncDesc)->helpcontext = 0;
7546 (*ppFuncDesc)->HelpStringContext = 0;
7547 (*ppFuncDesc)->HelpString = NULL;
7548 (*ppFuncDesc)->Entry = NULL;
7549 (*ppFuncDesc)->ctCustData = 0;
7550 (*ppFuncDesc)->pCustData = NULL;
7551 (*ppFuncDesc)->next = NULL;
7552 pTIIface->TypeAttr.cFuncs++;
7553 ppFuncDesc = &(*ppFuncDesc)->next;
7556 dump_TypeInfo(pTIIface);
7558 pTypeLibImpl->pTypeInfo = pTIIface;
7559 pTypeLibImpl->TypeInfoCount++;
7561 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7562 pTIClass->pTypeLib = pTypeLibImpl;
7563 pTIClass->index = 1;
7564 pTIClass->Name = NULL;
7565 pTIClass->dwHelpContext = -1;
7566 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7567 pTIClass->TypeAttr.lcid = lcid;
7568 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7569 pTIClass->TypeAttr.wMajorVerNum = 0;
7570 pTIClass->TypeAttr.wMinorVerNum = 0;
7571 pTIClass->TypeAttr.cbAlignment = 2;
7572 pTIClass->TypeAttr.cbSizeInstance = -1;
7573 pTIClass->TypeAttr.cbSizeVft = -1;
7574 pTIClass->TypeAttr.cFuncs = 0;
7575 pTIClass->TypeAttr.cImplTypes = 1;
7576 pTIClass->TypeAttr.cVars = 0;
7577 pTIClass->TypeAttr.wTypeFlags = 0;
7579 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7580 pTIClass->impltypelist->hRef = 0;
7582 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7583 ref->index = 0;
7584 ref->reference = 0;
7585 ref->pImpTLInfo = TLB_REF_INTERNAL;
7586 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7588 dump_TypeInfo(pTIClass);
7590 pTIIface->next = pTIClass;
7591 pTypeLibImpl->TypeInfoCount++;
7593 *pptinfo = (ITypeInfo*)pTIClass;
7595 ITypeInfo_AddRef(*pptinfo);
7596 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7598 return S_OK;
7602 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7604 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7606 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7609 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7611 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7613 return ITypeInfo_AddRef((ITypeInfo *)This);
7616 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7618 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7620 return ITypeInfo_Release((ITypeInfo *)This);
7623 static HRESULT WINAPI ITypeComp_fnBind(
7624 ITypeComp * iface,
7625 OLECHAR * szName,
7626 ULONG lHash,
7627 WORD wFlags,
7628 ITypeInfo ** ppTInfo,
7629 DESCKIND * pDescKind,
7630 BINDPTR * pBindPtr)
7632 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7633 const TLBFuncDesc *pFDesc;
7634 const TLBVarDesc *pVDesc;
7635 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7637 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7639 *pDescKind = DESCKIND_NONE;
7640 pBindPtr->lpfuncdesc = NULL;
7641 *ppTInfo = NULL;
7643 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7644 if (!strcmpiW(pFDesc->Name, szName)) {
7645 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7646 break;
7647 else
7648 /* name found, but wrong flags */
7649 hr = TYPE_E_TYPEMISMATCH;
7652 if (pFDesc)
7654 HRESULT hr = TLB_AllocAndInitFuncDesc(
7655 &pFDesc->funcdesc,
7656 &pBindPtr->lpfuncdesc,
7657 This->TypeAttr.typekind == TKIND_DISPATCH);
7658 if (FAILED(hr))
7659 return hr;
7660 *pDescKind = DESCKIND_FUNCDESC;
7661 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7662 ITypeInfo_AddRef(*ppTInfo);
7663 return S_OK;
7664 } else {
7665 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7666 if (!strcmpiW(pVDesc->Name, szName)) {
7667 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7668 if (FAILED(hr))
7669 return hr;
7670 *pDescKind = DESCKIND_VARDESC;
7671 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7672 ITypeInfo_AddRef(*ppTInfo);
7673 return S_OK;
7677 /* FIXME: search each inherited interface, not just the first */
7678 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7679 /* recursive search */
7680 ITypeInfo *pTInfo;
7681 ITypeComp *pTComp;
7682 HRESULT hr;
7683 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7684 if (SUCCEEDED(hr))
7686 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7687 ITypeInfo_Release(pTInfo);
7689 if (SUCCEEDED(hr))
7691 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7692 ITypeComp_Release(pTComp);
7693 return hr;
7695 WARN("Could not search inherited interface!\n");
7697 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7698 return hr;
7701 static HRESULT WINAPI ITypeComp_fnBindType(
7702 ITypeComp * iface,
7703 OLECHAR * szName,
7704 ULONG lHash,
7705 ITypeInfo ** ppTInfo,
7706 ITypeComp ** ppTComp)
7708 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7710 /* strange behaviour (does nothing) but like the
7711 * original */
7713 if (!ppTInfo || !ppTComp)
7714 return E_POINTER;
7716 *ppTInfo = NULL;
7717 *ppTComp = NULL;
7719 return S_OK;
7722 static const ITypeCompVtbl tcompvt =
7725 ITypeComp_fnQueryInterface,
7726 ITypeComp_fnAddRef,
7727 ITypeComp_fnRelease,
7729 ITypeComp_fnBind,
7730 ITypeComp_fnBindType