oleaut32: Store PARAMDESCEX structure inside lprgelemdescParam.
[wine.git] / dlls / oleaut32 / typelib.c
bloba8916d80c4402700c51dad1e1f49a74083c33ae2
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 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
63 #include "winerror.h"
64 #include "windef.h"
65 #include "winbase.h"
66 #include "winnls.h"
67 #include "winreg.h"
68 #include "winuser.h"
69 #include "winternl.h"
70 #include "lzexpand.h"
72 #include "wine/unicode.h"
73 #include "objbase.h"
74 #include "typelib.h"
75 #include "wine/debug.h"
76 #include "variant.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib);
82 typedef struct
84 WORD offset;
85 WORD length;
86 WORD flags;
87 WORD id;
88 WORD handle;
89 WORD usage;
90 } NE_NAMEINFO;
92 typedef struct
94 WORD type_id; /* Type identifier */
95 WORD count; /* Number of resources of this type */
96 DWORD resloader; /* SetResourceHandler() */
98 * Name info array.
100 } NE_TYPEINFO;
102 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
103 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
105 /****************************************************************************
106 * FromLExxx
108 * Takes p_iVal (which is in little endian) and returns it
109 * in the host machine's byte order.
111 #ifdef WORDS_BIGENDIAN
112 static WORD FromLEWord(WORD p_iVal)
114 return (((p_iVal & 0x00FF) << 8) |
115 ((p_iVal & 0xFF00) >> 8));
119 static DWORD FromLEDWord(DWORD p_iVal)
121 return (((p_iVal & 0x000000FF) << 24) |
122 ((p_iVal & 0x0000FF00) << 8) |
123 ((p_iVal & 0x00FF0000) >> 8) |
124 ((p_iVal & 0xFF000000) >> 24));
126 #else
127 #define FromLEWord(X) (X)
128 #define FromLEDWord(X) (X)
129 #endif
131 #define DISPATCH_HREF_OFFSET 0x01000000
132 #define DISPATCH_HREF_MASK 0xff000000
134 /****************************************************************************
135 * FromLExxx
137 * Fix byte order in any structure if necessary
139 #ifdef WORDS_BIGENDIAN
140 static void FromLEWords(void *p_Val, int p_iSize)
142 WORD *Val = p_Val;
144 p_iSize /= sizeof(WORD);
146 while (p_iSize) {
147 *Val = FromLEWord(*Val);
148 Val++;
149 p_iSize--;
154 static void FromLEDWords(void *p_Val, int p_iSize)
156 DWORD *Val = p_Val;
158 p_iSize /= sizeof(DWORD);
160 while (p_iSize) {
161 *Val = FromLEDWord(*Val);
162 Val++;
163 p_iSize--;
166 #else
167 #define FromLEWords(X,Y) /*nothing*/
168 #define FromLEDWords(X,Y) /*nothing*/
169 #endif
172 * Find a typelib key which matches a requested maj.min version.
174 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
176 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
177 WCHAR buffer[60];
178 char key_name[16];
179 DWORD len, i;
180 INT best_maj = -1, best_min = -1;
181 HKEY hkey;
183 memcpy( buffer, typelibW, sizeof(typelibW) );
184 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
186 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
187 return FALSE;
189 len = sizeof(key_name);
190 i = 0;
191 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
193 INT v_maj, v_min;
195 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
197 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
199 if (*wMaj == 0xffff && *wMin == 0xffff)
201 if (v_maj > best_maj) best_maj = v_maj;
202 if (v_min > best_min) best_min = v_min;
204 else if (*wMaj == v_maj)
206 best_maj = v_maj;
208 if (*wMin == v_min)
210 best_min = v_min;
211 break; /* exact match */
213 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
216 len = sizeof(key_name);
218 RegCloseKey( hkey );
220 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
222 if (*wMaj == 0xffff && *wMin == 0xffff)
224 if (best_maj >= 0 && best_min >= 0)
226 *wMaj = best_maj;
227 *wMin = best_min;
228 return TRUE;
232 if (*wMaj == best_maj && best_min >= 0)
234 *wMin = best_min;
235 return TRUE;
237 return FALSE;
240 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
241 /* buffer must be at least 60 characters long */
242 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
244 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
245 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
247 memcpy( buffer, TypelibW, sizeof(TypelibW) );
248 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
249 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
250 return buffer;
253 /* get the path of an interface key, in the form "Interface\\<guid>" */
254 /* buffer must be at least 50 characters long */
255 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
257 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
259 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
260 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
261 return buffer;
264 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
265 /* buffer must be at least 16 characters long */
266 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
268 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
269 static const WCHAR win16W[] = {'w','i','n','1','6',0};
270 static const WCHAR win32W[] = {'w','i','n','3','2',0};
271 static const WCHAR win64W[] = {'w','i','n','6','4',0};
273 sprintfW( buffer, LcidFormatW, lcid );
274 switch(syskind)
276 case SYS_WIN16: strcatW( buffer, win16W ); break;
277 case SYS_WIN32: strcatW( buffer, win32W ); break;
278 case SYS_WIN64: strcatW( buffer, win64W ); break;
279 default:
280 TRACE("Typelib is for unsupported syskind %i\n", syskind);
281 return NULL;
283 return buffer;
286 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
289 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
290 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
291 SYSKIND syskind, LCID lcid, LPBSTR path )
293 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
294 LCID myLCID = lcid;
295 HKEY hkey;
296 WCHAR buffer[60];
297 WCHAR Path[MAX_PATH];
298 LONG res;
300 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
302 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
303 get_typelib_key( guid, wMaj, wMin, buffer );
305 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
306 if (res == ERROR_FILE_NOT_FOUND)
308 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
309 return TYPE_E_LIBNOTREGISTERED;
311 else if (res != ERROR_SUCCESS)
313 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
314 return TYPE_E_REGISTRYACCESS;
317 while (hr != S_OK)
319 LONG dwPathLen = sizeof(Path);
321 get_lcid_subkey( myLCID, syskind, buffer );
323 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
325 if (!lcid)
326 break;
327 else if (myLCID == lcid)
329 /* try with sub-langid */
330 myLCID = SUBLANGID(lcid);
332 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
334 /* try with system langid */
335 myLCID = 0;
337 else
339 break;
342 else
344 *path = SysAllocString( Path );
345 hr = S_OK;
348 RegCloseKey( hkey );
349 TRACE_(typelib)("-- 0x%08x\n", hr);
350 return hr;
353 /****************************************************************************
354 * QueryPathOfRegTypeLib [OLEAUT32.164]
356 * Gets the path to a registered type library.
358 * PARAMS
359 * guid [I] referenced guid
360 * wMaj [I] major version
361 * wMin [I] minor version
362 * lcid [I] locale id
363 * path [O] path of typelib
365 * RETURNS
366 * Success: S_OK.
367 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
368 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
369 * opened.
371 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
373 #ifdef _WIN64
374 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
375 if(SUCCEEDED(hres))
376 return hres;
377 #endif
378 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
381 /******************************************************************************
382 * CreateTypeLib [OLEAUT32.160] creates a typelib
384 * RETURNS
385 * Success: S_OK
386 * Failure: Status
388 HRESULT WINAPI CreateTypeLib(
389 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
391 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
392 return E_FAIL;
395 /******************************************************************************
396 * LoadTypeLib [OLEAUT32.161]
398 * Loads a type library
400 * PARAMS
401 * szFile [I] Name of file to load from.
402 * pptLib [O] Pointer that receives ITypeLib object on success.
404 * RETURNS
405 * Success: S_OK
406 * Failure: Status
408 * SEE
409 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
411 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
413 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
414 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
417 /******************************************************************************
418 * LoadTypeLibEx [OLEAUT32.183]
420 * Loads and optionally registers a type library
422 * RETURNS
423 * Success: S_OK
424 * Failure: Status
426 HRESULT WINAPI LoadTypeLibEx(
427 LPCOLESTR szFile, /* [in] Name of file to load from */
428 REGKIND regkind, /* [in] Specify kind of registration */
429 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
431 WCHAR szPath[MAX_PATH+1];
432 HRESULT res;
434 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
436 *pptLib = NULL;
438 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
440 if (SUCCEEDED(res))
441 switch(regkind)
443 case REGKIND_DEFAULT:
444 /* don't register typelibs supplied with full path. Experimentation confirms the following */
445 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
446 (szFile[0] && (szFile[1] == ':'))) break;
447 /* else fall-through */
449 case REGKIND_REGISTER:
450 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
452 ITypeLib_Release(*pptLib);
453 *pptLib = 0;
455 break;
456 case REGKIND_NONE:
457 break;
460 TRACE(" returns %08x\n",res);
461 return res;
464 /******************************************************************************
465 * LoadRegTypeLib [OLEAUT32.162]
467 * Loads a registered type library.
469 * PARAMS
470 * rguid [I] GUID of the registered type library.
471 * wVerMajor [I] major version.
472 * wVerMinor [I] minor version.
473 * lcid [I] locale ID.
474 * ppTLib [O] pointer that receives an ITypeLib object on success.
476 * RETURNS
477 * Success: S_OK.
478 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
479 * LoadTypeLib.
481 HRESULT WINAPI LoadRegTypeLib(
482 REFGUID rguid,
483 WORD wVerMajor,
484 WORD wVerMinor,
485 LCID lcid,
486 ITypeLib **ppTLib)
488 BSTR bstr=NULL;
489 HRESULT res;
491 *ppTLib = NULL;
493 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
495 if(SUCCEEDED(res))
497 res= LoadTypeLib(bstr, ppTLib);
498 SysFreeString(bstr);
501 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
503 return res;
507 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
508 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
509 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
510 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
511 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
512 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
514 /******************************************************************************
515 * RegisterTypeLib [OLEAUT32.163]
516 * Adds information about a type library to the System Registry
517 * NOTES
518 * Docs: ITypeLib FAR * ptlib
519 * Docs: OLECHAR FAR* szFullPath
520 * Docs: OLECHAR FAR* szHelpDir
522 * RETURNS
523 * Success: S_OK
524 * Failure: Status
526 HRESULT WINAPI RegisterTypeLib(
527 ITypeLib * ptlib, /* [in] Pointer to the library*/
528 OLECHAR * szFullPath, /* [in] full Path of the library*/
529 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
530 may be NULL*/
532 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
533 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
534 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
535 HRESULT res;
536 TLIBATTR *attr;
537 WCHAR keyName[60];
538 WCHAR tmp[16];
539 HKEY key, subKey;
540 UINT types, tidx;
541 TYPEKIND kind;
542 DWORD disposition;
544 if (ptlib == NULL || szFullPath == NULL)
545 return E_INVALIDARG;
547 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
548 return E_FAIL;
550 #ifdef _WIN64
551 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
552 #else
553 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
554 #endif
556 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
558 res = S_OK;
559 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
560 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
562 LPOLESTR doc;
564 /* Set the human-readable name of the typelib */
565 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
566 res = E_FAIL;
567 else if (doc)
569 if (RegSetValueExW(key, NULL, 0, REG_SZ,
570 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
571 res = E_FAIL;
573 SysFreeString(doc);
576 /* Make up the name of the typelib path subkey */
577 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
579 /* Create the typelib path subkey */
580 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
581 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
583 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
584 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
585 res = E_FAIL;
587 RegCloseKey(subKey);
589 else
590 res = E_FAIL;
592 /* Create the flags subkey */
593 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
594 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
596 /* FIXME: is %u correct? */
597 static const WCHAR formatW[] = {'%','u',0};
598 WCHAR buf[20];
599 sprintfW(buf, formatW, attr->wLibFlags);
600 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
601 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
602 res = E_FAIL;
604 RegCloseKey(subKey);
606 else
607 res = E_FAIL;
609 /* create the helpdir subkey */
610 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
611 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
613 BOOL freeHelpDir = FALSE;
614 OLECHAR* pIndexStr;
616 /* if we created a new key, and helpDir was null, set the helpdir
617 to the directory which contains the typelib. However,
618 if we just opened an existing key, we leave the helpdir alone */
619 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
620 szHelpDir = SysAllocString(szFullPath);
621 pIndexStr = strrchrW(szHelpDir, '\\');
622 if (pIndexStr) {
623 *pIndexStr = 0;
625 freeHelpDir = TRUE;
628 /* if we have an szHelpDir, set it! */
629 if (szHelpDir != NULL) {
630 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
631 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
632 res = E_FAIL;
636 /* tidy up */
637 if (freeHelpDir) SysFreeString(szHelpDir);
638 RegCloseKey(subKey);
640 } else {
641 res = E_FAIL;
644 RegCloseKey(key);
646 else
647 res = E_FAIL;
649 /* register OLE Automation-compatible interfaces for this typelib */
650 types = ITypeLib_GetTypeInfoCount(ptlib);
651 for (tidx=0; tidx<types; tidx++) {
652 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
653 LPOLESTR name = NULL;
654 ITypeInfo *tinfo = NULL;
656 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
658 switch (kind) {
659 case TKIND_INTERFACE:
660 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
661 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
662 break;
664 case TKIND_DISPATCH:
665 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
666 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
667 break;
669 default:
670 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
671 break;
674 if (tinfo) {
675 TYPEATTR *tattr = NULL;
676 ITypeInfo_GetTypeAttr(tinfo, &tattr);
678 if (tattr) {
679 TRACE_(typelib)("guid=%s, flags=%04x (",
680 debugstr_guid(&tattr->guid),
681 tattr->wTypeFlags);
683 if (TRACE_ON(typelib)) {
684 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
685 XX(FAPPOBJECT);
686 XX(FCANCREATE);
687 XX(FLICENSED);
688 XX(FPREDECLID);
689 XX(FHIDDEN);
690 XX(FCONTROL);
691 XX(FDUAL);
692 XX(FNONEXTENSIBLE);
693 XX(FOLEAUTOMATION);
694 XX(FRESTRICTED);
695 XX(FAGGREGATABLE);
696 XX(FREPLACEABLE);
697 XX(FDISPATCHABLE);
698 XX(FREVERSEBIND);
699 XX(FPROXY);
700 #undef XX
701 MESSAGE("\n");
704 /* Register all dispinterfaces (which includes dual interfaces) and
705 oleautomation interfaces */
706 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
707 kind == TKIND_DISPATCH)
709 /* register interface<->typelib coupling */
710 get_interface_key( &tattr->guid, keyName );
711 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
712 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
714 if (name)
715 RegSetValueExW(key, NULL, 0, REG_SZ,
716 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
718 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
719 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
720 RegSetValueExW(subKey, NULL, 0, REG_SZ,
721 (const BYTE *)PSOA, sizeof PSOA);
722 RegCloseKey(subKey);
725 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
726 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
727 RegSetValueExW(subKey, NULL, 0, REG_SZ,
728 (const BYTE *)PSOA, sizeof PSOA);
729 RegCloseKey(subKey);
732 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
733 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
735 WCHAR buffer[40];
736 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
737 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
739 StringFromGUID2(&attr->guid, buffer, 40);
740 RegSetValueExW(subKey, NULL, 0, REG_SZ,
741 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
742 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
743 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
744 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
745 RegCloseKey(subKey);
748 RegCloseKey(key);
752 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
755 ITypeInfo_Release(tinfo);
758 SysFreeString(name);
762 ITypeLib_ReleaseTLibAttr(ptlib, attr);
764 return res;
768 /******************************************************************************
769 * UnRegisterTypeLib [OLEAUT32.186]
770 * Removes information about a type library from the System Registry
771 * NOTES
773 * RETURNS
774 * Success: S_OK
775 * Failure: Status
777 HRESULT WINAPI UnRegisterTypeLib(
778 REFGUID libid, /* [in] Guid of the library */
779 WORD wVerMajor, /* [in] major version */
780 WORD wVerMinor, /* [in] minor version */
781 LCID lcid, /* [in] locale id */
782 SYSKIND syskind)
784 BSTR tlibPath = NULL;
785 DWORD tmpLength;
786 WCHAR keyName[60];
787 WCHAR subKeyName[50];
788 int result = S_OK;
789 DWORD i = 0;
790 BOOL deleteOtherStuff;
791 HKEY key = NULL;
792 HKEY subKey = NULL;
793 TYPEATTR* typeAttr = NULL;
794 TYPEKIND kind;
795 ITypeInfo* typeInfo = NULL;
796 ITypeLib* typeLib = NULL;
797 int numTypes;
799 TRACE("(IID: %s)\n",debugstr_guid(libid));
801 /* Create the path to the key */
802 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
804 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
806 TRACE("Unsupported syskind %i\n", syskind);
807 result = E_INVALIDARG;
808 goto end;
811 /* get the path to the typelib on disk */
812 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
813 result = E_INVALIDARG;
814 goto end;
817 /* Try and open the key to the type library. */
818 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
819 result = E_INVALIDARG;
820 goto end;
823 /* Try and load the type library */
824 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
825 result = TYPE_E_INVALIDSTATE;
826 goto end;
829 /* remove any types registered with this typelib */
830 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
831 for (i=0; i<numTypes; i++) {
832 /* get the kind of type */
833 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
834 goto enddeleteloop;
837 /* skip non-interfaces, and get type info for the type */
838 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
839 goto enddeleteloop;
841 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
842 goto enddeleteloop;
844 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
845 goto enddeleteloop;
848 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
849 kind == TKIND_DISPATCH)
851 /* the path to the type */
852 get_interface_key( &typeAttr->guid, subKeyName );
854 /* Delete its bits */
855 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
856 goto enddeleteloop;
858 RegDeleteKeyW(subKey, ProxyStubClsidW);
859 RegDeleteKeyW(subKey, ProxyStubClsid32W);
860 RegDeleteKeyW(subKey, TypeLibW);
861 RegCloseKey(subKey);
862 subKey = NULL;
863 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
866 enddeleteloop:
867 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
868 typeAttr = NULL;
869 if (typeInfo) ITypeInfo_Release(typeInfo);
870 typeInfo = NULL;
873 /* Now, delete the type library path subkey */
874 get_lcid_subkey( lcid, syskind, subKeyName );
875 RegDeleteKeyW(key, subKeyName);
876 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
877 RegDeleteKeyW(key, subKeyName);
879 /* check if there is anything besides the FLAGS/HELPDIR keys.
880 If there is, we don't delete them */
881 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
882 deleteOtherStuff = TRUE;
883 i = 0;
884 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
885 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
887 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
888 if (!strcmpW(subKeyName, FLAGSW)) continue;
889 if (!strcmpW(subKeyName, HELPDIRW)) continue;
890 deleteOtherStuff = FALSE;
891 break;
894 /* only delete the other parts of the key if we're absolutely sure */
895 if (deleteOtherStuff) {
896 RegDeleteKeyW(key, FLAGSW);
897 RegDeleteKeyW(key, HELPDIRW);
898 RegCloseKey(key);
899 key = NULL;
901 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
902 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
903 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
906 end:
907 SysFreeString(tlibPath);
908 if (typeLib) ITypeLib_Release(typeLib);
909 if (subKey) RegCloseKey(subKey);
910 if (key) RegCloseKey(key);
911 return result;
914 /******************************************************************************
915 * RegisterTypeLibForUser [OLEAUT32.442]
916 * Adds information about a type library to the user registry
917 * NOTES
918 * Docs: ITypeLib FAR * ptlib
919 * Docs: OLECHAR FAR* szFullPath
920 * Docs: OLECHAR FAR* szHelpDir
922 * RETURNS
923 * Success: S_OK
924 * Failure: Status
926 HRESULT WINAPI RegisterTypeLibForUser(
927 ITypeLib * ptlib, /* [in] Pointer to the library*/
928 OLECHAR * szFullPath, /* [in] full Path of the library*/
929 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
930 may be NULL*/
932 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
933 debugstr_w(szFullPath), debugstr_w(szHelpDir));
934 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
937 /******************************************************************************
938 * UnRegisterTypeLibForUser [OLEAUT32.443]
939 * Removes information about a type library from the user registry
941 * RETURNS
942 * Success: S_OK
943 * Failure: Status
945 HRESULT WINAPI UnRegisterTypeLibForUser(
946 REFGUID libid, /* [in] GUID of the library */
947 WORD wVerMajor, /* [in] major version */
948 WORD wVerMinor, /* [in] minor version */
949 LCID lcid, /* [in] locale id */
950 SYSKIND syskind)
952 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
953 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
954 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
957 /*======================= ITypeLib implementation =======================*/
959 typedef struct tagTLBGuid {
960 GUID guid;
961 UINT offset;
962 struct list entry;
963 } TLBGuid;
965 typedef struct tagTLBCustData
967 TLBGuid *guid;
968 VARIANT data;
969 struct list entry;
970 } TLBCustData;
972 /* data structure for import typelibs */
973 typedef struct tagTLBImpLib
975 int offset; /* offset in the file (MSFT)
976 offset in nametable (SLTG)
977 just used to identify library while reading
978 data from file */
979 TLBGuid *guid; /* libid */
980 BSTR name; /* name */
982 LCID lcid; /* lcid of imported typelib */
984 WORD wVersionMajor; /* major version number */
985 WORD wVersionMinor; /* minor version number */
987 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
988 NULL if not yet loaded */
989 struct list entry;
990 } TLBImpLib;
992 typedef struct tagTLBString {
993 BSTR str;
994 UINT offset;
995 struct list entry;
996 } TLBString;
998 /* internal ITypeLib data */
999 typedef struct tagITypeLibImpl
1001 ITypeLib2 ITypeLib2_iface;
1002 ITypeComp ITypeComp_iface;
1003 ICreateTypeLib2 ICreateTypeLib2_iface;
1004 LONG ref;
1005 TLBGuid *guid;
1006 LCID lcid;
1007 SYSKIND syskind;
1008 int ptr_size;
1009 WORD ver_major;
1010 WORD ver_minor;
1011 WORD libflags;
1012 LCID set_lcid;
1014 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1015 * exported to the application as a UNICODE string.
1017 struct list string_list;
1018 struct list name_list;
1019 struct list guid_list;
1021 const TLBString *Name;
1022 const TLBString *DocString;
1023 const TLBString *HelpFile;
1024 const TLBString *HelpStringDll;
1025 DWORD dwHelpContext;
1026 int TypeInfoCount; /* nr of typeinfo's in librarry */
1027 struct tagITypeInfoImpl **typeinfos;
1028 struct list custdata_list;
1029 struct list implib_list;
1030 int ctTypeDesc; /* number of items in type desc array */
1031 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1032 library. Only used while reading MSFT
1033 typelibs */
1034 struct list ref_list; /* list of ref types in this typelib */
1035 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1038 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1039 struct list entry;
1040 WCHAR *path;
1041 INT index;
1042 } ITypeLibImpl;
1044 static const ITypeLib2Vtbl tlbvt;
1045 static const ITypeCompVtbl tlbtcvt;
1046 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1048 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1050 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1053 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1055 return impl_from_ITypeLib2((ITypeLib2*)iface);
1058 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1060 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1063 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1065 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1068 /* ITypeLib methods */
1069 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1070 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1072 /*======================= ITypeInfo implementation =======================*/
1074 /* data for referenced types */
1075 typedef struct tagTLBRefType
1077 INT index; /* Type index for internal ref or for external ref
1078 it the format is SLTG. -2 indicates to
1079 use guid */
1081 TYPEKIND tkind;
1082 TLBGuid *guid; /* guid of the referenced type */
1083 /* if index == TLB_REF_USE_GUID */
1085 HREFTYPE reference; /* The href of this ref */
1086 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1087 TLB_REF_INTERNAL for internal refs
1088 TLB_REF_NOT_FOUND for broken refs */
1090 struct list entry;
1091 } TLBRefType;
1093 #define TLB_REF_USE_GUID -2
1095 #define TLB_REF_INTERNAL (void*)-2
1096 #define TLB_REF_NOT_FOUND (void*)-1
1098 /* internal Parameter data */
1099 typedef struct tagTLBParDesc
1101 const TLBString *Name;
1102 struct list custdata_list;
1103 } TLBParDesc;
1105 /* internal Function data */
1106 typedef struct tagTLBFuncDesc
1108 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1109 const TLBString *Name; /* the name of this function */
1110 TLBParDesc *pParamDesc; /* array with param names and custom data */
1111 int helpcontext;
1112 int HelpStringContext;
1113 const TLBString *HelpString;
1114 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1115 struct list custdata_list;
1116 } TLBFuncDesc;
1118 /* internal Variable data */
1119 typedef struct tagTLBVarDesc
1121 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1122 const TLBString *Name; /* the name of this variable */
1123 int HelpContext;
1124 int HelpStringContext;
1125 const TLBString *HelpString;
1126 struct list custdata_list;
1127 } TLBVarDesc;
1129 /* internal implemented interface data */
1130 typedef struct tagTLBImplType
1132 HREFTYPE hRef; /* hRef of interface */
1133 int implflags; /* IMPLFLAG_*s */
1134 struct list custdata_list;
1135 } TLBImplType;
1137 /* internal TypeInfo data */
1138 typedef struct tagITypeInfoImpl
1140 ITypeInfo2 ITypeInfo2_iface;
1141 ITypeComp ITypeComp_iface;
1142 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1143 LONG ref;
1144 BOOL not_attached_to_typelib;
1145 BOOL needs_layout;
1147 TLBGuid *guid;
1148 LCID lcid;
1149 MEMBERID memidConstructor;
1150 MEMBERID memidDestructor;
1151 LPOLESTR lpstrSchema;
1152 ULONG cbSizeInstance;
1153 TYPEKIND typekind;
1154 WORD cFuncs;
1155 WORD cVars;
1156 WORD cImplTypes;
1157 WORD cbSizeVft;
1158 WORD cbAlignment;
1159 WORD wTypeFlags;
1160 WORD wMajorVerNum;
1161 WORD wMinorVerNum;
1162 TYPEDESC tdescAlias;
1163 IDLDESC idldescType;
1165 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1166 int index; /* index in this typelib; */
1167 HREFTYPE hreftype; /* hreftype for app object binding */
1168 /* type libs seem to store the doc strings in ascii
1169 * so why should we do it in unicode?
1171 const TLBString *Name;
1172 const TLBString *DocString;
1173 const TLBString *DllName;
1174 const TLBString *Schema;
1175 DWORD dwHelpContext;
1176 DWORD dwHelpStringContext;
1178 /* functions */
1179 TLBFuncDesc *funcdescs;
1181 /* variables */
1182 TLBVarDesc *vardescs;
1184 /* Implemented Interfaces */
1185 TLBImplType *impltypes;
1187 struct list *pcustdata_list;
1188 struct list custdata_list;
1189 } ITypeInfoImpl;
1191 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1193 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1196 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1198 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1201 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1203 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1206 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1208 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1211 static const ITypeInfo2Vtbl tinfvt;
1212 static const ITypeCompVtbl tcompvt;
1213 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1215 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1216 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1218 typedef struct tagTLBContext
1220 unsigned int oStart; /* start of TLB in file */
1221 unsigned int pos; /* current pos */
1222 unsigned int length; /* total length */
1223 void *mapping; /* memory mapping */
1224 MSFT_SegDir * pTblDir;
1225 ITypeLibImpl* pLibInfo;
1226 } TLBContext;
1229 static inline BSTR TLB_get_bstr(const TLBString *str)
1231 return str != NULL ? str->str : NULL;
1234 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1236 if(!str)
1237 return 1;
1238 return memcmp(left, str->str, len);
1241 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1243 return guid != NULL ? &guid->guid : NULL;
1246 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1248 return guid != NULL ? &guid->guid : &GUID_NULL;
1251 static int get_ptr_size(SYSKIND syskind)
1253 switch(syskind){
1254 case SYS_WIN64:
1255 return 8;
1256 case SYS_WIN32:
1257 case SYS_MAC:
1258 case SYS_WIN16:
1259 return 4;
1261 WARN("Unhandled syskind: 0x%x\n", syskind);
1262 return 4;
1266 debug
1268 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1269 if (pTD->vt & VT_RESERVED)
1270 szVarType += strlen(strcpy(szVarType, "reserved | "));
1271 if (pTD->vt & VT_BYREF)
1272 szVarType += strlen(strcpy(szVarType, "ref to "));
1273 if (pTD->vt & VT_ARRAY)
1274 szVarType += strlen(strcpy(szVarType, "array of "));
1275 if (pTD->vt & VT_VECTOR)
1276 szVarType += strlen(strcpy(szVarType, "vector of "));
1277 switch(pTD->vt & VT_TYPEMASK) {
1278 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1279 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1280 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1281 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1282 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1283 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1284 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1285 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1286 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1287 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1288 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1289 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1290 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1291 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1292 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1293 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1294 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1295 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1296 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1297 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1298 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1299 pTD->u.hreftype); break;
1300 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1301 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1302 case VT_PTR: sprintf(szVarType, "ptr to ");
1303 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1304 break;
1305 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1306 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1307 break;
1308 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1309 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1310 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1311 break;
1313 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1317 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1318 char buf[200];
1319 USHORT flags = edesc->u.paramdesc.wParamFlags;
1320 dump_TypeDesc(&edesc->tdesc,buf);
1321 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1322 MESSAGE("\t\tu.paramdesc.wParamFlags");
1323 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1324 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1325 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1326 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1327 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1328 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1329 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1330 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1331 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1333 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1334 int i;
1335 MESSAGE("memid is %08x\n",funcdesc->memid);
1336 for (i=0;i<funcdesc->cParams;i++) {
1337 MESSAGE("Param %d:\n",i);
1338 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1340 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1341 switch (funcdesc->funckind) {
1342 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1343 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1344 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1345 case FUNC_STATIC: MESSAGE("static");break;
1346 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1347 default: MESSAGE("unknown");break;
1349 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1350 switch (funcdesc->invkind) {
1351 case INVOKE_FUNC: MESSAGE("func");break;
1352 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1353 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1354 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1356 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1357 switch (funcdesc->callconv) {
1358 case CC_CDECL: MESSAGE("cdecl");break;
1359 case CC_PASCAL: MESSAGE("pascal");break;
1360 case CC_STDCALL: MESSAGE("stdcall");break;
1361 case CC_SYSCALL: MESSAGE("syscall");break;
1362 default:break;
1364 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1365 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1366 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1368 MESSAGE("\telemdescFunc (return value type):\n");
1369 dump_ELEMDESC(&funcdesc->elemdescFunc);
1372 static const char * const typekind_desc[] =
1374 "TKIND_ENUM",
1375 "TKIND_RECORD",
1376 "TKIND_MODULE",
1377 "TKIND_INTERFACE",
1378 "TKIND_DISPATCH",
1379 "TKIND_COCLASS",
1380 "TKIND_ALIAS",
1381 "TKIND_UNION",
1382 "TKIND_MAX"
1385 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1387 int i;
1388 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1389 for (i=0;i<pfd->funcdesc.cParams;i++)
1390 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1393 dump_FUNCDESC(&(pfd->funcdesc));
1395 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1396 if(pfd->Entry == NULL)
1397 MESSAGE("\tentry: (null)\n");
1398 else if(pfd->Entry == (void*)-1)
1399 MESSAGE("\tentry: invalid\n");
1400 else if(IS_INTRESOURCE(pfd->Entry))
1401 MESSAGE("\tentry: %p\n", pfd->Entry);
1402 else
1403 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1405 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1407 while (n)
1409 dump_TLBFuncDescOne(pfd);
1410 ++pfd;
1411 --n;
1414 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1416 while (n)
1418 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1419 ++pvd;
1420 --n;
1424 static void dump_TLBImpLib(const TLBImpLib *import)
1426 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1427 debugstr_w(import->name));
1428 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1429 import->wVersionMinor, import->lcid, import->offset);
1432 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1434 TLBRefType *ref;
1436 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1438 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1439 if(ref->index == -1)
1440 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1441 else
1442 TRACE_(typelib)("type no: %d\n", ref->index);
1444 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1446 TRACE_(typelib)("in lib\n");
1447 dump_TLBImpLib(ref->pImpTLInfo);
1452 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1454 if(!impl)
1455 return;
1456 while (n) {
1457 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1458 impl->hRef, impl->implflags);
1459 ++impl;
1460 --n;
1464 static void dump_Variant(const VARIANT * pvar)
1466 SYSTEMTIME st;
1468 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1470 if (pvar)
1472 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1473 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1475 TRACE(",%p", V_BYREF(pvar));
1477 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1479 TRACE(",%p", V_ARRAY(pvar));
1481 else switch (V_TYPE(pvar))
1483 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1484 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1485 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1486 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1487 case VT_INT:
1488 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1489 case VT_UINT:
1490 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1491 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1492 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1493 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1494 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1495 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1496 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1497 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1498 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1499 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1500 V_CY(pvar).s.Lo); break;
1501 case VT_DATE:
1502 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1503 TRACE(",<invalid>");
1504 else
1505 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1506 st.wHour, st.wMinute, st.wSecond);
1507 break;
1508 case VT_ERROR:
1509 case VT_VOID:
1510 case VT_USERDEFINED:
1511 case VT_EMPTY:
1512 case VT_NULL: break;
1513 default: TRACE(",?"); break;
1516 TRACE("}\n");
1519 static void dump_DispParms(const DISPPARAMS * pdp)
1521 unsigned int index;
1523 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1525 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1527 TRACE("named args:\n");
1528 for (index = 0; index < pdp->cNamedArgs; index++)
1529 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1532 if (pdp->cArgs && pdp->rgvarg)
1534 TRACE("args:\n");
1535 for (index = 0; index < pdp->cArgs; index++)
1536 dump_Variant( &pdp->rgvarg[index] );
1540 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1542 TRACE("%p ref=%u\n", pty, pty->ref);
1543 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1544 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1545 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1546 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1547 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1548 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1549 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1550 if (TRACE_ON(ole))
1551 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1552 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1553 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1556 static void dump_VARDESC(const VARDESC *v)
1558 MESSAGE("memid %d\n",v->memid);
1559 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1560 MESSAGE("oInst %d\n",v->u.oInst);
1561 dump_ELEMDESC(&(v->elemdescVar));
1562 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1563 MESSAGE("varkind %d\n",v->varkind);
1566 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1568 /* VT_LPWSTR is largest type that, may appear in type description */
1569 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1570 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1571 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1572 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1573 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1574 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1575 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1576 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1579 static void TLB_abort(void)
1581 DebugBreak();
1584 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1586 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1587 if (!ret) ERR("cannot allocate memory\n");
1588 return ret;
1591 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1593 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1594 if (!ret) ERR("cannot allocate memory\n");
1595 return ret;
1598 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1600 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1603 void heap_free(void *ptr)
1605 HeapFree(GetProcessHeap(), 0, ptr);
1608 /* returns the size required for a deep copy of a typedesc into a
1609 * flat buffer */
1610 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1612 SIZE_T size = 0;
1614 if (alloc_initial_space)
1615 size += sizeof(TYPEDESC);
1617 switch (tdesc->vt)
1619 case VT_PTR:
1620 case VT_SAFEARRAY:
1621 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1622 break;
1623 case VT_CARRAY:
1624 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1625 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1626 break;
1628 return size;
1631 /* deep copy a typedesc into a flat buffer */
1632 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1634 if (!dest)
1636 dest = buffer;
1637 buffer = (char *)buffer + sizeof(TYPEDESC);
1640 *dest = *src;
1642 switch (src->vt)
1644 case VT_PTR:
1645 case VT_SAFEARRAY:
1646 dest->u.lptdesc = buffer;
1647 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1648 break;
1649 case VT_CARRAY:
1650 dest->u.lpadesc = buffer;
1651 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1652 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1653 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1654 break;
1656 return buffer;
1659 /* free custom data allocated by MSFT_CustData */
1660 static inline void TLB_FreeCustData(struct list *custdata_list)
1662 TLBCustData *cd, *cdn;
1663 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1665 list_remove(&cd->entry);
1666 VariantClear(&cd->data);
1667 heap_free(cd);
1671 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1673 DWORD len;
1674 BSTR ret;
1676 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1677 ret = SysAllocStringLen(NULL, len - 1);
1678 if (!ret) return ret;
1679 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1680 return ret;
1683 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1684 UINT n, MEMBERID memid)
1686 while(n){
1687 if(funcdescs->funcdesc.memid == memid)
1688 return funcdescs;
1689 ++funcdescs;
1690 --n;
1692 return NULL;
1695 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1696 UINT n, const OLECHAR *name)
1698 while(n){
1699 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1700 return funcdescs;
1701 ++funcdescs;
1702 --n;
1704 return NULL;
1707 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1708 UINT n, MEMBERID memid)
1710 while(n){
1711 if(vardescs->vardesc.memid == memid)
1712 return vardescs;
1713 ++vardescs;
1714 --n;
1716 return NULL;
1719 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1720 UINT n, const OLECHAR *name)
1722 while(n){
1723 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1724 return vardescs;
1725 ++vardescs;
1726 --n;
1728 return NULL;
1731 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1733 TLBCustData *cust_data;
1734 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1735 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1736 return cust_data;
1737 return NULL;
1740 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1741 UINT n, const OLECHAR *name)
1743 while(n){
1744 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1745 return *typeinfos;
1746 ++typeinfos;
1747 --n;
1749 return NULL;
1752 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1754 list_init(&var_desc->custdata_list);
1757 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1759 TLBVarDesc *ret;
1761 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1762 if(!ret)
1763 return NULL;
1765 while(n){
1766 TLBVarDesc_Constructor(&ret[n-1]);
1767 --n;
1770 return ret;
1773 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1775 TLBParDesc *ret;
1777 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1778 if(!ret)
1779 return NULL;
1781 while(n){
1782 list_init(&ret[n-1].custdata_list);
1783 --n;
1786 return ret;
1789 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1791 list_init(&func_desc->custdata_list);
1794 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1796 TLBFuncDesc *ret;
1798 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1799 if(!ret)
1800 return NULL;
1802 while(n){
1803 TLBFuncDesc_Constructor(&ret[n-1]);
1804 --n;
1807 return ret;
1810 static void TLBImplType_Constructor(TLBImplType *impl)
1812 list_init(&impl->custdata_list);
1815 static TLBImplType *TLBImplType_Alloc(UINT n)
1817 TLBImplType *ret;
1819 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1820 if(!ret)
1821 return NULL;
1823 while(n){
1824 TLBImplType_Constructor(&ret[n-1]);
1825 --n;
1828 return ret;
1831 static TLBGuid *TLB_append_guid(struct list *guid_list, const GUID *new_guid)
1833 TLBGuid *guid;
1835 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1836 if (IsEqualGUID(&guid->guid, new_guid))
1837 return guid;
1840 guid = heap_alloc(sizeof(TLBGuid));
1841 if (!guid)
1842 return NULL;
1844 memcpy(&guid->guid, new_guid, sizeof(GUID));
1846 list_add_tail(guid_list, &guid->entry);
1848 return guid;
1851 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1853 TLBCustData *cust_data;
1855 switch(V_VT(var)){
1856 case VT_I4:
1857 case VT_R4:
1858 case VT_UI4:
1859 case VT_INT:
1860 case VT_UINT:
1861 case VT_HRESULT:
1862 case VT_BSTR:
1863 break;
1864 default:
1865 return DISP_E_BADVARTYPE;
1868 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1870 if (!cust_data) {
1871 cust_data = heap_alloc(sizeof(TLBCustData));
1872 if (!cust_data)
1873 return E_OUTOFMEMORY;
1875 cust_data->guid = tlbguid;
1876 VariantInit(&cust_data->data);
1878 list_add_tail(custdata_list, &cust_data->entry);
1879 }else
1880 VariantClear(&cust_data->data);
1882 return VariantCopy(&cust_data->data, var);
1885 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1887 TLBString *str;
1889 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1890 if (strcmpW(str->str, new_str) == 0)
1891 return str;
1894 str = heap_alloc(sizeof(TLBString));
1895 if (!str)
1896 return NULL;
1898 str->str = SysAllocString(new_str);
1899 if (!str->str) {
1900 heap_free(str);
1901 return NULL;
1904 list_add_tail(string_list, &str->entry);
1906 return str;
1909 /**********************************************************************
1911 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1913 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1915 return pcx->pos;
1918 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1920 if (where != DO_NOT_SEEK)
1922 where += pcx->oStart;
1923 if (where > pcx->length)
1925 /* FIXME */
1926 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1927 TLB_abort();
1929 pcx->pos = where;
1933 /* read function */
1934 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1936 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1937 pcx->pos, count, pcx->oStart, pcx->length, where);
1939 MSFT_Seek(pcx, where);
1940 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1941 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1942 pcx->pos += count;
1943 return count;
1946 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1947 LONG where )
1949 DWORD ret;
1951 ret = MSFT_Read(buffer, count, pcx, where);
1952 FromLEDWords(buffer, ret);
1954 return ret;
1957 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1958 LONG where )
1960 DWORD ret;
1962 ret = MSFT_Read(buffer, count, pcx, where);
1963 FromLEWords(buffer, ret);
1965 return ret;
1968 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
1970 TLBGuid *guid;
1971 MSFT_GuidEntry entry;
1972 int offs = 0;
1974 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
1975 while (1) {
1976 if (offs >= pcx->pTblDir->pGuidTab.length)
1977 return S_OK;
1979 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
1981 guid = heap_alloc(sizeof(TLBGuid));
1983 guid->offset = offs;
1984 guid->guid = entry.guid;
1986 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
1988 offs += sizeof(MSFT_GuidEntry);
1992 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
1994 TLBGuid *ret;
1996 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
1997 if(ret->offset == offset){
1998 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
1999 return ret;
2003 return NULL;
2006 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2008 MSFT_NameIntro niName;
2010 if (offset < 0)
2012 ERR_(typelib)("bad offset %d\n", offset);
2013 return -1;
2016 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2017 pcx->pTblDir->pNametab.offset+offset);
2019 return niName.hreftype;
2022 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2024 char *string;
2025 MSFT_NameIntro intro;
2026 INT16 len_piece;
2027 int offs = 0, lengthInChars;
2029 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2030 while (1) {
2031 TLBString *tlbstr;
2033 if (offs >= pcx->pTblDir->pNametab.length)
2034 return S_OK;
2036 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2037 intro.namelen &= 0xFF;
2038 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2039 if(len_piece % 4)
2040 len_piece = (len_piece + 4) & ~0x3;
2041 if(len_piece < 8)
2042 len_piece = 8;
2044 string = heap_alloc(len_piece + 1);
2045 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2046 string[intro.namelen] = '\0';
2048 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2049 string, -1, NULL, 0);
2050 if (!lengthInChars) {
2051 heap_free(string);
2052 return E_UNEXPECTED;
2055 tlbstr = heap_alloc(sizeof(TLBString));
2057 tlbstr->offset = offs;
2058 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2059 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2061 heap_free(string);
2063 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2065 offs += len_piece;
2069 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2071 TLBString *tlbstr;
2073 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2074 if (tlbstr->offset == offset) {
2075 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2076 return tlbstr;
2080 return NULL;
2083 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2085 TLBString *tlbstr;
2087 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2088 if (tlbstr->offset == offset) {
2089 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2090 return tlbstr;
2094 return NULL;
2098 * read a value and fill a VARIANT structure
2100 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2102 int size;
2104 TRACE_(typelib)("\n");
2106 if(offset <0) { /* data are packed in here */
2107 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2108 V_I4(pVar) = offset & 0x3ffffff;
2109 return;
2111 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2112 pcx->pTblDir->pCustData.offset + offset );
2113 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2114 switch (V_VT(pVar)){
2115 case VT_EMPTY: /* FIXME: is this right? */
2116 case VT_NULL: /* FIXME: is this right? */
2117 case VT_I2 : /* this should not happen */
2118 case VT_I4 :
2119 case VT_R4 :
2120 case VT_ERROR :
2121 case VT_BOOL :
2122 case VT_I1 :
2123 case VT_UI1 :
2124 case VT_UI2 :
2125 case VT_UI4 :
2126 case VT_INT :
2127 case VT_UINT :
2128 case VT_VOID : /* FIXME: is this right? */
2129 case VT_HRESULT :
2130 size=4; break;
2131 case VT_R8 :
2132 case VT_CY :
2133 case VT_DATE :
2134 case VT_I8 :
2135 case VT_UI8 :
2136 case VT_DECIMAL : /* FIXME: is this right? */
2137 case VT_FILETIME :
2138 size=8;break;
2139 /* pointer types with known behaviour */
2140 case VT_BSTR :{
2141 char * ptr;
2142 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2143 if(size < 0) {
2144 char next;
2145 DWORD origPos = MSFT_Tell(pcx), nullPos;
2147 do {
2148 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
2149 } while (next);
2150 nullPos = MSFT_Tell(pcx);
2151 size = nullPos - origPos;
2152 MSFT_Seek(pcx, origPos);
2154 ptr = heap_alloc_zero(size);/* allocate temp buffer */
2155 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
2156 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2157 /* FIXME: do we need a AtoW conversion here? */
2158 V_UNION(pVar, bstrVal[size])='\0';
2159 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2160 heap_free(ptr);
2162 size=-4; break;
2163 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2164 case VT_DISPATCH :
2165 case VT_VARIANT :
2166 case VT_UNKNOWN :
2167 case VT_PTR :
2168 case VT_SAFEARRAY :
2169 case VT_CARRAY :
2170 case VT_USERDEFINED :
2171 case VT_LPSTR :
2172 case VT_LPWSTR :
2173 case VT_BLOB :
2174 case VT_STREAM :
2175 case VT_STORAGE :
2176 case VT_STREAMED_OBJECT :
2177 case VT_STORED_OBJECT :
2178 case VT_BLOB_OBJECT :
2179 case VT_CF :
2180 case VT_CLSID :
2181 default:
2182 size=0;
2183 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2184 V_VT(pVar));
2187 if(size>0) /* (big|small) endian correct? */
2188 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2189 return;
2192 * create a linked list with custom data
2194 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2196 MSFT_CDGuid entry;
2197 TLBCustData* pNew;
2198 int count=0;
2200 TRACE_(typelib)("\n");
2202 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2204 while(offset >=0){
2205 count++;
2206 pNew=heap_alloc_zero(sizeof(TLBCustData));
2207 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2208 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2209 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2210 list_add_head(custdata_list, &pNew->entry);
2211 offset = entry.next;
2213 return count;
2216 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
2217 ITypeInfoImpl *pTI)
2219 if(type <0)
2220 pTd->vt=type & VT_TYPEMASK;
2221 else
2222 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2224 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2227 static int TLB_is_propgetput(INVOKEKIND invkind)
2229 return (invkind == INVOKE_PROPERTYGET ||
2230 invkind == INVOKE_PROPERTYPUT ||
2231 invkind == INVOKE_PROPERTYPUTREF);
2234 static void
2235 MSFT_DoFuncs(TLBContext* pcx,
2236 ITypeInfoImpl* pTI,
2237 int cFuncs,
2238 int cVars,
2239 int offset,
2240 TLBFuncDesc** pptfd)
2243 * member information is stored in a data structure at offset
2244 * indicated by the memoffset field of the typeinfo structure
2245 * There are several distinctive parts.
2246 * The first part starts with a field that holds the total length
2247 * of this (first) part excluding this field. Then follow the records,
2248 * for each member there is one record.
2250 * The first entry is always the length of the record (including this
2251 * length word).
2252 * The rest of the record depends on the type of the member. If there is
2253 * a field indicating the member type (function, variable, interface, etc)
2254 * I have not found it yet. At this time we depend on the information
2255 * in the type info and the usual order how things are stored.
2257 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2258 * for each member;
2260 * Third is an equal sized array with file offsets to the name entry
2261 * of each member.
2263 * The fourth and last (?) part is an array with offsets to the records
2264 * in the first part of this file segment.
2267 int infolen, nameoffset, reclength, i;
2268 int recoffset = offset + sizeof(INT);
2270 char *recbuf = heap_alloc(0xffff);
2271 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2272 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2274 TRACE_(typelib)("\n");
2276 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2278 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2279 ptfd = *pptfd;
2280 for ( i = 0; i < cFuncs ; i++ )
2282 int optional;
2284 /* name, eventually add to a hash table */
2285 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2286 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2288 /* read the function information record */
2289 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2291 reclength &= 0xffff;
2293 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2295 /* size without argument data */
2296 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2297 if (pFuncRec->FKCCIC & 0x1000)
2298 optional -= pFuncRec->nrargs * sizeof(INT);
2300 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2301 ptfd->helpcontext = pFuncRec->HelpContext;
2303 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2304 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2306 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2308 if (pFuncRec->FKCCIC & 0x2000 )
2310 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2311 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2312 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2314 else
2315 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2317 else
2318 ptfd->Entry = (TLBString*)-1;
2320 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2321 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2323 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2324 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2326 /* fill the FuncDesc Structure */
2327 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2328 offset + infolen + ( i + 1) * sizeof(INT));
2330 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2331 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2332 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2333 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2334 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2335 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2336 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2338 /* nameoffset is sometimes -1 on the second half of a propget/propput
2339 * pair of functions */
2340 if ((nameoffset == -1) && (i > 0) &&
2341 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2342 TLB_is_propgetput(ptfd->funcdesc.invkind))
2343 ptfd->Name = ptfd_prev->Name;
2344 else
2345 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2347 MSFT_GetTdesc(pcx,
2348 pFuncRec->DataType,
2349 &ptfd->funcdesc.elemdescFunc.tdesc,
2350 pTI);
2352 /* do the parameters/arguments */
2353 if(pFuncRec->nrargs)
2355 int j = 0;
2356 MSFT_ParameterInfo paraminfo;
2358 ptfd->funcdesc.lprgelemdescParam =
2359 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2361 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2363 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2364 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2366 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2368 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2370 MSFT_GetTdesc(pcx,
2371 paraminfo.DataType,
2372 &elemdesc->tdesc,
2373 pTI);
2375 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2377 /* name */
2378 if (paraminfo.oName != -1)
2379 ptfd->pParamDesc[j].Name =
2380 MSFT_ReadName( pcx, paraminfo.oName );
2381 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2383 /* default value */
2384 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2385 (pFuncRec->FKCCIC & 0x1000) )
2387 INT* pInt = (INT *)((char *)pFuncRec +
2388 reclength -
2389 (pFuncRec->nrargs * 4) * sizeof(INT) );
2391 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2393 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2394 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2396 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2397 pInt[j], pcx);
2399 else
2400 elemdesc->u.paramdesc.pparamdescex = NULL;
2402 /* custom info */
2403 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2404 j*sizeof(pFuncRec->oArgCustData[0])) &&
2405 pFuncRec->FKCCIC & 0x80 )
2407 MSFT_CustData(pcx,
2408 pFuncRec->oArgCustData[j],
2409 &ptfd->pParamDesc[j].custdata_list);
2412 /* SEEK value = jump to offset,
2413 * from there jump to the end of record,
2414 * go back by (j-1) arguments
2416 MSFT_ReadLEDWords( &paraminfo ,
2417 sizeof(MSFT_ParameterInfo), pcx,
2418 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2419 * sizeof(MSFT_ParameterInfo)));
2423 /* scode is not used: archaic win16 stuff FIXME: right? */
2424 ptfd->funcdesc.cScodes = 0 ;
2425 ptfd->funcdesc.lprgscode = NULL ;
2427 ptfd_prev = ptfd;
2428 ++ptfd;
2429 recoffset += reclength;
2431 heap_free(recbuf);
2434 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2435 int cVars, int offset, TLBVarDesc ** pptvd)
2437 int infolen, nameoffset, reclength;
2438 char recbuf[256];
2439 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2440 TLBVarDesc *ptvd;
2441 int i;
2442 int recoffset;
2444 TRACE_(typelib)("\n");
2446 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2447 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2448 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2449 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2450 recoffset += offset+sizeof(INT);
2451 for(i=0;i<cVars;i++, ++ptvd){
2452 /* name, eventually add to a hash table */
2453 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2454 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2455 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2456 /* read the variable information record */
2457 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2458 reclength &= 0xff;
2459 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2461 /* optional data */
2462 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2463 ptvd->HelpContext = pVarRec->HelpContext;
2465 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2466 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2468 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2469 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2471 /* fill the VarDesc Structure */
2472 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2473 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2474 ptvd->vardesc.varkind = pVarRec->VarKind;
2475 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2476 MSFT_GetTdesc(pcx, pVarRec->DataType,
2477 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2478 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2479 if(pVarRec->VarKind == VAR_CONST ){
2480 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2481 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2482 pVarRec->OffsValue, pcx);
2483 } else
2484 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2485 recoffset += reclength;
2489 /* process Implemented Interfaces of a com class */
2490 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2491 int offset)
2493 int i;
2494 MSFT_RefRecord refrec;
2495 TLBImplType *pImpl;
2497 TRACE_(typelib)("\n");
2499 pTI->impltypes = TLBImplType_Alloc(count);
2500 pImpl = pTI->impltypes;
2501 for(i=0;i<count;i++){
2502 if(offset<0) break; /* paranoia */
2503 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2504 pImpl->hRef = refrec.reftype;
2505 pImpl->implflags=refrec.flags;
2506 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2507 offset=refrec.onext;
2508 ++pImpl;
2512 * process a typeinfo record
2514 static ITypeInfoImpl * MSFT_DoTypeInfo(
2515 TLBContext *pcx,
2516 int count,
2517 ITypeLibImpl * pLibInfo)
2519 MSFT_TypeInfoBase tiBase;
2520 ITypeInfoImpl *ptiRet;
2522 TRACE_(typelib)("count=%u\n", count);
2524 ptiRet = ITypeInfoImpl_Constructor();
2525 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2526 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2528 /* this is where we are coming from */
2529 ptiRet->pTypeLib = pLibInfo;
2530 ptiRet->index=count;
2532 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2533 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2534 ptiRet->lpstrSchema=NULL; /* reserved */
2535 ptiRet->cbSizeInstance=tiBase.size;
2536 ptiRet->typekind=tiBase.typekind & 0xF;
2537 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2538 ptiRet->cVars=HIWORD(tiBase.cElement);
2539 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2540 ptiRet->wTypeFlags=tiBase.flags;
2541 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2542 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2543 ptiRet->cImplTypes=tiBase.cImplTypes;
2544 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2545 if(ptiRet->typekind == TKIND_ALIAS)
2546 MSFT_GetTdesc(pcx, tiBase.datatype1,
2547 &ptiRet->tdescAlias, ptiRet);
2549 /* FIXME: */
2550 /* IDLDESC idldescType; *//* never saw this one != zero */
2552 /* name, eventually add to a hash table */
2553 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2554 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2555 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2556 /* help info */
2557 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2558 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2559 ptiRet->dwHelpContext=tiBase.helpcontext;
2561 if (ptiRet->typekind == TKIND_MODULE)
2562 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2564 /* note: InfoType's Help file and HelpStringDll come from the containing
2565 * library. Further HelpString and Docstring appear to be the same thing :(
2567 /* functions */
2568 if(ptiRet->cFuncs >0 )
2569 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2570 ptiRet->cVars,
2571 tiBase.memoffset, &ptiRet->funcdescs);
2572 /* variables */
2573 if(ptiRet->cVars >0 )
2574 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2575 ptiRet->cVars,
2576 tiBase.memoffset, &ptiRet->vardescs);
2577 if(ptiRet->cImplTypes >0 ) {
2578 switch(ptiRet->typekind)
2580 case TKIND_COCLASS:
2581 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2582 tiBase.datatype1);
2583 break;
2584 case TKIND_DISPATCH:
2585 /* This is not -1 when the interface is a non-base dual interface or
2586 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2587 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2588 not this interface.
2591 if (tiBase.datatype1 != -1)
2593 ptiRet->impltypes = TLBImplType_Alloc(1);
2594 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2596 break;
2597 default:
2598 ptiRet->impltypes = TLBImplType_Alloc(1);
2599 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2600 break;
2603 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2605 TRACE_(typelib)("%s guid: %s kind:%s\n",
2606 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2607 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2608 typekind_desc[ptiRet->typekind]);
2609 if (TRACE_ON(typelib))
2610 dump_TypeInfo(ptiRet);
2612 return ptiRet;
2615 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2617 char *string;
2618 INT16 len_str, len_piece;
2619 int offs = 0, lengthInChars;
2621 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2622 while (1) {
2623 TLBString *tlbstr;
2625 if (offs >= pcx->pTblDir->pStringtab.length)
2626 return S_OK;
2628 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2629 len_piece = len_str + sizeof(INT16);
2630 if(len_piece % 4)
2631 len_piece = (len_piece + 4) & ~0x3;
2632 if(len_piece < 8)
2633 len_piece = 8;
2635 string = heap_alloc(len_piece + 1);
2636 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2637 string[len_str] = '\0';
2639 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2640 string, -1, NULL, 0);
2641 if (!lengthInChars) {
2642 heap_free(string);
2643 return E_UNEXPECTED;
2646 tlbstr = heap_alloc(sizeof(TLBString));
2648 tlbstr->offset = offs;
2649 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2650 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2652 heap_free(string);
2654 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2656 offs += len_piece;
2660 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2662 TLBRefType *ref;
2663 int offs = 0;
2665 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2666 while (offs < pcx->pTblDir->pImpInfo.length) {
2667 MSFT_ImpInfo impinfo;
2668 TLBImpLib *pImpLib;
2670 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2672 ref = heap_alloc_zero(sizeof(TLBRefType));
2673 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2675 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2676 if(pImpLib->offset==impinfo.oImpFile)
2677 break;
2679 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2680 ref->reference = offs;
2681 ref->pImpTLInfo = pImpLib;
2682 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2683 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2684 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2685 ref->index = TLB_REF_USE_GUID;
2686 } else
2687 ref->index = impinfo.oGuid;
2688 }else{
2689 ERR("Cannot find a reference\n");
2690 ref->reference = -1;
2691 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2694 offs += sizeof(impinfo);
2697 return S_OK;
2700 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2701 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2702 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2703 * tradeoff here.
2705 static struct list tlb_cache = LIST_INIT(tlb_cache);
2706 static CRITICAL_SECTION cache_section;
2707 static CRITICAL_SECTION_DEBUG cache_section_debug =
2709 0, 0, &cache_section,
2710 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2711 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2713 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2716 typedef struct TLB_PEFile
2718 IUnknown IUnknown_iface;
2719 LONG refs;
2720 HMODULE dll;
2721 HRSRC typelib_resource;
2722 HGLOBAL typelib_global;
2723 LPVOID typelib_base;
2724 } TLB_PEFile;
2726 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2728 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2731 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2733 if (IsEqualIID(riid, &IID_IUnknown))
2735 *ppv = iface;
2736 IUnknown_AddRef(iface);
2737 return S_OK;
2739 *ppv = NULL;
2740 return E_NOINTERFACE;
2743 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2745 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2746 return InterlockedIncrement(&This->refs);
2749 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2751 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2752 ULONG refs = InterlockedDecrement(&This->refs);
2753 if (!refs)
2755 if (This->typelib_global)
2756 FreeResource(This->typelib_global);
2757 if (This->dll)
2758 FreeLibrary(This->dll);
2759 heap_free(This);
2761 return refs;
2764 static const IUnknownVtbl TLB_PEFile_Vtable =
2766 TLB_PEFile_QueryInterface,
2767 TLB_PEFile_AddRef,
2768 TLB_PEFile_Release
2771 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2773 TLB_PEFile *This;
2774 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2776 This = heap_alloc(sizeof(TLB_PEFile));
2777 if (!This)
2778 return E_OUTOFMEMORY;
2780 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2781 This->refs = 1;
2782 This->dll = NULL;
2783 This->typelib_resource = NULL;
2784 This->typelib_global = NULL;
2785 This->typelib_base = NULL;
2787 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2788 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2790 if (This->dll)
2792 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2793 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2794 if (This->typelib_resource)
2796 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2797 if (This->typelib_global)
2799 This->typelib_base = LockResource(This->typelib_global);
2801 if (This->typelib_base)
2803 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2804 *ppBase = This->typelib_base;
2805 *ppFile = &This->IUnknown_iface;
2806 return S_OK;
2811 TRACE("No TYPELIB resource found\n");
2812 hr = E_FAIL;
2815 TLB_PEFile_Release(&This->IUnknown_iface);
2816 return hr;
2819 typedef struct TLB_NEFile
2821 IUnknown IUnknown_iface;
2822 LONG refs;
2823 LPVOID typelib_base;
2824 } TLB_NEFile;
2826 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2828 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2831 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2833 if (IsEqualIID(riid, &IID_IUnknown))
2835 *ppv = iface;
2836 IUnknown_AddRef(iface);
2837 return S_OK;
2839 *ppv = NULL;
2840 return E_NOINTERFACE;
2843 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2845 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2846 return InterlockedIncrement(&This->refs);
2849 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2851 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2852 ULONG refs = InterlockedDecrement(&This->refs);
2853 if (!refs)
2855 heap_free(This->typelib_base);
2856 heap_free(This);
2858 return refs;
2861 static const IUnknownVtbl TLB_NEFile_Vtable =
2863 TLB_NEFile_QueryInterface,
2864 TLB_NEFile_AddRef,
2865 TLB_NEFile_Release
2868 /***********************************************************************
2869 * read_xx_header [internal]
2871 static int read_xx_header( HFILE lzfd )
2873 IMAGE_DOS_HEADER mzh;
2874 char magic[3];
2876 LZSeek( lzfd, 0, SEEK_SET );
2877 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2878 return 0;
2879 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2880 return 0;
2882 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2883 if ( 2 != LZRead( lzfd, magic, 2 ) )
2884 return 0;
2886 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2888 if ( magic[0] == 'N' && magic[1] == 'E' )
2889 return IMAGE_OS2_SIGNATURE;
2890 if ( magic[0] == 'P' && magic[1] == 'E' )
2891 return IMAGE_NT_SIGNATURE;
2893 magic[2] = '\0';
2894 WARN("Can't handle %s files.\n", magic );
2895 return 0;
2899 /***********************************************************************
2900 * find_ne_resource [internal]
2902 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2903 DWORD *resLen, DWORD *resOff )
2905 IMAGE_OS2_HEADER nehd;
2906 NE_TYPEINFO *typeInfo;
2907 NE_NAMEINFO *nameInfo;
2908 DWORD nehdoffset;
2909 LPBYTE resTab;
2910 DWORD resTabSize;
2911 int count;
2913 /* Read in NE header */
2914 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2915 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2917 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2918 if ( !resTabSize )
2920 TRACE("No resources in NE dll\n" );
2921 return FALSE;
2924 /* Read in resource table */
2925 resTab = heap_alloc( resTabSize );
2926 if ( !resTab ) return FALSE;
2928 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2929 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2931 heap_free( resTab );
2932 return FALSE;
2935 /* Find resource */
2936 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2938 if (!IS_INTRESOURCE(typeid)) /* named type */
2940 BYTE len = strlen( typeid );
2941 while (typeInfo->type_id)
2943 if (!(typeInfo->type_id & 0x8000))
2945 BYTE *p = resTab + typeInfo->type_id;
2946 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2948 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2949 typeInfo->count * sizeof(NE_NAMEINFO));
2952 else /* numeric type id */
2954 WORD id = LOWORD(typeid) | 0x8000;
2955 while (typeInfo->type_id)
2957 if (typeInfo->type_id == id) goto found_type;
2958 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2959 typeInfo->count * sizeof(NE_NAMEINFO));
2962 TRACE("No typeid entry found for %p\n", typeid );
2963 heap_free( resTab );
2964 return FALSE;
2966 found_type:
2967 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2969 if (!IS_INTRESOURCE(resid)) /* named resource */
2971 BYTE len = strlen( resid );
2972 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2974 BYTE *p = resTab + nameInfo->id;
2975 if (nameInfo->id & 0x8000) continue;
2976 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2979 else /* numeric resource id */
2981 WORD id = LOWORD(resid) | 0x8000;
2982 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2983 if (nameInfo->id == id) goto found_name;
2985 TRACE("No resid entry found for %p\n", typeid );
2986 heap_free( resTab );
2987 return FALSE;
2989 found_name:
2990 /* Return resource data */
2991 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2992 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2994 heap_free( resTab );
2995 return TRUE;
2998 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3000 HFILE lzfd = -1;
3001 OFSTRUCT ofs;
3002 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3003 TLB_NEFile *This;
3005 This = heap_alloc(sizeof(TLB_NEFile));
3006 if (!This) return E_OUTOFMEMORY;
3008 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3009 This->refs = 1;
3010 This->typelib_base = NULL;
3012 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3013 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3015 DWORD reslen, offset;
3016 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3018 This->typelib_base = heap_alloc(reslen);
3019 if( !This->typelib_base )
3020 hr = E_OUTOFMEMORY;
3021 else
3023 LZSeek( lzfd, offset, SEEK_SET );
3024 reslen = LZRead( lzfd, This->typelib_base, reslen );
3025 LZClose( lzfd );
3026 *ppBase = This->typelib_base;
3027 *pdwTLBLength = reslen;
3028 *ppFile = &This->IUnknown_iface;
3029 return S_OK;
3034 if( lzfd >= 0) LZClose( lzfd );
3035 TLB_NEFile_Release(&This->IUnknown_iface);
3036 return hr;
3039 typedef struct TLB_Mapping
3041 IUnknown IUnknown_iface;
3042 LONG refs;
3043 HANDLE file;
3044 HANDLE mapping;
3045 LPVOID typelib_base;
3046 } TLB_Mapping;
3048 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3050 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3053 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3055 if (IsEqualIID(riid, &IID_IUnknown))
3057 *ppv = iface;
3058 IUnknown_AddRef(iface);
3059 return S_OK;
3061 *ppv = NULL;
3062 return E_NOINTERFACE;
3065 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3067 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3068 return InterlockedIncrement(&This->refs);
3071 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3073 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3074 ULONG refs = InterlockedDecrement(&This->refs);
3075 if (!refs)
3077 if (This->typelib_base)
3078 UnmapViewOfFile(This->typelib_base);
3079 if (This->mapping)
3080 CloseHandle(This->mapping);
3081 if (This->file != INVALID_HANDLE_VALUE)
3082 CloseHandle(This->file);
3083 heap_free(This);
3085 return refs;
3088 static const IUnknownVtbl TLB_Mapping_Vtable =
3090 TLB_Mapping_QueryInterface,
3091 TLB_Mapping_AddRef,
3092 TLB_Mapping_Release
3095 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3097 TLB_Mapping *This;
3099 This = heap_alloc(sizeof(TLB_Mapping));
3100 if (!This)
3101 return E_OUTOFMEMORY;
3103 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3104 This->refs = 1;
3105 This->file = INVALID_HANDLE_VALUE;
3106 This->mapping = NULL;
3107 This->typelib_base = NULL;
3109 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3110 if (INVALID_HANDLE_VALUE != This->file)
3112 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3113 if (This->mapping)
3115 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3116 if(This->typelib_base)
3118 /* retrieve file size */
3119 *pdwTLBLength = GetFileSize(This->file, NULL);
3120 *ppBase = This->typelib_base;
3121 *ppFile = &This->IUnknown_iface;
3122 return S_OK;
3127 IUnknown_Release(&This->IUnknown_iface);
3128 return TYPE_E_CANTLOADLIBRARY;
3131 /****************************************************************************
3132 * TLB_ReadTypeLib
3134 * find the type of the typelib file and map the typelib resource into
3135 * the memory
3138 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3139 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3141 ITypeLibImpl *entry;
3142 HRESULT ret;
3143 INT index = 1;
3144 LPWSTR index_str, file = (LPWSTR)pszFileName;
3145 LPVOID pBase = NULL;
3146 DWORD dwTLBLength = 0;
3147 IUnknown *pFile = NULL;
3148 HANDLE h;
3150 *ppTypeLib = NULL;
3152 index_str = strrchrW(pszFileName, '\\');
3153 if(index_str && *++index_str != '\0')
3155 LPWSTR end_ptr;
3156 LONG idx = strtolW(index_str, &end_ptr, 10);
3157 if(*end_ptr == '\0')
3159 int str_len = index_str - pszFileName - 1;
3160 index = idx;
3161 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3162 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3163 file[str_len] = 0;
3167 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3169 if(strchrW(file, '\\'))
3171 lstrcpyW(pszPath, file);
3173 else
3175 int len = GetSystemDirectoryW(pszPath, cchPath);
3176 pszPath[len] = '\\';
3177 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3181 if(file != pszFileName) heap_free(file);
3183 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_ALWAYS,
3184 FILE_ATTRIBUTE_NORMAL, NULL);
3185 if(h != INVALID_HANDLE_VALUE){
3186 FILE_NAME_INFORMATION *info;
3187 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3188 BOOL br;
3190 info = (FILE_NAME_INFORMATION*)data;
3191 /* GetFileInformationByHandleEx returns the path of the file without
3192 * WOW64 redirection */
3193 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3194 if(br){
3195 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3196 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3198 CloseHandle(h);
3201 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3203 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3204 EnterCriticalSection(&cache_section);
3205 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3207 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3209 TRACE("cache hit\n");
3210 *ppTypeLib = &entry->ITypeLib2_iface;
3211 ITypeLib2_AddRef(*ppTypeLib);
3212 LeaveCriticalSection(&cache_section);
3213 return S_OK;
3216 LeaveCriticalSection(&cache_section);
3218 /* now actually load and parse the typelib */
3220 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3221 if (ret == TYPE_E_CANTLOADLIBRARY)
3222 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3223 if (ret == TYPE_E_CANTLOADLIBRARY)
3224 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3225 if (SUCCEEDED(ret))
3227 if (dwTLBLength >= 4)
3229 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3230 if (dwSignature == MSFT_SIGNATURE)
3231 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3232 else if (dwSignature == SLTG_SIGNATURE)
3233 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3234 else
3236 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3237 ret = TYPE_E_CANTLOADLIBRARY;
3240 else
3241 ret = TYPE_E_CANTLOADLIBRARY;
3242 IUnknown_Release(pFile);
3245 if(*ppTypeLib) {
3246 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3248 TRACE("adding to cache\n");
3249 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3250 lstrcpyW(impl->path, pszPath);
3251 /* We should really canonicalise the path here. */
3252 impl->index = index;
3254 /* FIXME: check if it has added already in the meantime */
3255 EnterCriticalSection(&cache_section);
3256 list_add_head(&tlb_cache, &impl->entry);
3257 LeaveCriticalSection(&cache_section);
3258 ret = S_OK;
3260 else
3262 if(ret != E_FAIL)
3263 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3265 ret = TYPE_E_CANTLOADLIBRARY;
3269 return ret;
3272 /*================== ITypeLib(2) Methods ===================================*/
3274 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3276 ITypeLibImpl* pTypeLibImpl;
3278 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3279 if (!pTypeLibImpl) return NULL;
3281 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3282 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3283 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3284 pTypeLibImpl->ref = 1;
3286 list_init(&pTypeLibImpl->implib_list);
3287 list_init(&pTypeLibImpl->custdata_list);
3288 list_init(&pTypeLibImpl->name_list);
3289 list_init(&pTypeLibImpl->string_list);
3290 list_init(&pTypeLibImpl->guid_list);
3291 list_init(&pTypeLibImpl->ref_list);
3292 pTypeLibImpl->dispatch_href = -1;
3294 return pTypeLibImpl;
3297 /****************************************************************************
3298 * ITypeLib2_Constructor_MSFT
3300 * loading an MSFT typelib from an in-memory image
3302 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3304 TLBContext cx;
3305 LONG lPSegDir;
3306 MSFT_Header tlbHeader;
3307 MSFT_SegDir tlbSegDir;
3308 ITypeLibImpl * pTypeLibImpl;
3310 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3312 pTypeLibImpl = TypeLibImpl_Constructor();
3313 if (!pTypeLibImpl) return NULL;
3315 /* get pointer to beginning of typelib data */
3316 cx.pos = 0;
3317 cx.oStart=0;
3318 cx.mapping = pLib;
3319 cx.pLibInfo = pTypeLibImpl;
3320 cx.length = dwTLBLength;
3322 /* read header */
3323 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3324 TRACE_(typelib)("header:\n");
3325 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3326 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3327 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3328 return NULL;
3330 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3332 /* there is a small amount of information here until the next important
3333 * part:
3334 * the segment directory . Try to calculate the amount of data */
3335 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3337 /* now read the segment directory */
3338 TRACE("read segment directory (at %d)\n",lPSegDir);
3339 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3340 cx.pTblDir = &tlbSegDir;
3342 /* just check two entries */
3343 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3345 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3346 heap_free(pTypeLibImpl);
3347 return NULL;
3350 MSFT_ReadAllNames(&cx);
3351 MSFT_ReadAllStrings(&cx);
3352 MSFT_ReadAllGuids(&cx);
3354 /* now fill our internal data */
3355 /* TLIBATTR fields */
3356 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3358 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3359 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3360 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3361 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3362 pTypeLibImpl->libflags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3364 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3365 pTypeLibImpl->lcid = tlbHeader.lcid;
3367 /* name, eventually add to a hash table */
3368 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3370 /* help info */
3371 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3372 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3374 if( tlbHeader.varflags & HELPDLLFLAG)
3376 int offset;
3377 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3378 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3381 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3383 /* custom data */
3384 if(tlbHeader.CustomDataOffset >= 0)
3386 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3389 /* fill in type descriptions */
3390 if(tlbSegDir.pTypdescTab.length > 0)
3392 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3393 INT16 td[4];
3394 pTypeLibImpl->ctTypeDesc = cTD;
3395 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3396 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3397 for(i=0; i<cTD; )
3399 /* FIXME: add several sanity checks here */
3400 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3401 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3403 /* FIXME: check safearray */
3404 if(td[3] < 0)
3405 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3406 else
3407 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3409 else if(td[0] == VT_CARRAY)
3411 /* array descr table here */
3412 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3414 else if(td[0] == VT_USERDEFINED)
3416 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3418 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3421 /* second time around to fill the array subscript info */
3422 for(i=0;i<cTD;i++)
3424 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3425 if(tlbSegDir.pArrayDescriptions.offset>0)
3427 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3428 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3430 if(td[1]<0)
3431 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3432 else
3433 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3435 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3437 for(j = 0; j<td[2]; j++)
3439 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3440 sizeof(INT), &cx, DO_NOT_SEEK);
3441 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3442 sizeof(INT), &cx, DO_NOT_SEEK);
3445 else
3447 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3448 ERR("didn't find array description data\n");
3453 /* imported type libs */
3454 if(tlbSegDir.pImpFiles.offset>0)
3456 TLBImpLib *pImpLib;
3457 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3458 UINT16 size;
3460 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3462 char *name;
3464 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3465 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3466 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3468 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3469 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3470 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3471 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3473 size >>= 2;
3474 name = heap_alloc_zero(size+1);
3475 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3476 pImpLib->name = TLB_MultiByteToBSTR(name);
3477 heap_free(name);
3479 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3480 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3482 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3486 MSFT_ReadAllRefs(&cx);
3488 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3490 /* type infos */
3491 if(tlbHeader.nrtypeinfos >= 0 )
3493 ITypeInfoImpl **ppTI;
3494 int i;
3496 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3498 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3500 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3502 ++ppTI;
3503 (pTypeLibImpl->TypeInfoCount)++;
3507 TRACE("(%p)\n", pTypeLibImpl);
3508 return &pTypeLibImpl->ITypeLib2_iface;
3512 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3514 char b[3];
3515 int i;
3516 short s;
3518 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3519 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3520 return FALSE;
3523 guid->Data4[0] = s >> 8;
3524 guid->Data4[1] = s & 0xff;
3526 b[2] = '\0';
3527 for(i = 0; i < 6; i++) {
3528 memcpy(b, str + 24 + 2 * i, 2);
3529 guid->Data4[i + 2] = strtol(b, NULL, 16);
3531 return TRUE;
3534 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3536 WORD bytelen;
3537 DWORD len;
3538 BSTR tmp_str;
3540 *pStr = NULL;
3541 bytelen = *(const WORD*)ptr;
3542 if(bytelen == 0xffff) return 2;
3544 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3545 tmp_str = SysAllocStringLen(NULL, len);
3546 if (tmp_str) {
3547 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3548 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3549 SysFreeString(tmp_str);
3551 return bytelen + 2;
3554 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3556 WORD bytelen;
3558 *str = NULL;
3559 bytelen = *(const WORD*)ptr;
3560 if(bytelen == 0xffff) return 2;
3561 *str = heap_alloc(bytelen + 1);
3562 memcpy(*str, ptr + 2, bytelen);
3563 (*str)[bytelen] = '\0';
3564 return bytelen + 2;
3567 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3569 BSTR tmp_str;
3570 TLBString *tlbstr;
3572 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3573 if (tlbstr->offset == offset)
3574 return tlbstr;
3577 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3578 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3579 SysFreeString(tmp_str);
3581 return tlbstr;
3584 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3586 char *ptr = pLibBlk;
3587 WORD w;
3589 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3590 FIXME("libblk magic = %04x\n", w);
3591 return 0;
3594 ptr += 6;
3595 if((w = *(WORD*)ptr) != 0xffff) {
3596 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3597 ptr += w;
3599 ptr += 2;
3601 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3603 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3605 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3606 ptr += 4;
3608 pTypeLibImpl->syskind = *(WORD*)ptr;
3609 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3610 ptr += 2;
3612 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3613 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3614 else
3615 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3616 ptr += 2;
3618 ptr += 4; /* skip res12 */
3620 pTypeLibImpl->libflags = *(WORD*)ptr;
3621 ptr += 2;
3623 pTypeLibImpl->ver_major = *(WORD*)ptr;
3624 ptr += 2;
3626 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3627 ptr += 2;
3629 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr);
3630 ptr += sizeof(GUID);
3632 return ptr - (char*)pLibBlk;
3635 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3636 typedef struct
3638 unsigned int num;
3639 HREFTYPE refs[1];
3640 } sltg_ref_lookup_t;
3642 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3643 HREFTYPE *typelib_ref)
3645 if(table && typeinfo_ref < table->num)
3647 *typelib_ref = table->refs[typeinfo_ref];
3648 return S_OK;
3651 ERR_(typelib)("Unable to find reference\n");
3652 *typelib_ref = -1;
3653 return E_FAIL;
3656 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3658 BOOL done = FALSE;
3660 while(!done) {
3661 if((*pType & 0xe00) == 0xe00) {
3662 pTD->vt = VT_PTR;
3663 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3664 pTD = pTD->u.lptdesc;
3666 switch(*pType & 0x3f) {
3667 case VT_PTR:
3668 pTD->vt = VT_PTR;
3669 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3670 pTD = pTD->u.lptdesc;
3671 break;
3673 case VT_USERDEFINED:
3674 pTD->vt = VT_USERDEFINED;
3675 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3676 done = TRUE;
3677 break;
3679 case VT_CARRAY:
3681 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3682 array */
3684 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3686 pTD->vt = VT_CARRAY;
3687 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3688 pTD->u.lpadesc->cDims = pSA->cDims;
3689 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3690 pSA->cDims * sizeof(SAFEARRAYBOUND));
3692 pTD = &pTD->u.lpadesc->tdescElem;
3693 break;
3696 case VT_SAFEARRAY:
3698 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3699 useful? */
3701 pType++;
3702 pTD->vt = VT_SAFEARRAY;
3703 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3704 pTD = pTD->u.lptdesc;
3705 break;
3707 default:
3708 pTD->vt = *pType & 0x3f;
3709 done = TRUE;
3710 break;
3712 pType++;
3714 return pType;
3717 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3718 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3720 /* Handle [in/out] first */
3721 if((*pType & 0xc000) == 0xc000)
3722 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3723 else if(*pType & 0x8000)
3724 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3725 else if(*pType & 0x4000)
3726 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3727 else
3728 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3730 if(*pType & 0x2000)
3731 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3733 if(*pType & 0x80)
3734 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3736 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3740 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3741 char *pNameTable)
3743 unsigned int ref;
3744 char *name;
3745 TLBRefType *ref_type;
3746 sltg_ref_lookup_t *table;
3747 HREFTYPE typelib_ref;
3749 if(pRef->magic != SLTG_REF_MAGIC) {
3750 FIXME("Ref magic = %x\n", pRef->magic);
3751 return NULL;
3753 name = ( (char*)pRef->names + pRef->number);
3755 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3756 table->num = pRef->number >> 3;
3758 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3760 /* We don't want the first href to be 0 */
3761 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3763 for(ref = 0; ref < pRef->number >> 3; ref++) {
3764 char *refname;
3765 unsigned int lib_offs, type_num;
3767 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3769 name += SLTG_ReadStringA(name, &refname);
3770 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3771 FIXME_(typelib)("Can't sscanf ref\n");
3772 if(lib_offs != 0xffff) {
3773 TLBImpLib *import;
3775 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3776 if(import->offset == lib_offs)
3777 break;
3779 if(&import->entry == &pTL->implib_list) {
3780 char fname[MAX_PATH+1];
3781 int len;
3782 GUID tmpguid;
3784 import = heap_alloc_zero(sizeof(*import));
3785 import->offset = lib_offs;
3786 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3787 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid);
3788 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3789 &import->wVersionMajor,
3790 &import->wVersionMinor,
3791 &import->lcid, fname) != 4) {
3792 FIXME_(typelib)("can't sscanf ref %s\n",
3793 pNameTable + lib_offs + 40);
3795 len = strlen(fname);
3796 if(fname[len-1] != '#')
3797 FIXME("fname = %s\n", fname);
3798 fname[len-1] = '\0';
3799 import->name = TLB_MultiByteToBSTR(fname);
3800 list_add_tail(&pTL->implib_list, &import->entry);
3802 ref_type->pImpTLInfo = import;
3804 /* Store a reference to IDispatch */
3805 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3806 pTL->dispatch_href = typelib_ref;
3808 } else { /* internal ref */
3809 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3811 ref_type->reference = typelib_ref;
3812 ref_type->index = type_num;
3814 heap_free(refname);
3815 list_add_tail(&pTL->ref_list, &ref_type->entry);
3817 table->refs[ref] = typelib_ref;
3818 typelib_ref += 4;
3820 if((BYTE)*name != SLTG_REF_MAGIC)
3821 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3822 dump_TLBRefType(pTL);
3823 return table;
3826 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3827 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3829 SLTG_ImplInfo *info;
3830 TLBImplType *pImplType;
3831 /* I don't really get this structure, usually it's 0x16 bytes
3832 long, but iuser.tlb contains some that are 0x18 bytes long.
3833 That's ok because we can use the next ptr to jump to the next
3834 one. But how do we know the length of the last one? The WORD
3835 at offs 0x8 might be the clue. For now I'm just assuming that
3836 the last one is the regular 0x16 bytes. */
3838 info = (SLTG_ImplInfo*)pBlk;
3839 while(1){
3840 pTI->cImplTypes++;
3841 if(info->next == 0xffff)
3842 break;
3843 info = (SLTG_ImplInfo*)(pBlk + info->next);
3846 info = (SLTG_ImplInfo*)pBlk;
3847 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
3848 pImplType = pTI->impltypes;
3849 while(1) {
3850 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3851 pImplType->implflags = info->impltypeflags;
3852 ++pImplType;
3854 if(info->next == 0xffff)
3855 break;
3856 if(OneOnly)
3857 FIXME_(typelib)("Interface inheriting more than one interface\n");
3858 info = (SLTG_ImplInfo*)(pBlk + info->next);
3860 info++; /* see comment at top of function */
3861 return (char*)info;
3864 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3865 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3867 TLBVarDesc *pVarDesc;
3868 const TLBString *prevName = NULL;
3869 SLTG_Variable *pItem;
3870 unsigned short i;
3871 WORD *pType;
3873 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
3875 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3876 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3878 pVarDesc->vardesc.memid = pItem->memid;
3880 if (pItem->magic != SLTG_VAR_MAGIC &&
3881 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3882 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3883 return;
3886 if (pItem->name == 0xfffe)
3887 pVarDesc->Name = prevName;
3888 else
3889 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
3891 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
3892 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3893 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3895 if(pItem->flags & 0x02)
3896 pType = &pItem->type;
3897 else
3898 pType = (WORD*)(pBlk + pItem->type);
3900 if (pItem->flags & ~0xda)
3901 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3903 SLTG_DoElem(pType, pBlk,
3904 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3906 if (TRACE_ON(typelib)) {
3907 char buf[300];
3908 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3909 TRACE_(typelib)("elemdescVar: %s\n", buf);
3912 if (pItem->flags & 0x40) {
3913 TRACE_(typelib)("VAR_DISPATCH\n");
3914 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3916 else if (pItem->flags & 0x10) {
3917 TRACE_(typelib)("VAR_CONST\n");
3918 pVarDesc->vardesc.varkind = VAR_CONST;
3919 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3920 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3921 if (pItem->flags & 0x08)
3922 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3923 else {
3924 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3926 case VT_LPSTR:
3927 case VT_LPWSTR:
3928 case VT_BSTR:
3930 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3931 BSTR str;
3932 TRACE_(typelib)("len = %u\n", len);
3933 if (len == 0xffff) {
3934 str = NULL;
3935 } else {
3936 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3937 str = SysAllocStringLen(NULL, alloc_len);
3938 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3940 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3941 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3942 break;
3944 case VT_I2:
3945 case VT_UI2:
3946 case VT_I4:
3947 case VT_UI4:
3948 case VT_INT:
3949 case VT_UINT:
3950 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3951 *(INT*)(pBlk + pItem->byte_offs);
3952 break;
3953 default:
3954 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3958 else {
3959 TRACE_(typelib)("VAR_PERINSTANCE\n");
3960 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3961 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3964 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3965 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3967 if (pItem->flags & 0x80)
3968 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3970 prevName = pVarDesc->Name;
3972 pTI->cVars = cVars;
3975 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3976 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3978 SLTG_Function *pFunc;
3979 unsigned short i;
3980 TLBFuncDesc *pFuncDesc;
3982 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
3984 pFuncDesc = pTI->funcdescs;
3985 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3986 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3988 int param;
3989 WORD *pType, *pArg;
3991 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3992 case SLTG_FUNCTION_MAGIC:
3993 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3994 break;
3995 case SLTG_DISPATCH_FUNCTION_MAGIC:
3996 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3997 break;
3998 case SLTG_STATIC_FUNCTION_MAGIC:
3999 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4000 break;
4001 default:
4002 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4003 continue;
4005 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4007 pFuncDesc->funcdesc.memid = pFunc->dispid;
4008 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4009 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4010 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4011 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4012 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4014 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4015 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4017 if(pFunc->retnextopt & 0x80)
4018 pType = &pFunc->rettype;
4019 else
4020 pType = (WORD*)(pBlk + pFunc->rettype);
4022 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4024 pFuncDesc->funcdesc.lprgelemdescParam =
4025 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4026 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4028 pArg = (WORD*)(pBlk + pFunc->arg_off);
4030 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4031 char *paramName = pNameTable + *pArg;
4032 BOOL HaveOffs;
4033 /* If arg type follows then paramName points to the 2nd
4034 letter of the name, else the next WORD is an offset to
4035 the arg type and paramName points to the first letter.
4036 So let's take one char off paramName and see if we're
4037 pointing at an alpha-numeric char. However if *pArg is
4038 0xffff or 0xfffe then the param has no name, the former
4039 meaning that the next WORD is the type, the latter
4040 meaning that the next WORD is an offset to the type. */
4042 HaveOffs = FALSE;
4043 if(*pArg == 0xffff)
4044 paramName = NULL;
4045 else if(*pArg == 0xfffe) {
4046 paramName = NULL;
4047 HaveOffs = TRUE;
4049 else if(paramName[-1] && !isalnum(paramName[-1]))
4050 HaveOffs = TRUE;
4052 pArg++;
4054 if(HaveOffs) { /* the next word is an offset to type */
4055 pType = (WORD*)(pBlk + *pArg);
4056 SLTG_DoElem(pType, pBlk,
4057 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4058 pArg++;
4059 } else {
4060 if(paramName)
4061 paramName--;
4062 pArg = SLTG_DoElem(pArg, pBlk,
4063 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4066 /* Are we an optional param ? */
4067 if(pFuncDesc->funcdesc.cParams - param <=
4068 pFuncDesc->funcdesc.cParamsOpt)
4069 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4071 if(paramName) {
4072 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4073 paramName - pNameTable, pTI->pTypeLib);
4074 } else {
4075 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4079 pTI->cFuncs = cFuncs;
4082 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4083 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4084 SLTG_TypeInfoTail *pTITail)
4086 char *pFirstItem;
4087 sltg_ref_lookup_t *ref_lookup = NULL;
4089 if(pTIHeader->href_table != 0xffffffff) {
4090 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4091 pNameTable);
4094 pFirstItem = pBlk;
4096 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4097 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4099 heap_free(ref_lookup);
4103 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4104 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4105 const SLTG_TypeInfoTail *pTITail)
4107 char *pFirstItem;
4108 sltg_ref_lookup_t *ref_lookup = NULL;
4110 if(pTIHeader->href_table != 0xffffffff) {
4111 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4112 pNameTable);
4115 pFirstItem = pBlk;
4117 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4118 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4121 if (pTITail->funcs_off != 0xffff)
4122 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4124 heap_free(ref_lookup);
4126 if (TRACE_ON(typelib))
4127 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4130 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4131 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4132 const SLTG_TypeInfoTail *pTITail)
4134 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4137 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4138 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4139 const SLTG_TypeInfoTail *pTITail)
4141 WORD *pType;
4142 sltg_ref_lookup_t *ref_lookup = NULL;
4144 if (pTITail->simple_alias) {
4145 /* if simple alias, no more processing required */
4146 pTI->tdescAlias.vt = pTITail->tdescalias_vt;
4147 return;
4150 if(pTIHeader->href_table != 0xffffffff) {
4151 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4152 pNameTable);
4155 /* otherwise it is an offset to a type */
4156 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4158 SLTG_DoType(pType, pBlk, &pTI->tdescAlias, ref_lookup);
4160 heap_free(ref_lookup);
4163 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4164 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4165 const SLTG_TypeInfoTail *pTITail)
4167 sltg_ref_lookup_t *ref_lookup = NULL;
4168 if (pTIHeader->href_table != 0xffffffff)
4169 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4170 pNameTable);
4172 if (pTITail->vars_off != 0xffff)
4173 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4175 if (pTITail->funcs_off != 0xffff)
4176 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4178 if (pTITail->impls_off != 0xffff)
4179 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4181 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4182 * of dispinterface functions including the IDispatch ones, so
4183 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4184 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4186 heap_free(ref_lookup);
4187 if (TRACE_ON(typelib))
4188 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4191 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4192 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4193 const SLTG_TypeInfoTail *pTITail)
4195 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4198 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4199 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4200 const SLTG_TypeInfoTail *pTITail)
4202 sltg_ref_lookup_t *ref_lookup = NULL;
4203 if (pTIHeader->href_table != 0xffffffff)
4204 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4205 pNameTable);
4207 if (pTITail->vars_off != 0xffff)
4208 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4210 if (pTITail->funcs_off != 0xffff)
4211 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4212 heap_free(ref_lookup);
4213 if (TRACE_ON(typelib))
4214 dump_TypeInfo(pTI);
4217 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4218 manageable copy of it into this */
4219 typedef struct {
4220 WORD small_no;
4221 char *index_name;
4222 char *other_name;
4223 WORD res1a;
4224 WORD name_offs;
4225 WORD more_bytes;
4226 char *extra;
4227 WORD res20;
4228 DWORD helpcontext;
4229 WORD res26;
4230 GUID uuid;
4231 } SLTG_InternalOtherTypeInfo;
4233 /****************************************************************************
4234 * ITypeLib2_Constructor_SLTG
4236 * loading a SLTG typelib from an in-memory image
4238 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4240 ITypeLibImpl *pTypeLibImpl;
4241 SLTG_Header *pHeader;
4242 SLTG_BlkEntry *pBlkEntry;
4243 SLTG_Magic *pMagic;
4244 SLTG_Index *pIndex;
4245 SLTG_Pad9 *pPad9;
4246 LPVOID pBlk, pFirstBlk;
4247 SLTG_LibBlk *pLibBlk;
4248 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4249 char *pAfterOTIBlks = NULL;
4250 char *pNameTable, *ptr;
4251 int i;
4252 DWORD len, order;
4253 ITypeInfoImpl **ppTypeInfoImpl;
4255 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4258 pTypeLibImpl = TypeLibImpl_Constructor();
4259 if (!pTypeLibImpl) return NULL;
4261 pHeader = pLib;
4263 TRACE_(typelib)("header:\n");
4264 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4265 pHeader->nrOfFileBlks );
4266 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4267 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4268 pHeader->SLTG_magic);
4269 return NULL;
4272 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4273 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4275 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4276 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4278 /* Next we have a magic block */
4279 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4281 /* Let's see if we're still in sync */
4282 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4283 sizeof(SLTG_COMPOBJ_MAGIC))) {
4284 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4285 return NULL;
4287 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4288 sizeof(SLTG_DIR_MAGIC))) {
4289 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4290 return NULL;
4293 pIndex = (SLTG_Index*)(pMagic+1);
4295 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4297 pFirstBlk = pPad9 + 1;
4299 /* We'll set up a ptr to the main library block, which is the last one. */
4301 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4302 pBlkEntry[order].next != 0;
4303 order = pBlkEntry[order].next - 1, i++) {
4304 pBlk = (char*)pBlk + pBlkEntry[order].len;
4306 pLibBlk = pBlk;
4308 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4310 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4311 interspersed */
4313 len += 0x40;
4315 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4317 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4320 ptr = (char*)pLibBlk + len;
4322 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4323 WORD w, extra;
4324 len = 0;
4326 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4328 w = *(WORD*)(ptr + 2);
4329 if(w != 0xffff) {
4330 len += w;
4331 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4332 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4333 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4335 w = *(WORD*)(ptr + 4 + len);
4336 if(w != 0xffff) {
4337 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4338 len += w;
4339 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4340 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4341 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4343 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4344 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4345 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4346 if(extra) {
4347 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4348 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4349 len += extra;
4351 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4352 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4353 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4354 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4355 len += sizeof(SLTG_OtherTypeInfo);
4356 ptr += len;
4359 pAfterOTIBlks = ptr;
4361 /* Skip this WORD and get the next DWORD */
4362 len = *(DWORD*)(pAfterOTIBlks + 2);
4364 /* Now add this to pLibBLk look at what we're pointing at and
4365 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4366 dust and we should be pointing at the beginning of the name
4367 table */
4369 pNameTable = (char*)pLibBlk + len;
4371 switch(*(WORD*)pNameTable) {
4372 case 0xffff:
4373 break;
4374 case 0x0200:
4375 pNameTable += 0x20;
4376 break;
4377 default:
4378 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4379 break;
4382 pNameTable += 0x216;
4384 pNameTable += 2;
4386 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4388 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4391 /* Hopefully we now have enough ptrs set up to actually read in
4392 some TypeInfos. It's not clear which order to do them in, so
4393 I'll just follow the links along the BlkEntry chain and read
4394 them in the order in which they are in the file */
4396 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4397 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4399 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4400 pBlkEntry[order].next != 0;
4401 order = pBlkEntry[order].next - 1, i++) {
4403 SLTG_TypeInfoHeader *pTIHeader;
4404 SLTG_TypeInfoTail *pTITail;
4405 SLTG_MemberHeader *pMemHeader;
4407 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4408 FIXME_(typelib)("Index strings don't match\n");
4409 heap_free(pOtherTypeInfoBlks);
4410 return NULL;
4413 pTIHeader = pBlk;
4414 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4415 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4416 heap_free(pOtherTypeInfoBlks);
4417 return NULL;
4419 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4420 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4421 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4423 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4424 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4425 (*ppTypeInfoImpl)->index = i;
4426 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4427 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4428 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid);
4429 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4430 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4431 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4432 (*ppTypeInfoImpl)->wTypeFlags =
4433 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4435 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4436 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4438 if((pTIHeader->typeflags1 & 7) != 2)
4439 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4440 if(pTIHeader->typeflags3 != 2)
4441 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4443 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4444 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4445 typekind_desc[pTIHeader->typekind],
4446 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4447 (*ppTypeInfoImpl)->wTypeFlags);
4449 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4451 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4453 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4454 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4455 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4457 switch(pTIHeader->typekind) {
4458 case TKIND_ENUM:
4459 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4460 pTIHeader, pTITail);
4461 break;
4463 case TKIND_RECORD:
4464 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4465 pTIHeader, pTITail);
4466 break;
4468 case TKIND_INTERFACE:
4469 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4470 pTIHeader, pTITail);
4471 break;
4473 case TKIND_COCLASS:
4474 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4475 pTIHeader, pTITail);
4476 break;
4478 case TKIND_ALIAS:
4479 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4480 pTIHeader, pTITail);
4481 break;
4483 case TKIND_DISPATCH:
4484 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4485 pTIHeader, pTITail);
4486 break;
4488 case TKIND_MODULE:
4489 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4490 pTIHeader, pTITail);
4491 break;
4493 default:
4494 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4495 break;
4499 /* could get cFuncs, cVars and cImplTypes from here
4500 but we've already set those */
4501 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4502 X(06);
4503 X(16);
4504 X(18);
4505 X(1a);
4506 X(1e);
4507 X(24);
4508 X(26);
4509 X(2a);
4510 X(2c);
4511 X(2e);
4512 X(30);
4513 X(32);
4514 X(34);
4515 #undef X
4516 ++ppTypeInfoImpl;
4517 pBlk = (char*)pBlk + pBlkEntry[order].len;
4520 if(i != pTypeLibImpl->TypeInfoCount) {
4521 FIXME("Somehow processed %d TypeInfos\n", i);
4522 heap_free(pOtherTypeInfoBlks);
4523 return NULL;
4526 heap_free(pOtherTypeInfoBlks);
4527 return &pTypeLibImpl->ITypeLib2_iface;
4530 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4532 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4534 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4536 if(IsEqualIID(riid, &IID_IUnknown) ||
4537 IsEqualIID(riid,&IID_ITypeLib)||
4538 IsEqualIID(riid,&IID_ITypeLib2))
4540 *ppv = &This->ITypeLib2_iface;
4542 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4543 IsEqualIID(riid, &IID_ICreateTypeLib2))
4545 *ppv = &This->ICreateTypeLib2_iface;
4547 else
4549 *ppv = NULL;
4550 TRACE("-- Interface: E_NOINTERFACE\n");
4551 return E_NOINTERFACE;
4554 IUnknown_AddRef((IUnknown*)*ppv);
4555 return S_OK;
4558 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4560 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4561 ULONG ref = InterlockedIncrement(&This->ref);
4563 TRACE("(%p) ref=%u\n", This, ref);
4565 return ref;
4568 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4570 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4571 ULONG ref = InterlockedDecrement(&This->ref);
4573 TRACE("(%p) ref=%u\n",This, ref);
4575 if (!ref)
4577 TLBImpLib *pImpLib, *pImpLibNext;
4578 TLBRefType *ref_type;
4579 TLBString *tlbstr, *tlbstr_next;
4580 TLBGuid *tlbguid, *tlbguid_next;
4581 void *cursor2;
4582 int i;
4584 /* remove cache entry */
4585 if(This->path)
4587 TRACE("removing from cache list\n");
4588 EnterCriticalSection(&cache_section);
4589 if(This->entry.next)
4590 list_remove(&This->entry);
4591 LeaveCriticalSection(&cache_section);
4592 heap_free(This->path);
4594 TRACE(" destroying ITypeLib(%p)\n",This);
4596 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4597 list_remove(&tlbstr->entry);
4598 SysFreeString(tlbstr->str);
4599 heap_free(tlbstr);
4602 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4603 list_remove(&tlbstr->entry);
4604 SysFreeString(tlbstr->str);
4605 heap_free(tlbstr);
4608 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4609 list_remove(&tlbguid->entry);
4610 heap_free(tlbguid);
4613 TLB_FreeCustData(&This->custdata_list);
4615 for (i = 0; i < This->ctTypeDesc; i++)
4616 if (This->pTypeDesc[i].vt == VT_CARRAY)
4617 heap_free(This->pTypeDesc[i].u.lpadesc);
4619 heap_free(This->pTypeDesc);
4621 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4623 if (pImpLib->pImpTypeLib)
4624 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4625 SysFreeString(pImpLib->name);
4627 list_remove(&pImpLib->entry);
4628 heap_free(pImpLib);
4631 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4633 list_remove(&ref_type->entry);
4634 heap_free(ref_type);
4637 for (i = 0; i < This->TypeInfoCount; ++i)
4638 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4639 heap_free(This->typeinfos);
4640 heap_free(This);
4641 return 0;
4644 return ref;
4647 /* ITypeLib::GetTypeInfoCount
4649 * Returns the number of type descriptions in the type library
4651 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4653 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4654 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4655 return This->TypeInfoCount;
4658 /* ITypeLib::GetTypeInfo
4660 * retrieves the specified type description in the library.
4662 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4663 ITypeLib2 *iface,
4664 UINT index,
4665 ITypeInfo **ppTInfo)
4667 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4669 TRACE("%p %u %p\n", This, index, ppTInfo);
4671 if(!ppTInfo)
4672 return E_INVALIDARG;
4674 if(index >= This->TypeInfoCount)
4675 return TYPE_E_ELEMENTNOTFOUND;
4677 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4678 ITypeInfo_AddRef(*ppTInfo);
4680 return S_OK;
4684 /* ITypeLibs::GetTypeInfoType
4686 * Retrieves the type of a type description.
4688 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4689 ITypeLib2 *iface,
4690 UINT index,
4691 TYPEKIND *pTKind)
4693 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4695 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4697 if(!pTKind)
4698 return E_INVALIDARG;
4700 if(index >= This->TypeInfoCount)
4701 return TYPE_E_ELEMENTNOTFOUND;
4703 *pTKind = This->typeinfos[index]->typekind;
4705 return S_OK;
4708 /* ITypeLib::GetTypeInfoOfGuid
4710 * Retrieves the type description that corresponds to the specified GUID.
4713 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4714 ITypeLib2 *iface,
4715 REFGUID guid,
4716 ITypeInfo **ppTInfo)
4718 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4719 int i;
4721 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4723 for(i = 0; i < This->TypeInfoCount; ++i){
4724 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4725 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4726 ITypeInfo_AddRef(*ppTInfo);
4727 return S_OK;
4731 return TYPE_E_ELEMENTNOTFOUND;
4734 /* ITypeLib::GetLibAttr
4736 * Retrieves the structure that contains the library's attributes.
4739 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4740 ITypeLib2 *iface,
4741 LPTLIBATTR *attr)
4743 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4745 TRACE("(%p, %p)\n", This, attr);
4747 if (!attr) return E_INVALIDARG;
4749 *attr = heap_alloc(sizeof(**attr));
4750 if (!*attr) return E_OUTOFMEMORY;
4752 (*attr)->guid = *TLB_get_guid_null(This->guid);
4753 (*attr)->lcid = This->set_lcid;
4754 (*attr)->syskind = This->syskind;
4755 (*attr)->wMajorVerNum = This->ver_major;
4756 (*attr)->wMinorVerNum = This->ver_minor;
4757 (*attr)->wLibFlags = This->libflags;
4759 return S_OK;
4762 /* ITypeLib::GetTypeComp
4764 * Enables a client compiler to bind to a library's types, variables,
4765 * constants, and global functions.
4768 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4769 ITypeLib2 *iface,
4770 ITypeComp **ppTComp)
4772 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4774 TRACE("(%p)->(%p)\n",This,ppTComp);
4775 *ppTComp = &This->ITypeComp_iface;
4776 ITypeComp_AddRef(*ppTComp);
4778 return S_OK;
4781 /* ITypeLib::GetDocumentation
4783 * Retrieves the library's documentation string, the complete Help file name
4784 * and path, and the context identifier for the library Help topic in the Help
4785 * file.
4787 * On a successful return all non-null BSTR pointers will have been set,
4788 * possibly to NULL.
4790 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4791 ITypeLib2 *iface,
4792 INT index,
4793 BSTR *pBstrName,
4794 BSTR *pBstrDocString,
4795 DWORD *pdwHelpContext,
4796 BSTR *pBstrHelpFile)
4798 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4799 HRESULT result = E_INVALIDARG;
4800 ITypeInfo *pTInfo;
4802 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4803 This, index,
4804 pBstrName, pBstrDocString,
4805 pdwHelpContext, pBstrHelpFile);
4807 if(index<0)
4809 /* documentation for the typelib */
4810 if(pBstrName)
4812 if (This->Name)
4814 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4815 goto memerr1;
4817 else
4818 *pBstrName = NULL;
4820 if(pBstrDocString)
4822 if (This->DocString)
4824 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4825 goto memerr2;
4827 else
4828 *pBstrDocString = NULL;
4830 if(pdwHelpContext)
4832 *pdwHelpContext = This->dwHelpContext;
4834 if(pBstrHelpFile)
4836 if (This->HelpFile)
4838 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4839 goto memerr3;
4841 else
4842 *pBstrHelpFile = NULL;
4845 result = S_OK;
4847 else
4849 /* for a typeinfo */
4850 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4852 if(SUCCEEDED(result))
4854 result = ITypeInfo_GetDocumentation(pTInfo,
4855 MEMBERID_NIL,
4856 pBstrName,
4857 pBstrDocString,
4858 pdwHelpContext, pBstrHelpFile);
4860 ITypeInfo_Release(pTInfo);
4863 return result;
4864 memerr3:
4865 if (pBstrDocString) SysFreeString (*pBstrDocString);
4866 memerr2:
4867 if (pBstrName) SysFreeString (*pBstrName);
4868 memerr1:
4869 return STG_E_INSUFFICIENTMEMORY;
4872 /* ITypeLib::IsName
4874 * Indicates whether a passed-in string contains the name of a type or member
4875 * described in the library.
4878 static HRESULT WINAPI ITypeLib2_fnIsName(
4879 ITypeLib2 *iface,
4880 LPOLESTR szNameBuf,
4881 ULONG lHashVal,
4882 BOOL *pfName)
4884 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4885 int tic;
4886 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4888 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4889 pfName);
4891 *pfName=TRUE;
4892 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4893 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4894 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4895 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4896 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4897 int pc;
4898 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4899 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
4900 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
4901 goto ITypeLib2_fnIsName_exit;
4904 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
4905 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4906 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4910 *pfName=FALSE;
4912 ITypeLib2_fnIsName_exit:
4913 TRACE("(%p)slow! search for %s: %s found!\n", This,
4914 debugstr_w(szNameBuf), *pfName?"NOT":"");
4916 return S_OK;
4919 /* ITypeLib::FindName
4921 * Finds occurrences of a type description in a type library. This may be used
4922 * to quickly verify that a name exists in a type library.
4925 static HRESULT WINAPI ITypeLib2_fnFindName(
4926 ITypeLib2 *iface,
4927 LPOLESTR name,
4928 ULONG hash,
4929 ITypeInfo **ppTInfo,
4930 MEMBERID *memid,
4931 UINT16 *found)
4933 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4934 int tic;
4935 UINT count = 0;
4936 UINT len;
4938 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4940 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4941 return E_INVALIDARG;
4943 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4944 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4945 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4946 TLBVarDesc *var;
4947 UINT fdc;
4949 if(!TLB_str_memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4950 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
4951 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4952 int pc;
4954 if(!TLB_str_memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4955 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4956 if(!TLB_str_memcmp(name, func->pParamDesc[pc].Name, len))
4957 goto ITypeLib2_fnFindName_exit;
4961 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
4962 if (var)
4963 goto ITypeLib2_fnFindName_exit;
4965 continue;
4966 ITypeLib2_fnFindName_exit:
4967 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
4968 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
4969 count++;
4971 TRACE("found %d typeinfos\n", count);
4973 *found = count;
4975 return S_OK;
4978 /* ITypeLib::ReleaseTLibAttr
4980 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4983 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4984 ITypeLib2 *iface,
4985 TLIBATTR *pTLibAttr)
4987 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4988 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4989 heap_free(pTLibAttr);
4992 /* ITypeLib2::GetCustData
4994 * gets the custom data
4996 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4997 ITypeLib2 * iface,
4998 REFGUID guid,
4999 VARIANT *pVarVal)
5001 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5002 TLBCustData *pCData;
5004 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5006 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5007 if(!pCData)
5008 return TYPE_E_ELEMENTNOTFOUND;
5010 VariantInit(pVarVal);
5011 VariantCopy(pVarVal, &pCData->data);
5013 return S_OK;
5016 /* ITypeLib2::GetLibStatistics
5018 * Returns statistics about a type library that are required for efficient
5019 * sizing of hash tables.
5022 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5023 ITypeLib2 * iface,
5024 ULONG *pcUniqueNames,
5025 ULONG *pcchUniqueNames)
5027 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5029 FIXME("(%p): stub!\n", This);
5031 if(pcUniqueNames) *pcUniqueNames=1;
5032 if(pcchUniqueNames) *pcchUniqueNames=1;
5033 return S_OK;
5036 /* ITypeLib2::GetDocumentation2
5038 * Retrieves the library's documentation string, the complete Help file name
5039 * and path, the localization context to use, and the context ID for the
5040 * library Help topic in the Help file.
5043 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5044 ITypeLib2 * iface,
5045 INT index,
5046 LCID lcid,
5047 BSTR *pbstrHelpString,
5048 DWORD *pdwHelpStringContext,
5049 BSTR *pbstrHelpStringDll)
5051 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5052 HRESULT result;
5053 ITypeInfo *pTInfo;
5055 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5057 /* the help string should be obtained from the helpstringdll,
5058 * using the _DLLGetDocumentation function, based on the supplied
5059 * lcid. Nice to do sometime...
5061 if(index<0)
5063 /* documentation for the typelib */
5064 if(pbstrHelpString)
5065 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5066 if(pdwHelpStringContext)
5067 *pdwHelpStringContext=This->dwHelpContext;
5068 if(pbstrHelpStringDll)
5069 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5071 result = S_OK;
5073 else
5075 /* for a typeinfo */
5076 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5078 if(SUCCEEDED(result))
5080 ITypeInfo2 * pTInfo2;
5081 result = ITypeInfo_QueryInterface(pTInfo,
5082 &IID_ITypeInfo2,
5083 (LPVOID*) &pTInfo2);
5085 if(SUCCEEDED(result))
5087 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5088 MEMBERID_NIL,
5089 lcid,
5090 pbstrHelpString,
5091 pdwHelpStringContext,
5092 pbstrHelpStringDll);
5094 ITypeInfo2_Release(pTInfo2);
5097 ITypeInfo_Release(pTInfo);
5100 return result;
5103 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5105 TLBCustData *pCData;
5106 unsigned int ct;
5107 CUSTDATAITEM *cdi;
5109 ct = list_count(custdata_list);
5111 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
5112 if(!pCustData->prgCustData)
5113 return E_OUTOFMEMORY;
5115 pCustData->cCustData = ct;
5117 cdi = pCustData->prgCustData;
5118 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5119 cdi->guid = *TLB_get_guid_null(pCData->guid);
5120 VariantCopy(&cdi->varValue, &pCData->data);
5121 ++cdi;
5124 return S_OK;
5128 /* ITypeLib2::GetAllCustData
5130 * Gets all custom data items for the library.
5133 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5134 ITypeLib2 * iface,
5135 CUSTDATA *pCustData)
5137 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5138 TRACE("(%p)->(%p)\n", This, pCustData);
5139 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5142 static const ITypeLib2Vtbl tlbvt = {
5143 ITypeLib2_fnQueryInterface,
5144 ITypeLib2_fnAddRef,
5145 ITypeLib2_fnRelease,
5146 ITypeLib2_fnGetTypeInfoCount,
5147 ITypeLib2_fnGetTypeInfo,
5148 ITypeLib2_fnGetTypeInfoType,
5149 ITypeLib2_fnGetTypeInfoOfGuid,
5150 ITypeLib2_fnGetLibAttr,
5151 ITypeLib2_fnGetTypeComp,
5152 ITypeLib2_fnGetDocumentation,
5153 ITypeLib2_fnIsName,
5154 ITypeLib2_fnFindName,
5155 ITypeLib2_fnReleaseTLibAttr,
5157 ITypeLib2_fnGetCustData,
5158 ITypeLib2_fnGetLibStatistics,
5159 ITypeLib2_fnGetDocumentation2,
5160 ITypeLib2_fnGetAllCustData
5164 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5166 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5168 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5171 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5173 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5175 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5178 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5180 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5182 return ITypeLib2_Release(&This->ITypeLib2_iface);
5185 static HRESULT WINAPI ITypeLibComp_fnBind(
5186 ITypeComp * iface,
5187 OLECHAR * szName,
5188 ULONG lHash,
5189 WORD wFlags,
5190 ITypeInfo ** ppTInfo,
5191 DESCKIND * pDescKind,
5192 BINDPTR * pBindPtr)
5194 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5195 int typemismatch=0, i;
5197 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5199 *pDescKind = DESCKIND_NONE;
5200 pBindPtr->lptcomp = NULL;
5201 *ppTInfo = NULL;
5203 for(i = 0; i < This->TypeInfoCount; ++i){
5204 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5205 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5207 /* FIXME: check wFlags here? */
5208 /* FIXME: we should use a hash table to look this info up using lHash
5209 * instead of an O(n) search */
5210 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5211 (pTypeInfo->typekind == TKIND_MODULE))
5213 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5215 *pDescKind = DESCKIND_TYPECOMP;
5216 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5217 ITypeComp_AddRef(pBindPtr->lptcomp);
5218 TRACE("module or enum: %s\n", debugstr_w(szName));
5219 return S_OK;
5223 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5224 (pTypeInfo->typekind == TKIND_ENUM))
5226 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5227 HRESULT hr;
5229 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5230 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5232 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5233 return S_OK;
5235 else if (hr == TYPE_E_TYPEMISMATCH)
5236 typemismatch = 1;
5239 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5240 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5242 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5243 HRESULT hr;
5244 ITypeInfo *subtypeinfo;
5245 BINDPTR subbindptr;
5246 DESCKIND subdesckind;
5248 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5249 &subtypeinfo, &subdesckind, &subbindptr);
5250 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5252 TYPEDESC tdesc_appobject;
5253 const VARDESC vardesc_appobject =
5255 -2, /* memid */
5256 NULL, /* lpstrSchema */
5258 0 /* oInst */
5261 /* ELEMDESC */
5263 /* TYPEDESC */
5265 &tdesc_appobject
5267 VT_PTR
5270 0, /* wVarFlags */
5271 VAR_STATIC /* varkind */
5274 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5275 tdesc_appobject.vt = VT_USERDEFINED;
5277 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5279 /* cleanup things filled in by Bind call so we can put our
5280 * application object data in there instead */
5281 switch (subdesckind)
5283 case DESCKIND_FUNCDESC:
5284 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5285 break;
5286 case DESCKIND_VARDESC:
5287 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5288 break;
5289 default:
5290 break;
5292 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5294 if (pTypeInfo->hreftype == -1)
5295 FIXME("no hreftype for interface %p\n", pTypeInfo);
5297 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5298 if (FAILED(hr))
5299 return hr;
5301 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5302 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5303 ITypeInfo_AddRef(*ppTInfo);
5304 return S_OK;
5306 else if (hr == TYPE_E_TYPEMISMATCH)
5307 typemismatch = 1;
5311 if (typemismatch)
5313 TRACE("type mismatch %s\n", debugstr_w(szName));
5314 return TYPE_E_TYPEMISMATCH;
5316 else
5318 TRACE("name not found %s\n", debugstr_w(szName));
5319 return S_OK;
5323 static HRESULT WINAPI ITypeLibComp_fnBindType(
5324 ITypeComp * iface,
5325 OLECHAR * szName,
5326 ULONG lHash,
5327 ITypeInfo ** ppTInfo,
5328 ITypeComp ** ppTComp)
5330 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5331 ITypeInfoImpl *info;
5333 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5335 if(!szName || !ppTInfo || !ppTComp)
5336 return E_INVALIDARG;
5338 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5339 if(!info){
5340 *ppTInfo = NULL;
5341 *ppTComp = NULL;
5342 return S_OK;
5345 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5346 ITypeInfo_AddRef(*ppTInfo);
5347 *ppTComp = &info->ITypeComp_iface;
5348 ITypeComp_AddRef(*ppTComp);
5350 return S_OK;
5353 static const ITypeCompVtbl tlbtcvt =
5356 ITypeLibComp_fnQueryInterface,
5357 ITypeLibComp_fnAddRef,
5358 ITypeLibComp_fnRelease,
5360 ITypeLibComp_fnBind,
5361 ITypeLibComp_fnBindType
5364 /*================== ITypeInfo(2) Methods ===================================*/
5365 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5367 ITypeInfoImpl *pTypeInfoImpl;
5369 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5370 if (pTypeInfoImpl)
5372 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5373 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5374 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5375 pTypeInfoImpl->ref = 0;
5376 pTypeInfoImpl->hreftype = -1;
5377 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5378 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5379 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5380 list_init(pTypeInfoImpl->pcustdata_list);
5382 TRACE("(%p)\n", pTypeInfoImpl);
5383 return pTypeInfoImpl;
5386 /* ITypeInfo::QueryInterface
5388 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5389 ITypeInfo2 *iface,
5390 REFIID riid,
5391 VOID **ppvObject)
5393 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5395 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5397 *ppvObject=NULL;
5398 if(IsEqualIID(riid, &IID_IUnknown) ||
5399 IsEqualIID(riid,&IID_ITypeInfo)||
5400 IsEqualIID(riid,&IID_ITypeInfo2))
5401 *ppvObject = This;
5402 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5403 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5404 *ppvObject = &This->ICreateTypeInfo2_iface;
5406 if(*ppvObject){
5407 ITypeInfo2_AddRef(iface);
5408 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5409 return S_OK;
5411 TRACE("-- Interface: E_NOINTERFACE\n");
5412 return E_NOINTERFACE;
5415 /* ITypeInfo::AddRef
5417 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5419 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5420 ULONG ref = InterlockedIncrement(&This->ref);
5422 TRACE("(%p)->ref is %u\n",This, ref);
5424 if (ref == 1 /* incremented from 0 */)
5425 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5427 return ref;
5430 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5432 UINT i;
5434 TRACE("destroying ITypeInfo(%p)\n",This);
5436 for (i = 0; i < This->cFuncs; ++i)
5438 int j;
5439 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5440 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5442 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5443 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5444 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5445 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5447 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5448 heap_free(pFInfo->pParamDesc);
5449 TLB_FreeCustData(&pFInfo->custdata_list);
5451 heap_free(This->funcdescs);
5453 for(i = 0; i < This->cVars; ++i)
5455 TLBVarDesc *pVInfo = &This->vardescs[i];
5456 if (pVInfo->vardesc.varkind == VAR_CONST)
5458 VariantClear(pVInfo->vardesc.u.lpvarValue);
5459 heap_free(pVInfo->vardesc.u.lpvarValue);
5461 TLB_FreeCustData(&pVInfo->custdata_list);
5463 heap_free(This->vardescs);
5465 if(This->impltypes){
5466 for (i = 0; i < This->cImplTypes; ++i){
5467 TLBImplType *pImpl = &This->impltypes[i];
5468 TLB_FreeCustData(&pImpl->custdata_list);
5470 heap_free(This->impltypes);
5473 TLB_FreeCustData(&This->custdata_list);
5475 heap_free(This);
5478 /* ITypeInfo::Release
5480 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5482 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5483 ULONG ref = InterlockedDecrement(&This->ref);
5485 TRACE("(%p)->(%u)\n",This, ref);
5487 if (!ref)
5489 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5490 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5491 if (not_attached_to_typelib)
5492 heap_free(This);
5493 /* otherwise This will be freed when typelib is freed */
5496 return ref;
5499 /* ITypeInfo::GetTypeAttr
5501 * Retrieves a TYPEATTR structure that contains the attributes of the type
5502 * description.
5505 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5506 LPTYPEATTR *ppTypeAttr)
5508 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5509 SIZE_T size;
5511 TRACE("(%p)\n",This);
5513 size = sizeof(**ppTypeAttr);
5514 if (This->typekind == TKIND_ALIAS)
5515 size += TLB_SizeTypeDesc(&This->tdescAlias, FALSE);
5517 *ppTypeAttr = heap_alloc(size);
5518 if (!*ppTypeAttr)
5519 return E_OUTOFMEMORY;
5521 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5522 (*ppTypeAttr)->lcid = This->lcid;
5523 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5524 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5525 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5526 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5527 (*ppTypeAttr)->typekind = This->typekind;
5528 (*ppTypeAttr)->cFuncs = This->cFuncs;
5529 (*ppTypeAttr)->cVars = This->cVars;
5530 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5531 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5532 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5533 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5534 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5535 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5536 (*ppTypeAttr)->tdescAlias = This->tdescAlias;
5537 (*ppTypeAttr)->idldescType = This->idldescType;
5539 if (This->typekind == TKIND_ALIAS)
5540 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5541 &This->tdescAlias, *ppTypeAttr + 1);
5543 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5544 /* This should include all the inherited funcs */
5545 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5546 /* This is always the size of IDispatch's vtbl */
5547 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5548 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5550 return S_OK;
5553 /* ITypeInfo::GetTypeComp
5555 * Retrieves the ITypeComp interface for the type description, which enables a
5556 * client compiler to bind to the type description's members.
5559 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5560 ITypeComp * *ppTComp)
5562 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5564 TRACE("(%p)->(%p)\n", This, ppTComp);
5566 *ppTComp = &This->ITypeComp_iface;
5567 ITypeComp_AddRef(*ppTComp);
5568 return S_OK;
5571 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5573 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5574 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5575 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5576 return size;
5579 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5581 *dest = *src;
5582 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5583 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5585 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5586 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5587 *buffer += sizeof(PARAMDESCEX);
5588 *pparamdescex_dest = *pparamdescex_src;
5589 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5590 VariantInit(&pparamdescex_dest->varDefaultValue);
5591 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5592 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5594 else
5595 dest->u.paramdesc.pparamdescex = NULL;
5596 return S_OK;
5599 static HRESULT TLB_SanitizeBSTR(BSTR str)
5601 UINT len = SysStringLen(str), i;
5602 for (i = 0; i < len; ++i)
5603 if (str[i] > 0x7f)
5604 str[i] = '?';
5605 return S_OK;
5608 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5610 if (V_VT(var) == VT_INT)
5611 return VariantChangeType(var, var, 0, VT_I4);
5612 else if (V_VT(var) == VT_UINT)
5613 return VariantChangeType(var, var, 0, VT_UI4);
5614 else if (V_VT(var) == VT_BSTR)
5615 return TLB_SanitizeBSTR(V_BSTR(var));
5617 return S_OK;
5620 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5622 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5623 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5626 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5628 FUNCDESC *dest;
5629 char *buffer;
5630 SIZE_T size = sizeof(*src);
5631 SHORT i;
5632 HRESULT hr;
5634 size += sizeof(*src->lprgscode) * src->cScodes;
5635 size += TLB_SizeElemDesc(&src->elemdescFunc);
5636 for (i = 0; i < src->cParams; i++)
5638 size += sizeof(ELEMDESC);
5639 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5642 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5643 if (!dest) return E_OUTOFMEMORY;
5645 *dest = *src;
5646 if (dispinterface) /* overwrite funckind */
5647 dest->funckind = FUNC_DISPATCH;
5648 buffer = (char *)(dest + 1);
5650 dest->oVft = dest->oVft & 0xFFFC;
5652 if (dest->cScodes) {
5653 dest->lprgscode = (SCODE *)buffer;
5654 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5655 buffer += sizeof(*src->lprgscode) * src->cScodes;
5656 } else
5657 dest->lprgscode = NULL;
5659 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5660 if (FAILED(hr))
5662 SysFreeString((BSTR)dest);
5663 return hr;
5666 if (dest->cParams) {
5667 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5668 buffer += sizeof(ELEMDESC) * src->cParams;
5669 for (i = 0; i < src->cParams; i++)
5671 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5672 if (FAILED(hr))
5673 break;
5675 if (FAILED(hr))
5677 /* undo the above actions */
5678 for (i = i - 1; i >= 0; i--)
5679 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5680 TLB_FreeElemDesc(&dest->elemdescFunc);
5681 SysFreeString((BSTR)dest);
5682 return hr;
5684 } else
5685 dest->lprgelemdescParam = NULL;
5687 /* special treatment for dispinterfaces: this makes functions appear
5688 * to return their [retval] value when it is really returning an
5689 * HRESULT */
5690 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5692 if (dest->cParams &&
5693 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5695 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5696 if (elemdesc->tdesc.vt != VT_PTR)
5698 ERR("elemdesc should have started with VT_PTR instead of:\n");
5699 if (ERR_ON(ole))
5700 dump_ELEMDESC(elemdesc);
5701 return E_UNEXPECTED;
5704 /* copy last parameter to the return value. we are using a flat
5705 * buffer so there is no danger of leaking memory in
5706 * elemdescFunc */
5707 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5709 /* remove the last parameter */
5710 dest->cParams--;
5712 else
5713 /* otherwise this function is made to appear to have no return
5714 * value */
5715 dest->elemdescFunc.tdesc.vt = VT_VOID;
5719 *dest_ptr = dest;
5720 return S_OK;
5723 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5725 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5727 if (index >= This->cFuncs)
5728 return TYPE_E_ELEMENTNOTFOUND;
5730 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5731 return S_OK;
5734 /* internal function to make the inherited interfaces' methods appear
5735 * part of the interface */
5736 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5737 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5739 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5740 HRESULT hr;
5741 UINT implemented_funcs = 0;
5743 if (funcs)
5744 *funcs = 0;
5745 else
5746 *hrefoffset = DISPATCH_HREF_OFFSET;
5748 if(This->impltypes)
5750 ITypeInfo *pSubTypeInfo;
5751 UINT sub_funcs;
5753 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5754 if (FAILED(hr))
5755 return hr;
5757 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5758 index,
5759 ppFuncDesc,
5760 &sub_funcs, hrefoffset);
5761 implemented_funcs += sub_funcs;
5762 ITypeInfo_Release(pSubTypeInfo);
5763 if (SUCCEEDED(hr))
5764 return hr;
5765 *hrefoffset += DISPATCH_HREF_OFFSET;
5768 if (funcs)
5769 *funcs = implemented_funcs + This->cFuncs;
5770 else
5771 *hrefoffset = 0;
5773 if (index < implemented_funcs)
5774 return E_INVALIDARG;
5775 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5776 ppFuncDesc);
5779 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5781 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5782 while (TRUE)
5784 switch (pTypeDesc->vt)
5786 case VT_USERDEFINED:
5787 pTypeDesc->u.hreftype += hrefoffset;
5788 return;
5789 case VT_PTR:
5790 case VT_SAFEARRAY:
5791 pTypeDesc = pTypeDesc->u.lptdesc;
5792 break;
5793 case VT_CARRAY:
5794 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5795 break;
5796 default:
5797 return;
5802 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5804 SHORT i;
5805 for (i = 0; i < pFuncDesc->cParams; i++)
5806 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5807 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5810 /* ITypeInfo::GetFuncDesc
5812 * Retrieves the FUNCDESC structure that contains information about a
5813 * specified function.
5816 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5817 LPFUNCDESC *ppFuncDesc)
5819 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5820 const FUNCDESC *internal_funcdesc;
5821 HRESULT hr;
5822 UINT hrefoffset = 0;
5824 TRACE("(%p) index %d\n", This, index);
5826 if (!ppFuncDesc)
5827 return E_INVALIDARG;
5829 if (This->needs_layout)
5830 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5832 if (This->typekind == TKIND_DISPATCH)
5833 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5834 &internal_funcdesc, NULL,
5835 &hrefoffset);
5836 else
5837 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5838 &internal_funcdesc);
5839 if (FAILED(hr))
5841 WARN("description for function %d not found\n", index);
5842 return hr;
5845 hr = TLB_AllocAndInitFuncDesc(
5846 internal_funcdesc,
5847 ppFuncDesc,
5848 This->typekind == TKIND_DISPATCH);
5850 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
5851 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5853 TRACE("-- 0x%08x\n", hr);
5854 return hr;
5857 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5859 VARDESC *dest;
5860 char *buffer;
5861 SIZE_T size = sizeof(*src);
5862 HRESULT hr;
5864 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5865 if (src->varkind == VAR_CONST)
5866 size += sizeof(VARIANT);
5867 size += TLB_SizeElemDesc(&src->elemdescVar);
5869 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5870 if (!dest) return E_OUTOFMEMORY;
5872 *dest = *src;
5873 buffer = (char *)(dest + 1);
5874 if (src->lpstrSchema)
5876 int len;
5877 dest->lpstrSchema = (LPOLESTR)buffer;
5878 len = strlenW(src->lpstrSchema);
5879 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5880 buffer += (len + 1) * sizeof(WCHAR);
5883 if (src->varkind == VAR_CONST)
5885 HRESULT hr;
5887 dest->u.lpvarValue = (VARIANT *)buffer;
5888 *dest->u.lpvarValue = *src->u.lpvarValue;
5889 buffer += sizeof(VARIANT);
5890 VariantInit(dest->u.lpvarValue);
5891 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5892 if (FAILED(hr))
5894 SysFreeString((BSTR)dest);
5895 return hr;
5898 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5899 if (FAILED(hr))
5901 if (src->varkind == VAR_CONST)
5902 VariantClear(dest->u.lpvarValue);
5903 SysFreeString((BSTR)dest);
5904 return hr;
5906 *dest_ptr = dest;
5907 return S_OK;
5910 /* ITypeInfo::GetVarDesc
5912 * Retrieves a VARDESC structure that describes the specified variable.
5915 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5916 LPVARDESC *ppVarDesc)
5918 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5919 const TLBVarDesc *pVDesc = &This->vardescs[index];
5921 TRACE("(%p) index %d\n", This, index);
5923 if(index >= This->cVars)
5924 return TYPE_E_ELEMENTNOTFOUND;
5926 if (This->needs_layout)
5927 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5929 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5932 /* ITypeInfo_GetNames
5934 * Retrieves the variable with the specified member ID (or the name of the
5935 * property or method and its parameters) that correspond to the specified
5936 * function ID.
5938 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5939 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5941 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5942 const TLBFuncDesc *pFDesc;
5943 const TLBVarDesc *pVDesc;
5944 int i;
5945 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5947 if(!rgBstrNames)
5948 return E_INVALIDARG;
5950 *pcNames = 0;
5952 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
5953 if(pFDesc)
5955 if(!cMaxNames || !pFDesc->Name)
5956 return S_OK;
5958 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
5959 ++(*pcNames);
5961 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
5962 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
5963 return S_OK;
5964 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
5965 ++(*pcNames);
5967 return S_OK;
5970 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
5971 if(pVDesc)
5973 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
5974 *pcNames=1;
5976 else
5978 if(This->impltypes &&
5979 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
5980 /* recursive search */
5981 ITypeInfo *pTInfo;
5982 HRESULT result;
5983 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5984 if(SUCCEEDED(result))
5986 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5987 ITypeInfo_Release(pTInfo);
5988 return result;
5990 WARN("Could not search inherited interface!\n");
5992 else
5994 WARN("no names found\n");
5996 *pcNames=0;
5997 return TYPE_E_ELEMENTNOTFOUND;
5999 return S_OK;
6003 /* ITypeInfo::GetRefTypeOfImplType
6005 * If a type description describes a COM class, it retrieves the type
6006 * description of the implemented interface types. For an interface,
6007 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6008 * if any exist.
6011 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6012 ITypeInfo2 *iface,
6013 UINT index,
6014 HREFTYPE *pRefType)
6016 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6017 HRESULT hr = S_OK;
6019 TRACE("(%p) index %d\n", This, index);
6020 if (TRACE_ON(ole)) dump_TypeInfo(This);
6022 if(index==(UINT)-1)
6024 /* only valid on dual interfaces;
6025 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6028 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6030 *pRefType = -2;
6032 else
6034 hr = TYPE_E_ELEMENTNOTFOUND;
6037 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6039 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6040 *pRefType = This->pTypeLib->dispatch_href;
6042 else
6044 if(index >= This->cImplTypes)
6045 hr = TYPE_E_ELEMENTNOTFOUND;
6046 else{
6047 *pRefType = This->impltypes[index].hRef;
6048 if(This->typekind == TKIND_INTERFACE)
6049 *pRefType |= 0x2;
6053 if(TRACE_ON(ole))
6055 if(SUCCEEDED(hr))
6056 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6057 else
6058 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6061 return hr;
6064 /* ITypeInfo::GetImplTypeFlags
6066 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6067 * or base interface in a type description.
6069 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6070 UINT index, INT *pImplTypeFlags)
6072 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6074 TRACE("(%p) index %d\n", This, index);
6076 if(!pImplTypeFlags)
6077 return E_INVALIDARG;
6079 if(This->typekind == TKIND_DISPATCH && index == 0){
6080 *pImplTypeFlags = 0;
6081 return S_OK;
6084 if(index >= This->cImplTypes)
6085 return TYPE_E_ELEMENTNOTFOUND;
6087 *pImplTypeFlags = This->impltypes[index].implflags;
6089 return S_OK;
6092 /* GetIDsOfNames
6093 * Maps between member names and member IDs, and parameter names and
6094 * parameter IDs.
6096 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6097 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6099 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6100 const TLBVarDesc *pVDesc;
6101 HRESULT ret=S_OK;
6102 UINT i, fdc;
6104 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6105 cNames);
6107 /* init out parameters in case of failure */
6108 for (i = 0; i < cNames; i++)
6109 pMemId[i] = MEMBERID_NIL;
6111 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6112 int j;
6113 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6114 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6115 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6116 for(i=1; i < cNames; i++){
6117 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6118 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6119 break;
6120 if( j<pFDesc->funcdesc.cParams)
6121 pMemId[i]=j;
6122 else
6123 ret=DISP_E_UNKNOWNNAME;
6125 TRACE("-- 0x%08x\n", ret);
6126 return ret;
6129 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6130 if(pVDesc){
6131 if(cNames)
6132 *pMemId = pVDesc->vardesc.memid;
6133 return ret;
6135 /* not found, see if it can be found in an inherited interface */
6136 if(This->impltypes) {
6137 /* recursive search */
6138 ITypeInfo *pTInfo;
6139 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6140 if(SUCCEEDED(ret)){
6141 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6142 ITypeInfo_Release(pTInfo);
6143 return ret;
6145 WARN("Could not search inherited interface!\n");
6146 } else
6147 WARN("no names found\n");
6148 return DISP_E_UNKNOWNNAME;
6152 #ifdef __i386__
6154 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6155 __ASM_GLOBAL_FUNC( call_method,
6156 "pushl %ebp\n\t"
6157 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6158 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6159 "movl %esp,%ebp\n\t"
6160 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6161 "pushl %esi\n\t"
6162 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6163 "pushl %edi\n\t"
6164 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6165 "movl 12(%ebp),%edx\n\t"
6166 "movl %esp,%edi\n\t"
6167 "shll $2,%edx\n\t"
6168 "jz 1f\n\t"
6169 "subl %edx,%edi\n\t"
6170 "andl $~15,%edi\n\t"
6171 "movl %edi,%esp\n\t"
6172 "movl 12(%ebp),%ecx\n\t"
6173 "movl 16(%ebp),%esi\n\t"
6174 "cld\n\t"
6175 "rep; movsl\n"
6176 "1:\tcall *8(%ebp)\n\t"
6177 "subl %esp,%edi\n\t"
6178 "movl 20(%ebp),%ecx\n\t"
6179 "movl %edi,(%ecx)\n\t"
6180 "leal -8(%ebp),%esp\n\t"
6181 "popl %edi\n\t"
6182 __ASM_CFI(".cfi_same_value %edi\n\t")
6183 "popl %esi\n\t"
6184 __ASM_CFI(".cfi_same_value %esi\n\t")
6185 "popl %ebp\n\t"
6186 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6187 __ASM_CFI(".cfi_same_value %ebp\n\t")
6188 "ret" )
6190 /* same function but returning floating point */
6191 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6193 /* ITypeInfo::Invoke
6195 * Invokes a method, or accesses a property of an object, that implements the
6196 * interface described by the type description.
6198 DWORD
6199 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6200 DWORD res;
6201 int stack_offset;
6203 if (TRACE_ON(ole)) {
6204 int i;
6205 TRACE("Calling %p(",func);
6206 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6207 if (nrargs > 30) TRACE("...");
6208 TRACE(")\n");
6211 switch (callconv) {
6212 case CC_STDCALL:
6213 case CC_CDECL:
6214 res = call_method( func, nrargs, args, &stack_offset );
6215 break;
6216 default:
6217 FIXME("unsupported calling convention %d\n",callconv);
6218 res = -1;
6219 break;
6221 TRACE("returns %08x\n",res);
6222 return res;
6225 #elif defined(__x86_64__)
6227 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6228 __ASM_GLOBAL_FUNC( call_method,
6229 "pushq %rbp\n\t"
6230 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6231 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6232 "movq %rsp,%rbp\n\t"
6233 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6234 "pushq %rsi\n\t"
6235 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6236 "pushq %rdi\n\t"
6237 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6238 "movq %rcx,%rax\n\t"
6239 "movq $4,%rcx\n\t"
6240 "cmp %rcx,%rdx\n\t"
6241 "cmovgq %rdx,%rcx\n\t"
6242 "leaq 0(,%rcx,8),%rdx\n\t"
6243 "subq %rdx,%rsp\n\t"
6244 "andq $~15,%rsp\n\t"
6245 "movq %rsp,%rdi\n\t"
6246 "movq %r8,%rsi\n\t"
6247 "rep; movsq\n\t"
6248 "movq 0(%rsp),%rcx\n\t"
6249 "movq 8(%rsp),%rdx\n\t"
6250 "movq 16(%rsp),%r8\n\t"
6251 "movq 24(%rsp),%r9\n\t"
6252 "movq %rcx,%xmm0\n\t"
6253 "movq %rdx,%xmm1\n\t"
6254 "movq %r8,%xmm2\n\t"
6255 "movq %r9,%xmm3\n\t"
6256 "callq *%rax\n\t"
6257 "leaq -16(%rbp),%rsp\n\t"
6258 "popq %rdi\n\t"
6259 __ASM_CFI(".cfi_same_value %rdi\n\t")
6260 "popq %rsi\n\t"
6261 __ASM_CFI(".cfi_same_value %rsi\n\t")
6262 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6263 "popq %rbp\n\t"
6264 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6265 __ASM_CFI(".cfi_same_value %rbp\n\t")
6266 "ret")
6268 /* same function but returning floating point */
6269 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6271 #endif /* __x86_64__ */
6273 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6275 HRESULT hr = S_OK;
6276 ITypeInfo *tinfo2 = NULL;
6277 TYPEATTR *tattr = NULL;
6279 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6280 if (hr)
6282 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6283 "hr = 0x%08x\n",
6284 tdesc->u.hreftype, hr);
6285 return hr;
6287 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6288 if (hr)
6290 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6291 ITypeInfo_Release(tinfo2);
6292 return hr;
6295 switch (tattr->typekind)
6297 case TKIND_ENUM:
6298 *vt |= VT_I4;
6299 break;
6301 case TKIND_ALIAS:
6302 tdesc = &tattr->tdescAlias;
6303 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6304 break;
6306 case TKIND_INTERFACE:
6307 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6308 *vt |= VT_DISPATCH;
6309 else
6310 *vt |= VT_UNKNOWN;
6311 break;
6313 case TKIND_DISPATCH:
6314 *vt |= VT_DISPATCH;
6315 break;
6317 case TKIND_COCLASS:
6318 *vt |= VT_DISPATCH;
6319 break;
6321 case TKIND_RECORD:
6322 FIXME("TKIND_RECORD unhandled.\n");
6323 hr = E_NOTIMPL;
6324 break;
6326 case TKIND_UNION:
6327 FIXME("TKIND_UNION unhandled.\n");
6328 hr = E_NOTIMPL;
6329 break;
6331 default:
6332 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6333 hr = E_NOTIMPL;
6334 break;
6336 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6337 ITypeInfo_Release(tinfo2);
6338 return hr;
6341 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6343 HRESULT hr = S_OK;
6345 /* enforce only one level of pointer indirection */
6346 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6348 tdesc = tdesc->u.lptdesc;
6350 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6351 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6352 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6353 if ((tdesc->vt == VT_USERDEFINED) ||
6354 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6356 VARTYPE vt_userdefined = 0;
6357 const TYPEDESC *tdesc_userdefined = tdesc;
6358 if (tdesc->vt == VT_PTR)
6360 vt_userdefined = VT_BYREF;
6361 tdesc_userdefined = tdesc->u.lptdesc;
6363 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6364 if ((hr == S_OK) &&
6365 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6366 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6368 *vt |= vt_userdefined;
6369 return S_OK;
6372 *vt = VT_BYREF;
6375 switch (tdesc->vt)
6377 case VT_HRESULT:
6378 *vt |= VT_ERROR;
6379 break;
6380 case VT_USERDEFINED:
6381 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6382 break;
6383 case VT_VOID:
6384 case VT_CARRAY:
6385 case VT_PTR:
6386 case VT_LPSTR:
6387 case VT_LPWSTR:
6388 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6389 hr = DISP_E_BADVARTYPE;
6390 break;
6391 case VT_SAFEARRAY:
6392 *vt |= VT_ARRAY;
6393 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6394 break;
6395 case VT_INT:
6396 *vt |= VT_I4;
6397 break;
6398 case VT_UINT:
6399 *vt |= VT_UI4;
6400 break;
6401 default:
6402 *vt |= tdesc->vt;
6403 break;
6405 return hr;
6408 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6410 ITypeInfo *tinfo2;
6411 TYPEATTR *tattr;
6412 HRESULT hres;
6414 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6415 if(FAILED(hres))
6416 return hres;
6418 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6419 if(FAILED(hres)) {
6420 ITypeInfo_Release(tinfo2);
6421 return hres;
6424 switch(tattr->typekind) {
6425 case TKIND_ALIAS:
6426 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6427 break;
6429 case TKIND_INTERFACE:
6430 case TKIND_DISPATCH:
6431 *guid = tattr->guid;
6432 break;
6434 default:
6435 ERR("Unexpected typekind %d\n", tattr->typekind);
6436 hres = E_UNEXPECTED;
6439 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6440 ITypeInfo_Release(tinfo2);
6441 return hres;
6444 /***********************************************************************
6445 * DispCallFunc (OLEAUT32.@)
6447 * Invokes a function of the specified calling convention, passing the
6448 * specified arguments and returns the result.
6450 * PARAMS
6451 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6452 * oVft [I] The offset in the vtable. See notes.
6453 * cc [I] Calling convention of the function to call.
6454 * vtReturn [I] The return type of the function.
6455 * cActuals [I] Number of parameters.
6456 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6457 * prgpvarg [I] The arguments to pass.
6458 * pvargResult [O] The return value of the function. Can be NULL.
6460 * RETURNS
6461 * Success: S_OK.
6462 * Failure: HRESULT code.
6464 * NOTES
6465 * The HRESULT return value of this function is not affected by the return
6466 * value of the user supplied function, which is returned in pvargResult.
6468 * If pvInstance is NULL then a non-object function is to be called and oVft
6469 * is the address of the function to call.
6471 * The cc parameter can be one of the following values:
6472 *|CC_FASTCALL
6473 *|CC_CDECL
6474 *|CC_PASCAL
6475 *|CC_STDCALL
6476 *|CC_FPFASTCALL
6477 *|CC_SYSCALL
6478 *|CC_MPWCDECL
6479 *|CC_MPWPASCAL
6482 HRESULT WINAPI
6483 DispCallFunc(
6484 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6485 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6487 #ifdef __i386__
6488 int argspos, stack_offset;
6489 void *func;
6490 UINT i;
6491 DWORD *args;
6493 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6494 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6495 pvargResult, V_VT(pvargResult));
6497 if (cc != CC_STDCALL && cc != CC_CDECL)
6499 FIXME("unsupported calling convention %d\n",cc);
6500 return E_INVALIDARG;
6503 /* maximum size for an argument is sizeof(VARIANT) */
6504 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6506 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6507 argspos = 1;
6508 if (pvInstance)
6510 const FARPROC *vtable = *(FARPROC **)pvInstance;
6511 func = vtable[oVft/sizeof(void *)];
6512 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6514 else func = (void *)oVft;
6516 for (i = 0; i < cActuals; i++)
6518 VARIANT *arg = prgpvarg[i];
6520 switch (prgvt[i])
6522 case VT_EMPTY:
6523 break;
6524 case VT_I8:
6525 case VT_UI8:
6526 case VT_R8:
6527 case VT_DATE:
6528 case VT_CY:
6529 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6530 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6531 break;
6532 case VT_DECIMAL:
6533 case VT_VARIANT:
6534 memcpy( &args[argspos], arg, sizeof(*arg) );
6535 argspos += sizeof(*arg) / sizeof(DWORD);
6536 break;
6537 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6538 args[argspos++] = V_BOOL(arg);
6539 break;
6540 default:
6541 args[argspos++] = V_UI4(arg);
6542 break;
6544 TRACE("arg %u: type %d\n",i,prgvt[i]);
6545 dump_Variant(arg);
6548 switch (vtReturn)
6550 case VT_EMPTY:
6551 call_method( func, argspos - 1, args + 1, &stack_offset );
6552 break;
6553 case VT_R4:
6554 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6555 break;
6556 case VT_R8:
6557 case VT_DATE:
6558 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6559 break;
6560 case VT_DECIMAL:
6561 case VT_VARIANT:
6562 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6563 call_method( func, argspos, args, &stack_offset );
6564 break;
6565 case VT_I8:
6566 case VT_UI8:
6567 case VT_CY:
6568 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6569 break;
6570 case VT_HRESULT:
6571 WARN("invalid return type %u\n", vtReturn);
6572 heap_free( args );
6573 return E_INVALIDARG;
6574 default:
6575 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6576 break;
6578 heap_free( args );
6579 if (stack_offset && cc == CC_STDCALL)
6581 WARN( "stack pointer off by %d\n", stack_offset );
6582 return DISP_E_BADCALLEE;
6584 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6585 TRACE("retval: "); dump_Variant(pvargResult);
6586 return S_OK;
6588 #elif defined(__x86_64__)
6589 int argspos;
6590 UINT i;
6591 DWORD_PTR *args;
6592 void *func;
6594 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6595 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6596 pvargResult, V_VT(pvargResult));
6598 if (cc != CC_STDCALL && cc != CC_CDECL)
6600 FIXME("unsupported calling convention %d\n",cc);
6601 return E_INVALIDARG;
6604 /* maximum size for an argument is sizeof(DWORD_PTR) */
6605 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6607 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6608 argspos = 1;
6609 if (pvInstance)
6611 const FARPROC *vtable = *(FARPROC **)pvInstance;
6612 func = vtable[oVft/sizeof(void *)];
6613 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6615 else func = (void *)oVft;
6617 for (i = 0; i < cActuals; i++)
6619 VARIANT *arg = prgpvarg[i];
6621 switch (prgvt[i])
6623 case VT_DECIMAL:
6624 case VT_VARIANT:
6625 args[argspos++] = (ULONG_PTR)arg;
6626 break;
6627 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6628 args[argspos++] = V_BOOL(arg);
6629 break;
6630 default:
6631 args[argspos++] = V_UI8(arg);
6632 break;
6634 TRACE("arg %u: type %d\n",i,prgvt[i]);
6635 dump_Variant(arg);
6638 switch (vtReturn)
6640 case VT_R4:
6641 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6642 break;
6643 case VT_R8:
6644 case VT_DATE:
6645 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6646 break;
6647 case VT_DECIMAL:
6648 case VT_VARIANT:
6649 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6650 call_method( func, argspos, args );
6651 break;
6652 case VT_HRESULT:
6653 WARN("invalid return type %u\n", vtReturn);
6654 heap_free( args );
6655 return E_INVALIDARG;
6656 default:
6657 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6658 break;
6660 heap_free( args );
6661 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6662 TRACE("retval: "); dump_Variant(pvargResult);
6663 return S_OK;
6665 #else
6666 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6667 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6668 return E_NOTIMPL;
6669 #endif
6672 static inline BOOL func_restricted( const FUNCDESC *desc )
6674 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6677 #define INVBUF_ELEMENT_SIZE \
6678 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6679 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6680 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6681 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6682 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6683 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6684 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6685 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6687 static HRESULT WINAPI ITypeInfo_fnInvoke(
6688 ITypeInfo2 *iface,
6689 VOID *pIUnk,
6690 MEMBERID memid,
6691 UINT16 wFlags,
6692 DISPPARAMS *pDispParams,
6693 VARIANT *pVarResult,
6694 EXCEPINFO *pExcepInfo,
6695 UINT *pArgErr)
6697 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6698 int i;
6699 unsigned int var_index;
6700 TYPEKIND type_kind;
6701 HRESULT hres;
6702 const TLBFuncDesc *pFuncInfo;
6703 UINT fdc;
6705 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6706 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6709 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
6710 return DISP_E_MEMBERNOTFOUND;
6712 if (!pDispParams)
6714 ERR("NULL pDispParams not allowed\n");
6715 return E_INVALIDARG;
6718 dump_DispParms(pDispParams);
6720 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6722 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6723 pDispParams->cNamedArgs, pDispParams->cArgs);
6724 return E_INVALIDARG;
6727 /* we do this instead of using GetFuncDesc since it will return a fake
6728 * FUNCDESC for dispinterfaces and we want the real function description */
6729 for (fdc = 0; fdc < This->cFuncs; ++fdc){
6730 pFuncInfo = &This->funcdescs[fdc];
6731 if ((memid == pFuncInfo->funcdesc.memid) &&
6732 (wFlags & pFuncInfo->funcdesc.invkind) &&
6733 !func_restricted( &pFuncInfo->funcdesc ))
6734 break;
6737 if (fdc < This->cFuncs) {
6738 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6740 if (TRACE_ON(ole))
6742 TRACE("invoking:\n");
6743 dump_TLBFuncDescOne(pFuncInfo);
6746 switch (func_desc->funckind) {
6747 case FUNC_PUREVIRTUAL:
6748 case FUNC_VIRTUAL: {
6749 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6750 VARIANT varresult;
6751 VARIANT retval; /* pointer for storing byref retvals in */
6752 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6753 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6754 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6755 UINT cNamedArgs = pDispParams->cNamedArgs;
6756 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6757 UINT vargs_converted=0;
6759 hres = S_OK;
6761 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6763 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6765 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6766 hres = DISP_E_PARAMNOTFOUND;
6767 goto func_fail;
6771 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6773 ERR("functions with the vararg attribute do not support named arguments\n");
6774 hres = DISP_E_NONAMEDARGS;
6775 goto func_fail;
6778 for (i = 0; i < func_desc->cParams; i++)
6780 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6781 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6782 if (FAILED(hres))
6783 goto func_fail;
6786 TRACE("changing args\n");
6787 for (i = 0; i < func_desc->cParams; i++)
6789 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6790 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6791 VARIANTARG *src_arg;
6793 if (wParamFlags & PARAMFLAG_FLCID)
6795 VARIANTARG *arg;
6796 arg = prgpvarg[i] = &rgvarg[i];
6797 V_VT(arg) = VT_I4;
6798 V_I4(arg) = This->pTypeLib->lcid;
6799 continue;
6802 src_arg = NULL;
6804 if (cNamedArgs)
6806 USHORT j;
6807 for (j = 0; j < cNamedArgs; j++)
6808 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6810 src_arg = &pDispParams->rgvarg[j];
6811 break;
6815 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6817 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6818 vargs_converted++;
6821 if (wParamFlags & PARAMFLAG_FRETVAL)
6823 /* under most conditions the caller is not allowed to
6824 * pass in a dispparam arg in the index of what would be
6825 * the retval parameter. however, there is an exception
6826 * where the extra parameter is used in an extra
6827 * IDispatch::Invoke below */
6828 if ((i < pDispParams->cArgs) &&
6829 ((func_desc->cParams != 1) || !pVarResult ||
6830 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6832 hres = DISP_E_BADPARAMCOUNT;
6833 break;
6836 /* note: this check is placed so that if the caller passes
6837 * in a VARIANTARG for the retval we just ignore it, like
6838 * native does */
6839 if (i == func_desc->cParams - 1)
6841 VARIANTARG *arg;
6842 arg = prgpvarg[i] = &rgvarg[i];
6843 memset(arg, 0, sizeof(*arg));
6844 V_VT(arg) = rgvt[i];
6845 memset(&retval, 0, sizeof(retval));
6846 V_BYREF(arg) = &retval;
6848 else
6850 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6851 hres = E_UNEXPECTED;
6852 break;
6855 else if (src_arg)
6857 dump_Variant(src_arg);
6859 if(rgvt[i]!=V_VT(src_arg))
6861 if (rgvt[i] == VT_VARIANT)
6862 hres = VariantCopy(&rgvarg[i], src_arg);
6863 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6865 if (rgvt[i] == V_VT(src_arg))
6866 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6867 else
6869 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6870 if (wParamFlags & PARAMFLAG_FIN)
6871 hres = VariantCopy(&missing_arg[i], src_arg);
6872 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6874 V_VT(&rgvarg[i]) = rgvt[i];
6876 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6878 SAFEARRAY *a;
6879 SAFEARRAYBOUND bound;
6880 VARIANT *v;
6881 LONG j;
6882 bound.lLbound = 0;
6883 bound.cElements = pDispParams->cArgs-i;
6884 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6886 ERR("SafeArrayCreate failed\n");
6887 break;
6889 hres = SafeArrayAccessData(a, (LPVOID)&v);
6890 if (hres != S_OK)
6892 ERR("SafeArrayAccessData failed with %x\n", hres);
6893 SafeArrayDestroy(a);
6894 break;
6896 for (j = 0; j < bound.cElements; j++)
6897 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6898 hres = SafeArrayUnaccessData(a);
6899 if (hres != S_OK)
6901 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6902 SafeArrayDestroy(a);
6903 break;
6905 V_ARRAY(&rgvarg[i]) = a;
6906 V_VT(&rgvarg[i]) = rgvt[i];
6908 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6910 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6911 if (wParamFlags & PARAMFLAG_FIN)
6912 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6913 else
6914 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6915 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6916 V_VT(&rgvarg[i]) = rgvt[i];
6918 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6920 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6921 V_VT(&rgvarg[i]) = rgvt[i];
6923 else
6925 /* FIXME: this doesn't work for VT_BYREF arguments if
6926 * they are not the same type as in the paramdesc */
6927 V_VT(&rgvarg[i]) = V_VT(src_arg);
6928 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6929 V_VT(&rgvarg[i]) = rgvt[i];
6932 if (FAILED(hres))
6934 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6935 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6936 debugstr_VT(src_arg), debugstr_VF(src_arg));
6937 break;
6939 prgpvarg[i] = &rgvarg[i];
6941 else
6943 prgpvarg[i] = src_arg;
6946 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6947 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6948 && V_UNKNOWN(prgpvarg[i])) {
6949 IUnknown *userdefined_iface;
6950 GUID guid;
6952 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6953 if(FAILED(hres))
6954 break;
6956 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6957 if(FAILED(hres)) {
6958 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6959 break;
6962 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6963 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6966 else if (wParamFlags & PARAMFLAG_FOPT)
6968 VARIANTARG *arg;
6969 arg = prgpvarg[i] = &rgvarg[i];
6970 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6972 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6973 if (FAILED(hres))
6974 break;
6976 else
6978 VARIANTARG *missing_arg;
6979 /* if the function wants a pointer to a variant then
6980 * set that up, otherwise just pass the VT_ERROR in
6981 * the argument by value */
6982 if (rgvt[i] & VT_BYREF)
6984 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6985 V_VT(arg) = VT_VARIANT | VT_BYREF;
6986 V_VARIANTREF(arg) = missing_arg;
6988 else
6989 missing_arg = arg;
6990 V_VT(missing_arg) = VT_ERROR;
6991 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6994 else
6996 hres = DISP_E_BADPARAMCOUNT;
6997 break;
7000 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7002 /* VT_VOID is a special case for return types, so it is not
7003 * handled in the general function */
7004 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7005 V_VT(&varresult) = VT_EMPTY;
7006 else
7008 V_VT(&varresult) = 0;
7009 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7010 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7013 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7014 V_VT(&varresult), func_desc->cParams, rgvt,
7015 prgpvarg, &varresult);
7017 vargs_converted = 0;
7019 for (i = 0; i < func_desc->cParams; i++)
7021 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7022 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7024 if (wParamFlags & PARAMFLAG_FLCID)
7025 continue;
7026 else if (wParamFlags & PARAMFLAG_FRETVAL)
7028 if (TRACE_ON(ole))
7030 TRACE("[retval] value: ");
7031 dump_Variant(prgpvarg[i]);
7034 if (pVarResult)
7036 VariantInit(pVarResult);
7037 /* deref return value */
7038 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7041 VARIANT_ClearInd(prgpvarg[i]);
7043 else if (vargs_converted < pDispParams->cArgs)
7045 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7046 if (wParamFlags & PARAMFLAG_FOUT)
7048 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7050 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7052 if (FAILED(hres))
7054 ERR("failed to convert param %d to vt %d\n", i,
7055 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7056 break;
7060 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7061 func_desc->cParamsOpt < 0 &&
7062 i == func_desc->cParams-1)
7064 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7065 LONG j, ubound;
7066 VARIANT *v;
7067 hres = SafeArrayGetUBound(a, 1, &ubound);
7068 if (hres != S_OK)
7070 ERR("SafeArrayGetUBound failed with %x\n", hres);
7071 break;
7073 hres = SafeArrayAccessData(a, (LPVOID)&v);
7074 if (hres != S_OK)
7076 ERR("SafeArrayAccessData failed with %x\n", hres);
7077 break;
7079 for (j = 0; j <= ubound; j++)
7080 VariantClear(&v[j]);
7081 hres = SafeArrayUnaccessData(a);
7082 if (hres != S_OK)
7084 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7085 break;
7088 VariantClear(&rgvarg[i]);
7089 vargs_converted++;
7091 else if (wParamFlags & PARAMFLAG_FOPT)
7093 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7094 VariantClear(&rgvarg[i]);
7097 VariantClear(&missing_arg[i]);
7100 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7102 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7103 hres = DISP_E_EXCEPTION;
7104 if (pExcepInfo)
7106 IErrorInfo *pErrorInfo;
7107 pExcepInfo->scode = V_ERROR(&varresult);
7108 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7110 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7111 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7112 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7113 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7115 IErrorInfo_Release(pErrorInfo);
7119 if (V_VT(&varresult) != VT_ERROR)
7121 TRACE("varresult value: ");
7122 dump_Variant(&varresult);
7124 if (pVarResult)
7126 VariantClear(pVarResult);
7127 *pVarResult = varresult;
7129 else
7130 VariantClear(&varresult);
7133 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7134 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7135 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7136 (pDispParams->cArgs != 0))
7138 if (V_VT(pVarResult) == VT_DISPATCH)
7140 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7141 /* Note: not VariantClear; we still need the dispatch
7142 * pointer to be valid */
7143 VariantInit(pVarResult);
7144 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7145 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7146 pDispParams, pVarResult, pExcepInfo, pArgErr);
7147 IDispatch_Release(pDispatch);
7149 else
7151 VariantClear(pVarResult);
7152 hres = DISP_E_NOTACOLLECTION;
7156 func_fail:
7157 heap_free(buffer);
7158 break;
7160 case FUNC_DISPATCH: {
7161 IDispatch *disp;
7163 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7164 if (SUCCEEDED(hres)) {
7165 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7166 hres = IDispatch_Invoke(
7167 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7168 pVarResult,pExcepInfo,pArgErr
7170 if (FAILED(hres))
7171 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7172 IDispatch_Release(disp);
7173 } else
7174 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7175 break;
7177 default:
7178 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7179 hres = E_FAIL;
7180 break;
7183 TRACE("-- 0x%08x\n", hres);
7184 return hres;
7186 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7187 VARDESC *var_desc;
7189 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7190 if(FAILED(hres)) return hres;
7192 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7193 dump_VARDESC(var_desc);
7194 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7195 return E_NOTIMPL;
7198 /* not found, look for it in inherited interfaces */
7199 ITypeInfo2_GetTypeKind(iface, &type_kind);
7200 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7201 if(This->impltypes) {
7202 /* recursive search */
7203 ITypeInfo *pTInfo;
7204 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7205 if(SUCCEEDED(hres)){
7206 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7207 ITypeInfo_Release(pTInfo);
7208 return hres;
7210 WARN("Could not search inherited interface!\n");
7213 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7214 return DISP_E_MEMBERNOTFOUND;
7217 /* ITypeInfo::GetDocumentation
7219 * Retrieves the documentation string, the complete Help file name and path,
7220 * and the context ID for the Help topic for a specified type description.
7222 * (Can be tested by the Visual Basic Editor in Word for instance.)
7224 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7225 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7226 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7228 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7229 const TLBFuncDesc *pFDesc;
7230 const TLBVarDesc *pVDesc;
7231 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7232 " HelpContext(%p) HelpFile(%p)\n",
7233 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7234 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7235 if(pBstrName)
7236 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7237 if(pBstrDocString)
7238 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7239 if(pdwHelpContext)
7240 *pdwHelpContext=This->dwHelpContext;
7241 if(pBstrHelpFile)
7242 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7243 return S_OK;
7244 }else {/* for a member */
7245 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7246 if(pFDesc){
7247 if(pBstrName)
7248 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7249 if(pBstrDocString)
7250 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7251 if(pdwHelpContext)
7252 *pdwHelpContext=pFDesc->helpcontext;
7253 if(pBstrHelpFile)
7254 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7255 return S_OK;
7257 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7258 if(pVDesc){
7259 if(pBstrName)
7260 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7261 if(pBstrDocString)
7262 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7263 if(pdwHelpContext)
7264 *pdwHelpContext=pVDesc->HelpContext;
7265 if(pBstrHelpFile)
7266 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7267 return S_OK;
7271 if(This->impltypes &&
7272 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7273 /* recursive search */
7274 ITypeInfo *pTInfo;
7275 HRESULT result;
7276 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7277 if(SUCCEEDED(result)) {
7278 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7279 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7280 ITypeInfo_Release(pTInfo);
7281 return result;
7283 WARN("Could not search inherited interface!\n");
7286 WARN("member %d not found\n", memid);
7287 return TYPE_E_ELEMENTNOTFOUND;
7290 /* ITypeInfo::GetDllEntry
7292 * Retrieves a description or specification of an entry point for a function
7293 * in a DLL.
7295 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7296 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7297 WORD *pwOrdinal)
7299 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7300 const TLBFuncDesc *pFDesc;
7302 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7304 if (pBstrDllName) *pBstrDllName = NULL;
7305 if (pBstrName) *pBstrName = NULL;
7306 if (pwOrdinal) *pwOrdinal = 0;
7308 if (This->typekind != TKIND_MODULE)
7309 return TYPE_E_BADMODULEKIND;
7311 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7312 if(pFDesc){
7313 dump_TypeInfo(This);
7314 if (TRACE_ON(ole))
7315 dump_TLBFuncDescOne(pFDesc);
7317 if (pBstrDllName)
7318 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7320 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7321 if (pBstrName)
7322 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7323 if (pwOrdinal)
7324 *pwOrdinal = -1;
7325 return S_OK;
7327 if (pBstrName)
7328 *pBstrName = NULL;
7329 if (pwOrdinal)
7330 *pwOrdinal = LOWORD(pFDesc->Entry);
7331 return S_OK;
7333 return TYPE_E_ELEMENTNOTFOUND;
7336 /* internal function to make the inherited interfaces' methods appear
7337 * part of the interface */
7338 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7339 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7341 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7342 HRESULT hr;
7344 TRACE("%p, 0x%x\n", iface, *hRefType);
7346 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7348 ITypeInfo *pSubTypeInfo;
7350 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7351 if (FAILED(hr))
7352 return hr;
7354 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7355 hRefType, ppTInfo);
7356 ITypeInfo_Release(pSubTypeInfo);
7357 if (SUCCEEDED(hr))
7358 return hr;
7360 *hRefType -= DISPATCH_HREF_OFFSET;
7362 if (!(*hRefType & DISPATCH_HREF_MASK))
7363 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7364 else
7365 return E_FAIL;
7368 /* ITypeInfo::GetRefTypeInfo
7370 * If a type description references other type descriptions, it retrieves
7371 * the referenced type descriptions.
7373 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7374 ITypeInfo2 *iface,
7375 HREFTYPE hRefType,
7376 ITypeInfo **ppTInfo)
7378 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7379 HRESULT result = E_FAIL;
7381 if(!ppTInfo)
7382 return E_INVALIDARG;
7384 if ((INT)hRefType < 0) {
7385 ITypeInfoImpl *pTypeInfoImpl;
7387 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7388 !(This->typekind == TKIND_INTERFACE ||
7389 This->typekind == TKIND_DISPATCH))
7390 return TYPE_E_ELEMENTNOTFOUND;
7392 /* when we meet a DUAL typeinfo, we must create the alternate
7393 * version of it.
7395 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7397 *pTypeInfoImpl = *This;
7398 pTypeInfoImpl->ref = 0;
7399 list_init(&pTypeInfoImpl->custdata_list);
7401 if (This->typekind == TKIND_INTERFACE)
7402 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7403 else
7404 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7406 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7407 /* the AddRef implicitly adds a reference to the parent typelib, which
7408 * stops the copied data from being destroyed until the new typeinfo's
7409 * refcount goes to zero, but we need to signal to the new instance to
7410 * not free its data structures when it is destroyed */
7411 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7413 ITypeInfo_AddRef(*ppTInfo);
7415 result = S_OK;
7416 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7417 (This->typekind == TKIND_DISPATCH))
7419 HREFTYPE href_dispatch = hRefType;
7420 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7421 } else {
7422 TLBRefType *ref_type;
7423 ITypeLib *pTLib = NULL;
7424 UINT i;
7426 if(!(hRefType & 0x1)){
7427 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7429 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7431 result = S_OK;
7432 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7433 ITypeInfo_AddRef(*ppTInfo);
7434 goto end;
7439 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7441 if(ref_type->reference == (hRefType & (~0x3)))
7442 break;
7444 if(&ref_type->entry == &This->pTypeLib->ref_list)
7446 FIXME("Can't find pRefType for ref %x\n", hRefType);
7447 goto end;
7450 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7451 UINT Index;
7452 TRACE("internal reference\n");
7453 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7454 } else {
7455 if(ref_type->pImpTLInfo->pImpTypeLib) {
7456 TRACE("typeinfo in imported typelib that is already loaded\n");
7457 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7458 ITypeLib_AddRef(pTLib);
7459 result = S_OK;
7460 } else {
7461 BSTR libnam;
7463 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7465 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7466 ref_type->pImpTLInfo->wVersionMajor,
7467 ref_type->pImpTLInfo->wVersionMinor,
7468 This->pTypeLib->syskind,
7469 ref_type->pImpTLInfo->lcid, &libnam);
7470 if(FAILED(result))
7471 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7473 result = LoadTypeLib(libnam, &pTLib);
7474 SysFreeString(libnam);
7476 if(SUCCEEDED(result)) {
7477 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7478 ITypeLib_AddRef(pTLib);
7482 if(SUCCEEDED(result)) {
7483 if(ref_type->index == TLB_REF_USE_GUID)
7484 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7485 else
7486 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7488 if (pTLib != NULL)
7489 ITypeLib_Release(pTLib);
7492 end:
7493 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7494 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7495 return result;
7498 /* ITypeInfo::AddressOfMember
7500 * Retrieves the addresses of static functions or variables, such as those
7501 * defined in a DLL.
7503 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7504 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7506 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7507 HRESULT hr;
7508 BSTR dll, entry;
7509 WORD ordinal;
7510 HMODULE module;
7512 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7514 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7515 if (FAILED(hr))
7516 return hr;
7518 module = LoadLibraryW(dll);
7519 if (!module)
7521 ERR("couldn't load %s\n", debugstr_w(dll));
7522 SysFreeString(dll);
7523 SysFreeString(entry);
7524 return STG_E_FILENOTFOUND;
7526 /* FIXME: store library somewhere where we can free it */
7528 if (entry)
7530 LPSTR entryA;
7531 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7532 entryA = heap_alloc(len);
7533 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7535 *ppv = GetProcAddress(module, entryA);
7536 if (!*ppv)
7537 ERR("function not found %s\n", debugstr_a(entryA));
7539 heap_free(entryA);
7541 else
7543 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7544 if (!*ppv)
7545 ERR("function not found %d\n", ordinal);
7548 SysFreeString(dll);
7549 SysFreeString(entry);
7551 if (!*ppv)
7552 return TYPE_E_DLLFUNCTIONNOTFOUND;
7554 return S_OK;
7557 /* ITypeInfo::CreateInstance
7559 * Creates a new instance of a type that describes a component object class
7560 * (coclass).
7562 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7563 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7565 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7566 HRESULT hr;
7567 TYPEATTR *pTA;
7569 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7571 *ppvObj = NULL;
7573 if(pOuterUnk)
7575 WARN("Not able to aggregate\n");
7576 return CLASS_E_NOAGGREGATION;
7579 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7580 if(FAILED(hr)) return hr;
7582 if(pTA->typekind != TKIND_COCLASS)
7584 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7585 hr = E_INVALIDARG;
7586 goto end;
7589 hr = S_FALSE;
7590 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7592 IUnknown *pUnk;
7593 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7594 TRACE("GetActiveObject rets %08x\n", hr);
7595 if(hr == S_OK)
7597 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7598 IUnknown_Release(pUnk);
7602 if(hr != S_OK)
7603 hr = CoCreateInstance(&pTA->guid, NULL,
7604 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7605 riid, ppvObj);
7607 end:
7608 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7609 return hr;
7612 /* ITypeInfo::GetMops
7614 * Retrieves marshalling information.
7616 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7617 BSTR *pBstrMops)
7619 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7620 FIXME("(%p %d) stub!\n", This, memid);
7621 *pBstrMops = NULL;
7622 return S_OK;
7625 /* ITypeInfo::GetContainingTypeLib
7627 * Retrieves the containing type library and the index of the type description
7628 * within that type library.
7630 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7631 ITypeLib * *ppTLib, UINT *pIndex)
7633 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7635 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7636 if (pIndex) {
7637 *pIndex=This->index;
7638 TRACE("returning pIndex=%d\n", *pIndex);
7641 if (ppTLib) {
7642 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7643 ITypeLib_AddRef(*ppTLib);
7644 TRACE("returning ppTLib=%p\n", *ppTLib);
7647 return S_OK;
7650 /* ITypeInfo::ReleaseTypeAttr
7652 * Releases a TYPEATTR previously returned by Get
7655 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7656 TYPEATTR* pTypeAttr)
7658 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7659 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7660 heap_free(pTypeAttr);
7663 /* ITypeInfo::ReleaseFuncDesc
7665 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7667 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7668 ITypeInfo2 *iface,
7669 FUNCDESC *pFuncDesc)
7671 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7672 SHORT i;
7674 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7676 for (i = 0; i < pFuncDesc->cParams; i++)
7677 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7678 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7680 SysFreeString((BSTR)pFuncDesc);
7683 /* ITypeInfo::ReleaseVarDesc
7685 * Releases a VARDESC previously returned by GetVarDesc.
7687 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7688 VARDESC *pVarDesc)
7690 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7691 TRACE("(%p)->(%p)\n", This, pVarDesc);
7693 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7694 if (pVarDesc->varkind == VAR_CONST)
7695 VariantClear(pVarDesc->u.lpvarValue);
7696 SysFreeString((BSTR)pVarDesc);
7699 /* ITypeInfo2::GetTypeKind
7701 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7704 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7705 TYPEKIND *pTypeKind)
7707 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7708 *pTypeKind=This->typekind;
7709 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7710 return S_OK;
7713 /* ITypeInfo2::GetTypeFlags
7715 * Returns the type flags without any allocations. This returns a DWORD type
7716 * flag, which expands the type flags without growing the TYPEATTR (type
7717 * attribute).
7720 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7722 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7723 *pTypeFlags=This->wTypeFlags;
7724 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7725 return S_OK;
7728 /* ITypeInfo2::GetFuncIndexOfMemId
7729 * Binds to a specific member based on a known DISPID, where the member name
7730 * is not known (for example, when binding to a default member).
7733 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7734 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7736 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7737 UINT fdc;
7738 HRESULT result;
7740 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7741 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7742 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7743 break;
7745 if(fdc < This->cFuncs) {
7746 *pFuncIndex = fdc;
7747 result = S_OK;
7748 } else
7749 result = TYPE_E_ELEMENTNOTFOUND;
7751 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7752 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7753 return result;
7756 /* TypeInfo2::GetVarIndexOfMemId
7758 * Binds to a specific member based on a known DISPID, where the member name
7759 * is not known (for example, when binding to a default member).
7762 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7763 MEMBERID memid, UINT *pVarIndex)
7765 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7766 TLBVarDesc *pVarInfo;
7768 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7770 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7771 if(!pVarInfo)
7772 return TYPE_E_ELEMENTNOTFOUND;
7774 *pVarIndex = (pVarInfo - This->vardescs);
7776 return S_OK;
7779 /* ITypeInfo2::GetCustData
7781 * Gets the custom data
7783 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7784 ITypeInfo2 * iface,
7785 REFGUID guid,
7786 VARIANT *pVarVal)
7788 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7789 TLBCustData *pCData;
7791 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7793 if(!guid || !pVarVal)
7794 return E_INVALIDARG;
7796 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
7798 VariantInit( pVarVal);
7799 if (pCData)
7800 VariantCopy( pVarVal, &pCData->data);
7801 else
7802 VariantClear( pVarVal );
7803 return S_OK;
7806 /* ITypeInfo2::GetFuncCustData
7808 * Gets the custom data
7810 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7811 ITypeInfo2 * iface,
7812 UINT index,
7813 REFGUID guid,
7814 VARIANT *pVarVal)
7816 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7817 TLBCustData *pCData;
7818 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7820 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7822 if(index >= This->cFuncs)
7823 return TYPE_E_ELEMENTNOTFOUND;
7825 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7826 if(!pCData)
7827 return TYPE_E_ELEMENTNOTFOUND;
7829 VariantInit(pVarVal);
7830 VariantCopy(pVarVal, &pCData->data);
7832 return S_OK;
7835 /* ITypeInfo2::GetParamCustData
7837 * Gets the custom data
7839 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7840 ITypeInfo2 * iface,
7841 UINT indexFunc,
7842 UINT indexParam,
7843 REFGUID guid,
7844 VARIANT *pVarVal)
7846 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7847 TLBCustData *pCData;
7848 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7850 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7851 debugstr_guid(guid), pVarVal);
7853 if(indexFunc >= This->cFuncs)
7854 return TYPE_E_ELEMENTNOTFOUND;
7856 if(indexParam >= pFDesc->funcdesc.cParams)
7857 return TYPE_E_ELEMENTNOTFOUND;
7859 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7860 if(!pCData)
7861 return TYPE_E_ELEMENTNOTFOUND;
7863 VariantInit(pVarVal);
7864 VariantCopy(pVarVal, &pCData->data);
7866 return S_OK;
7869 /* ITypeInfo2::GetVarCustData
7871 * Gets the custom data
7873 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7874 ITypeInfo2 * iface,
7875 UINT index,
7876 REFGUID guid,
7877 VARIANT *pVarVal)
7879 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7880 TLBCustData *pCData;
7881 TLBVarDesc *pVDesc = &This->vardescs[index];
7883 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7885 if(index >= This->cVars)
7886 return TYPE_E_ELEMENTNOTFOUND;
7888 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7889 if(!pCData)
7890 return TYPE_E_ELEMENTNOTFOUND;
7892 VariantInit(pVarVal);
7893 VariantCopy(pVarVal, &pCData->data);
7895 return S_OK;
7898 /* ITypeInfo2::GetImplCustData
7900 * Gets the custom data
7902 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7903 ITypeInfo2 * iface,
7904 UINT index,
7905 REFGUID guid,
7906 VARIANT *pVarVal)
7908 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7909 TLBCustData *pCData;
7910 TLBImplType *pRDesc = &This->impltypes[index];
7912 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7914 if(index >= This->cImplTypes)
7915 return TYPE_E_ELEMENTNOTFOUND;
7917 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7918 if(!pCData)
7919 return TYPE_E_ELEMENTNOTFOUND;
7921 VariantInit(pVarVal);
7922 VariantCopy(pVarVal, &pCData->data);
7924 return S_OK;
7927 /* ITypeInfo2::GetDocumentation2
7929 * Retrieves the documentation string, the complete Help file name and path,
7930 * the localization context to use, and the context ID for the library Help
7931 * topic in the Help file.
7934 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7935 ITypeInfo2 * iface,
7936 MEMBERID memid,
7937 LCID lcid,
7938 BSTR *pbstrHelpString,
7939 DWORD *pdwHelpStringContext,
7940 BSTR *pbstrHelpStringDll)
7942 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7943 const TLBFuncDesc *pFDesc;
7944 const TLBVarDesc *pVDesc;
7945 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7946 "HelpStringContext(%p) HelpStringDll(%p)\n",
7947 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7948 pbstrHelpStringDll );
7949 /* the help string should be obtained from the helpstringdll,
7950 * using the _DLLGetDocumentation function, based on the supplied
7951 * lcid. Nice to do sometime...
7953 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7954 if(pbstrHelpString)
7955 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
7956 if(pdwHelpStringContext)
7957 *pdwHelpStringContext=This->dwHelpStringContext;
7958 if(pbstrHelpStringDll)
7959 *pbstrHelpStringDll=
7960 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7961 return S_OK;
7962 }else {/* for a member */
7963 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7964 if(pFDesc){
7965 if(pbstrHelpString)
7966 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7967 if(pdwHelpStringContext)
7968 *pdwHelpStringContext=pFDesc->HelpStringContext;
7969 if(pbstrHelpStringDll)
7970 *pbstrHelpStringDll=
7971 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7972 return S_OK;
7974 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7975 if(pVDesc){
7976 if(pbstrHelpString)
7977 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7978 if(pdwHelpStringContext)
7979 *pdwHelpStringContext=pVDesc->HelpStringContext;
7980 if(pbstrHelpStringDll)
7981 *pbstrHelpStringDll=
7982 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
7983 return S_OK;
7986 return TYPE_E_ELEMENTNOTFOUND;
7989 /* ITypeInfo2::GetAllCustData
7991 * Gets all custom data items for the Type info.
7994 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7995 ITypeInfo2 * iface,
7996 CUSTDATA *pCustData)
7998 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8000 TRACE("%p %p\n", This, pCustData);
8002 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8005 /* ITypeInfo2::GetAllFuncCustData
8007 * Gets all custom data items for the specified Function
8010 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8011 ITypeInfo2 * iface,
8012 UINT index,
8013 CUSTDATA *pCustData)
8015 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8016 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8018 TRACE("%p %u %p\n", This, index, pCustData);
8020 if(index >= This->cFuncs)
8021 return TYPE_E_ELEMENTNOTFOUND;
8023 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8026 /* ITypeInfo2::GetAllParamCustData
8028 * Gets all custom data items for the Functions
8031 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8032 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8034 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8035 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8037 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8039 if(indexFunc >= This->cFuncs)
8040 return TYPE_E_ELEMENTNOTFOUND;
8042 if(indexParam >= pFDesc->funcdesc.cParams)
8043 return TYPE_E_ELEMENTNOTFOUND;
8045 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8048 /* ITypeInfo2::GetAllVarCustData
8050 * Gets all custom data items for the specified Variable
8053 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8054 UINT index, CUSTDATA *pCustData)
8056 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8057 TLBVarDesc * pVDesc = &This->vardescs[index];
8059 TRACE("%p %u %p\n", This, index, pCustData);
8061 if(index >= This->cVars)
8062 return TYPE_E_ELEMENTNOTFOUND;
8064 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8067 /* ITypeInfo2::GetAllImplCustData
8069 * Gets all custom data items for the specified implementation type
8072 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8073 ITypeInfo2 * iface,
8074 UINT index,
8075 CUSTDATA *pCustData)
8077 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8078 TLBImplType *pRDesc = &This->impltypes[index];
8080 TRACE("%p %u %p\n", This, index, pCustData);
8082 if(index >= This->cImplTypes)
8083 return TYPE_E_ELEMENTNOTFOUND;
8085 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8088 static const ITypeInfo2Vtbl tinfvt =
8091 ITypeInfo_fnQueryInterface,
8092 ITypeInfo_fnAddRef,
8093 ITypeInfo_fnRelease,
8095 ITypeInfo_fnGetTypeAttr,
8096 ITypeInfo_fnGetTypeComp,
8097 ITypeInfo_fnGetFuncDesc,
8098 ITypeInfo_fnGetVarDesc,
8099 ITypeInfo_fnGetNames,
8100 ITypeInfo_fnGetRefTypeOfImplType,
8101 ITypeInfo_fnGetImplTypeFlags,
8102 ITypeInfo_fnGetIDsOfNames,
8103 ITypeInfo_fnInvoke,
8104 ITypeInfo_fnGetDocumentation,
8105 ITypeInfo_fnGetDllEntry,
8106 ITypeInfo_fnGetRefTypeInfo,
8107 ITypeInfo_fnAddressOfMember,
8108 ITypeInfo_fnCreateInstance,
8109 ITypeInfo_fnGetMops,
8110 ITypeInfo_fnGetContainingTypeLib,
8111 ITypeInfo_fnReleaseTypeAttr,
8112 ITypeInfo_fnReleaseFuncDesc,
8113 ITypeInfo_fnReleaseVarDesc,
8115 ITypeInfo2_fnGetTypeKind,
8116 ITypeInfo2_fnGetTypeFlags,
8117 ITypeInfo2_fnGetFuncIndexOfMemId,
8118 ITypeInfo2_fnGetVarIndexOfMemId,
8119 ITypeInfo2_fnGetCustData,
8120 ITypeInfo2_fnGetFuncCustData,
8121 ITypeInfo2_fnGetParamCustData,
8122 ITypeInfo2_fnGetVarCustData,
8123 ITypeInfo2_fnGetImplTypeCustData,
8124 ITypeInfo2_fnGetDocumentation2,
8125 ITypeInfo2_fnGetAllCustData,
8126 ITypeInfo2_fnGetAllFuncCustData,
8127 ITypeInfo2_fnGetAllParamCustData,
8128 ITypeInfo2_fnGetAllVarCustData,
8129 ITypeInfo2_fnGetAllImplTypeCustData,
8132 /******************************************************************************
8133 * CreateDispTypeInfo [OLEAUT32.31]
8135 * Build type information for an object so it can be called through an
8136 * IDispatch interface.
8138 * RETURNS
8139 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8140 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8142 * NOTES
8143 * This call allows an objects methods to be accessed through IDispatch, by
8144 * building an ITypeInfo object that IDispatch can use to call through.
8146 HRESULT WINAPI CreateDispTypeInfo(
8147 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8148 LCID lcid, /* [I] Locale Id */
8149 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8151 ITypeInfoImpl *pTIClass, *pTIIface;
8152 ITypeLibImpl *pTypeLibImpl;
8153 unsigned int param, func;
8154 TLBFuncDesc *pFuncDesc;
8155 TLBRefType *ref;
8157 TRACE("\n");
8158 pTypeLibImpl = TypeLibImpl_Constructor();
8159 if (!pTypeLibImpl) return E_FAIL;
8161 pTypeLibImpl->TypeInfoCount = 2;
8162 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8164 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8165 pTIIface->pTypeLib = pTypeLibImpl;
8166 pTIIface->index = 0;
8167 pTIIface->Name = NULL;
8168 pTIIface->dwHelpContext = -1;
8169 pTIIface->guid = NULL;
8170 pTIIface->lcid = lcid;
8171 pTIIface->typekind = TKIND_INTERFACE;
8172 pTIIface->wMajorVerNum = 0;
8173 pTIIface->wMinorVerNum = 0;
8174 pTIIface->cbAlignment = 2;
8175 pTIIface->cbSizeInstance = -1;
8176 pTIIface->cbSizeVft = -1;
8177 pTIIface->cFuncs = 0;
8178 pTIIface->cImplTypes = 0;
8179 pTIIface->cVars = 0;
8180 pTIIface->wTypeFlags = 0;
8181 pTIIface->hreftype = 0;
8183 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8184 pFuncDesc = pTIIface->funcdescs;
8185 for(func = 0; func < pidata->cMembers; func++) {
8186 METHODDATA *md = pidata->pmethdata + func;
8187 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8188 pFuncDesc->funcdesc.memid = md->dispid;
8189 pFuncDesc->funcdesc.lprgscode = NULL;
8190 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8191 pFuncDesc->funcdesc.invkind = md->wFlags;
8192 pFuncDesc->funcdesc.callconv = md->cc;
8193 pFuncDesc->funcdesc.cParams = md->cArgs;
8194 pFuncDesc->funcdesc.cParamsOpt = 0;
8195 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8196 pFuncDesc->funcdesc.cScodes = 0;
8197 pFuncDesc->funcdesc.wFuncFlags = 0;
8198 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8199 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8200 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8201 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8202 md->cArgs * sizeof(ELEMDESC));
8203 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8204 for(param = 0; param < md->cArgs; param++) {
8205 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8206 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8208 pFuncDesc->helpcontext = 0;
8209 pFuncDesc->HelpStringContext = 0;
8210 pFuncDesc->HelpString = NULL;
8211 pFuncDesc->Entry = NULL;
8212 list_init(&pFuncDesc->custdata_list);
8213 pTIIface->cFuncs++;
8214 ++pFuncDesc;
8217 dump_TypeInfo(pTIIface);
8219 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8220 pTIClass->pTypeLib = pTypeLibImpl;
8221 pTIClass->index = 1;
8222 pTIClass->Name = NULL;
8223 pTIClass->dwHelpContext = -1;
8224 pTIClass->guid = NULL;
8225 pTIClass->lcid = lcid;
8226 pTIClass->typekind = TKIND_COCLASS;
8227 pTIClass->wMajorVerNum = 0;
8228 pTIClass->wMinorVerNum = 0;
8229 pTIClass->cbAlignment = 2;
8230 pTIClass->cbSizeInstance = -1;
8231 pTIClass->cbSizeVft = -1;
8232 pTIClass->cFuncs = 0;
8233 pTIClass->cImplTypes = 1;
8234 pTIClass->cVars = 0;
8235 pTIClass->wTypeFlags = 0;
8236 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8238 pTIClass->impltypes = TLBImplType_Alloc(1);
8240 ref = heap_alloc_zero(sizeof(*ref));
8241 ref->pImpTLInfo = TLB_REF_INTERNAL;
8242 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8244 dump_TypeInfo(pTIClass);
8246 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8248 ITypeInfo_AddRef(*pptinfo);
8249 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8251 return S_OK;
8255 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8257 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8259 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8262 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8264 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8266 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8269 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8271 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8273 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8276 static HRESULT WINAPI ITypeComp_fnBind(
8277 ITypeComp * iface,
8278 OLECHAR * szName,
8279 ULONG lHash,
8280 WORD wFlags,
8281 ITypeInfo ** ppTInfo,
8282 DESCKIND * pDescKind,
8283 BINDPTR * pBindPtr)
8285 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8286 const TLBFuncDesc *pFDesc;
8287 const TLBVarDesc *pVDesc;
8288 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8289 UINT fdc;
8291 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8293 *pDescKind = DESCKIND_NONE;
8294 pBindPtr->lpfuncdesc = NULL;
8295 *ppTInfo = NULL;
8297 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8298 pFDesc = &This->funcdescs[fdc];
8299 if (!strcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8300 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8301 break;
8302 else
8303 /* name found, but wrong flags */
8304 hr = TYPE_E_TYPEMISMATCH;
8308 if (fdc < This->cFuncs)
8310 HRESULT hr = TLB_AllocAndInitFuncDesc(
8311 &pFDesc->funcdesc,
8312 &pBindPtr->lpfuncdesc,
8313 This->typekind == TKIND_DISPATCH);
8314 if (FAILED(hr))
8315 return hr;
8316 *pDescKind = DESCKIND_FUNCDESC;
8317 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8318 ITypeInfo_AddRef(*ppTInfo);
8319 return S_OK;
8320 } else {
8321 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8322 if(pVDesc){
8323 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8324 if (FAILED(hr))
8325 return hr;
8326 *pDescKind = DESCKIND_VARDESC;
8327 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8328 ITypeInfo_AddRef(*ppTInfo);
8329 return S_OK;
8332 /* FIXME: search each inherited interface, not just the first */
8333 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8334 /* recursive search */
8335 ITypeInfo *pTInfo;
8336 ITypeComp *pTComp;
8337 HRESULT hr;
8338 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8339 if (SUCCEEDED(hr))
8341 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8342 ITypeInfo_Release(pTInfo);
8344 if (SUCCEEDED(hr))
8346 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8347 ITypeComp_Release(pTComp);
8348 return hr;
8350 WARN("Could not search inherited interface!\n");
8352 if (hr == DISP_E_MEMBERNOTFOUND)
8353 hr = S_OK;
8354 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8355 return hr;
8358 static HRESULT WINAPI ITypeComp_fnBindType(
8359 ITypeComp * iface,
8360 OLECHAR * szName,
8361 ULONG lHash,
8362 ITypeInfo ** ppTInfo,
8363 ITypeComp ** ppTComp)
8365 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8367 /* strange behaviour (does nothing) but like the
8368 * original */
8370 if (!ppTInfo || !ppTComp)
8371 return E_POINTER;
8373 *ppTInfo = NULL;
8374 *ppTComp = NULL;
8376 return S_OK;
8379 static const ITypeCompVtbl tcompvt =
8382 ITypeComp_fnQueryInterface,
8383 ITypeComp_fnAddRef,
8384 ITypeComp_fnRelease,
8386 ITypeComp_fnBind,
8387 ITypeComp_fnBindType
8390 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8391 ICreateTypeLib2** ppctlib)
8393 ITypeLibImpl *This;
8394 HRESULT hres;
8396 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8398 if (!szFile) return E_INVALIDARG;
8400 This = TypeLibImpl_Constructor();
8401 if (!This)
8402 return E_OUTOFMEMORY;
8404 This->lcid = GetSystemDefaultLCID();
8405 This->syskind = syskind;
8406 This->ptr_size = get_ptr_size(syskind);
8408 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8409 if (!This->path) {
8410 ITypeLib2_Release(&This->ITypeLib2_iface);
8411 return E_OUTOFMEMORY;
8413 lstrcpyW(This->path, szFile);
8415 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8416 ITypeLib2_Release(&This->ITypeLib2_iface);
8417 return hres;
8420 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8421 REFIID riid, void **object)
8423 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8425 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8428 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8430 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8432 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8435 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8437 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8439 return ITypeLib2_Release(&This->ITypeLib2_iface);
8442 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8443 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8445 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8446 ITypeInfoImpl *info;
8447 HRESULT hres;
8449 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8451 if (!ctinfo || !name)
8452 return E_INVALIDARG;
8454 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8455 if (info)
8456 return TYPE_E_NAMECONFLICT;
8458 if (This->typeinfos)
8459 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8460 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8461 else
8462 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8464 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8466 info->pTypeLib = This;
8467 info->Name = TLB_append_str(&This->name_list, name);
8468 info->index = This->TypeInfoCount;
8469 info->typekind = kind;
8470 info->cbAlignment = 4;
8472 switch(info->typekind) {
8473 case TKIND_ENUM:
8474 case TKIND_INTERFACE:
8475 case TKIND_DISPATCH:
8476 case TKIND_COCLASS:
8477 info->cbSizeInstance = 4;
8478 break;
8479 case TKIND_RECORD:
8480 case TKIND_UNION:
8481 info->cbSizeInstance = 0;
8482 break;
8483 case TKIND_MODULE:
8484 info->cbSizeInstance = 2;
8485 break;
8486 case TKIND_ALIAS:
8487 info->cbSizeInstance = -0x75;
8488 break;
8489 default:
8490 FIXME("unrecognized typekind %d\n", info->typekind);
8491 info->cbSizeInstance = 0xdeadbeef;
8492 break;
8495 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8496 &IID_ICreateTypeInfo, (void **)ctinfo);
8497 if (FAILED(hres)) {
8498 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8499 return hres;
8502 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8504 ++This->TypeInfoCount;
8506 return S_OK;
8509 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8510 LPOLESTR name)
8512 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8514 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8516 if (!name)
8517 return E_INVALIDARG;
8519 This->Name = TLB_append_str(&This->name_list, name);
8521 return S_OK;
8524 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8525 WORD majorVerNum, WORD minorVerNum)
8527 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8529 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8531 This->ver_major = majorVerNum;
8532 This->ver_minor = minorVerNum;
8534 return S_OK;
8537 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8538 REFGUID guid)
8540 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8542 TRACE("%p %s\n", This, debugstr_guid(guid));
8544 This->guid = TLB_append_guid(&This->guid_list, guid);
8546 return S_OK;
8549 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8550 LPOLESTR doc)
8552 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8554 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8556 if (!doc)
8557 return E_INVALIDARG;
8559 This->DocString = TLB_append_str(&This->string_list, doc);
8561 return S_OK;
8564 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8565 LPOLESTR helpFileName)
8567 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8569 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8571 if (!helpFileName)
8572 return E_INVALIDARG;
8574 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8576 return S_OK;
8579 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8580 DWORD helpContext)
8582 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8584 TRACE("%p %d\n", This, helpContext);
8586 This->dwHelpContext = helpContext;
8588 return S_OK;
8591 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8592 LCID lcid)
8594 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8596 TRACE("%p %x\n", This, lcid);
8598 This->set_lcid = lcid;
8600 return S_OK;
8603 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8604 UINT libFlags)
8606 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8608 TRACE("%p %x\n", This, libFlags);
8610 This->libflags = libFlags;
8612 return S_OK;
8615 typedef struct tagWMSFT_SegContents {
8616 DWORD len;
8617 void *data;
8618 } WMSFT_SegContents;
8620 typedef struct tagWMSFT_TLBFile {
8621 MSFT_Header header;
8622 WMSFT_SegContents typeinfo_seg;
8623 WMSFT_SegContents impfile_seg;
8624 WMSFT_SegContents impinfo_seg;
8625 WMSFT_SegContents ref_seg;
8626 WMSFT_SegContents lib_seg;
8627 WMSFT_SegContents guid_seg;
8628 WMSFT_SegContents namehash_seg;
8629 WMSFT_SegContents name_seg;
8630 WMSFT_SegContents string_seg;
8631 WMSFT_SegContents typdesc_seg;
8632 WMSFT_SegContents arraydesc_seg;
8633 WMSFT_SegContents custdata_seg;
8634 WMSFT_SegContents cdguids_seg;
8635 MSFT_SegDir segdir;
8636 WMSFT_SegContents aux_seg;
8637 } WMSFT_TLBFile;
8639 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8640 WMSFT_TLBFile *file)
8642 TLBString *str;
8643 UINT last_offs;
8644 char *data;
8646 file->string_seg.len = 0;
8647 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8648 int size;
8650 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8651 if (size == 0)
8652 return E_UNEXPECTED;
8654 size += sizeof(INT16);
8655 if (size % 4)
8656 size = (size + 4) & ~0x3;
8657 if (size < 8)
8658 size = 8;
8660 file->string_seg.len += size;
8662 /* temporarily use str->offset to store the length of the aligned,
8663 * converted string */
8664 str->offset = size;
8667 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8669 last_offs = 0;
8670 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8671 int size;
8673 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8674 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8675 if (size == 0) {
8676 heap_free(file->string_seg.data);
8677 return E_UNEXPECTED;
8680 *((INT16*)data) = size;
8682 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8684 size = str->offset;
8685 data += size;
8686 str->offset = last_offs;
8687 last_offs += size;
8690 return S_OK;
8693 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8694 WMSFT_TLBFile *file)
8696 TLBString *str;
8697 UINT last_offs;
8698 char *data;
8699 MSFT_NameIntro *last_intro = NULL;
8701 file->header.nametablecount = 0;
8702 file->header.nametablechars = 0;
8704 file->name_seg.len = 0;
8705 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8706 int size;
8708 size = strlenW(str->str);
8709 file->header.nametablechars += size;
8710 file->header.nametablecount++;
8712 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8713 if (size == 0)
8714 return E_UNEXPECTED;
8716 size += sizeof(MSFT_NameIntro);
8717 if (size % 4)
8718 size = (size + 4) & ~0x3;
8719 if (size < 8)
8720 size = 8;
8722 file->name_seg.len += size;
8724 /* temporarily use str->offset to store the length of the aligned,
8725 * converted string */
8726 str->offset = size;
8729 file->name_seg.data = data = heap_alloc(file->name_seg.len);
8731 last_offs = 0;
8732 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8733 int size, hash;
8734 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8736 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8737 data + sizeof(MSFT_NameIntro),
8738 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8739 if (size == 0) {
8740 heap_free(file->name_seg.data);
8741 return E_UNEXPECTED;
8743 data[sizeof(MSFT_NameIntro) + size] = '\0';
8745 intro->hreftype = -1; /* TODO? */
8746 intro->namelen = size & 0xFF;
8747 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8748 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8749 intro->namelen |= hash << 16;
8750 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8751 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8753 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8754 str->offset - size - sizeof(MSFT_NameIntro));
8756 /* update str->offset to actual value to use in other
8757 * compilation functions that require positions within
8758 * the string table */
8759 last_intro = intro;
8760 size = str->offset;
8761 data += size;
8762 str->offset = last_offs;
8763 last_offs += size;
8766 if(last_intro)
8767 last_intro->hreftype = 0; /* last one is 0? */
8769 return S_OK;
8772 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8774 TLBGuid *guid;
8775 MSFT_GuidEntry *entry;
8776 DWORD offs;
8778 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8779 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8781 entry = file->guid_seg.data;
8782 offs = 0;
8783 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
8784 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
8785 entry->hreftype = 0xFFFFFFFF; /* TODO */
8786 entry->next_hash = 0xFFFFFFFF; /* TODO? */
8788 guid->offset = offs;
8790 offs += sizeof(MSFT_GuidEntry);
8791 ++entry;
8794 --entry;
8795 entry->next_hash = 0; /* last one has 0? */
8797 return S_OK;
8800 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
8802 VARIANT v = *value;
8803 VARTYPE arg_type = V_VT(value);
8804 int mask = 0;
8805 HRESULT hres;
8806 DWORD ret = file->custdata_seg.len;
8808 if(arg_type == VT_INT)
8809 arg_type = VT_I4;
8810 if(arg_type == VT_UINT)
8811 arg_type = VT_UI4;
8813 v = *value;
8814 if(V_VT(value) != arg_type) {
8815 hres = VariantChangeType(&v, value, 0, arg_type);
8816 if(FAILED(hres)){
8817 ERR("VariantChangeType failed: %08x\n", hres);
8818 return -1;
8822 /* Check if default value can be stored in-place */
8823 switch(arg_type){
8824 case VT_I4:
8825 case VT_UI4:
8826 mask = 0x3ffffff;
8827 if(V_UI4(&v) > 0x3ffffff)
8828 break;
8829 /* fall through */
8830 case VT_I1:
8831 case VT_UI1:
8832 case VT_BOOL:
8833 if(!mask)
8834 mask = 0xff;
8835 /* fall through */
8836 case VT_I2:
8837 case VT_UI2:
8838 if(!mask)
8839 mask = 0xffff;
8840 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
8843 /* have to allocate space in custdata_seg */
8844 switch(arg_type) {
8845 case VT_I4:
8846 case VT_R4:
8847 case VT_UI4:
8848 case VT_INT:
8849 case VT_UINT:
8850 case VT_HRESULT:
8851 case VT_PTR: {
8852 /* Construct the data to be allocated */
8853 int *data;
8855 if(file->custdata_seg.data){
8856 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
8857 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
8858 file->custdata_seg.len += sizeof(int) * 2;
8859 }else{
8860 file->custdata_seg.len = sizeof(int) * 2;
8861 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8864 data[0] = V_VT(value) + (V_UI4(&v) << 16);
8865 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
8867 /* TODO: Check if the encoded data is already present in custdata_seg */
8869 return ret;
8872 case VT_BSTR: {
8873 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
8874 char *data;
8876 if(file->custdata_seg.data){
8877 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
8878 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
8879 file->custdata_seg.len += len;
8880 }else{
8881 file->custdata_seg.len = len;
8882 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
8885 *((unsigned short *)data) = V_VT(value);
8886 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
8887 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
8888 if(V_BSTR(&v)[i] <= 0x7f)
8889 data[i+6] = V_BSTR(&v)[i];
8890 else
8891 data[i+6] = '?';
8893 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
8894 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
8895 data[i] = 0x57;
8897 /* TODO: Check if the encoded data is already present in custdata_seg */
8899 return ret;
8901 default:
8902 FIXME("Argument type not yet handled\n");
8903 return -1;
8907 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
8909 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
8911 DWORD offs = file->arraydesc_seg.len;
8912 DWORD *encoded;
8913 USHORT i;
8915 /* TODO: we should check for duplicates, but that's harder because each
8916 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8917 * at the library-level) */
8919 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
8920 if(!file->arraydesc_seg.data)
8921 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
8922 else
8923 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
8924 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
8926 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
8927 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
8928 for(i = 0; i < desc->cDims; ++i){
8929 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
8930 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
8933 return offs;
8936 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
8938 DWORD junk;
8939 INT16 junk2;
8940 DWORD offs = 0;
8941 DWORD encoded[2];
8942 VARTYPE vt = desc->vt & VT_TYPEMASK, subtype;
8943 char *data;
8945 if(!out_mix)
8946 out_mix = &junk;
8947 if(!out_size)
8948 out_size = &junk2;
8950 switch(vt){
8951 case VT_INT:
8952 subtype = VT_I4;
8953 break;
8954 case VT_UINT:
8955 subtype = VT_UI4;
8956 break;
8957 case VT_VOID:
8958 subtype = VT_EMPTY;
8959 break;
8960 default:
8961 subtype = vt;
8962 break;
8965 switch(vt){
8966 case VT_INT:
8967 case VT_UINT:
8968 case VT_I1:
8969 case VT_UI1:
8970 case VT_I2:
8971 case VT_UI2:
8972 case VT_I4:
8973 case VT_UI4:
8974 case VT_BOOL:
8975 case VT_R4:
8976 case VT_ERROR:
8977 case VT_BSTR:
8978 case VT_HRESULT:
8979 case VT_CY:
8980 case VT_VOID:
8981 case VT_VARIANT:
8982 *out_mix = subtype;
8983 return 0x80000000 | (subtype << 16) | desc->vt;
8986 if(vt == VT_PTR || vt == VT_SAFEARRAY){
8987 DWORD mix;
8988 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
8989 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
8990 *out_mix = 0x7FFF;
8991 *out_size += 2 * sizeof(DWORD);
8992 }else if(vt == VT_CARRAY){
8993 encoded[0] = desc->vt | (0x7FFE << 16);
8994 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
8995 *out_mix = 0x7FFE;
8996 }else if(vt == VT_USERDEFINED){
8997 encoded[0] = desc->vt | (0x7FFF << 16);
8998 encoded[1] = desc->u.hreftype;
8999 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9000 }else{
9001 FIXME("Don't know what to do! VT: 0x%x\n", desc->vt);
9002 *out_mix = desc->vt;
9003 return 0x80000000 | (desc->vt << 16) | desc->vt;
9006 data = file->typdesc_seg.data;
9007 while(offs < file->typdesc_seg.len){
9008 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9009 return offs;
9010 offs += sizeof(encoded);
9013 file->typdesc_seg.len += sizeof(encoded);
9014 if(!file->typdesc_seg.data)
9015 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9016 else
9017 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9019 memcpy(&data[offs], encoded, sizeof(encoded));
9021 return offs;
9024 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9026 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9027 DWORD ret = cdguids_seg->len, offs;
9028 MSFT_CDGuid *cdguid = cdguids_seg->data;
9029 TLBCustData *cd;
9031 if(list_empty(custdata_list))
9032 return -1;
9034 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9035 if(!cdguids_seg->data){
9036 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9037 }else
9038 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9040 offs = ret + sizeof(MSFT_CDGuid);
9041 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9042 cdguid->GuidOffset = cd->guid->offset;
9043 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9044 cdguid->next = offs;
9045 offs += sizeof(MSFT_CDGuid);
9046 ++cdguid;
9049 --cdguid;
9050 cdguid->next = -1;
9052 return ret;
9055 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9056 WMSFT_TLBFile *file)
9058 WMSFT_SegContents *aux_seg = &file->aux_seg;
9059 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9060 MSFT_VarRecord *varrecord;
9061 MSFT_FuncRecord *funcrecord;
9062 MEMBERID *memid;
9063 DWORD *name, *offsets, offs;
9065 for(i = 0; i < info->cFuncs; ++i){
9066 TLBFuncDesc *desc = &info->funcdescs[i];
9068 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9070 /* optional fields */
9071 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9072 if(!list_empty(&desc->custdata_list))
9073 recorded_size += 7 * sizeof(INT);
9074 else if(desc->HelpStringContext != 0)
9075 recorded_size += 6 * sizeof(INT);
9076 /* res9? resA? */
9077 else if(desc->Entry)
9078 recorded_size += 3 * sizeof(INT);
9079 else if(desc->HelpString)
9080 recorded_size += 2 * sizeof(INT);
9081 else if(desc->helpcontext)
9082 recorded_size += sizeof(INT);
9084 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9086 for(j = 0; j < desc->funcdesc.cParams; ++j){
9087 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9088 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9089 break;
9093 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9096 for(i = 0; i < info->cVars; ++i){
9097 TLBVarDesc *desc = &info->vardescs[i];
9099 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9101 /* optional fields */
9102 if(desc->HelpStringContext != 0)
9103 recorded_size += 5 * sizeof(INT);
9104 else if(!list_empty(&desc->custdata_list))
9105 recorded_size += 4 * sizeof(INT);
9106 /* res9? */
9107 else if(desc->HelpString)
9108 recorded_size += 2 * sizeof(INT);
9109 else if(desc->HelpContext != 0)
9110 recorded_size += sizeof(INT);
9112 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9115 if(!recorded_size && !extra_size)
9116 return ret;
9118 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9120 aux_seg->len += recorded_size + extra_size;
9122 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9124 if(aux_seg->data)
9125 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9126 else
9127 aux_seg->data = heap_alloc(aux_seg->len);
9129 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9131 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9132 offs = 0;
9134 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9135 for(i = 0; i < info->cFuncs; ++i){
9136 TLBFuncDesc *desc = &info->funcdescs[i];
9137 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9139 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9140 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9141 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9142 funcrecord->VtableOffset = desc->funcdesc.oVft;
9144 /* FKCCIC:
9145 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9146 * ^^^funckind
9147 * ^^^ ^invkind
9148 * ^has_cust_data
9149 * ^^^^callconv
9150 * ^has_param_defaults
9151 * ^oEntry_is_intresource
9153 funcrecord->FKCCIC =
9154 desc->funcdesc.funckind |
9155 (desc->funcdesc.invkind << 3) |
9156 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9157 (desc->funcdesc.callconv << 8);
9159 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9160 funcrecord->FKCCIC |= 0x2000;
9162 for(j = 0; j < desc->funcdesc.cParams; ++j){
9163 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9164 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9165 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9168 if(paramdefault_size > 0)
9169 funcrecord->FKCCIC |= 0x1000;
9171 funcrecord->nrargs = desc->funcdesc.cParams;
9172 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9174 /* optional fields */
9175 /* res9? resA? */
9176 if(!list_empty(&desc->custdata_list)){
9177 size += 7 * sizeof(INT);
9178 funcrecord->HelpContext = desc->helpcontext;
9179 if(desc->HelpString)
9180 funcrecord->oHelpString = desc->HelpString->offset;
9181 else
9182 funcrecord->oHelpString = -1;
9183 if(!desc->Entry)
9184 funcrecord->oEntry = -1;
9185 else if(IS_INTRESOURCE(desc->Entry))
9186 funcrecord->oEntry = LOWORD(desc->Entry);
9187 else
9188 funcrecord->oEntry = desc->Entry->offset;
9189 funcrecord->res9 = -1;
9190 funcrecord->resA = -1;
9191 funcrecord->HelpStringContext = desc->HelpStringContext;
9192 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9193 }else if(desc->HelpStringContext != 0){
9194 size += 6 * sizeof(INT);
9195 funcrecord->HelpContext = desc->helpcontext;
9196 if(desc->HelpString)
9197 funcrecord->oHelpString = desc->HelpString->offset;
9198 else
9199 funcrecord->oHelpString = -1;
9200 if(!desc->Entry)
9201 funcrecord->oEntry = -1;
9202 else if(IS_INTRESOURCE(desc->Entry))
9203 funcrecord->oEntry = LOWORD(desc->Entry);
9204 else
9205 funcrecord->oEntry = desc->Entry->offset;
9206 funcrecord->res9 = -1;
9207 funcrecord->resA = -1;
9208 funcrecord->HelpStringContext = desc->HelpStringContext;
9209 }else if(desc->Entry){
9210 size += 3 * sizeof(INT);
9211 funcrecord->HelpContext = desc->helpcontext;
9212 if(desc->HelpString)
9213 funcrecord->oHelpString = desc->HelpString->offset;
9214 else
9215 funcrecord->oHelpString = -1;
9216 if(!desc->Entry)
9217 funcrecord->oEntry = -1;
9218 else if(IS_INTRESOURCE(desc->Entry))
9219 funcrecord->oEntry = LOWORD(desc->Entry);
9220 else
9221 funcrecord->oEntry = desc->Entry->offset;
9222 }else if(desc->HelpString){
9223 size += 2 * sizeof(INT);
9224 funcrecord->HelpContext = desc->helpcontext;
9225 funcrecord->oHelpString = desc->HelpString->offset;
9226 }else if(desc->helpcontext){
9227 size += sizeof(INT);
9228 funcrecord->HelpContext = desc->helpcontext;
9231 paramdefault = (DWORD*)((char *)funcrecord + size);
9232 size += paramdefault_size;
9234 for(j = 0; j < desc->funcdesc.cParams; ++j){
9235 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9237 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9238 if(desc->pParamDesc[j].Name)
9239 info->oName = desc->pParamDesc[j].Name->offset;
9240 else
9241 info->oName = -1;
9242 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9244 if(paramdefault_size){
9245 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9246 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9247 else if(paramdefault_size)
9248 *paramdefault = -1;
9249 ++paramdefault;
9252 size += sizeof(MSFT_ParameterInfo);
9255 funcrecord->Info = size | (i << 16); /* is it just the index? */
9257 *offsets = offs;
9258 offs += size;
9259 ++offsets;
9261 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9264 varrecord = (MSFT_VarRecord*)funcrecord;
9265 for(i = 0; i < info->cVars; ++i){
9266 TLBVarDesc *desc = &info->vardescs[i];
9267 DWORD size = 5 * sizeof(INT);
9269 varrecord->vardescsize = sizeof(desc->vardesc);
9270 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9271 varrecord->Flags = desc->vardesc.wVarFlags;
9272 varrecord->VarKind = desc->vardesc.varkind;
9274 if(desc->vardesc.varkind == VAR_CONST){
9275 varrecord->vardescsize += sizeof(VARIANT);
9276 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9277 }else
9278 varrecord->OffsValue = desc->vardesc.u.oInst;
9280 /* res9? */
9281 if(desc->HelpStringContext != 0){
9282 size += 5 * sizeof(INT);
9283 varrecord->HelpContext = desc->HelpContext;
9284 if(desc->HelpString)
9285 varrecord->HelpString = desc->HelpString->offset;
9286 else
9287 varrecord->HelpString = -1;
9288 varrecord->res9 = -1;
9289 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9290 varrecord->HelpStringContext = desc->HelpStringContext;
9291 }else if(!list_empty(&desc->custdata_list)){
9292 size += 4 * sizeof(INT);
9293 varrecord->HelpContext = desc->HelpContext;
9294 if(desc->HelpString)
9295 varrecord->HelpString = desc->HelpString->offset;
9296 else
9297 varrecord->HelpString = -1;
9298 varrecord->res9 = -1;
9299 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9300 }else if(desc->HelpString){
9301 size += 2 * sizeof(INT);
9302 varrecord->HelpContext = desc->HelpContext;
9303 if(desc->HelpString)
9304 varrecord->HelpString = desc->HelpString->offset;
9305 else
9306 varrecord->HelpString = -1;
9307 }else if(desc->HelpContext != 0){
9308 size += sizeof(INT);
9309 varrecord->HelpContext = desc->HelpContext;
9312 varrecord->Info = size | (i << 16);
9314 *offsets = offs;
9315 offs += size;
9316 ++offsets;
9318 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9321 memid = (MEMBERID*)varrecord;
9322 for(i = 0; i < info->cFuncs; ++i){
9323 TLBFuncDesc *desc = &info->funcdescs[i];
9324 *memid = desc->funcdesc.memid;
9325 ++memid;
9327 for(i = 0; i < info->cVars; ++i){
9328 TLBVarDesc *desc = &info->vardescs[i];
9329 *memid = desc->vardesc.memid;
9330 ++memid;
9333 name = (UINT*)memid;
9334 for(i = 0; i < info->cFuncs; ++i){
9335 TLBFuncDesc *desc = &info->funcdescs[i];
9336 if(desc->Name)
9337 *name = desc->Name->offset;
9338 else
9339 *name = -1;
9340 ++name;
9342 for(i = 0; i < info->cVars; ++i){
9343 TLBVarDesc *desc = &info->vardescs[i];
9344 if(desc->Name)
9345 *name = desc->Name->offset;
9346 else
9347 *name = -1;
9348 ++name;
9351 return ret;
9354 typedef struct tagWMSFT_RefChunk {
9355 DWORD href;
9356 DWORD res04;
9357 DWORD res08;
9358 DWORD next;
9359 } WMSFT_RefChunk;
9361 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9363 DWORD offs = file->ref_seg.len, i;
9364 WMSFT_RefChunk *chunk;
9366 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9367 if(!file->ref_seg.data)
9368 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9369 else
9370 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9372 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9374 for(i = 0; i < info->cImplTypes; ++i){
9375 chunk->href = info->impltypes[i].hRef;
9376 chunk->res04 = info->impltypes[i].implflags;
9377 chunk->res08 = -1;
9378 if(i < info->cImplTypes - 1)
9379 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9380 else
9381 chunk->next = -1;
9382 ++chunk;
9385 return offs;
9388 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9390 DWORD size;
9392 size = sizeof(MSFT_TypeInfoBase);
9394 if(data){
9395 MSFT_TypeInfoBase *base = (void*)data;
9396 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9397 base->typekind = TKIND_DISPATCH;
9398 else
9399 base->typekind = info->typekind;
9400 base->typekind |= index << 16; /* TODO: There are some other flags here */
9401 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9402 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9403 base->res2 = 0;
9404 base->res3 = 0;
9405 base->res4 = 3;
9406 base->res5 = 0;
9407 base->cElement = (info->cVars << 16) | info->cFuncs;
9408 base->res7 = 0;
9409 base->res8 = 0;
9410 base->res9 = 0;
9411 base->resA = 0;
9412 if(info->guid)
9413 base->posguid = info->guid->offset;
9414 else
9415 base->posguid = -1;
9416 base->flags = info->wTypeFlags;
9417 if(info->Name) {
9418 base->NameOffset = info->Name->offset;
9420 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9421 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9422 }else {
9423 base->NameOffset = -1;
9425 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9426 if(info->DocString)
9427 base->docstringoffs = info->DocString->offset;
9428 else
9429 base->docstringoffs = -1;
9430 base->helpstringcontext = info->dwHelpStringContext;
9431 base->helpcontext = info->dwHelpContext;
9432 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9433 base->cImplTypes = info->cImplTypes;
9434 base->cbSizeVft = info->cbSizeVft;
9435 base->size = info->cbSizeInstance;
9436 if(info->typekind == TKIND_COCLASS){
9437 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9438 }else if(info->typekind == TKIND_ALIAS){
9439 base->datatype1 = WMSFT_append_typedesc(&info->tdescAlias, file, NULL, NULL);
9440 }else if(info->typekind == TKIND_MODULE){
9441 if(info->DllName)
9442 base->datatype1 = info->DllName->offset;
9443 else
9444 base->datatype1 = -1;
9445 }else{
9446 if(info->cImplTypes > 0)
9447 base->datatype1 = info->impltypes[0].hRef;
9448 else
9449 base->datatype1 = -1;
9451 base->datatype2 = index; /* FIXME: i think there's more here */
9452 base->res18 = 0;
9453 base->res19 = -1;
9456 return size;
9459 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9461 UINT i;
9463 file->typeinfo_seg.len = 0;
9464 for(i = 0; i < This->TypeInfoCount; ++i){
9465 ITypeInfoImpl *info = This->typeinfos[i];
9466 *junk = file->typeinfo_seg.len;
9467 ++junk;
9468 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9471 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9472 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9474 file->aux_seg.len = 0;
9475 file->aux_seg.data = NULL;
9477 file->typeinfo_seg.len = 0;
9478 for(i = 0; i < This->TypeInfoCount; ++i){
9479 ITypeInfoImpl *info = This->typeinfos[i];
9480 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9481 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9485 typedef struct tagWMSFT_ImpFile {
9486 INT guid_offs;
9487 LCID lcid;
9488 DWORD version;
9489 } WMSFT_ImpFile;
9491 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9493 TLBImpLib *implib;
9494 WMSFT_ImpFile *impfile;
9495 char *data;
9496 DWORD last_offs = 0;
9498 file->impfile_seg.len = 0;
9499 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9500 int size = 0;
9502 if(implib->name){
9503 WCHAR *path = strrchrW(implib->name, '\\');
9504 if(path)
9505 ++path;
9506 else
9507 path = implib->name;
9508 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9509 if (size == 0)
9510 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9513 size += sizeof(INT16);
9514 if (size % 4)
9515 size = (size + 4) & ~0x3;
9516 if (size < 8)
9517 size = 8;
9519 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9522 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9524 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9525 int strlen = 0, size;
9527 impfile = (WMSFT_ImpFile*)data;
9528 impfile->guid_offs = implib->guid->offset;
9529 impfile->lcid = implib->lcid;
9530 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9532 data += sizeof(WMSFT_ImpFile);
9534 if(implib->name){
9535 WCHAR *path= strrchrW(implib->name, '\\');
9536 if(path)
9537 ++path;
9538 else
9539 path = implib->name;
9540 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9541 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9542 if (strlen == 0)
9543 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9546 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9548 size = strlen + sizeof(INT16);
9549 if (size % 4)
9550 size = (size + 4) & ~0x3;
9551 if (size < 8)
9552 size = 8;
9553 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9555 data += size;
9556 implib->offset = last_offs;
9557 last_offs += size + sizeof(WMSFT_ImpFile);
9561 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9563 MSFT_ImpInfo *info;
9564 TLBRefType *ref_type;
9565 UINT i = 0;
9567 WMSFT_compile_impfile(This, file);
9569 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9570 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9572 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9573 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9574 if(ref_type->index == TLB_REF_USE_GUID){
9575 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9576 info->oGuid = ref_type->guid->offset;
9577 }else
9578 info->oGuid = ref_type->index;
9579 info->oImpFile = ref_type->pImpTLInfo->offset;
9580 ++i;
9581 ++info;
9585 static void WMSFT_compile_lib(ITypeLibImpl *This, WMSFT_TLBFile *file)
9587 /* TODO: What actually goes here? */
9588 file->lib_seg.len = 0x80;
9589 file->lib_seg.data = heap_alloc(file->lib_seg.len);
9590 memset(file->lib_seg.data, 0xFF, file->lib_seg.len);
9592 #if 0
9593 /* sometimes, first element is offset to last guid, for some reason */
9594 if(This->guid)
9595 *(DWORD*)file->lib_seg.data =
9596 (list_count(&This->guid_list) - 1) * sizeof(MSFT_GuidEntry);
9597 #endif
9600 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9602 file->namehash_seg.len = 0x200;
9603 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9604 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9607 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9609 if(contents && contents->len){
9610 segdir->offset = *running_offset;
9611 segdir->length = contents->len;
9612 *running_offset += segdir->length;
9613 }else{
9614 segdir->offset = -1;
9615 segdir->length = 0;
9618 /* TODO: do these ever change? */
9619 segdir->res08 = -1;
9620 segdir->res0c = 0xf;
9623 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9625 DWORD written;
9626 if(segment)
9627 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9630 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9631 DWORD file_len)
9633 DWORD i;
9634 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9636 for(i = 0; i < This->TypeInfoCount; ++i){
9637 base->memoffset += file_len;
9638 ++base;
9641 return S_OK;
9644 static void WMSFT_free_file(WMSFT_TLBFile *file)
9646 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9647 HeapFree(GetProcessHeap(), 0, file->lib_seg.data);
9648 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9649 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9650 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9651 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9652 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9653 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9654 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9655 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9656 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9657 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9658 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9659 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9662 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9664 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9665 WMSFT_TLBFile file;
9666 DWORD written, junk_size, junk_offs, running_offset;
9667 BOOL br;
9668 HANDLE outfile;
9669 HRESULT hres;
9670 DWORD *junk;
9672 TRACE("%p\n", This);
9674 memset(&file, 0, sizeof(file));
9676 file.header.magic1 = 0x5446534D;
9677 file.header.magic2 = 0x00010002;
9678 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9679 file.header.lcid2 = This->set_lcid;
9680 file.header.varflags = 0x41; /* TODO?? */
9681 if (This->HelpFile)
9682 file.header.varflags |= 0x10;
9683 if (This->HelpStringDll)
9684 file.header.varflags |= HELPDLLFLAG;
9685 file.header.version = (This->ver_major << 16) | This->ver_minor;
9686 file.header.flags = This->libflags;
9687 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9688 file.header.helpcontext = This->dwHelpContext;
9689 file.header.res44 = 0x20;
9690 file.header.res48 = 0x80;
9691 file.header.dispatchpos = This->dispatch_href;
9693 WMSFT_compile_namehash(This, &file);
9694 /* do name and string compilation to get offsets for other compilations */
9695 hres = WMSFT_compile_names(This, &file);
9696 if (FAILED(hres)){
9697 WMSFT_free_file(&file);
9698 return hres;
9701 hres = WMSFT_compile_strings(This, &file);
9702 if (FAILED(hres)){
9703 WMSFT_free_file(&file);
9704 return hres;
9707 hres = WMSFT_compile_guids(This, &file);
9708 if (FAILED(hres)){
9709 WMSFT_free_file(&file);
9710 return hres;
9713 if(This->HelpFile)
9714 file.header.helpfile = This->HelpFile->offset;
9715 else
9716 file.header.helpfile = -1;
9718 if(This->DocString)
9719 file.header.helpstring = This->DocString->offset;
9720 else
9721 file.header.helpstring = -1;
9723 /* do some more segment compilation */
9724 file.header.nimpinfos = list_count(&This->ref_list);
9725 file.header.nrtypeinfos = This->TypeInfoCount;
9727 if(This->Name)
9728 file.header.NameOffset = This->Name->offset;
9729 else
9730 file.header.NameOffset = -1;
9732 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
9734 if(This->guid)
9735 file.header.posguid = This->guid->offset;
9736 else
9737 file.header.posguid = -1;
9739 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9740 if(file.header.varflags & HELPDLLFLAG)
9741 junk_size += sizeof(DWORD);
9742 if(junk_size){
9743 junk = heap_alloc_zero(junk_size);
9744 if(file.header.varflags & HELPDLLFLAG){
9745 *junk = This->HelpStringDll->offset;
9746 junk_offs = 1;
9747 }else
9748 junk_offs = 0;
9749 }else{
9750 junk = NULL;
9751 junk_offs = 0;
9754 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9755 WMSFT_compile_impinfo(This, &file);
9756 WMSFT_compile_lib(This, &file);
9758 running_offset = 0;
9760 TRACE("header at: 0x%x\n", running_offset);
9761 running_offset += sizeof(file.header);
9763 TRACE("junk at: 0x%x\n", running_offset);
9764 running_offset += junk_size;
9766 TRACE("segdir at: 0x%x\n", running_offset);
9767 running_offset += sizeof(file.segdir);
9769 TRACE("typeinfo at: 0x%x\n", running_offset);
9770 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9772 TRACE("libtab at: 0x%x\n", running_offset);
9773 tmp_fill_segdir_seg(&file.segdir.pLibtab, &file.lib_seg, &running_offset);
9775 TRACE("guidtab at: 0x%x\n", running_offset);
9776 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9778 TRACE("reftab at: 0x%x\n", running_offset);
9779 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9781 TRACE("impinfo at: 0x%x\n", running_offset);
9782 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9784 TRACE("impfiles at: 0x%x\n", running_offset);
9785 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9787 TRACE("namehashtab at: 0x%x\n", running_offset);
9788 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
9790 TRACE("nametab at: 0x%x\n", running_offset);
9791 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9793 TRACE("stringtab at: 0x%x\n", running_offset);
9794 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9796 TRACE("typdesc at: 0x%x\n", running_offset);
9797 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9799 TRACE("arraydescriptions at: 0x%x\n", running_offset);
9800 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
9802 TRACE("custdata at: 0x%x\n", running_offset);
9803 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
9805 TRACE("cdguids at: 0x%x\n", running_offset);
9806 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
9808 TRACE("res0e at: 0x%x\n", running_offset);
9809 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
9811 TRACE("res0f at: 0x%x\n", running_offset);
9812 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
9814 TRACE("aux_seg at: 0x%x\n", running_offset);
9816 WMSFT_fixup_typeinfos(This, &file, running_offset);
9818 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
9819 FILE_ATTRIBUTE_NORMAL, 0);
9820 if (outfile == INVALID_HANDLE_VALUE){
9821 WMSFT_free_file(&file);
9822 heap_free(junk);
9823 return TYPE_E_IOERROR;
9826 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
9827 if (!br) {
9828 WMSFT_free_file(&file);
9829 CloseHandle(outfile);
9830 heap_free(junk);
9831 return TYPE_E_IOERROR;
9834 br = WriteFile(outfile, junk, junk_size, &written, NULL);
9835 heap_free(junk);
9836 if (!br) {
9837 WMSFT_free_file(&file);
9838 CloseHandle(outfile);
9839 return TYPE_E_IOERROR;
9842 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
9843 if (!br) {
9844 WMSFT_free_file(&file);
9845 CloseHandle(outfile);
9846 return TYPE_E_IOERROR;
9849 WMSFT_write_segment(outfile, &file.typeinfo_seg);
9850 WMSFT_write_segment(outfile, &file.lib_seg);
9851 WMSFT_write_segment(outfile, &file.guid_seg);
9852 WMSFT_write_segment(outfile, &file.ref_seg);
9853 WMSFT_write_segment(outfile, &file.impinfo_seg);
9854 WMSFT_write_segment(outfile, &file.impfile_seg);
9855 WMSFT_write_segment(outfile, &file.namehash_seg);
9856 WMSFT_write_segment(outfile, &file.name_seg);
9857 WMSFT_write_segment(outfile, &file.string_seg);
9858 WMSFT_write_segment(outfile, &file.typdesc_seg);
9859 WMSFT_write_segment(outfile, &file.arraydesc_seg);
9860 WMSFT_write_segment(outfile, &file.custdata_seg);
9861 WMSFT_write_segment(outfile, &file.cdguids_seg);
9862 WMSFT_write_segment(outfile, &file.aux_seg);
9864 WMSFT_free_file(&file);
9866 CloseHandle(outfile);
9868 return S_OK;
9871 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
9872 LPOLESTR name)
9874 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9875 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
9876 return E_NOTIMPL;
9879 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
9880 REFGUID guid, VARIANT *varVal)
9882 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9883 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
9884 return E_NOTIMPL;
9887 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
9888 ULONG helpStringContext)
9890 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9891 FIXME("%p %u - stub\n", This, helpStringContext);
9892 return E_NOTIMPL;
9895 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
9896 LPOLESTR filename)
9898 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9899 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
9901 if (!filename)
9902 return E_INVALIDARG;
9904 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
9906 return S_OK;
9909 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
9910 ICreateTypeLib2_fnQueryInterface,
9911 ICreateTypeLib2_fnAddRef,
9912 ICreateTypeLib2_fnRelease,
9913 ICreateTypeLib2_fnCreateTypeInfo,
9914 ICreateTypeLib2_fnSetName,
9915 ICreateTypeLib2_fnSetVersion,
9916 ICreateTypeLib2_fnSetGuid,
9917 ICreateTypeLib2_fnSetDocString,
9918 ICreateTypeLib2_fnSetHelpFileName,
9919 ICreateTypeLib2_fnSetHelpContext,
9920 ICreateTypeLib2_fnSetLcid,
9921 ICreateTypeLib2_fnSetLibFlags,
9922 ICreateTypeLib2_fnSaveAllChanges,
9923 ICreateTypeLib2_fnDeleteTypeInfo,
9924 ICreateTypeLib2_fnSetCustData,
9925 ICreateTypeLib2_fnSetHelpStringContext,
9926 ICreateTypeLib2_fnSetHelpStringDll
9929 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
9930 REFIID riid, void **object)
9932 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9934 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
9937 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
9939 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9941 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
9944 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
9946 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9948 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
9951 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
9952 REFGUID guid)
9954 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9956 TRACE("%p %s\n", This, debugstr_guid(guid));
9958 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
9960 return S_OK;
9963 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
9964 UINT typeFlags)
9966 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
9967 WORD old_flags;
9968 HRESULT hres;
9970 TRACE("%p %x\n", This, typeFlags);
9972 if (typeFlags & TYPEFLAG_FDUAL) {
9973 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9974 ITypeLib *stdole;
9975 ITypeInfo *dispatch;
9976 HREFTYPE hreftype;
9977 HRESULT hres;
9979 hres = LoadTypeLib(stdole2tlb, &stdole);
9980 if(FAILED(hres))
9981 return hres;
9983 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
9984 ITypeLib_Release(stdole);
9985 if(FAILED(hres))
9986 return hres;
9988 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
9989 ITypeInfo_Release(dispatch);
9990 if(FAILED(hres))
9991 return hres;
9994 old_flags = This->wTypeFlags;
9995 This->wTypeFlags = typeFlags;
9997 hres = ICreateTypeInfo2_LayOut(iface);
9998 if (FAILED(hres)) {
9999 This->wTypeFlags = old_flags;
10000 return hres;
10003 return S_OK;
10006 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10007 LPOLESTR doc)
10009 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10011 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10013 if (!doc)
10014 return E_INVALIDARG;
10016 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10018 return S_OK;
10021 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10022 DWORD helpContext)
10024 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10026 TRACE("%p %d\n", This, helpContext);
10028 This->dwHelpContext = helpContext;
10030 return S_OK;
10033 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10034 WORD majorVerNum, WORD minorVerNum)
10036 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10038 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10040 This->wMajorVerNum = majorVerNum;
10041 This->wMinorVerNum = minorVerNum;
10043 return S_OK;
10046 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10047 ITypeInfo *typeInfo, HREFTYPE *refType)
10049 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10050 UINT index;
10051 ITypeLib *container;
10052 TLBRefType *ref_type;
10053 TLBImpLib *implib;
10054 TYPEATTR *typeattr;
10055 TLIBATTR *libattr;
10056 HRESULT hres;
10058 TRACE("%p %p %p\n", This, typeInfo, refType);
10060 if (!typeInfo || !refType)
10061 return E_INVALIDARG;
10063 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10064 if (FAILED(hres))
10065 return hres;
10067 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10068 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10070 ITypeLib_Release(container);
10072 *refType = target->hreftype;
10074 return S_OK;
10077 hres = ITypeLib_GetLibAttr(container, &libattr);
10078 if (FAILED(hres)) {
10079 ITypeLib_Release(container);
10080 return hres;
10083 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10084 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10085 implib->lcid == libattr->lcid &&
10086 implib->wVersionMajor == libattr->wMajorVerNum &&
10087 implib->wVersionMinor == libattr->wMinorVerNum)
10088 break;
10091 if(&implib->entry == &This->pTypeLib->implib_list){
10092 implib = heap_alloc_zero(sizeof(TLBImpLib));
10094 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10095 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10096 implib->name = SysAllocString(our_container->path);
10097 }else{
10098 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10099 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10100 if(FAILED(hres)){
10101 implib->name = NULL;
10102 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10106 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid);
10107 implib->lcid = libattr->lcid;
10108 implib->wVersionMajor = libattr->wMajorVerNum;
10109 implib->wVersionMinor = libattr->wMinorVerNum;
10111 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10114 ITypeLib_ReleaseTLibAttr(container, libattr);
10115 ITypeLib_Release(container);
10117 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10118 if (FAILED(hres))
10119 return hres;
10121 index = 0;
10122 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10123 if(ref_type->index == TLB_REF_USE_GUID &&
10124 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10125 ref_type->tkind == typeattr->typekind)
10126 break;
10127 ++index;
10130 if(&ref_type->entry == &This->pTypeLib->ref_list){
10131 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10133 ref_type->tkind = typeattr->typekind;
10134 ref_type->pImpTLInfo = implib;
10135 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10137 ref_type->index = TLB_REF_USE_GUID;
10139 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid);
10141 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10144 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10146 *refType = ref_type->reference | 0x1;
10148 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10149 This->pTypeLib->dispatch_href = *refType;
10151 return S_OK;
10154 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10155 UINT index, FUNCDESC *funcDesc)
10157 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10158 TLBFuncDesc tmp_func_desc, *func_desc;
10159 int buf_size, i;
10160 char *buffer;
10161 HRESULT hres;
10163 TRACE("%p %u %p\n", This, index, funcDesc);
10165 if (!funcDesc || funcDesc->oVft & 3)
10166 return E_INVALIDARG;
10168 switch (This->typekind) {
10169 case TKIND_MODULE:
10170 if (funcDesc->funckind != FUNC_STATIC)
10171 return TYPE_E_BADMODULEKIND;
10172 break;
10173 case TKIND_DISPATCH:
10174 if (funcDesc->funckind != FUNC_DISPATCH)
10175 return TYPE_E_BADMODULEKIND;
10176 break;
10177 default:
10178 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10179 return TYPE_E_BADMODULEKIND;
10182 if (index > This->cFuncs)
10183 return TYPE_E_ELEMENTNOTFOUND;
10185 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10186 !funcDesc->cParams)
10187 return TYPE_E_INCONSISTENTPROPFUNCS;
10189 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10190 TLBFuncDesc_Constructor(&tmp_func_desc);
10192 tmp_func_desc.funcdesc = *funcDesc;
10194 if (tmp_func_desc.funcdesc.oVft != 0)
10195 tmp_func_desc.funcdesc.oVft |= 1;
10197 if (funcDesc->cScodes) {
10198 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10199 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10200 } else
10201 tmp_func_desc.funcdesc.lprgscode = NULL;
10203 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10204 for (i = 0; i < funcDesc->cParams; ++i) {
10205 buf_size += sizeof(ELEMDESC);
10206 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10208 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10209 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10211 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10212 if (FAILED(hres)) {
10213 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10214 heap_free(tmp_func_desc.funcdesc.lprgscode);
10215 return hres;
10218 for (i = 0; i < funcDesc->cParams; ++i) {
10219 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10220 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10221 if (FAILED(hres)) {
10222 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10223 heap_free(tmp_func_desc.funcdesc.lprgscode);
10224 return hres;
10226 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10227 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10228 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10229 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10230 if (FAILED(hres)) {
10231 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10232 heap_free(tmp_func_desc.funcdesc.lprgscode);
10233 return hres;
10238 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10240 if (This->funcdescs) {
10241 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10242 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10244 if (index < This->cFuncs) {
10245 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10246 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10247 func_desc = This->funcdescs + index;
10248 } else
10249 func_desc = This->funcdescs + This->cFuncs;
10251 /* move custdata lists to the new memory location */
10252 for(i = 0; i < This->cFuncs + 1; ++i){
10253 if(index != i){
10254 TLBFuncDesc *fd = &This->funcdescs[i];
10255 if(fd->custdata_list.prev == fd->custdata_list.next)
10256 list_init(&fd->custdata_list);
10257 else{
10258 fd->custdata_list.prev->next = &fd->custdata_list;
10259 fd->custdata_list.next->prev = &fd->custdata_list;
10263 } else
10264 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10266 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10267 list_init(&func_desc->custdata_list);
10269 ++This->cFuncs;
10271 This->needs_layout = TRUE;
10273 return S_OK;
10276 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10277 UINT index, HREFTYPE refType)
10279 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10280 TLBImplType *impl_type;
10281 HRESULT hres;
10283 TRACE("%p %u %d\n", This, index, refType);
10285 switch(This->typekind){
10286 case TKIND_COCLASS: {
10287 if (index == -1) {
10288 FIXME("Unhandled index: -1\n");
10289 return E_NOTIMPL;
10292 if(index != This->cImplTypes)
10293 return TYPE_E_ELEMENTNOTFOUND;
10295 break;
10297 case TKIND_INTERFACE:
10298 case TKIND_DISPATCH:
10299 if (index != 0 || This->cImplTypes)
10300 return TYPE_E_ELEMENTNOTFOUND;
10301 break;
10302 default:
10303 FIXME("Unimplemented typekind: %d\n", This->typekind);
10304 return E_NOTIMPL;
10307 if (This->impltypes){
10308 UINT i;
10310 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10311 sizeof(TLBImplType) * (This->cImplTypes + 1));
10313 if (index < This->cImplTypes) {
10314 memmove(This->impltypes + index + 1, This->impltypes + index,
10315 (This->cImplTypes - index) * sizeof(TLBImplType));
10316 impl_type = This->impltypes + index;
10317 } else
10318 impl_type = This->impltypes + This->cImplTypes;
10320 /* move custdata lists to the new memory location */
10321 for(i = 0; i < This->cImplTypes + 1; ++i){
10322 if(index != i){
10323 TLBImplType *it = &This->impltypes[i];
10324 if(it->custdata_list.prev == it->custdata_list.next)
10325 list_init(&it->custdata_list);
10326 else{
10327 it->custdata_list.prev->next = &it->custdata_list;
10328 it->custdata_list.next->prev = &it->custdata_list;
10332 } else
10333 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10335 memset(impl_type, 0, sizeof(TLBImplType));
10336 TLBImplType_Constructor(impl_type);
10337 impl_type->hRef = refType;
10339 ++This->cImplTypes;
10341 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10342 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10344 hres = ICreateTypeInfo2_LayOut(iface);
10345 if (FAILED(hres))
10346 return hres;
10348 return S_OK;
10351 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10352 UINT index, INT implTypeFlags)
10354 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10355 TLBImplType *impl_type = &This->impltypes[index];
10357 TRACE("%p %u %x\n", This, index, implTypeFlags);
10359 if (This->typekind != TKIND_COCLASS)
10360 return TYPE_E_BADMODULEKIND;
10362 if (index >= This->cImplTypes)
10363 return TYPE_E_ELEMENTNOTFOUND;
10365 impl_type->implflags = implTypeFlags;
10367 return S_OK;
10370 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10371 WORD alignment)
10373 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10375 TRACE("%p %d\n", This, alignment);
10377 This->cbAlignment = alignment;
10379 return S_OK;
10382 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10383 LPOLESTR schema)
10385 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10387 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10389 if (!schema)
10390 return E_INVALIDARG;
10392 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10394 This->lpstrSchema = This->Schema->str;
10396 return S_OK;
10399 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10400 UINT index, VARDESC *varDesc)
10402 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10403 TLBVarDesc *var_desc;
10405 TRACE("%p %u %p\n", This, index, varDesc);
10407 if (This->vardescs){
10408 UINT i;
10410 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10411 sizeof(TLBVarDesc) * (This->cVars + 1));
10413 if (index < This->cVars) {
10414 memmove(This->vardescs + index + 1, This->vardescs + index,
10415 (This->cVars - index) * sizeof(TLBVarDesc));
10416 var_desc = This->vardescs + index;
10417 } else
10418 var_desc = This->vardescs + This->cVars;
10420 /* move custdata lists to the new memory location */
10421 for(i = 0; i < This->cVars + 1; ++i){
10422 if(index != i){
10423 TLBVarDesc *var = &This->vardescs[i];
10424 if(var->custdata_list.prev == var->custdata_list.next)
10425 list_init(&var->custdata_list);
10426 else{
10427 var->custdata_list.prev->next = &var->custdata_list;
10428 var->custdata_list.next->prev = &var->custdata_list;
10432 } else
10433 var_desc = This->vardescs = heap_alloc(sizeof(TLBVarDesc));
10435 memset(var_desc, 0, sizeof(TLBVarDesc));
10436 TLBVarDesc_Constructor(var_desc);
10437 var_desc->vardesc = *varDesc;
10439 ++This->cVars;
10441 This->needs_layout = TRUE;
10443 return S_OK;
10446 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10447 UINT index, LPOLESTR *names, UINT numNames)
10449 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10450 TLBFuncDesc *func_desc = &This->funcdescs[index];
10451 int i;
10453 TRACE("%p %u %p %u\n", This, index, names, numNames);
10455 if (!names)
10456 return E_INVALIDARG;
10458 if (index >= This->cFuncs || numNames == 0)
10459 return TYPE_E_ELEMENTNOTFOUND;
10461 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10462 if(numNames > func_desc->funcdesc.cParams)
10463 return TYPE_E_ELEMENTNOTFOUND;
10464 } else
10465 if(numNames > func_desc->funcdesc.cParams + 1)
10466 return TYPE_E_ELEMENTNOTFOUND;
10468 for(i = 0; i < This->cFuncs; ++i) {
10469 TLBFuncDesc *iter = &This->funcdescs[i];
10470 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10471 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10472 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10473 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10474 continue;
10475 return TYPE_E_AMBIGUOUSNAME;
10479 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10481 for (i = 1; i < numNames; ++i) {
10482 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10483 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10486 return S_OK;
10489 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10490 UINT index, LPOLESTR name)
10492 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10493 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(name));
10494 return E_NOTIMPL;
10497 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10498 TYPEDESC *tdescAlias)
10500 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10501 FIXME("%p %p - stub\n", This, tdescAlias);
10502 return E_NOTIMPL;
10505 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10506 UINT index, LPOLESTR dllName, LPOLESTR procName)
10508 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10509 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10510 return E_NOTIMPL;
10513 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10514 UINT index, LPOLESTR docString)
10516 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10517 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(docString));
10518 return E_NOTIMPL;
10521 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10522 UINT index, LPOLESTR docString)
10524 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10525 TLBVarDesc *var_desc = &This->vardescs[index];
10527 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10529 if(!docString)
10530 return E_INVALIDARG;
10532 if(index >= This->cVars)
10533 return TYPE_E_ELEMENTNOTFOUND;
10535 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10537 return S_OK;
10540 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10541 UINT index, DWORD helpContext)
10543 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10544 TLBFuncDesc *func_desc = &This->funcdescs[index];
10546 TRACE("%p %u %d\n", This, index, helpContext);
10548 if(index >= This->cFuncs)
10549 return TYPE_E_ELEMENTNOTFOUND;
10551 func_desc->helpcontext = helpContext;
10553 return S_OK;
10556 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10557 UINT index, DWORD helpContext)
10559 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10560 TLBVarDesc *var_desc = &This->vardescs[index];
10562 TRACE("%p %u %d\n", This, index, helpContext);
10564 if(index >= This->cVars)
10565 return TYPE_E_ELEMENTNOTFOUND;
10567 var_desc->HelpContext = helpContext;
10569 return S_OK;
10572 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10573 UINT index, BSTR bstrMops)
10575 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10576 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10577 return E_NOTIMPL;
10580 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10581 IDLDESC *idlDesc)
10583 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10585 TRACE("%p %p\n", This, idlDesc);
10587 if (!idlDesc)
10588 return E_INVALIDARG;
10590 This->idldescType.dwReserved = idlDesc->dwReserved;
10591 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10593 return S_OK;
10596 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10598 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10599 ITypeInfo *tinfo;
10600 TLBFuncDesc *func_desc;
10601 UINT user_vft = 0, i, depth = 0;
10602 HRESULT hres = S_OK;
10604 TRACE("%p\n", This);
10606 This->needs_layout = FALSE;
10608 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10609 if (FAILED(hres))
10610 return hres;
10612 if (This->typekind == TKIND_INTERFACE) {
10613 ITypeInfo *inh;
10614 TYPEATTR *attr;
10615 HREFTYPE inh_href;
10617 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10619 if (SUCCEEDED(hres)) {
10620 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10622 if (SUCCEEDED(hres)) {
10623 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10624 if (FAILED(hres)) {
10625 ITypeInfo_Release(inh);
10626 ITypeInfo_Release(tinfo);
10627 return hres;
10629 This->cbSizeVft = attr->cbSizeVft;
10630 ITypeInfo_ReleaseTypeAttr(inh, attr);
10633 ++depth;
10634 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10635 if(SUCCEEDED(hres)){
10636 ITypeInfo *next;
10637 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10638 if(SUCCEEDED(hres)){
10639 ITypeInfo_Release(inh);
10640 inh = next;
10643 }while(SUCCEEDED(hres));
10644 hres = S_OK;
10646 ITypeInfo_Release(inh);
10647 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10648 This->cbSizeVft = 0;
10649 hres = S_OK;
10650 } else {
10651 ITypeInfo_Release(tinfo);
10652 return hres;
10654 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10655 This->cbSizeVft = 0;
10656 hres = S_OK;
10657 } else {
10658 ITypeInfo_Release(tinfo);
10659 return hres;
10661 } else if (This->typekind == TKIND_DISPATCH)
10662 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10663 else
10664 This->cbSizeVft = 0;
10666 func_desc = This->funcdescs;
10667 i = 0;
10668 while (i < This->cFuncs) {
10669 if (!(func_desc->funcdesc.oVft & 0x1))
10670 func_desc->funcdesc.oVft = This->cbSizeVft;
10672 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10673 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10675 This->cbSizeVft += This->pTypeLib->ptr_size;
10677 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10678 TLBFuncDesc *iter;
10679 UINT j = 0;
10680 BOOL reset = FALSE;
10682 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10684 iter = This->funcdescs;
10685 while (j < This->cFuncs) {
10686 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10687 if (!reset) {
10688 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
10689 reset = TRUE;
10690 } else
10691 ++func_desc->funcdesc.memid;
10692 iter = This->funcdescs;
10693 j = 0;
10694 } else {
10695 ++iter;
10696 ++j;
10701 ++func_desc;
10702 ++i;
10705 if (user_vft > This->cbSizeVft)
10706 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10708 ITypeInfo_Release(tinfo);
10709 return hres;
10712 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10713 UINT index)
10715 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10716 FIXME("%p %u - stub\n", This, index);
10717 return E_NOTIMPL;
10720 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
10721 MEMBERID memid, INVOKEKIND invKind)
10723 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10724 FIXME("%p %x %d - stub\n", This, memid, invKind);
10725 return E_NOTIMPL;
10728 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
10729 UINT index)
10731 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10732 FIXME("%p %u - stub\n", This, index);
10733 return E_NOTIMPL;
10736 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
10737 MEMBERID memid)
10739 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10740 FIXME("%p %x - stub\n", This, memid);
10741 return E_NOTIMPL;
10744 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
10745 UINT index)
10747 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10748 FIXME("%p %u - stub\n", This, index);
10749 return E_NOTIMPL;
10752 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
10753 REFGUID guid, VARIANT *varVal)
10755 TLBGuid *tlbguid;
10757 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10759 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10761 if (!guid || !varVal)
10762 return E_INVALIDARG;
10764 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid);
10766 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
10769 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
10770 UINT index, REFGUID guid, VARIANT *varVal)
10772 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10773 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10774 return E_NOTIMPL;
10777 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
10778 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
10780 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10781 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
10782 return E_NOTIMPL;
10785 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
10786 UINT index, REFGUID guid, VARIANT *varVal)
10788 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10789 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10790 return E_NOTIMPL;
10793 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
10794 UINT index, REFGUID guid, VARIANT *varVal)
10796 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10797 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
10798 return E_NOTIMPL;
10801 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
10802 ULONG helpStringContext)
10804 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10806 TRACE("%p %u\n", This, helpStringContext);
10808 This->dwHelpStringContext = helpStringContext;
10810 return S_OK;
10813 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
10814 UINT index, ULONG helpStringContext)
10816 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10817 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10818 return E_NOTIMPL;
10821 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
10822 UINT index, ULONG helpStringContext)
10824 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10825 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
10826 return E_NOTIMPL;
10829 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
10831 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10832 FIXME("%p - stub\n", This);
10833 return E_NOTIMPL;
10836 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
10837 LPOLESTR name)
10839 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10841 TRACE("%p %s\n", This, wine_dbgstr_w(name));
10843 if (!name)
10844 return E_INVALIDARG;
10846 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
10848 return S_OK;
10851 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
10852 ICreateTypeInfo2_fnQueryInterface,
10853 ICreateTypeInfo2_fnAddRef,
10854 ICreateTypeInfo2_fnRelease,
10855 ICreateTypeInfo2_fnSetGuid,
10856 ICreateTypeInfo2_fnSetTypeFlags,
10857 ICreateTypeInfo2_fnSetDocString,
10858 ICreateTypeInfo2_fnSetHelpContext,
10859 ICreateTypeInfo2_fnSetVersion,
10860 ICreateTypeInfo2_fnAddRefTypeInfo,
10861 ICreateTypeInfo2_fnAddFuncDesc,
10862 ICreateTypeInfo2_fnAddImplType,
10863 ICreateTypeInfo2_fnSetImplTypeFlags,
10864 ICreateTypeInfo2_fnSetAlignment,
10865 ICreateTypeInfo2_fnSetSchema,
10866 ICreateTypeInfo2_fnAddVarDesc,
10867 ICreateTypeInfo2_fnSetFuncAndParamNames,
10868 ICreateTypeInfo2_fnSetVarName,
10869 ICreateTypeInfo2_fnSetTypeDescAlias,
10870 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
10871 ICreateTypeInfo2_fnSetFuncDocString,
10872 ICreateTypeInfo2_fnSetVarDocString,
10873 ICreateTypeInfo2_fnSetFuncHelpContext,
10874 ICreateTypeInfo2_fnSetVarHelpContext,
10875 ICreateTypeInfo2_fnSetMops,
10876 ICreateTypeInfo2_fnSetTypeIdldesc,
10877 ICreateTypeInfo2_fnLayOut,
10878 ICreateTypeInfo2_fnDeleteFuncDesc,
10879 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
10880 ICreateTypeInfo2_fnDeleteVarDesc,
10881 ICreateTypeInfo2_fnDeleteVarDescByMemId,
10882 ICreateTypeInfo2_fnDeleteImplType,
10883 ICreateTypeInfo2_fnSetCustData,
10884 ICreateTypeInfo2_fnSetFuncCustData,
10885 ICreateTypeInfo2_fnSetParamCustData,
10886 ICreateTypeInfo2_fnSetVarCustData,
10887 ICreateTypeInfo2_fnSetImplTypeCustData,
10888 ICreateTypeInfo2_fnSetHelpStringContext,
10889 ICreateTypeInfo2_fnSetFuncHelpStringContext,
10890 ICreateTypeInfo2_fnSetVarHelpStringContext,
10891 ICreateTypeInfo2_fnInvalidate,
10892 ICreateTypeInfo2_fnSetName
10895 /******************************************************************************
10896 * ClearCustData (OLEAUT32.171)
10898 * Clear a custom data type's data.
10900 * PARAMS
10901 * lpCust [I] The custom data type instance
10903 * RETURNS
10904 * Nothing.
10906 void WINAPI ClearCustData(CUSTDATA *lpCust)
10908 if (lpCust && lpCust->cCustData)
10910 if (lpCust->prgCustData)
10912 DWORD i;
10914 for (i = 0; i < lpCust->cCustData; i++)
10915 VariantClear(&lpCust->prgCustData[i].varValue);
10917 /* FIXME - Should be using a per-thread IMalloc */
10918 heap_free(lpCust->prgCustData);
10919 lpCust->prgCustData = NULL;
10921 lpCust->cCustData = 0;