d3d10: Return the read value from read_dword().
[wine.git] / dlls / oleaut32 / typelib.c
blob2a453a1f0e0c9d3bb6479adffb90256b57bef5d7
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 <stdlib.h>
51 #include <string.h>
52 #include <stdarg.h>
53 #include <stdio.h>
54 #include <ctype.h>
56 #define COBJMACROS
57 #define NONAMELESSUNION
59 #include "winerror.h"
60 #include "windef.h"
61 #include "winbase.h"
62 #include "winnls.h"
63 #include "winreg.h"
64 #include "winuser.h"
65 #include "winternl.h"
66 #include "lzexpand.h"
68 #include "objbase.h"
69 #include "typelib.h"
70 #include "wine/debug.h"
71 #include "variant.h"
72 #include "wine/asm.h"
73 #include "wine/heap.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
101 static void TLB_FreeVarDesc(VARDESC*);
103 /****************************************************************************
104 * FromLExxx
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
109 #ifdef WORDS_BIGENDIAN
110 static WORD FromLEWord(WORD p_iVal)
112 return (((p_iVal & 0x00FF) << 8) |
113 ((p_iVal & 0xFF00) >> 8));
117 static DWORD FromLEDWord(DWORD p_iVal)
119 return (((p_iVal & 0x000000FF) << 24) |
120 ((p_iVal & 0x0000FF00) << 8) |
121 ((p_iVal & 0x00FF0000) >> 8) |
122 ((p_iVal & 0xFF000000) >> 24));
124 #else
125 #define FromLEWord(X) (X)
126 #define FromLEDWord(X) (X)
127 #endif
129 #define DISPATCH_HREF_OFFSET 0x01000000
130 #define DISPATCH_HREF_MASK 0xff000000
132 /****************************************************************************
133 * FromLExxx
135 * Fix byte order in any structure if necessary
137 #ifdef WORDS_BIGENDIAN
138 static void FromLEWords(void *p_Val, int p_iSize)
140 WORD *Val = p_Val;
142 p_iSize /= sizeof(WORD);
144 while (p_iSize) {
145 *Val = FromLEWord(*Val);
146 Val++;
147 p_iSize--;
152 static void FromLEDWords(void *p_Val, int p_iSize)
154 DWORD *Val = p_Val;
156 p_iSize /= sizeof(DWORD);
158 while (p_iSize) {
159 *Val = FromLEDWord(*Val);
160 Val++;
161 p_iSize--;
164 #else
165 #define FromLEWords(X,Y) /*nothing*/
166 #define FromLEDWords(X,Y) /*nothing*/
167 #endif
170 * Find a typelib key which matches a requested maj.min version.
172 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 lstrcpyW( buffer, L"Typelib\\" );
181 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 lstrcpyW( buffer, L"Typelib\\" );
242 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
243 swprintf( buffer + lstrlenW(buffer), 20, L"\\%x.%x", wMaj, wMin );
244 return buffer;
247 /* get the path of an interface key, in the form "Interface\\<guid>" */
248 /* buffer must be at least 50 characters long */
249 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
251 lstrcpyW( buffer, L"Interface\\" );
252 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
253 return buffer;
256 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
257 /* buffer must be at least 16 characters long */
258 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
260 swprintf( buffer, 16, L"%lx\\", lcid );
261 switch(syskind)
263 case SYS_WIN16: lstrcatW( buffer, L"win16" ); break;
264 case SYS_WIN32: lstrcatW( buffer, L"win32" ); break;
265 case SYS_WIN64: lstrcatW( buffer, L"win64" ); break;
266 default:
267 TRACE("Typelib is for unsupported syskind %i\n", syskind);
268 return NULL;
270 return buffer;
273 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
275 struct tlibredirect_data
277 ULONG size;
278 DWORD res;
279 ULONG name_len;
280 ULONG name_offset;
281 LANGID langid;
282 WORD flags;
283 ULONG help_len;
284 ULONG help_offset;
285 WORD major_version;
286 WORD minor_version;
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, BSTR *path, BOOL redir )
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 (redir)
304 ACTCTX_SECTION_KEYED_DATA data;
306 data.cbSize = sizeof(data);
307 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
309 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
310 WCHAR *nameW;
311 DWORD len;
313 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
314 return TYPE_E_LIBNOTREGISTERED;
316 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
317 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
318 if (!len) return TYPE_E_LIBNOTREGISTERED;
320 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
321 *path = SysAllocString( Path );
322 return S_OK;
326 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
327 get_typelib_key( guid, wMaj, wMin, buffer );
329 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
330 if (res == ERROR_FILE_NOT_FOUND)
332 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
333 return TYPE_E_LIBNOTREGISTERED;
335 else if (res != ERROR_SUCCESS)
337 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
338 return TYPE_E_REGISTRYACCESS;
341 while (hr != S_OK)
343 LONG dwPathLen = sizeof(Path);
345 get_lcid_subkey( myLCID, syskind, buffer );
347 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
349 if (!lcid)
350 break;
351 else if (myLCID == lcid)
353 /* try with sub-langid */
354 myLCID = SUBLANGID(lcid);
356 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
358 /* try with system langid */
359 myLCID = 0;
361 else
363 break;
366 else
368 *path = SysAllocString( Path );
369 hr = S_OK;
372 RegCloseKey( hkey );
373 TRACE_(typelib)("-- 0x%08x\n", hr);
374 return hr;
377 /****************************************************************************
378 * QueryPathOfRegTypeLib [OLEAUT32.164]
380 * Gets the path to a registered type library.
382 * PARAMS
383 * guid [I] referenced guid
384 * wMaj [I] major version
385 * wMin [I] minor version
386 * lcid [I] locale id
387 * path [O] path of typelib
389 * RETURNS
390 * Success: S_OK.
391 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
392 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
393 * opened.
395 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
397 BOOL redir = TRUE;
398 #ifdef _WIN64
399 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
400 if(SUCCEEDED(hres))
401 return hres;
402 redir = FALSE;
403 #endif
404 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
407 /******************************************************************************
408 * CreateTypeLib [OLEAUT32.160] creates a typelib
410 * RETURNS
411 * Success: S_OK
412 * Failure: Status
414 HRESULT WINAPI CreateTypeLib(
415 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
417 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
418 return E_FAIL;
421 /******************************************************************************
422 * LoadTypeLib [OLEAUT32.161]
424 * Loads a type library
426 * PARAMS
427 * szFile [I] Name of file to load from.
428 * pptLib [O] Pointer that receives ITypeLib object on success.
430 * RETURNS
431 * Success: S_OK
432 * Failure: Status
434 * SEE
435 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
437 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
439 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
440 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
443 /******************************************************************************
444 * LoadTypeLibEx [OLEAUT32.183]
446 * Loads and optionally registers a type library
448 * RETURNS
449 * Success: S_OK
450 * Failure: Status
452 HRESULT WINAPI LoadTypeLibEx(
453 LPCOLESTR szFile, /* [in] Name of file to load from */
454 REGKIND regkind, /* [in] Specify kind of registration */
455 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
457 WCHAR szPath[MAX_PATH+1];
458 HRESULT res;
460 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
462 if (!szFile || !pptLib)
463 return E_INVALIDARG;
465 *pptLib = NULL;
467 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
469 if (SUCCEEDED(res))
470 switch(regkind)
472 case REGKIND_DEFAULT:
473 /* don't register typelibs supplied with full path. Experimentation confirms the following */
474 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
475 (szFile[0] && (szFile[1] == ':'))) break;
476 /* else fall-through */
478 case REGKIND_REGISTER:
479 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
481 ITypeLib_Release(*pptLib);
482 *pptLib = 0;
484 break;
485 case REGKIND_NONE:
486 break;
489 TRACE(" returns %08x\n",res);
490 return res;
493 /******************************************************************************
494 * LoadRegTypeLib [OLEAUT32.162]
496 * Loads a registered type library.
498 * PARAMS
499 * rguid [I] GUID of the registered type library.
500 * wVerMajor [I] major version.
501 * wVerMinor [I] minor version.
502 * lcid [I] locale ID.
503 * ppTLib [O] pointer that receives an ITypeLib object on success.
505 * RETURNS
506 * Success: S_OK.
507 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
508 * LoadTypeLib.
510 HRESULT WINAPI LoadRegTypeLib(
511 REFGUID rguid,
512 WORD wVerMajor,
513 WORD wVerMinor,
514 LCID lcid,
515 ITypeLib **ppTLib)
517 BSTR bstr=NULL;
518 HRESULT res;
520 *ppTLib = NULL;
522 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
524 if(SUCCEEDED(res))
526 res= LoadTypeLib(bstr, ppTLib);
527 SysFreeString(bstr);
529 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
531 TLIBATTR *attr;
533 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
534 if (res == S_OK)
536 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
537 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
539 if (mismatch)
541 ITypeLib_Release(*ppTLib);
542 *ppTLib = NULL;
543 res = TYPE_E_LIBNOTREGISTERED;
549 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
551 return res;
554 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
556 WCHAR keyName[60];
557 HKEY key, subKey;
559 get_interface_key( &tattr->guid, keyName );
560 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
561 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
563 const WCHAR *proxy_clsid;
565 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
566 proxy_clsid = L"{00020424-0000-0000-C000-000000000046}";
567 else
568 proxy_clsid = L"{00020420-0000-0000-C000-000000000046}";
570 if (name)
571 RegSetValueExW(key, NULL, 0, REG_SZ,
572 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR));
574 if (!RegCreateKeyExW(key, L"ProxyStubClsid", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
576 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
577 RegCloseKey(subKey);
580 if (!RegCreateKeyExW(key, L"ProxyStubClsid32", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
582 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
583 RegCloseKey(subKey);
586 if (RegCreateKeyExW(key, L"TypeLib", 0, NULL, 0,
587 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
589 WCHAR buffer[40];
591 StringFromGUID2(&libattr->guid, buffer, 40);
592 RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
594 swprintf(buffer, ARRAY_SIZE(buffer), L"%x.%x", libattr->wMajorVerNum, libattr->wMinorVerNum);
595 RegSetValueExW(subKey, L"Version", 0, REG_SZ, (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
596 RegCloseKey(subKey);
599 RegCloseKey(key);
603 /******************************************************************************
604 * RegisterTypeLib [OLEAUT32.163]
605 * Adds information about a type library to the System Registry
606 * NOTES
607 * Docs: ITypeLib FAR * ptlib
608 * Docs: OLECHAR FAR* szFullPath
609 * Docs: OLECHAR FAR* szHelpDir
611 * RETURNS
612 * Success: S_OK
613 * Failure: Status
615 HRESULT WINAPI RegisterTypeLib(ITypeLib *ptlib, const WCHAR *szFullPath, const WCHAR *szHelpDir)
617 HRESULT res;
618 TLIBATTR *attr;
619 WCHAR keyName[60];
620 WCHAR tmp[16];
621 HKEY key, subKey;
622 UINT types, tidx;
623 TYPEKIND kind;
624 DWORD disposition;
626 if (ptlib == NULL || szFullPath == NULL)
627 return E_INVALIDARG;
629 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
630 return E_FAIL;
632 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
634 res = S_OK;
635 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
636 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
638 LPOLESTR doc;
639 LPOLESTR libName;
641 /* Set the human-readable name of the typelib to
642 the typelib's doc, if it exists, else to the typelib's name. */
643 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, &libName, &doc, NULL, NULL)))
644 res = E_FAIL;
645 else if (doc || libName)
647 WCHAR *name = doc ? doc : libName;
649 if (RegSetValueExW(key, NULL, 0, REG_SZ,
650 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
651 res = E_FAIL;
653 SysFreeString(doc);
654 SysFreeString(libName);
657 /* Make up the name of the typelib path subkey */
658 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
660 /* Create the typelib path subkey */
661 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
662 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
664 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
665 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
666 res = E_FAIL;
668 RegCloseKey(subKey);
670 else
671 res = E_FAIL;
673 /* Create the flags subkey */
674 if (res == S_OK && RegCreateKeyExW(key, L"FLAGS", 0, NULL, 0,
675 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
677 WCHAR buf[20];
679 /* FIXME: is %u correct? */
680 swprintf(buf, ARRAY_SIZE(buf), L"%u", attr->wLibFlags);
681 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
682 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
683 res = E_FAIL;
685 RegCloseKey(subKey);
687 else
688 res = E_FAIL;
690 /* create the helpdir subkey */
691 if (res == S_OK && RegCreateKeyExW(key, L"HELPDIR", 0, NULL, 0,
692 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
694 BSTR freeHelpDir = NULL;
695 WCHAR *file_name;
697 /* if we created a new key, and helpDir was null, set the helpdir
698 to the directory which contains the typelib. However,
699 if we just opened an existing key, we leave the helpdir alone */
700 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
701 szHelpDir = freeHelpDir = SysAllocString(szFullPath);
702 file_name = wcsrchr(szHelpDir, '\\');
703 if (file_name && file_name[1]) {
704 /* possible remove a numeric \index (resource-id) */
705 WCHAR *end_ptr = file_name + 1;
706 while ('0' <= *end_ptr && *end_ptr <= '9') end_ptr++;
707 if (!*end_ptr)
709 *file_name = 0;
710 file_name = wcsrchr(szHelpDir, '\\');
713 if (file_name)
714 *file_name = 0;
717 /* if we have an szHelpDir, set it! */
718 if (szHelpDir != NULL) {
719 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
721 res = E_FAIL;
725 SysFreeString(freeHelpDir);
726 RegCloseKey(subKey);
727 } else {
728 res = E_FAIL;
731 RegCloseKey(key);
733 else
734 res = E_FAIL;
736 /* register OLE Automation-compatible interfaces for this typelib */
737 types = ITypeLib_GetTypeInfoCount(ptlib);
738 for (tidx=0; tidx<types; tidx++) {
739 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
740 LPOLESTR name = NULL;
741 ITypeInfo *tinfo = NULL;
743 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
745 switch (kind) {
746 case TKIND_INTERFACE:
747 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
748 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
749 break;
751 case TKIND_DISPATCH:
752 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
753 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
754 break;
756 default:
757 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
758 break;
761 if (tinfo) {
762 TYPEATTR *tattr = NULL;
763 ITypeInfo_GetTypeAttr(tinfo, &tattr);
765 if (tattr) {
766 TRACE_(typelib)("guid=%s, flags=%04x (",
767 debugstr_guid(&tattr->guid),
768 tattr->wTypeFlags);
770 if (TRACE_ON(typelib)) {
771 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
772 XX(FAPPOBJECT);
773 XX(FCANCREATE);
774 XX(FLICENSED);
775 XX(FPREDECLID);
776 XX(FHIDDEN);
777 XX(FCONTROL);
778 XX(FDUAL);
779 XX(FNONEXTENSIBLE);
780 XX(FOLEAUTOMATION);
781 XX(FRESTRICTED);
782 XX(FAGGREGATABLE);
783 XX(FREPLACEABLE);
784 XX(FDISPATCHABLE);
785 XX(FREVERSEBIND);
786 XX(FPROXY);
787 #undef XX
788 MESSAGE("\n");
791 /* Register all dispinterfaces (which includes dual interfaces) and
792 oleautomation interfaces */
793 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
794 kind == TKIND_DISPATCH)
796 BOOL is_wow64;
797 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
799 /* register interface<->typelib coupling */
800 TLB_register_interface(attr, name, tattr, 0);
802 /* register TLBs into the opposite registry view, too */
803 if(opposite == KEY_WOW64_32KEY ||
804 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
805 TLB_register_interface(attr, name, tattr, opposite);
808 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
811 ITypeInfo_Release(tinfo);
814 SysFreeString(name);
818 ITypeLib_ReleaseTLibAttr(ptlib, attr);
820 return res;
823 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
825 WCHAR subKeyName[50];
826 HKEY subKey;
828 /* the path to the type */
829 get_interface_key( guid, subKeyName );
831 /* Delete its bits */
832 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
833 return;
835 RegDeleteKeyW(subKey, L"ProxyStubClsid");
836 RegDeleteKeyW(subKey, L"ProxyStubClsid32");
837 RegDeleteKeyW(subKey, L"TypeLib");
838 RegCloseKey(subKey);
839 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
842 /******************************************************************************
843 * UnRegisterTypeLib [OLEAUT32.186]
844 * Removes information about a type library from the System Registry
845 * NOTES
847 * RETURNS
848 * Success: S_OK
849 * Failure: Status
851 HRESULT WINAPI UnRegisterTypeLib(
852 REFGUID libid, /* [in] Guid of the library */
853 WORD wVerMajor, /* [in] major version */
854 WORD wVerMinor, /* [in] minor version */
855 LCID lcid, /* [in] locale id */
856 SYSKIND syskind)
858 BSTR tlibPath = NULL;
859 DWORD tmpLength;
860 WCHAR keyName[60];
861 WCHAR subKeyName[50];
862 int result = S_OK;
863 DWORD i = 0;
864 BOOL deleteOtherStuff;
865 HKEY key = NULL;
866 TYPEATTR* typeAttr = NULL;
867 TYPEKIND kind;
868 ITypeInfo* typeInfo = NULL;
869 ITypeLib* typeLib = NULL;
870 int numTypes;
872 TRACE("(IID: %s)\n",debugstr_guid(libid));
874 /* Create the path to the key */
875 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
877 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
879 TRACE("Unsupported syskind %i\n", syskind);
880 result = E_INVALIDARG;
881 goto end;
884 /* get the path to the typelib on disk */
885 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
886 result = E_INVALIDARG;
887 goto end;
890 /* Try and open the key to the type library. */
891 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
892 result = E_INVALIDARG;
893 goto end;
896 /* Try and load the type library */
897 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
898 result = TYPE_E_INVALIDSTATE;
899 goto end;
902 /* remove any types registered with this typelib */
903 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
904 for (i=0; i<numTypes; i++) {
905 /* get the kind of type */
906 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
907 goto enddeleteloop;
910 /* skip non-interfaces, and get type info for the type */
911 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
912 goto enddeleteloop;
914 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
915 goto enddeleteloop;
917 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
918 goto enddeleteloop;
921 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
922 kind == TKIND_DISPATCH)
924 BOOL is_wow64;
925 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
927 TLB_unregister_interface(&typeAttr->guid, 0);
929 /* unregister TLBs into the opposite registry view, too */
930 if(opposite == KEY_WOW64_32KEY ||
931 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
932 TLB_unregister_interface(&typeAttr->guid, opposite);
936 enddeleteloop:
937 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
938 typeAttr = NULL;
939 if (typeInfo) ITypeInfo_Release(typeInfo);
940 typeInfo = NULL;
943 /* Now, delete the type library path subkey */
944 get_lcid_subkey( lcid, syskind, subKeyName );
945 RegDeleteKeyW(key, subKeyName);
946 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
947 RegDeleteKeyW(key, subKeyName);
949 /* check if there is anything besides the FLAGS/HELPDIR keys.
950 If there is, we don't delete them */
951 tmpLength = ARRAY_SIZE(subKeyName);
952 deleteOtherStuff = TRUE;
953 i = 0;
954 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
955 tmpLength = ARRAY_SIZE(subKeyName);
957 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
958 if (!wcscmp(subKeyName, L"FLAGS")) continue;
959 if (!wcscmp(subKeyName, L"HELPDIR")) continue;
960 deleteOtherStuff = FALSE;
961 break;
964 /* only delete the other parts of the key if we're absolutely sure */
965 if (deleteOtherStuff) {
966 RegDeleteKeyW(key, L"FLAGS");
967 RegDeleteKeyW(key, L"HELPDIR");
968 RegCloseKey(key);
969 key = NULL;
971 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
972 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
973 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
976 end:
977 SysFreeString(tlibPath);
978 if (typeLib) ITypeLib_Release(typeLib);
979 if (key) RegCloseKey(key);
980 return result;
983 /******************************************************************************
984 * RegisterTypeLibForUser [OLEAUT32.442]
985 * Adds information about a type library to the user registry
986 * NOTES
987 * Docs: ITypeLib FAR * ptlib
988 * Docs: OLECHAR FAR* szFullPath
989 * Docs: OLECHAR FAR* szHelpDir
991 * RETURNS
992 * Success: S_OK
993 * Failure: Status
995 HRESULT WINAPI RegisterTypeLibForUser(
996 ITypeLib * ptlib, /* [in] Pointer to the library*/
997 OLECHAR * szFullPath, /* [in] full Path of the library*/
998 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
999 may be NULL*/
1001 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1002 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1003 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1006 /******************************************************************************
1007 * UnRegisterTypeLibForUser [OLEAUT32.443]
1008 * Removes information about a type library from the user registry
1010 * RETURNS
1011 * Success: S_OK
1012 * Failure: Status
1014 HRESULT WINAPI UnRegisterTypeLibForUser(
1015 REFGUID libid, /* [in] GUID of the library */
1016 WORD wVerMajor, /* [in] major version */
1017 WORD wVerMinor, /* [in] minor version */
1018 LCID lcid, /* [in] locale id */
1019 SYSKIND syskind)
1021 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1022 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1023 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1026 /*======================= ITypeLib implementation =======================*/
1028 typedef struct tagTLBGuid {
1029 GUID guid;
1030 INT hreftype;
1031 UINT offset;
1032 struct list entry;
1033 } TLBGuid;
1035 typedef struct tagTLBCustData
1037 TLBGuid *guid;
1038 VARIANT data;
1039 struct list entry;
1040 } TLBCustData;
1042 /* data structure for import typelibs */
1043 typedef struct tagTLBImpLib
1045 int offset; /* offset in the file (MSFT)
1046 offset in nametable (SLTG)
1047 just used to identify library while reading
1048 data from file */
1049 TLBGuid *guid; /* libid */
1050 BSTR name; /* name */
1052 LCID lcid; /* lcid of imported typelib */
1054 WORD wVersionMajor; /* major version number */
1055 WORD wVersionMinor; /* minor version number */
1057 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1058 NULL if not yet loaded */
1059 struct list entry;
1060 } TLBImpLib;
1062 typedef struct tagTLBString {
1063 BSTR str;
1064 UINT offset;
1065 struct list entry;
1066 } TLBString;
1068 /* internal ITypeLib data */
1069 typedef struct tagITypeLibImpl
1071 ITypeLib2 ITypeLib2_iface;
1072 ITypeComp ITypeComp_iface;
1073 ICreateTypeLib2 ICreateTypeLib2_iface;
1074 LONG ref;
1075 TLBGuid *guid;
1076 LCID lcid;
1077 SYSKIND syskind;
1078 int ptr_size;
1079 WORD ver_major;
1080 WORD ver_minor;
1081 WORD libflags;
1082 LCID set_lcid;
1084 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1085 * exported to the application as a UNICODE string.
1087 struct list string_list;
1088 struct list name_list;
1089 struct list guid_list;
1091 const TLBString *Name;
1092 const TLBString *DocString;
1093 const TLBString *HelpFile;
1094 const TLBString *HelpStringDll;
1095 DWORD dwHelpContext;
1096 int TypeInfoCount; /* nr of typeinfo's in librarry */
1097 struct tagITypeInfoImpl **typeinfos;
1098 struct list custdata_list;
1099 struct list implib_list;
1100 int ctTypeDesc; /* number of items in type desc array */
1101 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1102 library. Only used while reading MSFT
1103 typelibs */
1104 struct list ref_list; /* list of ref types in this typelib */
1105 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1108 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1109 struct list entry;
1110 WCHAR *path;
1111 INT index;
1112 } ITypeLibImpl;
1114 static const ITypeLib2Vtbl tlbvt;
1115 static const ITypeCompVtbl tlbtcvt;
1116 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1118 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1120 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1123 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1125 return impl_from_ITypeLib2((ITypeLib2*)iface);
1128 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1130 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1133 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1135 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1138 /* ITypeLib methods */
1139 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1140 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1142 /*======================= ITypeInfo implementation =======================*/
1144 /* data for referenced types */
1145 typedef struct tagTLBRefType
1147 INT index; /* Type index for internal ref or for external ref
1148 it the format is SLTG. -2 indicates to
1149 use guid */
1151 TYPEKIND tkind;
1152 TLBGuid *guid; /* guid of the referenced type */
1153 /* if index == TLB_REF_USE_GUID */
1155 HREFTYPE reference; /* The href of this ref */
1156 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1157 TLB_REF_INTERNAL for internal refs
1158 TLB_REF_NOT_FOUND for broken refs */
1160 struct list entry;
1161 } TLBRefType;
1163 #define TLB_REF_USE_GUID -2
1165 #define TLB_REF_INTERNAL (void*)-2
1166 #define TLB_REF_NOT_FOUND (void*)-1
1168 /* internal Parameter data */
1169 typedef struct tagTLBParDesc
1171 const TLBString *Name;
1172 struct list custdata_list;
1173 } TLBParDesc;
1175 /* internal Function data */
1176 typedef struct tagTLBFuncDesc
1178 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1179 const TLBString *Name; /* the name of this function */
1180 TLBParDesc *pParamDesc; /* array with param names and custom data */
1181 int helpcontext;
1182 int HelpStringContext;
1183 const TLBString *HelpString;
1184 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1185 struct list custdata_list;
1186 } TLBFuncDesc;
1188 /* internal Variable data */
1189 typedef struct tagTLBVarDesc
1191 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1192 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1193 const TLBString *Name; /* the name of this variable */
1194 int HelpContext;
1195 int HelpStringContext;
1196 const TLBString *HelpString;
1197 struct list custdata_list;
1198 } TLBVarDesc;
1200 /* internal implemented interface data */
1201 typedef struct tagTLBImplType
1203 HREFTYPE hRef; /* hRef of interface */
1204 int implflags; /* IMPLFLAG_*s */
1205 struct list custdata_list;
1206 } TLBImplType;
1208 /* internal TypeInfo data */
1209 typedef struct tagITypeInfoImpl
1211 ITypeInfo2 ITypeInfo2_iface;
1212 ITypeComp ITypeComp_iface;
1213 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1214 LONG ref;
1215 BOOL not_attached_to_typelib;
1216 BOOL needs_layout;
1218 TLBGuid *guid;
1219 TYPEATTR typeattr;
1220 TYPEDESC *tdescAlias;
1222 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1223 int index; /* index in this typelib; */
1224 HREFTYPE hreftype; /* hreftype for app object binding */
1225 /* type libs seem to store the doc strings in ascii
1226 * so why should we do it in unicode?
1228 const TLBString *Name;
1229 const TLBString *DocString;
1230 const TLBString *DllName;
1231 const TLBString *Schema;
1232 DWORD dwHelpContext;
1233 DWORD dwHelpStringContext;
1235 /* functions */
1236 TLBFuncDesc *funcdescs;
1238 /* variables */
1239 TLBVarDesc *vardescs;
1241 /* Implemented Interfaces */
1242 TLBImplType *impltypes;
1244 struct list *pcustdata_list;
1245 struct list custdata_list;
1246 } ITypeInfoImpl;
1248 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1250 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1253 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1255 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1258 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1260 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1263 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1265 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1268 static const ITypeInfo2Vtbl tinfvt;
1269 static const ITypeCompVtbl tcompvt;
1270 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1272 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1273 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1275 typedef struct tagTLBContext
1277 unsigned int oStart; /* start of TLB in file */
1278 unsigned int pos; /* current pos */
1279 unsigned int length; /* total length */
1280 void *mapping; /* memory mapping */
1281 MSFT_SegDir * pTblDir;
1282 ITypeLibImpl* pLibInfo;
1283 } TLBContext;
1286 static inline BSTR TLB_get_bstr(const TLBString *str)
1288 return str != NULL ? str->str : NULL;
1291 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1293 if(!str)
1294 return 1;
1295 return memcmp(left, str->str, len);
1298 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1300 return guid != NULL ? &guid->guid : NULL;
1303 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1305 return guid != NULL ? &guid->guid : &GUID_NULL;
1308 static int get_ptr_size(SYSKIND syskind)
1310 switch(syskind){
1311 case SYS_WIN64:
1312 return 8;
1313 case SYS_WIN32:
1314 case SYS_MAC:
1315 case SYS_WIN16:
1316 return 4;
1318 WARN("Unhandled syskind: 0x%x\n", syskind);
1319 return 4;
1323 debug
1325 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1326 if (pTD->vt & VT_RESERVED)
1327 szVarType += strlen(strcpy(szVarType, "reserved | "));
1328 if (pTD->vt & VT_BYREF)
1329 szVarType += strlen(strcpy(szVarType, "ref to "));
1330 if (pTD->vt & VT_ARRAY)
1331 szVarType += strlen(strcpy(szVarType, "array of "));
1332 if (pTD->vt & VT_VECTOR)
1333 szVarType += strlen(strcpy(szVarType, "vector of "));
1334 switch(pTD->vt & VT_TYPEMASK) {
1335 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1336 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1337 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1338 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1339 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1340 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1341 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1342 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1343 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1344 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1345 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1346 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1347 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1348 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1349 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1350 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1351 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1352 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1353 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1354 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1355 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1356 pTD->u.hreftype); break;
1357 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1358 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1359 case VT_PTR: sprintf(szVarType, "ptr to ");
1360 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1361 break;
1362 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1363 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1364 break;
1365 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1366 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1367 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1368 break;
1370 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1374 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1375 char buf[200];
1376 USHORT flags = edesc->u.paramdesc.wParamFlags;
1377 dump_TypeDesc(&edesc->tdesc,buf);
1378 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1379 MESSAGE("\t\tu.paramdesc.wParamFlags");
1380 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1381 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1382 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1383 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1384 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1385 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1386 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1387 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1388 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1390 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1391 int i;
1392 MESSAGE("memid is %08x\n",funcdesc->memid);
1393 for (i=0;i<funcdesc->cParams;i++) {
1394 MESSAGE("Param %d:\n",i);
1395 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1397 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1398 switch (funcdesc->funckind) {
1399 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1400 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1401 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1402 case FUNC_STATIC: MESSAGE("static");break;
1403 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1404 default: MESSAGE("unknown");break;
1406 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1407 switch (funcdesc->invkind) {
1408 case INVOKE_FUNC: MESSAGE("func");break;
1409 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1410 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1411 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1413 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1414 switch (funcdesc->callconv) {
1415 case CC_CDECL: MESSAGE("cdecl");break;
1416 case CC_PASCAL: MESSAGE("pascal");break;
1417 case CC_STDCALL: MESSAGE("stdcall");break;
1418 case CC_SYSCALL: MESSAGE("syscall");break;
1419 default:break;
1421 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1422 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1423 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1425 MESSAGE("\telemdescFunc (return value type):\n");
1426 dump_ELEMDESC(&funcdesc->elemdescFunc);
1429 static const char * const typekind_desc[] =
1431 "TKIND_ENUM",
1432 "TKIND_RECORD",
1433 "TKIND_MODULE",
1434 "TKIND_INTERFACE",
1435 "TKIND_DISPATCH",
1436 "TKIND_COCLASS",
1437 "TKIND_ALIAS",
1438 "TKIND_UNION",
1439 "TKIND_MAX"
1442 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1444 int i;
1445 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1446 for (i=0;i<pfd->funcdesc.cParams;i++)
1447 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1450 dump_FUNCDESC(&(pfd->funcdesc));
1452 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1453 if(pfd->Entry == NULL)
1454 MESSAGE("\tentry: (null)\n");
1455 else if(pfd->Entry == (void*)-1)
1456 MESSAGE("\tentry: invalid\n");
1457 else if(IS_INTRESOURCE(pfd->Entry))
1458 MESSAGE("\tentry: %p\n", pfd->Entry);
1459 else
1460 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1462 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1464 while (n)
1466 dump_TLBFuncDescOne(pfd);
1467 ++pfd;
1468 --n;
1471 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1473 while (n)
1475 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1476 ++pvd;
1477 --n;
1481 static void dump_TLBImpLib(const TLBImpLib *import)
1483 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1484 debugstr_w(import->name));
1485 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1486 import->wVersionMinor, import->lcid, import->offset);
1489 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1491 TLBRefType *ref;
1493 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1495 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1496 if(ref->index == -1)
1497 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1498 else
1499 TRACE_(typelib)("type no: %d\n", ref->index);
1501 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1503 TRACE_(typelib)("in lib\n");
1504 dump_TLBImpLib(ref->pImpTLInfo);
1509 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1511 if(!impl)
1512 return;
1513 while (n) {
1514 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1515 impl->hRef, impl->implflags);
1516 ++impl;
1517 --n;
1521 static void dump_DispParms(const DISPPARAMS * pdp)
1523 unsigned int index;
1525 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1527 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1529 TRACE("named args:\n");
1530 for (index = 0; index < pdp->cNamedArgs; index++)
1531 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1534 if (pdp->cArgs && pdp->rgvarg)
1536 TRACE("args:\n");
1537 for (index = 0; index < pdp->cArgs; index++)
1538 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1542 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1544 TRACE("%p ref=%u\n", pty, pty->ref);
1545 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1546 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1547 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1548 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1549 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1550 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1551 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1552 if (TRACE_ON(ole))
1553 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1554 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1555 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1558 static void dump_VARDESC(const VARDESC *v)
1560 MESSAGE("memid %d\n",v->memid);
1561 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1562 MESSAGE("oInst %d\n",v->u.oInst);
1563 dump_ELEMDESC(&(v->elemdescVar));
1564 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1565 MESSAGE("varkind %d\n",v->varkind);
1568 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1570 /* VT_LPWSTR is largest type that, may appear in type description */
1571 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1572 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1573 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1574 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1575 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1576 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1577 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1578 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1581 static void TLB_abort(void)
1583 DebugBreak();
1586 /* returns the size required for a deep copy of a typedesc into a
1587 * flat buffer */
1588 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1590 SIZE_T size = 0;
1592 if (alloc_initial_space)
1593 size += sizeof(TYPEDESC);
1595 switch (tdesc->vt)
1597 case VT_PTR:
1598 case VT_SAFEARRAY:
1599 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1600 break;
1601 case VT_CARRAY:
1602 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1603 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1604 break;
1606 return size;
1609 /* deep copy a typedesc into a flat buffer */
1610 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1612 if (!dest)
1614 dest = buffer;
1615 buffer = (char *)buffer + sizeof(TYPEDESC);
1618 *dest = *src;
1620 switch (src->vt)
1622 case VT_PTR:
1623 case VT_SAFEARRAY:
1624 dest->u.lptdesc = buffer;
1625 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1626 break;
1627 case VT_CARRAY:
1628 dest->u.lpadesc = buffer;
1629 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1630 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1631 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1632 break;
1634 return buffer;
1637 /* free custom data allocated by MSFT_CustData */
1638 static inline void TLB_FreeCustData(struct list *custdata_list)
1640 TLBCustData *cd, *cdn;
1641 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1643 list_remove(&cd->entry);
1644 VariantClear(&cd->data);
1645 heap_free(cd);
1649 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1651 DWORD len;
1652 BSTR ret;
1654 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1655 ret = SysAllocStringLen(NULL, len - 1);
1656 if (!ret) return ret;
1657 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1658 return ret;
1661 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1663 int i;
1665 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1667 if (typeinfo->funcdescs[i].funcdesc.memid == memid)
1668 return &typeinfo->funcdescs[i];
1671 return NULL;
1674 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl *typeinfo, MEMBERID memid, INVOKEKIND invkind)
1676 int i;
1678 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1680 if (typeinfo->funcdescs[i].funcdesc.memid == memid && typeinfo->funcdescs[i].funcdesc.invkind == invkind)
1681 return &typeinfo->funcdescs[i];
1684 return NULL;
1687 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1689 int i;
1691 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1693 if (typeinfo->vardescs[i].vardesc.memid == memid)
1694 return &typeinfo->vardescs[i];
1697 return NULL;
1700 static inline TLBVarDesc *TLB_get_vardesc_by_name(ITypeInfoImpl *typeinfo, const OLECHAR *name)
1702 int i;
1704 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1706 if (!lstrcmpiW(TLB_get_bstr(typeinfo->vardescs[i].Name), name))
1707 return &typeinfo->vardescs[i];
1710 return NULL;
1713 static inline TLBCustData *TLB_get_custdata_by_guid(const struct list *custdata_list, REFGUID guid)
1715 TLBCustData *cust_data;
1716 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1717 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1718 return cust_data;
1719 return NULL;
1722 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeLibImpl *typelib, const OLECHAR *name)
1724 int i;
1726 for (i = 0; i < typelib->TypeInfoCount; ++i)
1728 if (!lstrcmpiW(TLB_get_bstr(typelib->typeinfos[i]->Name), name))
1729 return typelib->typeinfos[i];
1732 return NULL;
1735 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1737 list_init(&var_desc->custdata_list);
1740 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1742 TLBVarDesc *ret;
1744 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1745 if(!ret)
1746 return NULL;
1748 while(n){
1749 TLBVarDesc_Constructor(&ret[n-1]);
1750 --n;
1753 return ret;
1756 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1758 TLBParDesc *ret;
1760 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1761 if(!ret)
1762 return NULL;
1764 while(n){
1765 list_init(&ret[n-1].custdata_list);
1766 --n;
1769 return ret;
1772 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1774 list_init(&func_desc->custdata_list);
1777 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1779 TLBFuncDesc *ret;
1781 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1782 if(!ret)
1783 return NULL;
1785 while(n){
1786 TLBFuncDesc_Constructor(&ret[n-1]);
1787 --n;
1790 return ret;
1793 static void TLBImplType_Constructor(TLBImplType *impl)
1795 list_init(&impl->custdata_list);
1798 static TLBImplType *TLBImplType_Alloc(UINT n)
1800 TLBImplType *ret;
1802 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1803 if(!ret)
1804 return NULL;
1806 while(n){
1807 TLBImplType_Constructor(&ret[n-1]);
1808 --n;
1811 return ret;
1814 static TLBGuid *TLB_append_guid(struct list *guid_list,
1815 const GUID *new_guid, HREFTYPE hreftype)
1817 TLBGuid *guid;
1819 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1820 if (IsEqualGUID(&guid->guid, new_guid))
1821 return guid;
1824 guid = heap_alloc(sizeof(TLBGuid));
1825 if (!guid)
1826 return NULL;
1828 memcpy(&guid->guid, new_guid, sizeof(GUID));
1829 guid->hreftype = hreftype;
1831 list_add_tail(guid_list, &guid->entry);
1833 return guid;
1836 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1838 TLBCustData *cust_data;
1840 switch(V_VT(var)){
1841 case VT_I4:
1842 case VT_R4:
1843 case VT_UI4:
1844 case VT_INT:
1845 case VT_UINT:
1846 case VT_HRESULT:
1847 case VT_BSTR:
1848 break;
1849 default:
1850 return DISP_E_BADVARTYPE;
1853 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1855 if (!cust_data) {
1856 cust_data = heap_alloc(sizeof(TLBCustData));
1857 if (!cust_data)
1858 return E_OUTOFMEMORY;
1860 cust_data->guid = tlbguid;
1861 VariantInit(&cust_data->data);
1863 list_add_tail(custdata_list, &cust_data->entry);
1864 }else
1865 VariantClear(&cust_data->data);
1867 return VariantCopy(&cust_data->data, var);
1870 /* Used to update list pointers after list itself was moved. */
1871 static void TLB_relink_custdata(struct list *custdata_list)
1873 if (custdata_list->prev == custdata_list->next)
1874 list_init(custdata_list);
1875 else
1877 custdata_list->prev->next = custdata_list;
1878 custdata_list->next->prev = custdata_list;
1882 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1884 TLBString *str;
1886 if(!new_str)
1887 return NULL;
1889 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1890 if (wcscmp(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 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1910 ULONG *size, WORD *align)
1912 ITypeInfo *other;
1913 TYPEATTR *attr;
1914 HRESULT hr;
1916 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1917 if(FAILED(hr))
1918 return hr;
1920 hr = ITypeInfo_GetTypeAttr(other, &attr);
1921 if(FAILED(hr)){
1922 ITypeInfo_Release(other);
1923 return hr;
1926 if(size)
1927 *size = attr->cbSizeInstance;
1928 if(align)
1929 *align = attr->cbAlignment;
1931 ITypeInfo_ReleaseTypeAttr(other, attr);
1932 ITypeInfo_Release(other);
1934 return S_OK;
1937 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1938 TYPEDESC *tdesc, ULONG *size, WORD *align)
1940 ULONG i, sub, ptr_size;
1941 HRESULT hr;
1943 ptr_size = get_ptr_size(sys);
1945 switch(tdesc->vt){
1946 case VT_VOID:
1947 *size = 0;
1948 break;
1949 case VT_I1:
1950 case VT_UI1:
1951 *size = 1;
1952 break;
1953 case VT_I2:
1954 case VT_BOOL:
1955 case VT_UI2:
1956 *size = 2;
1957 break;
1958 case VT_I4:
1959 case VT_R4:
1960 case VT_ERROR:
1961 case VT_UI4:
1962 case VT_INT:
1963 case VT_UINT:
1964 case VT_HRESULT:
1965 *size = 4;
1966 break;
1967 case VT_R8:
1968 case VT_I8:
1969 case VT_UI8:
1970 *size = 8;
1971 break;
1972 case VT_BSTR:
1973 case VT_DISPATCH:
1974 case VT_UNKNOWN:
1975 case VT_PTR:
1976 case VT_SAFEARRAY:
1977 case VT_LPSTR:
1978 case VT_LPWSTR:
1979 *size = ptr_size;
1980 break;
1981 case VT_DATE:
1982 *size = sizeof(DATE);
1983 break;
1984 case VT_VARIANT:
1985 *size = sizeof(VARIANT);
1986 #ifdef _WIN64
1987 if(sys == SYS_WIN32)
1988 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1989 #endif
1990 break;
1991 case VT_DECIMAL:
1992 *size = sizeof(DECIMAL);
1993 break;
1994 case VT_CY:
1995 *size = sizeof(CY);
1996 break;
1997 case VT_CARRAY:
1998 *size = 0;
1999 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2000 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2001 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2002 if(FAILED(hr))
2003 return hr;
2004 *size *= sub;
2005 return S_OK;
2006 case VT_USERDEFINED:
2007 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2008 default:
2009 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2010 return E_FAIL;
2013 if(align){
2014 if(*size < 4)
2015 *align = *size;
2016 else
2017 *align = 4;
2020 return S_OK;
2023 /**********************************************************************
2025 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2028 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2030 if (where != DO_NOT_SEEK)
2032 where += pcx->oStart;
2033 if (where > pcx->length)
2035 /* FIXME */
2036 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2037 TLB_abort();
2039 pcx->pos = where;
2043 /* read function */
2044 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2046 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2047 pcx->pos, count, pcx->oStart, pcx->length, where);
2049 MSFT_Seek(pcx, where);
2050 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2051 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2052 pcx->pos += count;
2053 return count;
2056 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2057 LONG where )
2059 DWORD ret;
2061 ret = MSFT_Read(buffer, count, pcx, where);
2062 FromLEDWords(buffer, ret);
2064 return ret;
2067 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2068 LONG where )
2070 DWORD ret;
2072 ret = MSFT_Read(buffer, count, pcx, where);
2073 FromLEWords(buffer, ret);
2075 return ret;
2078 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2080 TLBGuid *guid;
2081 MSFT_GuidEntry entry;
2082 int offs = 0;
2084 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2085 while (1) {
2086 if (offs >= pcx->pTblDir->pGuidTab.length)
2087 return S_OK;
2089 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2091 guid = heap_alloc(sizeof(TLBGuid));
2093 guid->offset = offs;
2094 guid->guid = entry.guid;
2095 guid->hreftype = entry.hreftype;
2097 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2099 offs += sizeof(MSFT_GuidEntry);
2103 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2105 TLBGuid *ret;
2107 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2108 if(ret->offset == offset){
2109 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2110 return ret;
2114 return NULL;
2117 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2119 MSFT_NameIntro niName;
2121 if (offset < 0)
2123 ERR_(typelib)("bad offset %d\n", offset);
2124 return -1;
2127 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2128 pcx->pTblDir->pNametab.offset+offset);
2130 return niName.hreftype;
2133 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2135 char *string;
2136 MSFT_NameIntro intro;
2137 INT16 len_piece;
2138 int offs = 0, lengthInChars;
2140 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2141 while (1) {
2142 TLBString *tlbstr;
2144 if (offs >= pcx->pTblDir->pNametab.length)
2145 return S_OK;
2147 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2148 intro.namelen &= 0xFF;
2149 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2150 if(len_piece % 4)
2151 len_piece = (len_piece + 4) & ~0x3;
2152 if(len_piece < 8)
2153 len_piece = 8;
2155 string = heap_alloc(len_piece + 1);
2156 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2157 string[intro.namelen] = '\0';
2159 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2160 string, -1, NULL, 0);
2161 if (!lengthInChars) {
2162 heap_free(string);
2163 return E_UNEXPECTED;
2166 tlbstr = heap_alloc(sizeof(TLBString));
2168 tlbstr->offset = offs;
2169 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2170 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2172 heap_free(string);
2174 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2176 offs += len_piece;
2180 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2182 TLBString *tlbstr;
2184 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2185 if (tlbstr->offset == offset) {
2186 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2187 return tlbstr;
2191 return NULL;
2194 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2196 TLBString *tlbstr;
2198 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2199 if (tlbstr->offset == offset) {
2200 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2201 return tlbstr;
2205 return NULL;
2209 * read a value and fill a VARIANT structure
2211 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2213 int size;
2215 TRACE_(typelib)("\n");
2217 if(offset <0) { /* data are packed in here */
2218 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2219 V_I4(pVar) = offset & 0x3ffffff;
2220 return;
2222 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2223 pcx->pTblDir->pCustData.offset + offset );
2224 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2225 switch (V_VT(pVar)){
2226 case VT_EMPTY: /* FIXME: is this right? */
2227 case VT_NULL: /* FIXME: is this right? */
2228 case VT_I2 : /* this should not happen */
2229 case VT_I4 :
2230 case VT_R4 :
2231 case VT_ERROR :
2232 case VT_BOOL :
2233 case VT_I1 :
2234 case VT_UI1 :
2235 case VT_UI2 :
2236 case VT_UI4 :
2237 case VT_INT :
2238 case VT_UINT :
2239 case VT_VOID : /* FIXME: is this right? */
2240 case VT_HRESULT :
2241 size=4; break;
2242 case VT_R8 :
2243 case VT_CY :
2244 case VT_DATE :
2245 case VT_I8 :
2246 case VT_UI8 :
2247 case VT_DECIMAL : /* FIXME: is this right? */
2248 case VT_FILETIME :
2249 size=8;break;
2250 /* pointer types with known behaviour */
2251 case VT_BSTR :{
2252 char * ptr;
2253 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2254 if(size == -1){
2255 V_BSTR(pVar) = NULL;
2256 }else{
2257 ptr = heap_alloc_zero(size);
2258 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2259 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2260 /* FIXME: do we need a AtoW conversion here? */
2261 V_UNION(pVar, bstrVal[size])='\0';
2262 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2263 heap_free(ptr);
2266 size=-4; break;
2267 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2268 case VT_DISPATCH :
2269 case VT_VARIANT :
2270 case VT_UNKNOWN :
2271 case VT_PTR :
2272 case VT_SAFEARRAY :
2273 case VT_CARRAY :
2274 case VT_USERDEFINED :
2275 case VT_LPSTR :
2276 case VT_LPWSTR :
2277 case VT_BLOB :
2278 case VT_STREAM :
2279 case VT_STORAGE :
2280 case VT_STREAMED_OBJECT :
2281 case VT_STORED_OBJECT :
2282 case VT_BLOB_OBJECT :
2283 case VT_CF :
2284 case VT_CLSID :
2285 default:
2286 size=0;
2287 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2288 V_VT(pVar));
2291 if(size>0) /* (big|small) endian correct? */
2292 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2293 return;
2296 * create a linked list with custom data
2298 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2300 MSFT_CDGuid entry;
2301 TLBCustData* pNew;
2302 int count=0;
2304 TRACE_(typelib)("\n");
2306 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2308 while(offset >=0){
2309 count++;
2310 pNew=heap_alloc_zero(sizeof(TLBCustData));
2311 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2312 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2313 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2314 list_add_head(custdata_list, &pNew->entry);
2315 offset = entry.next;
2317 return count;
2320 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2322 if(type <0)
2323 pTd->vt=type & VT_TYPEMASK;
2324 else
2325 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2327 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2330 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2332 return (invkind == INVOKE_PROPERTYGET ||
2333 invkind == INVOKE_PROPERTYPUT ||
2334 invkind == INVOKE_PROPERTYPUTREF);
2337 static void
2338 MSFT_DoFuncs(TLBContext* pcx,
2339 ITypeInfoImpl* pTI,
2340 int cFuncs,
2341 int cVars,
2342 int offset,
2343 TLBFuncDesc** pptfd)
2346 * member information is stored in a data structure at offset
2347 * indicated by the memoffset field of the typeinfo structure
2348 * There are several distinctive parts.
2349 * The first part starts with a field that holds the total length
2350 * of this (first) part excluding this field. Then follow the records,
2351 * for each member there is one record.
2353 * The first entry is always the length of the record (including this
2354 * length word).
2355 * The rest of the record depends on the type of the member. If there is
2356 * a field indicating the member type (function, variable, interface, etc)
2357 * I have not found it yet. At this time we depend on the information
2358 * in the type info and the usual order how things are stored.
2360 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2361 * for each member;
2363 * Third is an equal sized array with file offsets to the name entry
2364 * of each member.
2366 * The fourth and last (?) part is an array with offsets to the records
2367 * in the first part of this file segment.
2370 int infolen, nameoffset, reclength, i;
2371 int recoffset = offset + sizeof(INT);
2373 char *recbuf = heap_alloc(0xffff);
2374 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2375 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2377 TRACE_(typelib)("\n");
2379 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2381 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2382 ptfd = *pptfd;
2383 for ( i = 0; i < cFuncs ; i++ )
2385 int optional;
2387 /* name, eventually add to a hash table */
2388 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2389 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2391 /* read the function information record */
2392 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2394 reclength &= 0xffff;
2396 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2398 /* size without argument data */
2399 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2400 if (pFuncRec->FKCCIC & 0x1000)
2401 optional -= pFuncRec->nrargs * sizeof(INT);
2403 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2404 ptfd->helpcontext = pFuncRec->HelpContext;
2406 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2407 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2409 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2411 if (pFuncRec->FKCCIC & 0x2000 )
2413 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2414 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2415 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2417 else
2418 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2420 else
2421 ptfd->Entry = (TLBString*)-1;
2423 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2424 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2426 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2427 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2429 /* fill the FuncDesc Structure */
2430 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2431 offset + infolen + ( i + 1) * sizeof(INT));
2433 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2434 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2435 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2436 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2437 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2438 if (ptfd->funcdesc.funckind == FUNC_DISPATCH)
2439 ptfd->funcdesc.oVft = 0;
2440 else
2441 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2442 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2444 /* nameoffset is sometimes -1 on the second half of a propget/propput
2445 * pair of functions */
2446 if ((nameoffset == -1) && (i > 0) &&
2447 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2448 TLB_is_propgetput(ptfd->funcdesc.invkind))
2449 ptfd->Name = ptfd_prev->Name;
2450 else
2451 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2453 MSFT_GetTdesc(pcx,
2454 pFuncRec->DataType,
2455 &ptfd->funcdesc.elemdescFunc.tdesc);
2457 /* do the parameters/arguments */
2458 if(pFuncRec->nrargs)
2460 int j = 0;
2461 MSFT_ParameterInfo paraminfo;
2463 ptfd->funcdesc.lprgelemdescParam =
2464 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2466 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2468 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2469 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2471 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2473 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2475 MSFT_GetTdesc(pcx,
2476 paraminfo.DataType,
2477 &elemdesc->tdesc);
2479 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2481 /* name */
2482 if (paraminfo.oName != -1)
2483 ptfd->pParamDesc[j].Name =
2484 MSFT_ReadName( pcx, paraminfo.oName );
2485 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2487 /* default value */
2488 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2489 (pFuncRec->FKCCIC & 0x1000) )
2491 INT* pInt = (INT *)((char *)pFuncRec +
2492 reclength -
2493 (pFuncRec->nrargs * 4) * sizeof(INT) );
2495 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2497 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2498 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2500 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2501 pInt[j], pcx);
2503 else
2504 elemdesc->u.paramdesc.pparamdescex = NULL;
2506 /* custom info */
2507 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2508 j*sizeof(pFuncRec->oArgCustData[0])) &&
2509 pFuncRec->FKCCIC & 0x80 )
2511 MSFT_CustData(pcx,
2512 pFuncRec->oArgCustData[j],
2513 &ptfd->pParamDesc[j].custdata_list);
2516 /* SEEK value = jump to offset,
2517 * from there jump to the end of record,
2518 * go back by (j-1) arguments
2520 MSFT_ReadLEDWords( &paraminfo ,
2521 sizeof(MSFT_ParameterInfo), pcx,
2522 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2523 * sizeof(MSFT_ParameterInfo)));
2527 /* scode is not used: archaic win16 stuff FIXME: right? */
2528 ptfd->funcdesc.cScodes = 0 ;
2529 ptfd->funcdesc.lprgscode = NULL ;
2531 ptfd_prev = ptfd;
2532 ++ptfd;
2533 recoffset += reclength;
2535 heap_free(recbuf);
2538 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2539 int cVars, int offset, TLBVarDesc ** pptvd)
2541 int infolen, nameoffset, reclength;
2542 char recbuf[256];
2543 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2544 TLBVarDesc *ptvd;
2545 int i;
2546 int recoffset;
2548 TRACE_(typelib)("\n");
2550 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2551 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2552 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2553 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2554 recoffset += offset+sizeof(INT);
2555 for(i=0;i<cVars;i++, ++ptvd){
2556 /* name, eventually add to a hash table */
2557 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2558 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2559 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2560 /* read the variable information record */
2561 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2562 reclength &= 0xff;
2563 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2565 /* optional data */
2566 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2567 ptvd->HelpContext = pVarRec->HelpContext;
2569 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2570 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2572 if (reclength > FIELD_OFFSET(MSFT_VarRecord, oCustData))
2573 MSFT_CustData(pcx, pVarRec->oCustData, &ptvd->custdata_list);
2575 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2576 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2578 /* fill the VarDesc Structure */
2579 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2580 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2581 ptvd->vardesc.varkind = pVarRec->VarKind;
2582 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2583 MSFT_GetTdesc(pcx, pVarRec->DataType,
2584 &ptvd->vardesc.elemdescVar.tdesc);
2585 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2586 if(pVarRec->VarKind == VAR_CONST ){
2587 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2588 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2589 pVarRec->OffsValue, pcx);
2590 } else
2591 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2592 recoffset += reclength;
2596 /* process Implemented Interfaces of a com class */
2597 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2598 int offset)
2600 int i;
2601 MSFT_RefRecord refrec;
2602 TLBImplType *pImpl;
2604 TRACE_(typelib)("\n");
2606 pTI->impltypes = TLBImplType_Alloc(count);
2607 pImpl = pTI->impltypes;
2608 for(i=0;i<count;i++){
2609 if(offset<0) break; /* paranoia */
2610 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2611 pImpl->hRef = refrec.reftype;
2612 pImpl->implflags=refrec.flags;
2613 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2614 offset=refrec.onext;
2615 ++pImpl;
2619 #ifdef _WIN64
2620 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2621 * and some structures, and fix the alignment */
2622 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2624 if(info->typeattr.typekind == TKIND_ALIAS){
2625 switch(info->tdescAlias->vt){
2626 case VT_BSTR:
2627 case VT_DISPATCH:
2628 case VT_UNKNOWN:
2629 case VT_PTR:
2630 case VT_SAFEARRAY:
2631 case VT_LPSTR:
2632 case VT_LPWSTR:
2633 info->typeattr.cbSizeInstance = sizeof(void*);
2634 info->typeattr.cbAlignment = sizeof(void*);
2635 break;
2636 case VT_CARRAY:
2637 case VT_USERDEFINED:
2638 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2639 break;
2640 case VT_VARIANT:
2641 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2642 info->typeattr.cbAlignment = 8;
2643 default:
2644 if(info->typeattr.cbSizeInstance < sizeof(void*))
2645 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2646 else
2647 info->typeattr.cbAlignment = sizeof(void*);
2648 break;
2650 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2651 info->typeattr.typekind == TKIND_DISPATCH ||
2652 info->typeattr.typekind == TKIND_COCLASS){
2653 info->typeattr.cbSizeInstance = sizeof(void*);
2654 info->typeattr.cbAlignment = sizeof(void*);
2657 #endif
2660 * process a typeinfo record
2662 static ITypeInfoImpl * MSFT_DoTypeInfo(
2663 TLBContext *pcx,
2664 int count,
2665 ITypeLibImpl * pLibInfo)
2667 MSFT_TypeInfoBase tiBase;
2668 ITypeInfoImpl *ptiRet;
2670 TRACE_(typelib)("count=%u\n", count);
2672 ptiRet = ITypeInfoImpl_Constructor();
2673 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2674 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2676 /* this is where we are coming from */
2677 ptiRet->pTypeLib = pLibInfo;
2678 ptiRet->index=count;
2680 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2681 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2682 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2683 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2684 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2685 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2686 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2687 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2688 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2689 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2690 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2691 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2692 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2693 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2694 TYPEDESC tmp;
2695 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2696 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2697 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2700 /* FIXME: */
2701 /* IDLDESC idldescType; *//* never saw this one != zero */
2703 /* name, eventually add to a hash table */
2704 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2705 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2706 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2707 /* help info */
2708 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2709 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2710 ptiRet->dwHelpContext=tiBase.helpcontext;
2712 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2713 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2715 /* note: InfoType's Help file and HelpStringDll come from the containing
2716 * library. Further HelpString and Docstring appear to be the same thing :(
2718 /* functions */
2719 if(ptiRet->typeattr.cFuncs >0 )
2720 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2721 ptiRet->typeattr.cVars,
2722 tiBase.memoffset, &ptiRet->funcdescs);
2723 /* variables */
2724 if(ptiRet->typeattr.cVars >0 )
2725 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2726 ptiRet->typeattr.cVars,
2727 tiBase.memoffset, &ptiRet->vardescs);
2728 if(ptiRet->typeattr.cImplTypes >0 ) {
2729 switch(ptiRet->typeattr.typekind)
2731 case TKIND_COCLASS:
2732 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2733 tiBase.datatype1);
2734 break;
2735 case TKIND_DISPATCH:
2736 /* This is not -1 when the interface is a non-base dual interface or
2737 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2738 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2739 not this interface.
2742 if (tiBase.datatype1 != -1)
2744 ptiRet->impltypes = TLBImplType_Alloc(1);
2745 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2747 break;
2748 default:
2749 ptiRet->impltypes = TLBImplType_Alloc(1);
2750 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2751 break;
2754 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2756 TRACE_(typelib)("%s guid: %s kind:%s\n",
2757 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2758 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2759 typekind_desc[ptiRet->typeattr.typekind]);
2760 if (TRACE_ON(typelib))
2761 dump_TypeInfo(ptiRet);
2763 return ptiRet;
2766 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2768 char *string;
2769 INT16 len_str, len_piece;
2770 int offs = 0, lengthInChars;
2772 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2773 while (1) {
2774 TLBString *tlbstr;
2776 if (offs >= pcx->pTblDir->pStringtab.length)
2777 return S_OK;
2779 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2780 len_piece = len_str + sizeof(INT16);
2781 if(len_piece % 4)
2782 len_piece = (len_piece + 4) & ~0x3;
2783 if(len_piece < 8)
2784 len_piece = 8;
2786 string = heap_alloc(len_piece + 1);
2787 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2788 string[len_str] = '\0';
2790 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2791 string, -1, NULL, 0);
2792 if (!lengthInChars) {
2793 heap_free(string);
2794 return E_UNEXPECTED;
2797 tlbstr = heap_alloc(sizeof(TLBString));
2799 tlbstr->offset = offs;
2800 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2801 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2803 heap_free(string);
2805 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2807 offs += len_piece;
2811 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2813 TLBRefType *ref;
2814 int offs = 0;
2816 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2817 while (offs < pcx->pTblDir->pImpInfo.length) {
2818 MSFT_ImpInfo impinfo;
2819 TLBImpLib *pImpLib;
2821 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2823 ref = heap_alloc_zero(sizeof(TLBRefType));
2824 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2826 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2827 if(pImpLib->offset==impinfo.oImpFile)
2828 break;
2830 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2831 ref->reference = offs;
2832 ref->pImpTLInfo = pImpLib;
2833 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2834 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2835 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2836 ref->index = TLB_REF_USE_GUID;
2837 } else
2838 ref->index = impinfo.oGuid;
2839 }else{
2840 ERR("Cannot find a reference\n");
2841 ref->reference = -1;
2842 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2845 offs += sizeof(impinfo);
2848 return S_OK;
2851 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2852 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2853 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2854 * tradeoff here.
2856 static struct list tlb_cache = LIST_INIT(tlb_cache);
2857 static CRITICAL_SECTION cache_section;
2858 static CRITICAL_SECTION_DEBUG cache_section_debug =
2860 0, 0, &cache_section,
2861 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2862 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2864 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2867 typedef struct TLB_PEFile
2869 IUnknown IUnknown_iface;
2870 LONG refs;
2871 HMODULE dll;
2872 HRSRC typelib_resource;
2873 HGLOBAL typelib_global;
2874 LPVOID typelib_base;
2875 } TLB_PEFile;
2877 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2879 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2882 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2884 if (IsEqualIID(riid, &IID_IUnknown))
2886 *ppv = iface;
2887 IUnknown_AddRef(iface);
2888 return S_OK;
2890 *ppv = NULL;
2891 return E_NOINTERFACE;
2894 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2896 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2897 return InterlockedIncrement(&This->refs);
2900 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2902 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2903 ULONG refs = InterlockedDecrement(&This->refs);
2904 if (!refs)
2906 if (This->typelib_global)
2907 FreeResource(This->typelib_global);
2908 if (This->dll)
2909 FreeLibrary(This->dll);
2910 heap_free(This);
2912 return refs;
2915 static const IUnknownVtbl TLB_PEFile_Vtable =
2917 TLB_PEFile_QueryInterface,
2918 TLB_PEFile_AddRef,
2919 TLB_PEFile_Release
2922 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2924 TLB_PEFile *This;
2925 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2927 This = heap_alloc(sizeof(TLB_PEFile));
2928 if (!This)
2929 return E_OUTOFMEMORY;
2931 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2932 This->refs = 1;
2933 This->dll = NULL;
2934 This->typelib_resource = NULL;
2935 This->typelib_global = NULL;
2936 This->typelib_base = NULL;
2938 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2939 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2941 if (This->dll)
2943 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), L"TYPELIB");
2944 if (This->typelib_resource)
2946 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2947 if (This->typelib_global)
2949 This->typelib_base = LockResource(This->typelib_global);
2951 if (This->typelib_base)
2953 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2954 *ppBase = This->typelib_base;
2955 *ppFile = &This->IUnknown_iface;
2956 return S_OK;
2961 TRACE("No TYPELIB resource found\n");
2962 hr = E_FAIL;
2965 TLB_PEFile_Release(&This->IUnknown_iface);
2966 return hr;
2969 typedef struct TLB_NEFile
2971 IUnknown IUnknown_iface;
2972 LONG refs;
2973 LPVOID typelib_base;
2974 } TLB_NEFile;
2976 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2978 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2981 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2983 if (IsEqualIID(riid, &IID_IUnknown))
2985 *ppv = iface;
2986 IUnknown_AddRef(iface);
2987 return S_OK;
2989 *ppv = NULL;
2990 return E_NOINTERFACE;
2993 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2995 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2996 return InterlockedIncrement(&This->refs);
2999 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3001 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3002 ULONG refs = InterlockedDecrement(&This->refs);
3003 if (!refs)
3005 heap_free(This->typelib_base);
3006 heap_free(This);
3008 return refs;
3011 static const IUnknownVtbl TLB_NEFile_Vtable =
3013 TLB_NEFile_QueryInterface,
3014 TLB_NEFile_AddRef,
3015 TLB_NEFile_Release
3018 /***********************************************************************
3019 * read_xx_header [internal]
3021 static int read_xx_header( HFILE lzfd )
3023 IMAGE_DOS_HEADER mzh;
3024 char magic[3];
3026 LZSeek( lzfd, 0, SEEK_SET );
3027 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3028 return 0;
3029 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3030 return 0;
3032 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3033 if ( 2 != LZRead( lzfd, magic, 2 ) )
3034 return 0;
3036 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3038 if ( magic[0] == 'N' && magic[1] == 'E' )
3039 return IMAGE_OS2_SIGNATURE;
3040 if ( magic[0] == 'P' && magic[1] == 'E' )
3041 return IMAGE_NT_SIGNATURE;
3043 magic[2] = '\0';
3044 WARN("Can't handle %s files.\n", magic );
3045 return 0;
3049 /***********************************************************************
3050 * find_ne_resource [internal]
3052 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3053 DWORD *resLen, DWORD *resOff )
3055 IMAGE_OS2_HEADER nehd;
3056 NE_TYPEINFO *typeInfo;
3057 NE_NAMEINFO *nameInfo;
3058 DWORD nehdoffset;
3059 LPBYTE resTab;
3060 DWORD resTabSize;
3061 int count;
3063 /* Read in NE header */
3064 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3065 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3067 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3068 if ( !resTabSize )
3070 TRACE("No resources in NE dll\n" );
3071 return FALSE;
3074 /* Read in resource table */
3075 resTab = heap_alloc( resTabSize );
3076 if ( !resTab ) return FALSE;
3078 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3079 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3081 heap_free( resTab );
3082 return FALSE;
3085 /* Find resource */
3086 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3088 if (!IS_INTRESOURCE(typeid)) /* named type */
3090 BYTE len = strlen( typeid );
3091 while (typeInfo->type_id)
3093 if (!(typeInfo->type_id & 0x8000))
3095 BYTE *p = resTab + typeInfo->type_id;
3096 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3098 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3099 typeInfo->count * sizeof(NE_NAMEINFO));
3102 else /* numeric type id */
3104 WORD id = LOWORD(typeid) | 0x8000;
3105 while (typeInfo->type_id)
3107 if (typeInfo->type_id == id) goto found_type;
3108 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3109 typeInfo->count * sizeof(NE_NAMEINFO));
3112 TRACE("No typeid entry found for %p\n", typeid );
3113 heap_free( resTab );
3114 return FALSE;
3116 found_type:
3117 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3119 if (!IS_INTRESOURCE(resid)) /* named resource */
3121 BYTE len = strlen( resid );
3122 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3124 BYTE *p = resTab + nameInfo->id;
3125 if (nameInfo->id & 0x8000) continue;
3126 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3129 else /* numeric resource id */
3131 WORD id = LOWORD(resid) | 0x8000;
3132 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3133 if (nameInfo->id == id) goto found_name;
3135 TRACE("No resid entry found for %p\n", typeid );
3136 heap_free( resTab );
3137 return FALSE;
3139 found_name:
3140 /* Return resource data */
3141 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3142 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3144 heap_free( resTab );
3145 return TRUE;
3148 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3150 HFILE lzfd = -1;
3151 OFSTRUCT ofs;
3152 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3153 TLB_NEFile *This;
3155 This = heap_alloc(sizeof(TLB_NEFile));
3156 if (!This) return E_OUTOFMEMORY;
3158 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3159 This->refs = 1;
3160 This->typelib_base = NULL;
3162 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3163 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3165 DWORD reslen, offset;
3166 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3168 This->typelib_base = heap_alloc(reslen);
3169 if( !This->typelib_base )
3170 hr = E_OUTOFMEMORY;
3171 else
3173 LZSeek( lzfd, offset, SEEK_SET );
3174 reslen = LZRead( lzfd, This->typelib_base, reslen );
3175 LZClose( lzfd );
3176 *ppBase = This->typelib_base;
3177 *pdwTLBLength = reslen;
3178 *ppFile = &This->IUnknown_iface;
3179 return S_OK;
3184 if( lzfd >= 0) LZClose( lzfd );
3185 TLB_NEFile_Release(&This->IUnknown_iface);
3186 return hr;
3189 typedef struct TLB_Mapping
3191 IUnknown IUnknown_iface;
3192 LONG refs;
3193 HANDLE file;
3194 HANDLE mapping;
3195 LPVOID typelib_base;
3196 } TLB_Mapping;
3198 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3200 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3203 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3205 if (IsEqualIID(riid, &IID_IUnknown))
3207 *ppv = iface;
3208 IUnknown_AddRef(iface);
3209 return S_OK;
3211 *ppv = NULL;
3212 return E_NOINTERFACE;
3215 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3217 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3218 return InterlockedIncrement(&This->refs);
3221 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3223 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3224 ULONG refs = InterlockedDecrement(&This->refs);
3225 if (!refs)
3227 if (This->typelib_base)
3228 UnmapViewOfFile(This->typelib_base);
3229 if (This->mapping)
3230 CloseHandle(This->mapping);
3231 if (This->file != INVALID_HANDLE_VALUE)
3232 CloseHandle(This->file);
3233 heap_free(This);
3235 return refs;
3238 static const IUnknownVtbl TLB_Mapping_Vtable =
3240 TLB_Mapping_QueryInterface,
3241 TLB_Mapping_AddRef,
3242 TLB_Mapping_Release
3245 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3247 TLB_Mapping *This;
3249 This = heap_alloc(sizeof(TLB_Mapping));
3250 if (!This)
3251 return E_OUTOFMEMORY;
3253 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3254 This->refs = 1;
3255 This->file = INVALID_HANDLE_VALUE;
3256 This->mapping = NULL;
3257 This->typelib_base = NULL;
3259 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3260 if (INVALID_HANDLE_VALUE != This->file)
3262 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3263 if (This->mapping)
3265 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3266 if(This->typelib_base)
3268 /* retrieve file size */
3269 *pdwTLBLength = GetFileSize(This->file, NULL);
3270 *ppBase = This->typelib_base;
3271 *ppFile = &This->IUnknown_iface;
3272 return S_OK;
3277 IUnknown_Release(&This->IUnknown_iface);
3278 return TYPE_E_CANTLOADLIBRARY;
3281 /****************************************************************************
3282 * TLB_ReadTypeLib
3284 * find the type of the typelib file and map the typelib resource into
3285 * the memory
3288 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3289 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3291 ITypeLibImpl *entry;
3292 HRESULT ret;
3293 INT index = 1;
3294 LPWSTR index_str, file = (LPWSTR)pszFileName;
3295 LPVOID pBase = NULL;
3296 DWORD dwTLBLength = 0;
3297 IUnknown *pFile = NULL;
3298 HANDLE h;
3300 *ppTypeLib = NULL;
3302 index_str = wcsrchr(pszFileName, '\\');
3303 if(index_str && *++index_str != '\0')
3305 LPWSTR end_ptr;
3306 LONG idx = wcstol(index_str, &end_ptr, 10);
3307 if(*end_ptr == '\0')
3309 int str_len = index_str - pszFileName - 1;
3310 index = idx;
3311 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3312 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3313 file[str_len] = 0;
3317 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3319 if(wcschr(file, '\\'))
3321 lstrcpyW(pszPath, file);
3323 else
3325 int len = GetSystemDirectoryW(pszPath, cchPath);
3326 pszPath[len] = '\\';
3327 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3331 if(file != pszFileName) heap_free(file);
3333 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3334 if(h != INVALID_HANDLE_VALUE){
3335 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3336 CloseHandle(h);
3339 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3341 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3342 EnterCriticalSection(&cache_section);
3343 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3345 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3347 TRACE("cache hit\n");
3348 *ppTypeLib = &entry->ITypeLib2_iface;
3349 ITypeLib2_AddRef(*ppTypeLib);
3350 LeaveCriticalSection(&cache_section);
3351 return S_OK;
3354 LeaveCriticalSection(&cache_section);
3356 /* now actually load and parse the typelib */
3358 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3359 if (ret == TYPE_E_CANTLOADLIBRARY)
3360 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3361 if (ret == TYPE_E_CANTLOADLIBRARY)
3362 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3363 if (SUCCEEDED(ret))
3365 if (dwTLBLength >= 4)
3367 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3368 if (dwSignature == MSFT_SIGNATURE)
3369 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3370 else if (dwSignature == SLTG_SIGNATURE)
3371 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3372 else
3374 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3375 ret = TYPE_E_CANTLOADLIBRARY;
3378 else
3379 ret = TYPE_E_CANTLOADLIBRARY;
3380 IUnknown_Release(pFile);
3383 if(*ppTypeLib) {
3384 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3386 TRACE("adding to cache\n");
3387 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3388 lstrcpyW(impl->path, pszPath);
3389 /* We should really canonicalise the path here. */
3390 impl->index = index;
3392 /* FIXME: check if it has added already in the meantime */
3393 EnterCriticalSection(&cache_section);
3394 list_add_head(&tlb_cache, &impl->entry);
3395 LeaveCriticalSection(&cache_section);
3396 ret = S_OK;
3398 else
3400 if(ret != E_FAIL)
3401 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3403 ret = TYPE_E_CANTLOADLIBRARY;
3407 return ret;
3410 /*================== ITypeLib(2) Methods ===================================*/
3412 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3414 ITypeLibImpl* pTypeLibImpl;
3416 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3417 if (!pTypeLibImpl) return NULL;
3419 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3420 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3421 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3422 pTypeLibImpl->ref = 1;
3424 list_init(&pTypeLibImpl->implib_list);
3425 list_init(&pTypeLibImpl->custdata_list);
3426 list_init(&pTypeLibImpl->name_list);
3427 list_init(&pTypeLibImpl->string_list);
3428 list_init(&pTypeLibImpl->guid_list);
3429 list_init(&pTypeLibImpl->ref_list);
3430 pTypeLibImpl->dispatch_href = -1;
3432 return pTypeLibImpl;
3435 /****************************************************************************
3436 * ITypeLib2_Constructor_MSFT
3438 * loading an MSFT typelib from an in-memory image
3440 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3442 TLBContext cx;
3443 LONG lPSegDir;
3444 MSFT_Header tlbHeader;
3445 MSFT_SegDir tlbSegDir;
3446 ITypeLibImpl * pTypeLibImpl;
3447 int i;
3449 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3451 pTypeLibImpl = TypeLibImpl_Constructor();
3452 if (!pTypeLibImpl) return NULL;
3454 /* get pointer to beginning of typelib data */
3455 cx.pos = 0;
3456 cx.oStart=0;
3457 cx.mapping = pLib;
3458 cx.pLibInfo = pTypeLibImpl;
3459 cx.length = dwTLBLength;
3461 /* read header */
3462 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3463 TRACE_(typelib)("header:\n");
3464 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3465 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3466 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3467 return NULL;
3469 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3471 /* there is a small amount of information here until the next important
3472 * part:
3473 * the segment directory . Try to calculate the amount of data */
3474 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3476 /* now read the segment directory */
3477 TRACE("read segment directory (at %d)\n",lPSegDir);
3478 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3479 cx.pTblDir = &tlbSegDir;
3481 /* just check two entries */
3482 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3484 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3485 heap_free(pTypeLibImpl);
3486 return NULL;
3489 MSFT_ReadAllNames(&cx);
3490 MSFT_ReadAllStrings(&cx);
3491 MSFT_ReadAllGuids(&cx);
3493 /* now fill our internal data */
3494 /* TLIBATTR fields */
3495 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3497 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3498 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3499 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3500 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3501 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3503 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3504 pTypeLibImpl->lcid = tlbHeader.lcid;
3506 /* name, eventually add to a hash table */
3507 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3509 /* help info */
3510 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3511 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3513 if( tlbHeader.varflags & HELPDLLFLAG)
3515 int offset;
3516 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3517 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3520 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3522 /* custom data */
3523 if(tlbHeader.CustomDataOffset >= 0)
3525 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3528 /* fill in type descriptions */
3529 if(tlbSegDir.pTypdescTab.length > 0)
3531 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3532 INT16 td[4];
3533 pTypeLibImpl->ctTypeDesc = cTD;
3534 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3535 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3536 for(i=0; i<cTD; )
3538 /* FIXME: add several sanity checks here */
3539 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3540 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3542 /* FIXME: check safearray */
3543 if(td[3] < 0)
3544 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3545 else
3546 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3548 else if(td[0] == VT_CARRAY)
3550 /* array descr table here */
3551 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3553 else if(td[0] == VT_USERDEFINED)
3555 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3557 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3560 /* second time around to fill the array subscript info */
3561 for(i=0;i<cTD;i++)
3563 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3564 if(tlbSegDir.pArrayDescriptions.offset>0)
3566 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3567 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3569 if(td[1]<0)
3570 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3571 else
3572 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3574 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3576 for(j = 0; j<td[2]; j++)
3578 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3579 sizeof(INT), &cx, DO_NOT_SEEK);
3580 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3581 sizeof(INT), &cx, DO_NOT_SEEK);
3584 else
3586 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3587 ERR("didn't find array description data\n");
3592 /* imported type libs */
3593 if(tlbSegDir.pImpFiles.offset>0)
3595 TLBImpLib *pImpLib;
3596 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3597 UINT16 size;
3599 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3601 char *name;
3603 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3604 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3605 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3607 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3608 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3609 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3610 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3612 size >>= 2;
3613 name = heap_alloc_zero(size+1);
3614 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3615 pImpLib->name = TLB_MultiByteToBSTR(name);
3616 heap_free(name);
3618 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3619 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3621 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3625 MSFT_ReadAllRefs(&cx);
3627 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3629 /* type infos */
3630 if(tlbHeader.nrtypeinfos >= 0 )
3632 ITypeInfoImpl **ppTI;
3634 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3636 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3638 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3640 ++ppTI;
3641 (pTypeLibImpl->TypeInfoCount)++;
3645 #ifdef _WIN64
3646 if(pTypeLibImpl->syskind == SYS_WIN32){
3647 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3648 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3650 #endif
3652 TRACE("(%p)\n", pTypeLibImpl);
3653 return &pTypeLibImpl->ITypeLib2_iface;
3657 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3659 char b[3];
3660 int i;
3661 short s;
3663 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3664 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3665 return FALSE;
3668 guid->Data4[0] = s >> 8;
3669 guid->Data4[1] = s & 0xff;
3671 b[2] = '\0';
3672 for(i = 0; i < 6; i++) {
3673 memcpy(b, str + 24 + 2 * i, 2);
3674 guid->Data4[i + 2] = strtol(b, NULL, 16);
3676 return TRUE;
3679 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3681 WORD bytelen;
3682 DWORD len;
3683 BSTR tmp_str;
3685 *pStr = NULL;
3686 bytelen = *(const WORD*)ptr;
3687 if(bytelen == 0xffff) return 2;
3689 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3690 tmp_str = SysAllocStringLen(NULL, len);
3691 if (tmp_str) {
3692 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3693 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3694 SysFreeString(tmp_str);
3696 return bytelen + 2;
3699 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3701 WORD bytelen;
3703 *str = NULL;
3704 bytelen = *(const WORD*)ptr;
3705 if(bytelen == 0xffff) return 2;
3706 *str = heap_alloc(bytelen + 1);
3707 memcpy(*str, ptr + 2, bytelen);
3708 (*str)[bytelen] = '\0';
3709 return bytelen + 2;
3712 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3714 BSTR tmp_str;
3715 TLBString *tlbstr;
3717 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3718 if (tlbstr->offset == offset)
3719 return tlbstr;
3722 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3723 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3724 SysFreeString(tmp_str);
3726 return tlbstr;
3729 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3731 char *ptr = pLibBlk;
3732 WORD w;
3734 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3735 FIXME("libblk magic = %04x\n", w);
3736 return 0;
3739 ptr += 6;
3740 if((w = *(WORD*)ptr) != 0xffff) {
3741 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3742 ptr += w;
3744 ptr += 2;
3746 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3748 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3750 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3751 ptr += 4;
3753 pTypeLibImpl->syskind = *(WORD*)ptr;
3754 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3755 ptr += 2;
3757 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3758 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3759 else
3760 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3761 ptr += 2;
3763 ptr += 4; /* skip res12 */
3765 pTypeLibImpl->libflags = *(WORD*)ptr;
3766 ptr += 2;
3768 pTypeLibImpl->ver_major = *(WORD*)ptr;
3769 ptr += 2;
3771 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3772 ptr += 2;
3774 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3775 ptr += sizeof(GUID);
3777 return ptr - (char*)pLibBlk;
3780 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3781 typedef struct
3783 unsigned int num;
3784 HREFTYPE refs[1];
3785 } sltg_ref_lookup_t;
3787 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3788 HREFTYPE *typelib_ref)
3790 if(table && typeinfo_ref < table->num)
3792 *typelib_ref = table->refs[typeinfo_ref];
3793 return S_OK;
3796 ERR_(typelib)("Unable to find reference\n");
3797 *typelib_ref = -1;
3798 return E_FAIL;
3801 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3803 BOOL done = FALSE;
3805 while(!done) {
3806 if((*pType & 0xe00) == 0xe00) {
3807 pTD->vt = VT_PTR;
3808 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3809 pTD = pTD->u.lptdesc;
3811 switch(*pType & 0x3f) {
3812 case VT_PTR:
3813 pTD->vt = VT_PTR;
3814 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3815 pTD = pTD->u.lptdesc;
3816 break;
3818 case VT_USERDEFINED:
3819 pTD->vt = VT_USERDEFINED;
3820 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3821 done = TRUE;
3822 break;
3824 case VT_CARRAY:
3826 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3827 array */
3829 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3831 pTD->vt = VT_CARRAY;
3832 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3833 pTD->u.lpadesc->cDims = pSA->cDims;
3834 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3835 pSA->cDims * sizeof(SAFEARRAYBOUND));
3837 pTD = &pTD->u.lpadesc->tdescElem;
3838 break;
3841 case VT_SAFEARRAY:
3843 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3844 useful? */
3846 pType++;
3847 pTD->vt = VT_SAFEARRAY;
3848 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3849 pTD = pTD->u.lptdesc;
3850 break;
3852 default:
3853 pTD->vt = *pType & 0x3f;
3854 done = TRUE;
3855 break;
3857 pType++;
3859 return pType;
3862 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3863 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3865 /* Handle [in/out] first */
3866 if((*pType & 0xc000) == 0xc000)
3867 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3868 else if(*pType & 0x8000)
3869 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3870 else if(*pType & 0x4000)
3871 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3872 else
3873 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3875 if(*pType & 0x2000)
3876 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3878 if(*pType & 0x80)
3879 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3881 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3885 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3886 char *pNameTable)
3888 unsigned int ref;
3889 char *name;
3890 TLBRefType *ref_type;
3891 sltg_ref_lookup_t *table;
3892 HREFTYPE typelib_ref;
3894 if(pRef->magic != SLTG_REF_MAGIC) {
3895 FIXME("Ref magic = %x\n", pRef->magic);
3896 return NULL;
3898 name = ( (char*)pRef->names + pRef->number);
3900 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3901 table->num = pRef->number >> 3;
3903 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3905 /* We don't want the first href to be 0 */
3906 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3908 for(ref = 0; ref < pRef->number >> 3; ref++) {
3909 char *refname;
3910 unsigned int lib_offs, type_num;
3912 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3914 name += SLTG_ReadStringA(name, &refname);
3915 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3916 FIXME_(typelib)("Can't sscanf ref\n");
3917 if(lib_offs != 0xffff) {
3918 TLBImpLib *import;
3920 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3921 if(import->offset == lib_offs)
3922 break;
3924 if(&import->entry == &pTL->implib_list) {
3925 char fname[MAX_PATH+1];
3926 int len;
3927 GUID tmpguid;
3929 import = heap_alloc_zero(sizeof(*import));
3930 import->offset = lib_offs;
3931 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3932 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3933 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3934 &import->wVersionMajor,
3935 &import->wVersionMinor,
3936 &import->lcid, fname) != 4) {
3937 FIXME_(typelib)("can't sscanf ref %s\n",
3938 pNameTable + lib_offs + 40);
3940 len = strlen(fname);
3941 if(fname[len-1] != '#')
3942 FIXME("fname = %s\n", fname);
3943 fname[len-1] = '\0';
3944 import->name = TLB_MultiByteToBSTR(fname);
3945 list_add_tail(&pTL->implib_list, &import->entry);
3947 ref_type->pImpTLInfo = import;
3949 /* Store a reference to IDispatch */
3950 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3951 pTL->dispatch_href = typelib_ref;
3953 } else { /* internal ref */
3954 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3956 ref_type->reference = typelib_ref;
3957 ref_type->index = type_num;
3959 heap_free(refname);
3960 list_add_tail(&pTL->ref_list, &ref_type->entry);
3962 table->refs[ref] = typelib_ref;
3963 typelib_ref += 4;
3965 if((BYTE)*name != SLTG_REF_MAGIC)
3966 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3967 dump_TLBRefType(pTL);
3968 return table;
3971 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3972 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3974 SLTG_ImplInfo *info;
3975 TLBImplType *pImplType;
3976 /* I don't really get this structure, usually it's 0x16 bytes
3977 long, but iuser.tlb contains some that are 0x18 bytes long.
3978 That's ok because we can use the next ptr to jump to the next
3979 one. But how do we know the length of the last one? The WORD
3980 at offs 0x8 might be the clue. For now I'm just assuming that
3981 the last one is the regular 0x16 bytes. */
3983 info = (SLTG_ImplInfo*)pBlk;
3984 while(1){
3985 pTI->typeattr.cImplTypes++;
3986 if(info->next == 0xffff)
3987 break;
3988 info = (SLTG_ImplInfo*)(pBlk + info->next);
3991 info = (SLTG_ImplInfo*)pBlk;
3992 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3993 pImplType = pTI->impltypes;
3994 while(1) {
3995 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3996 pImplType->implflags = info->impltypeflags;
3997 ++pImplType;
3999 if(info->next == 0xffff)
4000 break;
4001 if(OneOnly)
4002 FIXME_(typelib)("Interface inheriting more than one interface\n");
4003 info = (SLTG_ImplInfo*)(pBlk + info->next);
4005 info++; /* see comment at top of function */
4006 return (char*)info;
4009 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4010 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4012 TLBVarDesc *pVarDesc;
4013 const TLBString *prevName = NULL;
4014 SLTG_Variable *pItem;
4015 unsigned short i;
4016 WORD *pType;
4018 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4020 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4021 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4023 pVarDesc->vardesc.memid = pItem->memid;
4025 if (pItem->magic != SLTG_VAR_MAGIC &&
4026 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4027 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4028 return;
4031 if (pItem->name == 0xfffe)
4032 pVarDesc->Name = prevName;
4033 else
4034 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4036 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4037 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4038 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4040 if(pItem->flags & 0x02)
4041 pType = &pItem->type;
4042 else
4043 pType = (WORD*)(pBlk + pItem->type);
4045 if (pItem->flags & ~0xda)
4046 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4048 SLTG_DoElem(pType, pBlk,
4049 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4051 if (TRACE_ON(typelib)) {
4052 char buf[300];
4053 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4054 TRACE_(typelib)("elemdescVar: %s\n", buf);
4057 if (pItem->flags & 0x40) {
4058 TRACE_(typelib)("VAR_DISPATCH\n");
4059 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4061 else if (pItem->flags & 0x10) {
4062 TRACE_(typelib)("VAR_CONST\n");
4063 pVarDesc->vardesc.varkind = VAR_CONST;
4064 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4065 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4066 if (pItem->flags & 0x08)
4067 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4068 else {
4069 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4071 case VT_LPSTR:
4072 case VT_LPWSTR:
4073 case VT_BSTR:
4075 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4076 BSTR str;
4077 TRACE_(typelib)("len = %u\n", len);
4078 if (len == 0xffff) {
4079 str = NULL;
4080 } else {
4081 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4082 str = SysAllocStringLen(NULL, alloc_len);
4083 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4085 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4086 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4087 break;
4089 case VT_I2:
4090 case VT_UI2:
4091 case VT_I4:
4092 case VT_UI4:
4093 case VT_INT:
4094 case VT_UINT:
4095 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4096 *(INT*)(pBlk + pItem->byte_offs);
4097 break;
4098 default:
4099 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4103 else {
4104 TRACE_(typelib)("VAR_PERINSTANCE\n");
4105 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4106 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4109 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4110 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4112 if (pItem->flags & 0x80)
4113 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4115 prevName = pVarDesc->Name;
4117 pTI->typeattr.cVars = cVars;
4120 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4121 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4123 SLTG_Function *pFunc;
4124 unsigned short i;
4125 TLBFuncDesc *pFuncDesc;
4127 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4129 pFuncDesc = pTI->funcdescs;
4130 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4131 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4133 int param;
4134 WORD *pType, *pArg;
4136 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4137 case SLTG_FUNCTION_MAGIC:
4138 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4139 break;
4140 case SLTG_DISPATCH_FUNCTION_MAGIC:
4141 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4142 break;
4143 case SLTG_STATIC_FUNCTION_MAGIC:
4144 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4145 break;
4146 default:
4147 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4148 continue;
4150 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4152 pFuncDesc->funcdesc.memid = pFunc->dispid;
4153 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4154 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4155 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4156 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4157 if (pFuncDesc->funcdesc.funckind == FUNC_DISPATCH)
4158 pFuncDesc->funcdesc.oVft = 0;
4159 else
4160 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4162 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4163 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4165 if(pFunc->retnextopt & 0x80)
4166 pType = &pFunc->rettype;
4167 else
4168 pType = (WORD*)(pBlk + pFunc->rettype);
4170 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4172 pFuncDesc->funcdesc.lprgelemdescParam =
4173 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4174 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4176 pArg = (WORD*)(pBlk + pFunc->arg_off);
4178 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4179 char *paramName = pNameTable + *pArg;
4180 BOOL HaveOffs;
4181 /* If arg type follows then paramName points to the 2nd
4182 letter of the name, else the next WORD is an offset to
4183 the arg type and paramName points to the first letter.
4184 So let's take one char off paramName and see if we're
4185 pointing at an alphanumeric char. However if *pArg is
4186 0xffff or 0xfffe then the param has no name, the former
4187 meaning that the next WORD is the type, the latter
4188 meaning that the next WORD is an offset to the type. */
4190 HaveOffs = FALSE;
4191 if(*pArg == 0xffff)
4192 paramName = NULL;
4193 else if(*pArg == 0xfffe) {
4194 paramName = NULL;
4195 HaveOffs = TRUE;
4197 else if(paramName[-1] && !isalnum(paramName[-1]))
4198 HaveOffs = TRUE;
4200 pArg++;
4202 if(HaveOffs) { /* the next word is an offset to type */
4203 pType = (WORD*)(pBlk + *pArg);
4204 SLTG_DoElem(pType, pBlk,
4205 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4206 pArg++;
4207 } else {
4208 if(paramName)
4209 paramName--;
4210 pArg = SLTG_DoElem(pArg, pBlk,
4211 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4214 /* Are we an optional param ? */
4215 if(pFuncDesc->funcdesc.cParams - param <=
4216 pFuncDesc->funcdesc.cParamsOpt)
4217 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4219 if(paramName) {
4220 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4221 paramName - pNameTable, pTI->pTypeLib);
4222 } else {
4223 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4227 pTI->typeattr.cFuncs = cFuncs;
4230 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4231 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4232 SLTG_TypeInfoTail *pTITail)
4234 char *pFirstItem;
4235 sltg_ref_lookup_t *ref_lookup = NULL;
4237 if(pTIHeader->href_table != 0xffffffff) {
4238 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4239 pNameTable);
4242 pFirstItem = pBlk;
4244 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4245 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4247 heap_free(ref_lookup);
4251 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4252 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4253 const SLTG_TypeInfoTail *pTITail)
4255 char *pFirstItem;
4256 sltg_ref_lookup_t *ref_lookup = NULL;
4258 if(pTIHeader->href_table != 0xffffffff) {
4259 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4260 pNameTable);
4263 pFirstItem = pBlk;
4265 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4266 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4269 if (pTITail->funcs_off != 0xffff)
4270 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4272 heap_free(ref_lookup);
4274 if (TRACE_ON(typelib))
4275 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4278 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4279 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4280 const SLTG_TypeInfoTail *pTITail)
4282 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4285 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4286 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4287 const SLTG_TypeInfoTail *pTITail)
4289 WORD *pType;
4290 sltg_ref_lookup_t *ref_lookup = NULL;
4292 if (pTITail->simple_alias) {
4293 /* if simple alias, no more processing required */
4294 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4295 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4296 return;
4299 if(pTIHeader->href_table != 0xffffffff) {
4300 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4301 pNameTable);
4304 /* otherwise it is an offset to a type */
4305 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4307 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4308 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4310 heap_free(ref_lookup);
4313 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4314 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4315 const SLTG_TypeInfoTail *pTITail)
4317 sltg_ref_lookup_t *ref_lookup = NULL;
4318 if (pTIHeader->href_table != 0xffffffff)
4319 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4320 pNameTable);
4322 if (pTITail->vars_off != 0xffff)
4323 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4325 if (pTITail->funcs_off != 0xffff)
4326 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4328 if (pTITail->impls_off != 0xffff)
4329 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4331 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4332 * of dispinterface functions including the IDispatch ones, so
4333 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4334 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4336 heap_free(ref_lookup);
4337 if (TRACE_ON(typelib))
4338 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4341 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4342 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4343 const SLTG_TypeInfoTail *pTITail)
4345 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4348 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4349 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4350 const SLTG_TypeInfoTail *pTITail)
4352 sltg_ref_lookup_t *ref_lookup = NULL;
4353 if (pTIHeader->href_table != 0xffffffff)
4354 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4355 pNameTable);
4357 if (pTITail->vars_off != 0xffff)
4358 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4360 if (pTITail->funcs_off != 0xffff)
4361 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4362 heap_free(ref_lookup);
4363 if (TRACE_ON(typelib))
4364 dump_TypeInfo(pTI);
4367 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4368 manageable copy of it into this */
4369 typedef struct {
4370 WORD small_no;
4371 char *index_name;
4372 char *other_name;
4373 WORD res1a;
4374 WORD name_offs;
4375 WORD more_bytes;
4376 char *extra;
4377 WORD res20;
4378 DWORD helpcontext;
4379 WORD res26;
4380 GUID uuid;
4381 } SLTG_InternalOtherTypeInfo;
4383 /****************************************************************************
4384 * ITypeLib2_Constructor_SLTG
4386 * loading a SLTG typelib from an in-memory image
4388 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4390 ITypeLibImpl *pTypeLibImpl;
4391 SLTG_Header *pHeader;
4392 SLTG_BlkEntry *pBlkEntry;
4393 SLTG_Magic *pMagic;
4394 SLTG_Index *pIndex;
4395 SLTG_Pad9 *pPad9;
4396 LPVOID pBlk, pFirstBlk;
4397 SLTG_LibBlk *pLibBlk;
4398 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4399 char *pAfterOTIBlks = NULL;
4400 char *pNameTable, *ptr;
4401 int i;
4402 DWORD len, order;
4403 ITypeInfoImpl **ppTypeInfoImpl;
4405 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4408 pTypeLibImpl = TypeLibImpl_Constructor();
4409 if (!pTypeLibImpl) return NULL;
4411 pHeader = pLib;
4413 TRACE_(typelib)("header:\n");
4414 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4415 pHeader->nrOfFileBlks );
4416 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4417 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4418 pHeader->SLTG_magic);
4419 return NULL;
4422 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4423 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4425 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4426 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4428 /* Next we have a magic block */
4429 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4431 /* Let's see if we're still in sync */
4432 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4433 sizeof(SLTG_COMPOBJ_MAGIC))) {
4434 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4435 return NULL;
4437 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4438 sizeof(SLTG_DIR_MAGIC))) {
4439 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4440 return NULL;
4443 pIndex = (SLTG_Index*)(pMagic+1);
4445 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4447 pFirstBlk = pPad9 + 1;
4449 /* We'll set up a ptr to the main library block, which is the last one. */
4451 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4452 pBlkEntry[order].next != 0;
4453 order = pBlkEntry[order].next - 1) {
4454 pBlk = (char*)pBlk + pBlkEntry[order].len;
4456 pLibBlk = pBlk;
4458 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4460 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4461 interspersed */
4463 len += 0x40;
4465 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4467 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4470 ptr = (char*)pLibBlk + len;
4472 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4473 WORD w, extra;
4474 len = 0;
4476 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4478 w = *(WORD*)(ptr + 2);
4479 if(w != 0xffff) {
4480 len += w;
4481 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4482 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4483 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4485 w = *(WORD*)(ptr + 4 + len);
4486 if(w != 0xffff) {
4487 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4488 len += w;
4489 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4490 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4491 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4493 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4494 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4495 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4496 if(extra) {
4497 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4498 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4499 len += extra;
4501 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4502 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4503 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4504 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4505 len += sizeof(SLTG_OtherTypeInfo);
4506 ptr += len;
4509 pAfterOTIBlks = ptr;
4511 /* Skip this WORD and get the next DWORD */
4512 len = *(DWORD*)(pAfterOTIBlks + 2);
4514 /* Now add this to pLibBLk look at what we're pointing at and
4515 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4516 dust and we should be pointing at the beginning of the name
4517 table */
4519 pNameTable = (char*)pLibBlk + len;
4521 switch(*(WORD*)pNameTable) {
4522 case 0xffff:
4523 break;
4524 case 0x0200:
4525 pNameTable += 0x20;
4526 break;
4527 default:
4528 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4529 break;
4532 pNameTable += 0x216;
4534 pNameTable += 2;
4536 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4538 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4541 /* Hopefully we now have enough ptrs set up to actually read in
4542 some TypeInfos. It's not clear which order to do them in, so
4543 I'll just follow the links along the BlkEntry chain and read
4544 them in the order in which they are in the file */
4546 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4547 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4549 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4550 pBlkEntry[order].next != 0;
4551 order = pBlkEntry[order].next - 1, i++) {
4553 SLTG_TypeInfoHeader *pTIHeader;
4554 SLTG_TypeInfoTail *pTITail;
4555 SLTG_MemberHeader *pMemHeader;
4557 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4558 FIXME_(typelib)("Index strings don't match\n");
4559 heap_free(pOtherTypeInfoBlks);
4560 return NULL;
4563 pTIHeader = pBlk;
4564 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4565 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4566 heap_free(pOtherTypeInfoBlks);
4567 return NULL;
4569 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4570 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4571 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4573 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4574 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4575 (*ppTypeInfoImpl)->index = i;
4576 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4577 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4578 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4579 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4580 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4581 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4582 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4583 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4585 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4586 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4588 if((pTIHeader->typeflags1 & 7) != 2)
4589 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4590 if(pTIHeader->typeflags3 != 2)
4591 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4593 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4594 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4595 typekind_desc[pTIHeader->typekind],
4596 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4597 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4599 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4601 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4603 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4604 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4605 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4607 switch(pTIHeader->typekind) {
4608 case TKIND_ENUM:
4609 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4610 pTIHeader, pTITail);
4611 break;
4613 case TKIND_RECORD:
4614 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4615 pTIHeader, pTITail);
4616 break;
4618 case TKIND_INTERFACE:
4619 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4620 pTIHeader, pTITail);
4621 break;
4623 case TKIND_COCLASS:
4624 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4625 pTIHeader, pTITail);
4626 break;
4628 case TKIND_ALIAS:
4629 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4630 pTIHeader, pTITail);
4631 break;
4633 case TKIND_DISPATCH:
4634 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4635 pTIHeader, pTITail);
4636 break;
4638 case TKIND_MODULE:
4639 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4640 pTIHeader, pTITail);
4641 break;
4643 default:
4644 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4645 break;
4649 /* could get cFuncs, cVars and cImplTypes from here
4650 but we've already set those */
4651 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4652 X(06);
4653 X(16);
4654 X(18);
4655 X(1a);
4656 X(1e);
4657 X(24);
4658 X(26);
4659 X(2a);
4660 X(2c);
4661 X(2e);
4662 X(30);
4663 X(32);
4664 X(34);
4665 #undef X
4666 ++ppTypeInfoImpl;
4667 pBlk = (char*)pBlk + pBlkEntry[order].len;
4670 if(i != pTypeLibImpl->TypeInfoCount) {
4671 FIXME("Somehow processed %d TypeInfos\n", i);
4672 heap_free(pOtherTypeInfoBlks);
4673 return NULL;
4676 heap_free(pOtherTypeInfoBlks);
4677 return &pTypeLibImpl->ITypeLib2_iface;
4680 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4682 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4684 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4686 if(IsEqualIID(riid, &IID_IUnknown) ||
4687 IsEqualIID(riid,&IID_ITypeLib)||
4688 IsEqualIID(riid,&IID_ITypeLib2))
4690 *ppv = &This->ITypeLib2_iface;
4692 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4693 IsEqualIID(riid, &IID_ICreateTypeLib2))
4695 *ppv = &This->ICreateTypeLib2_iface;
4697 else
4699 *ppv = NULL;
4700 TRACE("-- Interface: E_NOINTERFACE\n");
4701 return E_NOINTERFACE;
4704 IUnknown_AddRef((IUnknown*)*ppv);
4705 return S_OK;
4708 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4710 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4711 ULONG ref = InterlockedIncrement(&This->ref);
4713 TRACE("(%p) ref=%u\n", This, ref);
4715 return ref;
4718 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4720 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4721 ULONG ref = InterlockedDecrement(&This->ref);
4723 TRACE("(%p) ref=%u\n",This, ref);
4725 if (!ref)
4727 TLBImpLib *pImpLib, *pImpLibNext;
4728 TLBRefType *ref_type, *ref_type_next;
4729 TLBString *tlbstr, *tlbstr_next;
4730 TLBGuid *tlbguid, *tlbguid_next;
4731 int i;
4733 /* remove cache entry */
4734 if(This->path)
4736 TRACE("removing from cache list\n");
4737 EnterCriticalSection(&cache_section);
4738 if(This->entry.next)
4739 list_remove(&This->entry);
4740 LeaveCriticalSection(&cache_section);
4741 heap_free(This->path);
4743 TRACE(" destroying ITypeLib(%p)\n",This);
4745 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4746 list_remove(&tlbstr->entry);
4747 SysFreeString(tlbstr->str);
4748 heap_free(tlbstr);
4751 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4752 list_remove(&tlbstr->entry);
4753 SysFreeString(tlbstr->str);
4754 heap_free(tlbstr);
4757 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4758 list_remove(&tlbguid->entry);
4759 heap_free(tlbguid);
4762 TLB_FreeCustData(&This->custdata_list);
4764 for (i = 0; i < This->ctTypeDesc; i++)
4765 if (This->pTypeDesc[i].vt == VT_CARRAY)
4766 heap_free(This->pTypeDesc[i].u.lpadesc);
4768 heap_free(This->pTypeDesc);
4770 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4772 if (pImpLib->pImpTypeLib)
4773 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4774 SysFreeString(pImpLib->name);
4776 list_remove(&pImpLib->entry);
4777 heap_free(pImpLib);
4780 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4782 list_remove(&ref_type->entry);
4783 heap_free(ref_type);
4786 for (i = 0; i < This->TypeInfoCount; ++i){
4787 heap_free(This->typeinfos[i]->tdescAlias);
4788 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4790 heap_free(This->typeinfos);
4791 heap_free(This);
4792 return 0;
4795 return ref;
4798 /* ITypeLib::GetTypeInfoCount
4800 * Returns the number of type descriptions in the type library
4802 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4804 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4805 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4806 return This->TypeInfoCount;
4809 /* ITypeLib::GetTypeInfo
4811 * retrieves the specified type description in the library.
4813 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4814 ITypeLib2 *iface,
4815 UINT index,
4816 ITypeInfo **ppTInfo)
4818 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4820 TRACE("%p %u %p\n", This, index, ppTInfo);
4822 if(!ppTInfo)
4823 return E_INVALIDARG;
4825 if(index >= This->TypeInfoCount)
4826 return TYPE_E_ELEMENTNOTFOUND;
4828 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4829 ITypeInfo_AddRef(*ppTInfo);
4831 return S_OK;
4835 /* ITypeLibs::GetTypeInfoType
4837 * Retrieves the type of a type description.
4839 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4840 ITypeLib2 *iface,
4841 UINT index,
4842 TYPEKIND *pTKind)
4844 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4846 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4848 if(!pTKind)
4849 return E_INVALIDARG;
4851 if(index >= This->TypeInfoCount)
4852 return TYPE_E_ELEMENTNOTFOUND;
4854 *pTKind = This->typeinfos[index]->typeattr.typekind;
4856 return S_OK;
4859 /* ITypeLib::GetTypeInfoOfGuid
4861 * Retrieves the type description that corresponds to the specified GUID.
4864 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4865 ITypeLib2 *iface,
4866 REFGUID guid,
4867 ITypeInfo **ppTInfo)
4869 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4870 int i;
4872 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4874 for(i = 0; i < This->TypeInfoCount; ++i){
4875 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4876 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4877 ITypeInfo_AddRef(*ppTInfo);
4878 return S_OK;
4882 return TYPE_E_ELEMENTNOTFOUND;
4885 /* ITypeLib::GetLibAttr
4887 * Retrieves the structure that contains the library's attributes.
4890 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4891 ITypeLib2 *iface,
4892 LPTLIBATTR *attr)
4894 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4896 TRACE("(%p, %p)\n", This, attr);
4898 if (!attr) return E_INVALIDARG;
4900 *attr = heap_alloc(sizeof(**attr));
4901 if (!*attr) return E_OUTOFMEMORY;
4903 (*attr)->guid = *TLB_get_guid_null(This->guid);
4904 (*attr)->lcid = This->set_lcid;
4905 (*attr)->syskind = This->syskind;
4906 (*attr)->wMajorVerNum = This->ver_major;
4907 (*attr)->wMinorVerNum = This->ver_minor;
4908 (*attr)->wLibFlags = This->libflags;
4910 return S_OK;
4913 /* ITypeLib::GetTypeComp
4915 * Enables a client compiler to bind to a library's types, variables,
4916 * constants, and global functions.
4919 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4920 ITypeLib2 *iface,
4921 ITypeComp **ppTComp)
4923 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4925 TRACE("(%p)->(%p)\n",This,ppTComp);
4926 *ppTComp = &This->ITypeComp_iface;
4927 ITypeComp_AddRef(*ppTComp);
4929 return S_OK;
4932 /* ITypeLib::GetDocumentation
4934 * Retrieves the library's documentation string, the complete Help file name
4935 * and path, and the context identifier for the library Help topic in the Help
4936 * file.
4938 * On a successful return all non-null BSTR pointers will have been set,
4939 * possibly to NULL.
4941 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4942 ITypeLib2 *iface,
4943 INT index,
4944 BSTR *pBstrName,
4945 BSTR *pBstrDocString,
4946 DWORD *pdwHelpContext,
4947 BSTR *pBstrHelpFile)
4949 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4950 HRESULT result = E_INVALIDARG;
4951 ITypeInfo *pTInfo;
4953 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4954 This, index,
4955 pBstrName, pBstrDocString,
4956 pdwHelpContext, pBstrHelpFile);
4958 if(index<0)
4960 /* documentation for the typelib */
4961 if(pBstrName)
4963 if (This->Name)
4965 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4966 goto memerr1;
4968 else
4969 *pBstrName = NULL;
4971 if(pBstrDocString)
4973 if (This->DocString)
4975 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4976 goto memerr2;
4978 else
4979 *pBstrDocString = NULL;
4981 if(pdwHelpContext)
4983 *pdwHelpContext = This->dwHelpContext;
4985 if(pBstrHelpFile)
4987 if (This->HelpFile)
4989 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4990 goto memerr3;
4992 else
4993 *pBstrHelpFile = NULL;
4996 result = S_OK;
4998 else
5000 /* for a typeinfo */
5001 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5003 if(SUCCEEDED(result))
5005 result = ITypeInfo_GetDocumentation(pTInfo,
5006 MEMBERID_NIL,
5007 pBstrName,
5008 pBstrDocString,
5009 pdwHelpContext, pBstrHelpFile);
5011 ITypeInfo_Release(pTInfo);
5014 return result;
5015 memerr3:
5016 if (pBstrDocString) SysFreeString (*pBstrDocString);
5017 memerr2:
5018 if (pBstrName) SysFreeString (*pBstrName);
5019 memerr1:
5020 return STG_E_INSUFFICIENTMEMORY;
5023 /* ITypeLib::IsName
5025 * Indicates whether a passed-in string contains the name of a type or member
5026 * described in the library.
5029 static HRESULT WINAPI ITypeLib2_fnIsName(
5030 ITypeLib2 *iface,
5031 LPOLESTR szNameBuf,
5032 ULONG lHashVal,
5033 BOOL *pfName)
5035 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5036 int tic;
5037 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5039 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5040 pfName);
5042 *pfName=TRUE;
5043 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5044 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5045 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5046 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5047 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5048 int pc;
5049 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5050 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5051 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5052 goto ITypeLib2_fnIsName_exit;
5055 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5056 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5057 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5061 *pfName=FALSE;
5063 ITypeLib2_fnIsName_exit:
5064 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5065 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5067 return S_OK;
5070 /* ITypeLib::FindName
5072 * Finds occurrences of a type description in a type library. This may be used
5073 * to quickly verify that a name exists in a type library.
5076 static HRESULT WINAPI ITypeLib2_fnFindName(
5077 ITypeLib2 *iface,
5078 LPOLESTR name,
5079 ULONG hash,
5080 ITypeInfo **ppTInfo,
5081 MEMBERID *memid,
5082 UINT16 *found)
5084 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5085 int tic;
5086 UINT count = 0;
5087 UINT len;
5089 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5091 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5092 return E_INVALIDARG;
5094 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5095 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5096 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5097 TLBVarDesc *var;
5098 UINT fdc;
5100 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5101 memid[count] = MEMBERID_NIL;
5102 goto ITypeLib2_fnFindName_exit;
5105 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5106 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5108 if(!TLB_str_memcmp(name, func->Name, len)) {
5109 memid[count] = func->funcdesc.memid;
5110 goto ITypeLib2_fnFindName_exit;
5114 var = TLB_get_vardesc_by_name(pTInfo, name);
5115 if (var) {
5116 memid[count] = var->vardesc.memid;
5117 goto ITypeLib2_fnFindName_exit;
5120 continue;
5121 ITypeLib2_fnFindName_exit:
5122 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5123 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5124 count++;
5126 TRACE("found %d typeinfos\n", count);
5128 *found = count;
5130 return S_OK;
5133 /* ITypeLib::ReleaseTLibAttr
5135 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5138 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5139 ITypeLib2 *iface,
5140 TLIBATTR *pTLibAttr)
5142 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5143 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5144 heap_free(pTLibAttr);
5147 /* ITypeLib2::GetCustData
5149 * gets the custom data
5151 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5152 ITypeLib2 * iface,
5153 REFGUID guid,
5154 VARIANT *pVarVal)
5156 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5157 TLBCustData *pCData;
5159 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5161 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5162 if(!pCData)
5163 return TYPE_E_ELEMENTNOTFOUND;
5165 VariantInit(pVarVal);
5166 VariantCopy(pVarVal, &pCData->data);
5168 return S_OK;
5171 /* ITypeLib2::GetLibStatistics
5173 * Returns statistics about a type library that are required for efficient
5174 * sizing of hash tables.
5177 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5178 ITypeLib2 * iface,
5179 ULONG *pcUniqueNames,
5180 ULONG *pcchUniqueNames)
5182 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5184 FIXME("(%p): stub!\n", This);
5186 if(pcUniqueNames) *pcUniqueNames=1;
5187 if(pcchUniqueNames) *pcchUniqueNames=1;
5188 return S_OK;
5191 /* ITypeLib2::GetDocumentation2
5193 * Retrieves the library's documentation string, the complete Help file name
5194 * and path, the localization context to use, and the context ID for the
5195 * library Help topic in the Help file.
5198 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5199 ITypeLib2 * iface,
5200 INT index,
5201 LCID lcid,
5202 BSTR *pbstrHelpString,
5203 DWORD *pdwHelpStringContext,
5204 BSTR *pbstrHelpStringDll)
5206 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5207 HRESULT result;
5208 ITypeInfo *pTInfo;
5210 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5212 /* the help string should be obtained from the helpstringdll,
5213 * using the _DLLGetDocumentation function, based on the supplied
5214 * lcid. Nice to do sometime...
5216 if(index<0)
5218 /* documentation for the typelib */
5219 if(pbstrHelpString)
5220 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5221 if(pdwHelpStringContext)
5222 *pdwHelpStringContext=This->dwHelpContext;
5223 if(pbstrHelpStringDll)
5224 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5226 result = S_OK;
5228 else
5230 /* for a typeinfo */
5231 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5233 if(SUCCEEDED(result))
5235 ITypeInfo2 * pTInfo2;
5236 result = ITypeInfo_QueryInterface(pTInfo,
5237 &IID_ITypeInfo2,
5238 (LPVOID*) &pTInfo2);
5240 if(SUCCEEDED(result))
5242 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5243 MEMBERID_NIL,
5244 lcid,
5245 pbstrHelpString,
5246 pdwHelpStringContext,
5247 pbstrHelpStringDll);
5249 ITypeInfo2_Release(pTInfo2);
5252 ITypeInfo_Release(pTInfo);
5255 return result;
5258 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5260 TLBCustData *pCData;
5261 unsigned int ct;
5262 CUSTDATAITEM *cdi;
5263 HRESULT hr = S_OK;
5265 ct = list_count(custdata_list);
5267 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5268 if(!pCustData->prgCustData)
5269 return E_OUTOFMEMORY;
5271 pCustData->cCustData = ct;
5273 cdi = pCustData->prgCustData;
5274 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5275 cdi->guid = *TLB_get_guid_null(pCData->guid);
5276 VariantInit(&cdi->varValue);
5277 hr = VariantCopy(&cdi->varValue, &pCData->data);
5278 if(FAILED(hr)) break;
5279 ++cdi;
5282 return hr;
5286 /* ITypeLib2::GetAllCustData
5288 * Gets all custom data items for the library.
5291 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5292 ITypeLib2 * iface,
5293 CUSTDATA *pCustData)
5295 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5296 TRACE("(%p)->(%p)\n", This, pCustData);
5297 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5300 static const ITypeLib2Vtbl tlbvt = {
5301 ITypeLib2_fnQueryInterface,
5302 ITypeLib2_fnAddRef,
5303 ITypeLib2_fnRelease,
5304 ITypeLib2_fnGetTypeInfoCount,
5305 ITypeLib2_fnGetTypeInfo,
5306 ITypeLib2_fnGetTypeInfoType,
5307 ITypeLib2_fnGetTypeInfoOfGuid,
5308 ITypeLib2_fnGetLibAttr,
5309 ITypeLib2_fnGetTypeComp,
5310 ITypeLib2_fnGetDocumentation,
5311 ITypeLib2_fnIsName,
5312 ITypeLib2_fnFindName,
5313 ITypeLib2_fnReleaseTLibAttr,
5315 ITypeLib2_fnGetCustData,
5316 ITypeLib2_fnGetLibStatistics,
5317 ITypeLib2_fnGetDocumentation2,
5318 ITypeLib2_fnGetAllCustData
5322 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5324 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5326 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5329 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5331 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5333 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5336 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5338 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5340 return ITypeLib2_Release(&This->ITypeLib2_iface);
5343 static HRESULT WINAPI ITypeLibComp_fnBind(
5344 ITypeComp * iface,
5345 OLECHAR * szName,
5346 ULONG lHash,
5347 WORD wFlags,
5348 ITypeInfo ** ppTInfo,
5349 DESCKIND * pDescKind,
5350 BINDPTR * pBindPtr)
5352 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5353 BOOL typemismatch = FALSE;
5354 int i;
5356 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5358 *pDescKind = DESCKIND_NONE;
5359 pBindPtr->lptcomp = NULL;
5360 *ppTInfo = NULL;
5362 for(i = 0; i < This->TypeInfoCount; ++i){
5363 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5364 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5366 /* FIXME: check wFlags here? */
5367 /* FIXME: we should use a hash table to look this info up using lHash
5368 * instead of an O(n) search */
5369 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5370 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5372 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5374 *pDescKind = DESCKIND_TYPECOMP;
5375 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5376 ITypeComp_AddRef(pBindPtr->lptcomp);
5377 TRACE("module or enum: %s\n", debugstr_w(szName));
5378 return S_OK;
5382 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5383 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5385 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5386 HRESULT hr;
5388 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5389 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5391 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5392 return S_OK;
5394 else if (hr == TYPE_E_TYPEMISMATCH)
5395 typemismatch = TRUE;
5398 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5399 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5401 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5402 HRESULT hr;
5403 ITypeInfo *subtypeinfo;
5404 BINDPTR subbindptr;
5405 DESCKIND subdesckind;
5407 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5408 &subtypeinfo, &subdesckind, &subbindptr);
5409 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5411 TYPEDESC tdesc_appobject;
5412 const VARDESC vardesc_appobject =
5414 -2, /* memid */
5415 NULL, /* lpstrSchema */
5417 0 /* oInst */
5420 /* ELEMDESC */
5422 /* TYPEDESC */
5424 &tdesc_appobject
5426 VT_PTR
5429 0, /* wVarFlags */
5430 VAR_STATIC /* varkind */
5433 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5434 tdesc_appobject.vt = VT_USERDEFINED;
5436 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5438 /* cleanup things filled in by Bind call so we can put our
5439 * application object data in there instead */
5440 switch (subdesckind)
5442 case DESCKIND_FUNCDESC:
5443 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5444 break;
5445 case DESCKIND_VARDESC:
5446 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5447 break;
5448 default:
5449 break;
5451 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5453 if (pTypeInfo->hreftype == -1)
5454 FIXME("no hreftype for interface %p\n", pTypeInfo);
5456 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5457 if (FAILED(hr))
5458 return hr;
5460 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5461 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5462 ITypeInfo_AddRef(*ppTInfo);
5463 return S_OK;
5465 else if (hr == TYPE_E_TYPEMISMATCH)
5466 typemismatch = TRUE;
5470 if (typemismatch)
5472 TRACE("type mismatch %s\n", debugstr_w(szName));
5473 return TYPE_E_TYPEMISMATCH;
5475 else
5477 TRACE("name not found %s\n", debugstr_w(szName));
5478 return S_OK;
5482 static HRESULT WINAPI ITypeLibComp_fnBindType(
5483 ITypeComp * iface,
5484 OLECHAR * szName,
5485 ULONG lHash,
5486 ITypeInfo ** ppTInfo,
5487 ITypeComp ** ppTComp)
5489 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5490 ITypeInfoImpl *info;
5492 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5494 if(!szName || !ppTInfo || !ppTComp)
5495 return E_INVALIDARG;
5497 info = TLB_get_typeinfo_by_name(This, szName);
5498 if(!info){
5499 *ppTInfo = NULL;
5500 *ppTComp = NULL;
5501 return S_OK;
5504 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5505 ITypeInfo_AddRef(*ppTInfo);
5506 *ppTComp = &info->ITypeComp_iface;
5507 ITypeComp_AddRef(*ppTComp);
5509 return S_OK;
5512 static const ITypeCompVtbl tlbtcvt =
5515 ITypeLibComp_fnQueryInterface,
5516 ITypeLibComp_fnAddRef,
5517 ITypeLibComp_fnRelease,
5519 ITypeLibComp_fnBind,
5520 ITypeLibComp_fnBindType
5523 /*================== ITypeInfo(2) Methods ===================================*/
5524 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5526 ITypeInfoImpl *pTypeInfoImpl;
5528 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5529 if (pTypeInfoImpl)
5531 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5532 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5533 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5534 pTypeInfoImpl->ref = 0;
5535 pTypeInfoImpl->hreftype = -1;
5536 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5537 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5538 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5539 list_init(pTypeInfoImpl->pcustdata_list);
5541 TRACE("(%p)\n", pTypeInfoImpl);
5542 return pTypeInfoImpl;
5545 /* ITypeInfo::QueryInterface
5547 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5548 ITypeInfo2 *iface,
5549 REFIID riid,
5550 VOID **ppvObject)
5552 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5554 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5556 *ppvObject=NULL;
5557 if(IsEqualIID(riid, &IID_IUnknown) ||
5558 IsEqualIID(riid,&IID_ITypeInfo)||
5559 IsEqualIID(riid,&IID_ITypeInfo2))
5560 *ppvObject = &This->ITypeInfo2_iface;
5561 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5562 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5563 *ppvObject = &This->ICreateTypeInfo2_iface;
5564 else if(IsEqualIID(riid, &IID_ITypeComp))
5565 *ppvObject = &This->ITypeComp_iface;
5567 if(*ppvObject){
5568 IUnknown_AddRef((IUnknown*)*ppvObject);
5569 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5570 return S_OK;
5572 TRACE("-- Interface: E_NOINTERFACE\n");
5573 return E_NOINTERFACE;
5576 /* ITypeInfo::AddRef
5578 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5580 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5581 ULONG ref = InterlockedIncrement(&This->ref);
5583 TRACE("(%p)->ref is %u\n",This, ref);
5585 if (ref == 1 /* incremented from 0 */)
5586 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5588 return ref;
5591 static void typeinfo_release_funcdesc(TLBFuncDesc *func)
5593 unsigned int i;
5595 for (i = 0; i < func->funcdesc.cParams; ++i)
5597 ELEMDESC *elemdesc = &func->funcdesc.lprgelemdescParam[i];
5598 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5599 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5600 TLB_FreeCustData(&func->pParamDesc[i].custdata_list);
5602 heap_free(func->funcdesc.lprgelemdescParam);
5603 heap_free(func->pParamDesc);
5604 TLB_FreeCustData(&func->custdata_list);
5607 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5609 UINT i;
5611 TRACE("destroying ITypeInfo(%p)\n",This);
5613 for (i = 0; i < This->typeattr.cFuncs; ++i)
5615 typeinfo_release_funcdesc(&This->funcdescs[i]);
5617 heap_free(This->funcdescs);
5619 for(i = 0; i < This->typeattr.cVars; ++i)
5621 TLBVarDesc *pVInfo = &This->vardescs[i];
5622 if (pVInfo->vardesc_create) {
5623 TLB_FreeVarDesc(pVInfo->vardesc_create);
5624 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5625 VariantClear(pVInfo->vardesc.u.lpvarValue);
5626 heap_free(pVInfo->vardesc.u.lpvarValue);
5628 TLB_FreeCustData(&pVInfo->custdata_list);
5630 heap_free(This->vardescs);
5632 if(This->impltypes){
5633 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5634 TLBImplType *pImpl = &This->impltypes[i];
5635 TLB_FreeCustData(&pImpl->custdata_list);
5637 heap_free(This->impltypes);
5640 TLB_FreeCustData(&This->custdata_list);
5642 heap_free(This);
5645 /* ITypeInfo::Release
5647 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5649 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5650 ULONG ref = InterlockedDecrement(&This->ref);
5652 TRACE("(%p)->(%u)\n",This, ref);
5654 if (!ref)
5656 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5657 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5658 if (not_attached_to_typelib)
5659 heap_free(This);
5660 /* otherwise This will be freed when typelib is freed */
5663 return ref;
5666 /* ITypeInfo::GetTypeAttr
5668 * Retrieves a TYPEATTR structure that contains the attributes of the type
5669 * description.
5672 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5673 LPTYPEATTR *ppTypeAttr)
5675 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5676 SIZE_T size;
5678 TRACE("(%p)\n",This);
5680 size = sizeof(**ppTypeAttr);
5681 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5682 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5684 *ppTypeAttr = heap_alloc(size);
5685 if (!*ppTypeAttr)
5686 return E_OUTOFMEMORY;
5688 **ppTypeAttr = This->typeattr;
5689 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5691 if (This->tdescAlias)
5692 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5694 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5695 /* This should include all the inherited funcs */
5696 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5697 /* This is always the size of IDispatch's vtbl */
5698 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5699 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5701 return S_OK;
5704 /* ITypeInfo::GetTypeComp
5706 * Retrieves the ITypeComp interface for the type description, which enables a
5707 * client compiler to bind to the type description's members.
5710 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5711 ITypeComp * *ppTComp)
5713 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5715 TRACE("(%p)->(%p)\n", This, ppTComp);
5717 *ppTComp = &This->ITypeComp_iface;
5718 ITypeComp_AddRef(*ppTComp);
5719 return S_OK;
5722 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5724 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5725 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5726 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5727 return size;
5730 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5732 *dest = *src;
5733 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5734 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5736 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5737 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5738 *buffer += sizeof(PARAMDESCEX);
5739 *pparamdescex_dest = *pparamdescex_src;
5740 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5741 VariantInit(&pparamdescex_dest->varDefaultValue);
5742 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5743 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5745 else
5746 dest->u.paramdesc.pparamdescex = NULL;
5747 return S_OK;
5750 static HRESULT TLB_SanitizeBSTR(BSTR str)
5752 UINT len = SysStringLen(str), i;
5753 for (i = 0; i < len; ++i)
5754 if (str[i] > 0x7f)
5755 str[i] = '?';
5756 return S_OK;
5759 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5761 if (V_VT(var) == VT_INT)
5762 return VariantChangeType(var, var, 0, VT_I4);
5763 else if (V_VT(var) == VT_UINT)
5764 return VariantChangeType(var, var, 0, VT_UI4);
5765 else if (V_VT(var) == VT_BSTR)
5766 return TLB_SanitizeBSTR(V_BSTR(var));
5768 return S_OK;
5771 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5773 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5774 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5777 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5779 FUNCDESC *dest;
5780 char *buffer;
5781 SIZE_T size = sizeof(*src);
5782 SHORT i;
5783 HRESULT hr;
5785 size += sizeof(*src->lprgscode) * src->cScodes;
5786 size += TLB_SizeElemDesc(&src->elemdescFunc);
5787 for (i = 0; i < src->cParams; i++)
5789 size += sizeof(ELEMDESC);
5790 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5793 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5794 if (!dest) return E_OUTOFMEMORY;
5796 *dest = *src;
5797 if (dispinterface) /* overwrite funckind */
5798 dest->funckind = FUNC_DISPATCH;
5799 buffer = (char *)(dest + 1);
5801 dest->oVft = dest->oVft & 0xFFFC;
5803 if (dest->cScodes) {
5804 dest->lprgscode = (SCODE *)buffer;
5805 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5806 buffer += sizeof(*src->lprgscode) * src->cScodes;
5807 } else
5808 dest->lprgscode = NULL;
5810 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5811 if (FAILED(hr))
5813 SysFreeString((BSTR)dest);
5814 return hr;
5817 if (dest->cParams) {
5818 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5819 buffer += sizeof(ELEMDESC) * src->cParams;
5820 for (i = 0; i < src->cParams; i++)
5822 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5823 if (FAILED(hr))
5824 break;
5826 if (FAILED(hr))
5828 /* undo the above actions */
5829 for (i = i - 1; i >= 0; i--)
5830 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5831 TLB_FreeElemDesc(&dest->elemdescFunc);
5832 SysFreeString((BSTR)dest);
5833 return hr;
5835 } else
5836 dest->lprgelemdescParam = NULL;
5838 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5839 * This accounts for several arguments that are separate in the signature of
5840 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5841 if (dispinterface && (src->funckind != FUNC_DISPATCH))
5843 /* functions that have a [retval] parameter return this value into pVarResult.
5844 * [retval] is always the last parameter (if present) */
5845 if (dest->cParams &&
5846 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5848 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5849 if (elemdesc->tdesc.vt != VT_PTR)
5851 ERR("elemdesc should have started with VT_PTR instead of:\n");
5852 if (ERR_ON(ole))
5853 dump_ELEMDESC(elemdesc);
5854 return E_UNEXPECTED;
5857 /* the type pointed to by this [retval] becomes elemdescFunc,
5858 * i.e. the function signature's return type.
5859 * We are using a flat buffer so there is no danger of leaking memory */
5860 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5862 /* remove the last parameter */
5863 dest->cParams--;
5865 else if (dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5866 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5867 * not pVarResult. So the function signature should show no return value. */
5868 dest->elemdescFunc.tdesc.vt = VT_VOID;
5870 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5871 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5872 if (dest->cParams && (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
5873 dest->cParams--;
5876 *dest_ptr = dest;
5877 return S_OK;
5880 static void TLB_FreeVarDesc(VARDESC *var_desc)
5882 TLB_FreeElemDesc(&var_desc->elemdescVar);
5883 if (var_desc->varkind == VAR_CONST)
5884 VariantClear(var_desc->u.lpvarValue);
5885 SysFreeString((BSTR)var_desc);
5888 /* internal function to make the inherited interfaces' methods appear
5889 * part of the interface */
5890 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5891 UINT index, const TLBFuncDesc **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5893 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5894 HRESULT hr;
5895 UINT implemented_funcs = 0;
5897 if (funcs)
5898 *funcs = 0;
5899 else
5900 *hrefoffset = DISPATCH_HREF_OFFSET;
5902 if(This->impltypes)
5904 ITypeInfo *pSubTypeInfo;
5905 UINT sub_funcs;
5907 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5908 if (FAILED(hr))
5909 return hr;
5911 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5912 index,
5913 ppFuncDesc,
5914 &sub_funcs, hrefoffset);
5915 implemented_funcs += sub_funcs;
5916 ITypeInfo_Release(pSubTypeInfo);
5917 if (SUCCEEDED(hr))
5918 return hr;
5919 *hrefoffset += DISPATCH_HREF_OFFSET;
5922 if (funcs)
5923 *funcs = implemented_funcs + This->typeattr.cFuncs;
5924 else
5925 *hrefoffset = 0;
5927 if (index < implemented_funcs)
5928 return E_INVALIDARG;
5929 index -= implemented_funcs;
5931 if (index >= This->typeattr.cFuncs)
5932 return TYPE_E_ELEMENTNOTFOUND;
5934 *ppFuncDesc = &This->funcdescs[index];
5935 return S_OK;
5938 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5940 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5942 if (This->typeattr.typekind == TKIND_DISPATCH)
5943 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5945 if (index >= This->typeattr.cFuncs)
5946 return TYPE_E_ELEMENTNOTFOUND;
5948 *func_desc = &This->funcdescs[index];
5949 return S_OK;
5952 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5954 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5955 while (TRUE)
5957 switch (pTypeDesc->vt)
5959 case VT_USERDEFINED:
5960 pTypeDesc->u.hreftype += hrefoffset;
5961 return;
5962 case VT_PTR:
5963 case VT_SAFEARRAY:
5964 pTypeDesc = pTypeDesc->u.lptdesc;
5965 break;
5966 case VT_CARRAY:
5967 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5968 break;
5969 default:
5970 return;
5975 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5977 SHORT i;
5978 for (i = 0; i < pFuncDesc->cParams; i++)
5979 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5980 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5983 /* ITypeInfo::GetFuncDesc
5985 * Retrieves the FUNCDESC structure that contains information about a
5986 * specified function.
5989 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5990 LPFUNCDESC *ppFuncDesc)
5992 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5993 const TLBFuncDesc *internal_funcdesc;
5994 HRESULT hr;
5995 UINT hrefoffset = 0;
5997 TRACE("(%p) index %d\n", This, index);
5999 if (!ppFuncDesc)
6000 return E_INVALIDARG;
6002 if (This->needs_layout)
6003 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6005 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6006 &internal_funcdesc, &hrefoffset);
6007 if (FAILED(hr))
6009 WARN("description for function %d not found\n", index);
6010 return hr;
6013 hr = TLB_AllocAndInitFuncDesc(
6014 &internal_funcdesc->funcdesc,
6015 ppFuncDesc,
6016 This->typeattr.typekind == TKIND_DISPATCH);
6018 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6019 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6021 TRACE("-- 0x%08x\n", hr);
6022 return hr;
6025 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6027 VARDESC *dest;
6028 char *buffer;
6029 SIZE_T size = sizeof(*src);
6030 HRESULT hr;
6032 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6033 if (src->varkind == VAR_CONST)
6034 size += sizeof(VARIANT);
6035 size += TLB_SizeElemDesc(&src->elemdescVar);
6037 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6038 if (!dest) return E_OUTOFMEMORY;
6040 *dest = *src;
6041 buffer = (char *)(dest + 1);
6042 if (src->lpstrSchema)
6044 int len;
6045 dest->lpstrSchema = (LPOLESTR)buffer;
6046 len = lstrlenW(src->lpstrSchema);
6047 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6048 buffer += (len + 1) * sizeof(WCHAR);
6051 if (src->varkind == VAR_CONST)
6053 HRESULT hr;
6055 dest->u.lpvarValue = (VARIANT *)buffer;
6056 *dest->u.lpvarValue = *src->u.lpvarValue;
6057 buffer += sizeof(VARIANT);
6058 VariantInit(dest->u.lpvarValue);
6059 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6060 if (FAILED(hr))
6062 SysFreeString((BSTR)dest);
6063 return hr;
6066 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6067 if (FAILED(hr))
6069 if (src->varkind == VAR_CONST)
6070 VariantClear(dest->u.lpvarValue);
6071 SysFreeString((BSTR)dest);
6072 return hr;
6074 *dest_ptr = dest;
6075 return S_OK;
6078 /* ITypeInfo::GetVarDesc
6080 * Retrieves a VARDESC structure that describes the specified variable.
6083 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6084 LPVARDESC *ppVarDesc)
6086 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6087 const TLBVarDesc *pVDesc = &This->vardescs[index];
6089 TRACE("(%p) index %d\n", This, index);
6091 if(index >= This->typeattr.cVars)
6092 return TYPE_E_ELEMENTNOTFOUND;
6094 if (This->needs_layout)
6095 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6097 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6100 /* internal function to make the inherited interfaces' methods appear
6101 * part of the interface, remembering if the top-level was dispinterface */
6102 static HRESULT typeinfo_getnames( ITypeInfo *iface, MEMBERID memid, BSTR *names,
6103 UINT max_names, UINT *num_names, BOOL dispinterface)
6105 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6106 const TLBFuncDesc *func_desc;
6107 const TLBVarDesc *var_desc;
6108 int i;
6110 *num_names = 0;
6112 func_desc = TLB_get_funcdesc_by_memberid(This, memid);
6113 if (func_desc)
6115 UINT params = func_desc->funcdesc.cParams;
6116 if (!max_names || !func_desc->Name)
6117 return S_OK;
6119 *names = SysAllocString(TLB_get_bstr(func_desc->Name));
6120 ++(*num_names);
6122 if (dispinterface && (func_desc->funcdesc.funckind != FUNC_DISPATCH))
6124 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6125 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
6126 --params; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6127 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
6128 --params; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6131 for (i = 0; i < params; i++)
6133 if (*num_names >= max_names || !func_desc->pParamDesc[i].Name)
6134 return S_OK;
6135 names[*num_names] = SysAllocString(TLB_get_bstr(func_desc->pParamDesc[i].Name));
6136 ++(*num_names);
6138 return S_OK;
6141 var_desc = TLB_get_vardesc_by_memberid(This, memid);
6142 if (var_desc)
6144 *names = SysAllocString(TLB_get_bstr(var_desc->Name));
6145 *num_names = 1;
6147 else
6149 if (This->impltypes &&
6150 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH))
6152 /* recursive search */
6153 ITypeInfo *parent;
6154 HRESULT result;
6155 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &parent);
6156 if (SUCCEEDED(result))
6158 result = typeinfo_getnames(parent, memid, names, max_names, num_names, dispinterface);
6159 ITypeInfo_Release(parent);
6160 return result;
6162 WARN("Could not search inherited interface!\n");
6164 else
6166 WARN("no names found\n");
6168 *num_names = 0;
6169 return TYPE_E_ELEMENTNOTFOUND;
6171 return S_OK;
6174 /* ITypeInfo_GetNames
6176 * Retrieves the variable with the specified member ID (or the name of the
6177 * property or method and its parameters) that correspond to the specified
6178 * function ID.
6180 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6181 BSTR *names, UINT max_names, UINT *num_names)
6183 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6185 TRACE("(%p) memid 0x%08x max_names %d\n", This, memid, max_names);
6187 if (!names) return E_INVALIDARG;
6189 return typeinfo_getnames((ITypeInfo *)iface, memid, names, max_names, num_names,
6190 This->typeattr.typekind == TKIND_DISPATCH);
6193 /* ITypeInfo::GetRefTypeOfImplType
6195 * If a type description describes a COM class, it retrieves the type
6196 * description of the implemented interface types. For an interface,
6197 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6198 * if any exist.
6201 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6202 ITypeInfo2 *iface,
6203 UINT index,
6204 HREFTYPE *pRefType)
6206 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6207 HRESULT hr = S_OK;
6209 TRACE("(%p) index %d\n", This, index);
6210 if (TRACE_ON(ole)) dump_TypeInfo(This);
6212 if(index==(UINT)-1)
6214 /* only valid on dual interfaces;
6215 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6218 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6220 *pRefType = -2;
6222 else
6224 hr = TYPE_E_ELEMENTNOTFOUND;
6227 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6229 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6230 *pRefType = This->pTypeLib->dispatch_href;
6232 else
6234 if(index >= This->typeattr.cImplTypes)
6235 hr = TYPE_E_ELEMENTNOTFOUND;
6236 else{
6237 *pRefType = This->impltypes[index].hRef;
6238 if (This->typeattr.typekind == TKIND_INTERFACE)
6239 *pRefType |= 0x2;
6243 if(TRACE_ON(ole))
6245 if(SUCCEEDED(hr))
6246 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6247 else
6248 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6251 return hr;
6254 /* ITypeInfo::GetImplTypeFlags
6256 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6257 * or base interface in a type description.
6259 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6260 UINT index, INT *pImplTypeFlags)
6262 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6264 TRACE("(%p) index %d\n", This, index);
6266 if(!pImplTypeFlags)
6267 return E_INVALIDARG;
6269 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6270 *pImplTypeFlags = 0;
6271 return S_OK;
6274 if(index >= This->typeattr.cImplTypes)
6275 return TYPE_E_ELEMENTNOTFOUND;
6277 *pImplTypeFlags = This->impltypes[index].implflags;
6279 return S_OK;
6282 /* GetIDsOfNames
6283 * Maps between member names and member IDs, and parameter names and
6284 * parameter IDs.
6286 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6287 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6289 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6290 const TLBVarDesc *pVDesc;
6291 HRESULT ret=S_OK;
6292 UINT i, fdc;
6294 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6295 cNames);
6297 /* init out parameters in case of failure */
6298 for (i = 0; i < cNames; i++)
6299 pMemId[i] = MEMBERID_NIL;
6301 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6302 int j;
6303 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6304 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6305 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6306 for(i=1; i < cNames; i++){
6307 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6308 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6309 break;
6310 if( j<pFDesc->funcdesc.cParams)
6311 pMemId[i]=j;
6312 else
6313 ret=DISP_E_UNKNOWNNAME;
6315 TRACE("-- 0x%08x\n", ret);
6316 return ret;
6319 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6320 if(pVDesc){
6321 if(cNames)
6322 *pMemId = pVDesc->vardesc.memid;
6323 return ret;
6325 /* not found, see if it can be found in an inherited interface */
6326 if(This->impltypes) {
6327 /* recursive search */
6328 ITypeInfo *pTInfo;
6329 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6330 if(SUCCEEDED(ret)){
6331 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6332 ITypeInfo_Release(pTInfo);
6333 return ret;
6335 WARN("Could not search inherited interface!\n");
6336 } else
6337 WARN("no names found\n");
6338 return DISP_E_UNKNOWNNAME;
6342 #ifdef __i386__
6344 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6345 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6346 __ASM_GLOBAL_FUNC( call_method,
6347 "pushl %ebp\n\t"
6348 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6349 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6350 "movl %esp,%ebp\n\t"
6351 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6352 "pushl %esi\n\t"
6353 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6354 "pushl %edi\n\t"
6355 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6356 "movl 12(%ebp),%edx\n\t"
6357 "movl %esp,%edi\n\t"
6358 "shll $2,%edx\n\t"
6359 "jz 1f\n\t"
6360 "subl %edx,%edi\n\t"
6361 "andl $~15,%edi\n\t"
6362 "movl %edi,%esp\n\t"
6363 "movl 12(%ebp),%ecx\n\t"
6364 "movl 16(%ebp),%esi\n\t"
6365 "cld\n\t"
6366 "rep; movsl\n"
6367 "1:\tcall *8(%ebp)\n\t"
6368 "subl %esp,%edi\n\t"
6369 "movl 20(%ebp),%ecx\n\t"
6370 "movl %edi,(%ecx)\n\t"
6371 "leal -8(%ebp),%esp\n\t"
6372 "popl %edi\n\t"
6373 __ASM_CFI(".cfi_same_value %edi\n\t")
6374 "popl %esi\n\t"
6375 __ASM_CFI(".cfi_same_value %esi\n\t")
6376 "popl %ebp\n\t"
6377 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6378 __ASM_CFI(".cfi_same_value %ebp\n\t")
6379 "ret" )
6380 __ASM_GLOBAL_FUNC( call_double_method,
6381 "jmp " __ASM_NAME("call_method") )
6383 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6384 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6386 int argspos = 0, stack_offset;
6387 void *func;
6388 UINT i;
6389 DWORD *args;
6391 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6392 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6393 pvargResult, V_VT(pvargResult));
6395 if (cc != CC_STDCALL && cc != CC_CDECL)
6397 FIXME("unsupported calling convention %d\n",cc);
6398 return E_INVALIDARG;
6401 /* maximum size for an argument is sizeof(VARIANT) */
6402 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6404 if (pvInstance)
6406 const FARPROC *vtable = *(FARPROC **)pvInstance;
6407 func = vtable[oVft/sizeof(void *)];
6408 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6410 else func = (void *)oVft;
6412 switch (vtReturn)
6414 case VT_DECIMAL:
6415 case VT_VARIANT:
6416 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6417 break;
6418 case VT_HRESULT:
6419 WARN("invalid return type %u\n", vtReturn);
6420 heap_free( args );
6421 return E_INVALIDARG;
6422 default:
6423 break;
6426 for (i = 0; i < cActuals; i++)
6428 VARIANT *arg = prgpvarg[i];
6430 switch (prgvt[i])
6432 case VT_EMPTY:
6433 break;
6434 case VT_I8:
6435 case VT_UI8:
6436 case VT_R8:
6437 case VT_DATE:
6438 case VT_CY:
6439 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6440 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6441 break;
6442 case VT_DECIMAL:
6443 case VT_VARIANT:
6444 memcpy( &args[argspos], arg, sizeof(*arg) );
6445 argspos += sizeof(*arg) / sizeof(DWORD);
6446 break;
6447 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6448 args[argspos++] = V_BOOL(arg);
6449 break;
6450 default:
6451 args[argspos++] = V_UI4(arg);
6452 break;
6454 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6457 switch (vtReturn)
6459 case VT_EMPTY:
6460 case VT_DECIMAL:
6461 case VT_VARIANT:
6462 call_method( func, argspos, args, &stack_offset );
6463 break;
6464 case VT_R4:
6465 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6466 break;
6467 case VT_R8:
6468 case VT_DATE:
6469 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6470 break;
6471 case VT_I8:
6472 case VT_UI8:
6473 case VT_CY:
6474 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6475 break;
6476 default:
6477 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6478 break;
6480 heap_free( args );
6481 if (stack_offset && cc == CC_STDCALL)
6483 WARN( "stack pointer off by %d\n", stack_offset );
6484 return DISP_E_BADCALLEE;
6486 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6487 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6488 return S_OK;
6491 #elif defined(__x86_64__)
6493 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6494 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6495 __ASM_GLOBAL_FUNC( call_method,
6496 "pushq %rbp\n\t"
6497 __ASM_SEH(".seh_pushreg %rbp\n\t")
6498 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6499 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6500 "movq %rsp,%rbp\n\t"
6501 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6502 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6503 "pushq %rsi\n\t"
6504 __ASM_SEH(".seh_pushreg %rsi\n\t")
6505 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6506 "pushq %rdi\n\t"
6507 __ASM_SEH(".seh_pushreg %rdi\n\t")
6508 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6509 __ASM_SEH(".seh_endprologue\n\t")
6510 "movq %rcx,%rax\n\t"
6511 "movq $4,%rcx\n\t"
6512 "cmp %rcx,%rdx\n\t"
6513 "cmovgq %rdx,%rcx\n\t"
6514 "leaq 0(,%rcx,8),%rdx\n\t"
6515 "subq %rdx,%rsp\n\t"
6516 "andq $~15,%rsp\n\t"
6517 "movq %rsp,%rdi\n\t"
6518 "movq %r8,%rsi\n\t"
6519 "rep; movsq\n\t"
6520 "movq 0(%rsp),%rcx\n\t"
6521 "movq 8(%rsp),%rdx\n\t"
6522 "movq 16(%rsp),%r8\n\t"
6523 "movq 24(%rsp),%r9\n\t"
6524 "movq 0(%rsp),%xmm0\n\t"
6525 "movq 8(%rsp),%xmm1\n\t"
6526 "movq 16(%rsp),%xmm2\n\t"
6527 "movq 24(%rsp),%xmm3\n\t"
6528 "callq *%rax\n\t"
6529 "leaq -16(%rbp),%rsp\n\t"
6530 "popq %rdi\n\t"
6531 __ASM_CFI(".cfi_same_value %rdi\n\t")
6532 "popq %rsi\n\t"
6533 __ASM_CFI(".cfi_same_value %rsi\n\t")
6534 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6535 "popq %rbp\n\t"
6536 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6537 __ASM_CFI(".cfi_same_value %rbp\n\t")
6538 "ret")
6539 __ASM_GLOBAL_FUNC( call_double_method,
6540 "jmp " __ASM_NAME("call_method") )
6542 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6543 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6545 int argspos = 0;
6546 UINT i;
6547 DWORD_PTR *args;
6548 void *func;
6550 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6551 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6552 pvargResult, V_VT(pvargResult));
6554 if (cc != CC_STDCALL && cc != CC_CDECL)
6556 FIXME("unsupported calling convention %d\n",cc);
6557 return E_INVALIDARG;
6560 /* maximum size for an argument is sizeof(DWORD_PTR) */
6561 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6563 if (pvInstance)
6565 const FARPROC *vtable = *(FARPROC **)pvInstance;
6566 func = vtable[oVft/sizeof(void *)];
6567 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6569 else func = (void *)oVft;
6571 switch (vtReturn)
6573 case VT_DECIMAL:
6574 case VT_VARIANT:
6575 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6576 break;
6577 case VT_HRESULT:
6578 WARN("invalid return type %u\n", vtReturn);
6579 heap_free( args );
6580 return E_INVALIDARG;
6581 default:
6582 break;
6585 for (i = 0; i < cActuals; i++)
6587 VARIANT *arg = prgpvarg[i];
6589 switch (prgvt[i])
6591 case VT_DECIMAL:
6592 case VT_VARIANT:
6593 args[argspos++] = (ULONG_PTR)arg;
6594 break;
6595 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6596 args[argspos++] = V_BOOL(arg);
6597 break;
6598 default:
6599 args[argspos++] = V_UI8(arg);
6600 break;
6602 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6605 switch (vtReturn)
6607 case VT_R4:
6608 V_R4(pvargResult) = call_double_method( func, argspos, args );
6609 break;
6610 case VT_R8:
6611 case VT_DATE:
6612 V_R8(pvargResult) = call_double_method( func, argspos, args );
6613 break;
6614 case VT_DECIMAL:
6615 case VT_VARIANT:
6616 call_method( func, argspos, args );
6617 break;
6618 default:
6619 V_UI8(pvargResult) = call_method( func, argspos, args );
6620 break;
6622 heap_free( args );
6623 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6624 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6625 return S_OK;
6628 #elif defined(__arm__)
6630 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6631 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6632 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6633 __ASM_GLOBAL_FUNC( call_method,
6634 /* r0 = *func
6635 * r1 = nb_stk_args
6636 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6637 * r3 = *reg_args (pointer to 8, 64-bit d0-d7 (double) values OR as 16, 32-bit s0-s15 (float) values, followed by 4, 32-bit (DWORD) r0-r3 values)
6640 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6641 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6643 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6644 "beq 1f\n\t" /* Skip allocation if no stack args */
6645 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6646 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6647 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6648 "subs r1, r1, #4\n\t" /* Decrement count */
6649 "bgt 2b\n\t" /* Loop till done */
6651 "1:\n\t"
6652 #ifndef __SOFTFP__
6653 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6654 #endif
6655 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6656 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6658 "blx ip\n\t" /* Call the target function */
6660 "mov sp, fp\n\t" /* Clean the stack using fp */
6661 "pop {fp, pc}\n\t" /* Restore fp and return */
6663 __ASM_GLOBAL_FUNC( call_float_method,
6664 "b " __ASM_NAME("call_method") )
6665 __ASM_GLOBAL_FUNC( call_double_method,
6666 "b " __ASM_NAME("call_method") )
6668 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6669 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6671 int argspos;
6672 void *func;
6673 UINT i;
6674 DWORD *args;
6675 struct {
6676 #ifndef __SOFTFP__
6677 union {
6678 float s[16];
6679 double d[8];
6680 } sd;
6681 #endif
6682 DWORD r[4];
6683 } regs;
6684 int rcount; /* 32-bit register index count */
6685 #ifndef __SOFTFP__
6686 int scount = 0; /* single-precision float register index count */
6687 int dcount = 0; /* double-precision float register index count */
6688 #endif
6690 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6691 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6693 if (cc != CC_STDCALL && cc != CC_CDECL)
6695 FIXME("unsupported calling convention %d\n",cc);
6696 return E_INVALIDARG;
6699 argspos = 0;
6700 rcount = 0;
6702 if (pvInstance)
6704 const FARPROC *vtable = *(FARPROC **)pvInstance;
6705 func = vtable[oVft/sizeof(void *)];
6706 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6708 else func = (void *)oVft;
6710 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6711 /* first as it will need to be in the 'r' registers: */
6712 switch (vtReturn)
6714 case VT_DECIMAL:
6715 case VT_VARIANT:
6716 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6717 break;
6718 case VT_HRESULT:
6719 WARN("invalid return type %u\n", vtReturn);
6720 return E_INVALIDARG;
6721 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6722 break;
6725 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6726 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6728 for (i = 0; i < cActuals; i++)
6730 VARIANT *arg = prgpvarg[i];
6731 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6732 int ntemp; /* Used for counting words split between registers and stack */
6734 switch (prgvt[i])
6736 case VT_EMPTY:
6737 break;
6738 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6739 case VT_DATE:
6740 #ifndef __SOFTFP__
6741 dcount = max( (scount + 1) / 2, dcount );
6742 if (dcount < 8)
6744 regs.sd.d[dcount++] = V_R8(arg);
6746 else
6748 argspos += (argspos % 2); /* align argspos to 8-bytes */
6749 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6750 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6752 break;
6753 #endif
6754 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6755 case VT_UI8:
6756 case VT_CY:
6757 if (rcount < 3)
6759 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6760 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6761 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6763 else
6765 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6766 argspos += (argspos % 2); /* align argspos to 8-bytes */
6767 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6768 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6770 break;
6771 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6772 case VT_VARIANT:
6773 /* 8-byte align 'r' and/or stack: */
6774 if (rcount < 3)
6775 rcount += (rcount % 2);
6776 else
6778 rcount = 4;
6779 argspos += (argspos % 2);
6781 ntemp = sizeof(*arg) / sizeof(DWORD);
6782 while (ntemp > 0)
6784 if (rcount < 4)
6785 regs.r[rcount++] = *pdwarg++;
6786 else
6787 args[argspos++] = *pdwarg++;
6788 --ntemp;
6790 break;
6791 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6792 if (rcount < 4)
6793 regs.r[rcount++] = V_BOOL(arg);
6794 else
6795 args[argspos++] = V_BOOL(arg);
6796 break;
6797 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6798 #ifndef __SOFTFP__
6799 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6800 if (scount < 16)
6801 regs.sd.s[scount++] = V_R4(arg);
6802 else
6803 args[argspos++] = V_UI4(arg);
6804 break;
6805 #endif
6806 default:
6807 if (rcount < 4)
6808 regs.r[rcount++] = V_UI4(arg);
6809 else
6810 args[argspos++] = V_UI4(arg);
6811 break;
6813 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6816 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6818 switch (vtReturn)
6820 case VT_EMPTY: /* EMPTY = no return value */
6821 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6822 case VT_VARIANT:
6823 call_method( func, argspos, args, (DWORD*)&regs );
6824 break;
6825 case VT_R4:
6826 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6827 break;
6828 case VT_R8:
6829 case VT_DATE:
6830 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6831 break;
6832 case VT_I8:
6833 case VT_UI8:
6834 case VT_CY:
6835 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6836 break;
6837 default:
6838 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6839 break;
6841 heap_free( args );
6842 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6843 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6844 return S_OK;
6847 #elif defined(__aarch64__)
6849 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6850 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6851 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6852 __ASM_GLOBAL_FUNC( call_method,
6853 "stp x29, x30, [sp, #-16]!\n\t"
6854 "mov x29, sp\n\t"
6855 "sub sp, sp, x1, lsl #3\n\t"
6856 "cbz x1, 2f\n"
6857 "1:\tsub x1, x1, #1\n\t"
6858 "ldr x4, [x2, x1, lsl #3]\n\t"
6859 "str x4, [sp, x1, lsl #3]\n\t"
6860 "cbnz x1, 1b\n"
6861 "2:\tmov x16, x0\n\t"
6862 "mov x9, x3\n\t"
6863 "ldp d0, d1, [x9]\n\t"
6864 "ldp d2, d3, [x9, #0x10]\n\t"
6865 "ldp d4, d5, [x9, #0x20]\n\t"
6866 "ldp d6, d7, [x9, #0x30]\n\t"
6867 "ldp x0, x1, [x9, #0x40]\n\t"
6868 "ldp x2, x3, [x9, #0x50]\n\t"
6869 "ldp x4, x5, [x9, #0x60]\n\t"
6870 "ldp x6, x7, [x9, #0x70]\n\t"
6871 "ldr x8, [x9, #0x80]\n\t"
6872 "blr x16\n\t"
6873 "mov sp, x29\n\t"
6874 "ldp x29, x30, [sp], #16\n\t"
6875 "ret" )
6876 __ASM_GLOBAL_FUNC( call_float_method,
6877 "b " __ASM_NAME("call_method") )
6878 __ASM_GLOBAL_FUNC( call_double_method,
6879 "b " __ASM_NAME("call_method") )
6881 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6882 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6884 int argspos;
6885 void *func;
6886 UINT i;
6887 DWORD_PTR *args;
6888 struct
6890 union
6892 float f;
6893 double d;
6894 } fp[8];
6895 DWORD_PTR x[9];
6896 } regs;
6897 int rcount; /* 64-bit register index count */
6898 int fpcount = 0; /* float register index count */
6900 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6901 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6903 if (cc != CC_STDCALL && cc != CC_CDECL)
6905 FIXME("unsupported calling convention %d\n",cc);
6906 return E_INVALIDARG;
6909 argspos = 0;
6910 rcount = 0;
6912 if (instance)
6914 const FARPROC *vtable = *(FARPROC **)instance;
6915 func = vtable[offset/sizeof(void *)];
6916 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6918 else func = (void *)offset;
6920 /* maximum size for an argument is 16 */
6921 args = heap_alloc( 16 * count );
6923 for (i = 0; i < count; i++)
6925 VARIANT *arg = vargs[i];
6927 switch (types[i])
6929 case VT_R4:
6930 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6931 else *(float *)&args[argspos++] = V_R4(arg);
6932 break;
6933 case VT_R8:
6934 case VT_DATE:
6935 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6936 else *(double *)&args[argspos++] = V_R8(arg);
6937 break;
6938 case VT_DECIMAL:
6939 if (rcount < 7)
6941 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6942 rcount += 2;
6944 else
6946 memcpy( &args[argspos], arg, sizeof(*arg) );
6947 argspos += 2;
6949 break;
6950 case VT_VARIANT:
6951 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6952 else args[argspos++] = (DWORD_PTR)arg;
6953 break;
6954 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6955 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6956 else args[argspos++] = V_BOOL(arg);
6957 break;
6958 default:
6959 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6960 else args[argspos++] = V_UI8(arg);
6961 break;
6963 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6966 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6968 switch (ret_type)
6970 case VT_HRESULT:
6971 heap_free( args );
6972 return E_INVALIDARG;
6973 case VT_DECIMAL:
6974 case VT_VARIANT:
6975 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6976 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6977 break;
6978 case VT_R4:
6979 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6980 break;
6981 case VT_R8:
6982 case VT_DATE:
6983 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6984 break;
6985 default:
6986 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6987 break;
6989 heap_free( args );
6990 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6991 TRACE("retval: %s\n", debugstr_variant(result));
6992 return S_OK;
6995 #else /* __aarch64__ */
6997 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6998 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
7000 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7001 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
7002 return E_NOTIMPL;
7005 #endif
7007 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7009 HRESULT hr = S_OK;
7010 ITypeInfo *tinfo2 = NULL;
7011 TYPEATTR *tattr = NULL;
7013 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
7014 if (hr)
7016 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
7017 "hr = 0x%08x\n",
7018 tdesc->u.hreftype, hr);
7019 return hr;
7021 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7022 if (hr)
7024 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
7025 ITypeInfo_Release(tinfo2);
7026 return hr;
7029 switch (tattr->typekind)
7031 case TKIND_ENUM:
7032 *vt |= VT_I4;
7033 break;
7035 case TKIND_ALIAS:
7036 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7037 break;
7039 case TKIND_INTERFACE:
7040 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7041 *vt |= VT_DISPATCH;
7042 else
7043 *vt |= VT_UNKNOWN;
7044 break;
7046 case TKIND_DISPATCH:
7047 *vt |= VT_DISPATCH;
7048 break;
7050 case TKIND_COCLASS:
7051 *vt |= VT_DISPATCH;
7052 break;
7054 case TKIND_RECORD:
7055 FIXME("TKIND_RECORD unhandled.\n");
7056 hr = E_NOTIMPL;
7057 break;
7059 case TKIND_UNION:
7060 FIXME("TKIND_UNION unhandled.\n");
7061 hr = E_NOTIMPL;
7062 break;
7064 default:
7065 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7066 hr = E_NOTIMPL;
7067 break;
7069 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7070 ITypeInfo_Release(tinfo2);
7071 return hr;
7074 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7076 HRESULT hr = S_OK;
7078 /* enforce only one level of pointer indirection */
7079 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7081 tdesc = tdesc->u.lptdesc;
7083 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7084 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7085 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7086 if ((tdesc->vt == VT_USERDEFINED) ||
7087 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
7089 VARTYPE vt_userdefined = 0;
7090 const TYPEDESC *tdesc_userdefined = tdesc;
7091 if (tdesc->vt == VT_PTR)
7093 vt_userdefined = VT_BYREF;
7094 tdesc_userdefined = tdesc->u.lptdesc;
7096 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7097 if ((hr == S_OK) &&
7098 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7099 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7101 *vt |= vt_userdefined;
7102 return S_OK;
7105 *vt = VT_BYREF;
7108 switch (tdesc->vt)
7110 case VT_HRESULT:
7111 *vt |= VT_ERROR;
7112 break;
7113 case VT_USERDEFINED:
7114 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7115 break;
7116 case VT_VOID:
7117 case VT_CARRAY:
7118 case VT_PTR:
7119 case VT_LPSTR:
7120 case VT_LPWSTR:
7121 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7122 hr = DISP_E_BADVARTYPE;
7123 break;
7124 case VT_SAFEARRAY:
7125 *vt |= VT_ARRAY;
7126 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
7127 break;
7128 case VT_INT:
7129 *vt |= VT_I4;
7130 break;
7131 case VT_UINT:
7132 *vt |= VT_UI4;
7133 break;
7134 default:
7135 *vt |= tdesc->vt;
7136 break;
7138 return hr;
7141 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7143 ITypeInfo *tinfo2;
7144 TYPEATTR *tattr;
7145 HRESULT hres;
7146 int flags, i;
7148 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7149 if(FAILED(hres))
7150 return hres;
7152 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7153 if(FAILED(hres)) {
7154 ITypeInfo_Release(tinfo2);
7155 return hres;
7158 switch(tattr->typekind) {
7159 case TKIND_ALIAS:
7160 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
7161 break;
7163 case TKIND_INTERFACE:
7164 case TKIND_DISPATCH:
7165 *guid = tattr->guid;
7166 break;
7168 case TKIND_COCLASS:
7169 for (i = 0; i < tattr->cImplTypes; i++)
7171 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7172 if (flags & IMPLTYPEFLAG_FDEFAULT)
7173 break;
7176 if (i == tattr->cImplTypes)
7177 i = 0;
7179 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7180 if (SUCCEEDED(hres))
7181 hres = get_iface_guid(tinfo2, href, guid);
7182 break;
7184 default:
7185 ERR("Unexpected typekind %d\n", tattr->typekind);
7186 hres = E_UNEXPECTED;
7189 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7190 ITypeInfo_Release(tinfo2);
7191 return hres;
7194 static inline BOOL func_restricted( const FUNCDESC *desc )
7196 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7199 #define INVBUF_ELEMENT_SIZE \
7200 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7201 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7202 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7203 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7204 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7205 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7206 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7207 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7209 static HRESULT WINAPI ITypeInfo_fnInvoke(
7210 ITypeInfo2 *iface,
7211 VOID *pIUnk,
7212 MEMBERID memid,
7213 UINT16 wFlags,
7214 DISPPARAMS *pDispParams,
7215 VARIANT *pVarResult,
7216 EXCEPINFO *pExcepInfo,
7217 UINT *pArgErr)
7219 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7220 int i, j;
7221 unsigned int var_index;
7222 TYPEKIND type_kind;
7223 HRESULT hres;
7224 const TLBFuncDesc *pFuncInfo;
7225 UINT fdc;
7227 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7228 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7231 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7232 return DISP_E_MEMBERNOTFOUND;
7234 if (!pDispParams)
7236 ERR("NULL pDispParams not allowed\n");
7237 return E_INVALIDARG;
7240 dump_DispParms(pDispParams);
7242 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7244 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7245 pDispParams->cNamedArgs, pDispParams->cArgs);
7246 return E_INVALIDARG;
7249 /* we do this instead of using GetFuncDesc since it will return a fake
7250 * FUNCDESC for dispinterfaces and we want the real function description */
7251 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7252 pFuncInfo = &This->funcdescs[fdc];
7253 if ((memid == pFuncInfo->funcdesc.memid) &&
7254 (wFlags & pFuncInfo->funcdesc.invkind) &&
7255 !func_restricted( &pFuncInfo->funcdesc ))
7256 break;
7259 if (fdc < This->typeattr.cFuncs) {
7260 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7262 if (TRACE_ON(ole))
7264 TRACE("invoking:\n");
7265 dump_TLBFuncDescOne(pFuncInfo);
7268 switch (func_desc->funckind) {
7269 case FUNC_PUREVIRTUAL:
7270 case FUNC_VIRTUAL: {
7271 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7272 VARIANT varresult;
7273 VARIANT retval = {{{0}}}; /* pointer for storing byref retvals in */
7274 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7275 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7276 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7277 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7278 UINT cNamedArgs = pDispParams->cNamedArgs;
7279 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7280 UINT vargs_converted=0;
7281 SAFEARRAY *a;
7283 hres = S_OK;
7285 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7287 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7289 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7290 hres = DISP_E_PARAMNOTFOUND;
7291 goto func_fail;
7295 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7297 ERR("functions with the vararg attribute do not support named arguments\n");
7298 hres = DISP_E_NONAMEDARGS;
7299 goto func_fail;
7302 for (i = 0; i < func_desc->cParams; i++)
7304 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7305 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7306 if (FAILED(hres))
7307 goto func_fail;
7310 TRACE("changing args\n");
7311 for (i = 0; i < func_desc->cParams; i++)
7313 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7314 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7315 VARIANTARG *src_arg;
7317 if (wParamFlags & PARAMFLAG_FLCID)
7319 prgpvarg[i] = &rgvarg[i];
7320 V_VT(prgpvarg[i]) = VT_I4;
7321 V_I4(prgpvarg[i]) = This->pTypeLib->lcid;
7322 continue;
7325 src_arg = NULL;
7327 for (j = 0; j < cNamedArgs; j++)
7329 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7331 src_arg = &pDispParams->rgvarg[j];
7332 break;
7336 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7338 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7339 vargs_converted++;
7342 if (wParamFlags & PARAMFLAG_FRETVAL)
7344 /* under most conditions the caller is not allowed to
7345 * pass in a dispparam arg in the index of what would be
7346 * the retval parameter. however, there is an exception
7347 * where the extra parameter is used in an extra
7348 * IDispatch::Invoke below */
7349 if ((i < pDispParams->cArgs) &&
7350 ((func_desc->cParams != 1) || !pVarResult ||
7351 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7353 hres = DISP_E_BADPARAMCOUNT;
7354 break;
7357 /* note: this check is placed so that if the caller passes
7358 * in a VARIANTARG for the retval we just ignore it, like
7359 * native does */
7360 if (i == func_desc->cParams - 1)
7362 prgpvarg[i] = &rgvarg[i];
7363 V_BYREF(prgpvarg[i]) = &retval;
7364 V_VT(prgpvarg[i]) = rgvt[i];
7366 else
7368 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7369 hres = E_UNEXPECTED;
7370 break;
7373 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7374 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7376 TRACE("%s\n", debugstr_variant(src_arg));
7378 if(rgvt[i]!=V_VT(src_arg))
7380 if (rgvt[i] == VT_VARIANT)
7381 hres = VariantCopy(&rgvarg[i], src_arg);
7382 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7384 if (rgvt[i] == V_VT(src_arg))
7385 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7386 else
7388 if (wParamFlags & PARAMFLAG_FIN)
7389 hres = VariantCopy(&missing_arg[i], src_arg);
7390 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7392 V_VT(&rgvarg[i]) = rgvt[i];
7394 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7396 SAFEARRAYBOUND bound;
7397 VARIANT *v;
7399 bound.lLbound = 0;
7400 bound.cElements = pDispParams->cArgs-i;
7401 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7403 ERR("SafeArrayCreate failed\n");
7404 break;
7406 hres = SafeArrayAccessData(a, (LPVOID)&v);
7407 if (hres != S_OK)
7409 ERR("SafeArrayAccessData failed with %x\n", hres);
7410 SafeArrayDestroy(a);
7411 break;
7413 for (j = 0; j < bound.cElements; j++)
7414 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7415 hres = SafeArrayUnaccessData(a);
7416 if (hres != S_OK)
7418 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7419 SafeArrayDestroy(a);
7420 break;
7422 if (rgvt[i] & VT_BYREF)
7423 V_BYREF(&rgvarg[i]) = &a;
7424 else
7425 V_ARRAY(&rgvarg[i]) = a;
7426 V_VT(&rgvarg[i]) = rgvt[i];
7428 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7430 if (wParamFlags & PARAMFLAG_FIN)
7431 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7432 else
7433 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7434 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7435 V_VT(&rgvarg[i]) = rgvt[i];
7437 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7439 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7440 V_VT(&rgvarg[i]) = rgvt[i];
7442 else
7444 /* FIXME: this doesn't work for VT_BYREF arguments if
7445 * they are not the same type as in the paramdesc */
7446 V_VT(&rgvarg[i]) = V_VT(src_arg);
7447 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7448 V_VT(&rgvarg[i]) = rgvt[i];
7451 if (FAILED(hres))
7453 ERR("failed to convert param %d to %s from %s\n", i,
7454 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7455 break;
7457 prgpvarg[i] = &rgvarg[i];
7459 else
7461 prgpvarg[i] = src_arg;
7464 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7465 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7466 && V_UNKNOWN(prgpvarg[i])) {
7467 IUnknown *userdefined_iface;
7468 GUID guid;
7470 if (tdesc->vt == VT_PTR)
7471 tdesc = tdesc->u.lptdesc;
7473 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7474 if(FAILED(hres))
7475 break;
7477 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7478 if(FAILED(hres)) {
7479 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7480 break;
7483 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7484 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7487 else if (wParamFlags & PARAMFLAG_FOPT)
7489 VARIANTARG *arg;
7490 arg = prgpvarg[i] = &rgvarg[i];
7491 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7493 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7494 if (FAILED(hres))
7495 break;
7497 else
7499 /* if the function wants a pointer to a variant then
7500 * set that up, otherwise just pass the VT_ERROR in
7501 * the argument by value */
7502 if (rgvt[i] & VT_BYREF)
7504 V_VT(&missing_arg[i]) = VT_ERROR;
7505 V_ERROR(&missing_arg[i]) = DISP_E_PARAMNOTFOUND;
7507 V_VT(arg) = VT_VARIANT | VT_BYREF;
7508 V_VARIANTREF(arg) = &missing_arg[i];
7510 else
7512 V_VT(arg) = VT_ERROR;
7513 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
7517 else
7519 hres = DISP_E_BADPARAMCOUNT;
7520 break;
7523 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7525 /* VT_VOID is a special case for return types, so it is not
7526 * handled in the general function */
7527 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7528 V_VT(&varresult) = VT_EMPTY;
7529 else
7531 V_VT(&varresult) = 0;
7532 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7533 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7536 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7537 V_VT(&varresult), func_desc->cParams, rgvt,
7538 prgpvarg, &varresult);
7540 vargs_converted = 0;
7542 for (i = 0; i < func_desc->cParams; i++)
7544 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7546 if (wParamFlags & PARAMFLAG_FLCID)
7547 continue;
7548 else if (wParamFlags & PARAMFLAG_FRETVAL)
7550 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7552 if (pVarResult)
7554 VariantInit(pVarResult);
7555 /* deref return value */
7556 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7559 VARIANT_ClearInd(prgpvarg[i]);
7561 else if (vargs_converted < pDispParams->cArgs)
7563 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7564 if (wParamFlags & PARAMFLAG_FOUT)
7566 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7568 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7570 if (FAILED(hres))
7572 ERR("failed to convert param %d to vt %d\n", i,
7573 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7574 break;
7578 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7579 func_desc->cParamsOpt < 0 &&
7580 i == func_desc->cParams-1)
7582 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7583 LONG ubound;
7584 VARIANT *v;
7585 hres = SafeArrayGetUBound(a, 1, &ubound);
7586 if (hres != S_OK)
7588 ERR("SafeArrayGetUBound failed with %x\n", hres);
7589 break;
7591 hres = SafeArrayAccessData(a, (LPVOID)&v);
7592 if (hres != S_OK)
7594 ERR("SafeArrayAccessData failed with %x\n", hres);
7595 break;
7597 for (j = 0; j <= ubound; j++)
7598 VariantClear(&v[j]);
7599 hres = SafeArrayUnaccessData(a);
7600 if (hres != S_OK)
7602 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7603 break;
7606 VariantClear(&rgvarg[i]);
7607 vargs_converted++;
7609 else if (wParamFlags & PARAMFLAG_FOPT)
7611 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7612 VariantClear(&rgvarg[i]);
7615 VariantClear(&missing_arg[i]);
7618 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7620 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7621 hres = DISP_E_EXCEPTION;
7622 if (pExcepInfo)
7624 IErrorInfo *pErrorInfo;
7625 pExcepInfo->scode = V_ERROR(&varresult);
7626 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7628 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7629 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7630 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7631 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7633 IErrorInfo_Release(pErrorInfo);
7637 if (V_VT(&varresult) != VT_ERROR)
7639 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7641 if (pVarResult)
7643 VariantClear(pVarResult);
7644 *pVarResult = varresult;
7646 else
7647 VariantClear(&varresult);
7650 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7651 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7652 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7653 (pDispParams->cArgs != 0))
7655 if (V_VT(pVarResult) == VT_DISPATCH)
7657 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7658 /* Note: not VariantClear; we still need the dispatch
7659 * pointer to be valid */
7660 VariantInit(pVarResult);
7661 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7662 GetSystemDefaultLCID(), wFlags,
7663 pDispParams, pVarResult, pExcepInfo, pArgErr);
7664 IDispatch_Release(pDispatch);
7666 else
7668 VariantClear(pVarResult);
7669 hres = DISP_E_NOTACOLLECTION;
7673 func_fail:
7674 heap_free(buffer);
7675 break;
7677 case FUNC_DISPATCH: {
7678 IDispatch *disp;
7680 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7681 if (SUCCEEDED(hres)) {
7682 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7683 hres = IDispatch_Invoke(
7684 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7685 pVarResult,pExcepInfo,pArgErr
7687 if (FAILED(hres))
7688 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7689 IDispatch_Release(disp);
7690 } else
7691 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7692 break;
7694 default:
7695 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7696 hres = E_FAIL;
7697 break;
7700 TRACE("-- 0x%08x\n", hres);
7701 return hres;
7703 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7704 VARDESC *var_desc;
7706 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7707 if(FAILED(hres)) return hres;
7709 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7710 dump_VARDESC(var_desc);
7711 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7712 return E_NOTIMPL;
7715 /* not found, look for it in inherited interfaces */
7716 ITypeInfo2_GetTypeKind(iface, &type_kind);
7717 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7718 if(This->impltypes) {
7719 /* recursive search */
7720 ITypeInfo *pTInfo;
7721 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7722 if(SUCCEEDED(hres)){
7723 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7724 ITypeInfo_Release(pTInfo);
7725 return hres;
7727 WARN("Could not search inherited interface!\n");
7730 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7731 return DISP_E_MEMBERNOTFOUND;
7734 /* ITypeInfo::GetDocumentation
7736 * Retrieves the documentation string, the complete Help file name and path,
7737 * and the context ID for the Help topic for a specified type description.
7739 * (Can be tested by the Visual Basic Editor in Word for instance.)
7741 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7742 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7743 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7745 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7746 const TLBFuncDesc *pFDesc;
7747 const TLBVarDesc *pVDesc;
7748 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7749 " HelpContext(%p) HelpFile(%p)\n",
7750 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7751 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7752 if(pBstrName)
7753 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7754 if(pBstrDocString)
7755 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7756 if(pdwHelpContext)
7757 *pdwHelpContext=This->dwHelpContext;
7758 if(pBstrHelpFile)
7759 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7760 return S_OK;
7761 }else {/* for a member */
7762 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7763 if(pFDesc){
7764 if(pBstrName)
7765 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7766 if(pBstrDocString)
7767 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7768 if(pdwHelpContext)
7769 *pdwHelpContext=pFDesc->helpcontext;
7770 if(pBstrHelpFile)
7771 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7772 return S_OK;
7774 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7775 if(pVDesc){
7776 if(pBstrName)
7777 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7778 if(pBstrDocString)
7779 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7780 if(pdwHelpContext)
7781 *pdwHelpContext=pVDesc->HelpContext;
7782 if(pBstrHelpFile)
7783 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7784 return S_OK;
7788 if(This->impltypes &&
7789 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7790 /* recursive search */
7791 ITypeInfo *pTInfo;
7792 HRESULT result;
7793 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7794 if(SUCCEEDED(result)) {
7795 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7796 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7797 ITypeInfo_Release(pTInfo);
7798 return result;
7800 WARN("Could not search inherited interface!\n");
7803 WARN("member %d not found\n", memid);
7804 return TYPE_E_ELEMENTNOTFOUND;
7807 /* ITypeInfo::GetDllEntry
7809 * Retrieves a description or specification of an entry point for a function
7810 * in a DLL.
7812 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7813 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7814 WORD *pwOrdinal)
7816 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7817 const TLBFuncDesc *pFDesc;
7819 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7821 if (pBstrDllName) *pBstrDllName = NULL;
7822 if (pBstrName) *pBstrName = NULL;
7823 if (pwOrdinal) *pwOrdinal = 0;
7825 if (This->typeattr.typekind != TKIND_MODULE)
7826 return TYPE_E_BADMODULEKIND;
7828 pFDesc = TLB_get_funcdesc_by_memberid_invkind(This, memid, invKind);
7829 if (!pFDesc) return TYPE_E_ELEMENTNOTFOUND;
7831 dump_TypeInfo(This);
7832 if (TRACE_ON(ole)) dump_TLBFuncDescOne(pFDesc);
7834 if (pBstrDllName) *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7836 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1))
7838 if (pBstrName) *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7839 if (pwOrdinal) *pwOrdinal = -1;
7841 else
7843 if (pBstrName) *pBstrName = NULL;
7844 if (pwOrdinal) *pwOrdinal = LOWORD(pFDesc->Entry);
7846 return S_OK;
7849 /* internal function to make the inherited interfaces' methods appear
7850 * part of the interface */
7851 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7852 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7854 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7855 HRESULT hr;
7857 TRACE("%p, 0x%x\n", iface, *hRefType);
7859 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7861 ITypeInfo *pSubTypeInfo;
7863 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7864 if (FAILED(hr))
7865 return hr;
7867 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7868 hRefType, ppTInfo);
7869 ITypeInfo_Release(pSubTypeInfo);
7870 if (SUCCEEDED(hr))
7871 return hr;
7873 *hRefType -= DISPATCH_HREF_OFFSET;
7875 if (!(*hRefType & DISPATCH_HREF_MASK))
7876 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7877 else
7878 return E_FAIL;
7881 /* ITypeInfo::GetRefTypeInfo
7883 * If a type description references other type descriptions, it retrieves
7884 * the referenced type descriptions.
7886 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7887 ITypeInfo2 *iface,
7888 HREFTYPE hRefType,
7889 ITypeInfo **ppTInfo)
7891 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7892 ITypeInfo *type_info = NULL;
7893 HRESULT result = E_FAIL;
7894 TLBRefType *ref_type;
7895 UINT i;
7897 if(!ppTInfo)
7898 return E_INVALIDARG;
7900 if ((INT)hRefType < 0) {
7901 ITypeInfoImpl *pTypeInfoImpl;
7903 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7904 !(This->typeattr.typekind == TKIND_INTERFACE ||
7905 This->typeattr.typekind == TKIND_DISPATCH))
7906 return TYPE_E_ELEMENTNOTFOUND;
7908 /* when we meet a DUAL typeinfo, we must create the alternate
7909 * version of it.
7911 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7913 *pTypeInfoImpl = *This;
7914 pTypeInfoImpl->ref = 0;
7915 list_init(&pTypeInfoImpl->custdata_list);
7917 if (This->typeattr.typekind == TKIND_INTERFACE)
7918 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7919 else
7920 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7922 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7923 /* the AddRef implicitly adds a reference to the parent typelib, which
7924 * stops the copied data from being destroyed until the new typeinfo's
7925 * refcount goes to zero, but we need to signal to the new instance to
7926 * not free its data structures when it is destroyed */
7927 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7928 ITypeInfo_AddRef(*ppTInfo);
7930 TRACE("got dual interface %p\n", *ppTInfo);
7931 return S_OK;
7934 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7935 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7937 if(!(hRefType & 0x1))
7939 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7941 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7943 result = S_OK;
7944 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7945 ITypeInfo_AddRef(type_info);
7946 break;
7951 if (!type_info)
7953 ITypeLib *pTLib = NULL;
7955 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7957 if(ref_type->reference == (hRefType & (~0x3)))
7958 break;
7960 if(&ref_type->entry == &This->pTypeLib->ref_list)
7962 FIXME("Can't find pRefType for ref %x\n", hRefType);
7963 return E_FAIL;
7966 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7967 UINT Index;
7968 TRACE("internal reference\n");
7969 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7970 } else {
7971 if(ref_type->pImpTLInfo->pImpTypeLib) {
7972 TRACE("typeinfo in imported typelib that is already loaded\n");
7973 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7974 ITypeLib_AddRef(pTLib);
7975 result = S_OK;
7976 } else {
7977 /* Search in cached typelibs */
7978 ITypeLibImpl *entry;
7980 EnterCriticalSection(&cache_section);
7981 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
7983 if (entry->guid
7984 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
7985 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
7986 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
7987 && entry->set_lcid == ref_type->pImpTLInfo->lcid)
7989 TRACE("got cached %p\n", entry);
7990 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
7991 ITypeLib_AddRef(pTLib);
7992 result = S_OK;
7993 break;
7996 LeaveCriticalSection(&cache_section);
7998 if (!pTLib)
8000 BSTR libnam;
8002 /* Search on disk */
8003 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
8004 ref_type->pImpTLInfo->wVersionMajor,
8005 ref_type->pImpTLInfo->wVersionMinor,
8006 This->pTypeLib->syskind,
8007 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
8008 if (FAILED(result))
8009 libnam = SysAllocString(ref_type->pImpTLInfo->name);
8011 result = LoadTypeLib(libnam, &pTLib);
8012 SysFreeString(libnam);
8015 if(SUCCEEDED(result)) {
8016 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
8017 ITypeLib_AddRef(pTLib);
8021 if(SUCCEEDED(result)) {
8022 if(ref_type->index == TLB_REF_USE_GUID)
8023 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
8024 else
8025 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
8027 if (pTLib != NULL)
8028 ITypeLib_Release(pTLib);
8029 if (FAILED(result))
8031 WARN("(%p) failed hreftype 0x%04x\n", This, hRefType);
8032 return result;
8036 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
8037 ITypeInfo_Release(type_info);
8038 else *ppTInfo = type_info;
8040 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
8041 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8042 return result;
8045 /* ITypeInfo::AddressOfMember
8047 * Retrieves the addresses of static functions or variables, such as those
8048 * defined in a DLL.
8050 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8051 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8053 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8054 HRESULT hr;
8055 BSTR dll, entry;
8056 WORD ordinal;
8057 HMODULE module;
8059 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
8061 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8062 if (FAILED(hr))
8063 return hr;
8065 module = LoadLibraryW(dll);
8066 if (!module)
8068 ERR("couldn't load %s\n", debugstr_w(dll));
8069 SysFreeString(dll);
8070 SysFreeString(entry);
8071 return STG_E_FILENOTFOUND;
8073 /* FIXME: store library somewhere where we can free it */
8075 if (entry)
8077 LPSTR entryA;
8078 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8079 entryA = heap_alloc(len);
8080 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8082 *ppv = GetProcAddress(module, entryA);
8083 if (!*ppv)
8084 ERR("function not found %s\n", debugstr_a(entryA));
8086 heap_free(entryA);
8088 else
8090 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8091 if (!*ppv)
8092 ERR("function not found %d\n", ordinal);
8095 SysFreeString(dll);
8096 SysFreeString(entry);
8098 if (!*ppv)
8099 return TYPE_E_DLLFUNCTIONNOTFOUND;
8101 return S_OK;
8104 /* ITypeInfo::CreateInstance
8106 * Creates a new instance of a type that describes a component object class
8107 * (coclass).
8109 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8110 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8112 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8113 HRESULT hr;
8114 TYPEATTR *pTA;
8116 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8118 *ppvObj = NULL;
8120 if(pOuterUnk)
8122 WARN("Not able to aggregate\n");
8123 return CLASS_E_NOAGGREGATION;
8126 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8127 if(FAILED(hr)) return hr;
8129 if(pTA->typekind != TKIND_COCLASS)
8131 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8132 hr = E_INVALIDARG;
8133 goto end;
8136 hr = S_FALSE;
8137 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8139 IUnknown *pUnk;
8140 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8141 TRACE("GetActiveObject rets %08x\n", hr);
8142 if(hr == S_OK)
8144 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8145 IUnknown_Release(pUnk);
8149 if(hr != S_OK)
8150 hr = CoCreateInstance(&pTA->guid, NULL,
8151 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8152 riid, ppvObj);
8154 end:
8155 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8156 return hr;
8159 /* ITypeInfo::GetMops
8161 * Retrieves marshalling information.
8163 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8164 BSTR *pBstrMops)
8166 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8167 FIXME("(%p %d) stub!\n", This, memid);
8168 *pBstrMops = NULL;
8169 return S_OK;
8172 /* ITypeInfo::GetContainingTypeLib
8174 * Retrieves the containing type library and the index of the type description
8175 * within that type library.
8177 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8178 ITypeLib * *ppTLib, UINT *pIndex)
8180 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8182 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8183 if (pIndex) {
8184 *pIndex=This->index;
8185 TRACE("returning pIndex=%d\n", *pIndex);
8188 if (ppTLib) {
8189 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8190 ITypeLib_AddRef(*ppTLib);
8191 TRACE("returning ppTLib=%p\n", *ppTLib);
8194 return S_OK;
8197 /* ITypeInfo::ReleaseTypeAttr
8199 * Releases a TYPEATTR previously returned by Get
8202 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8203 TYPEATTR* pTypeAttr)
8205 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8206 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8207 heap_free(pTypeAttr);
8210 /* ITypeInfo::ReleaseFuncDesc
8212 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8214 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8215 ITypeInfo2 *iface,
8216 FUNCDESC *pFuncDesc)
8218 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8219 SHORT i;
8221 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8223 for (i = 0; i < pFuncDesc->cParams; i++)
8224 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8225 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8227 SysFreeString((BSTR)pFuncDesc);
8230 /* ITypeInfo::ReleaseVarDesc
8232 * Releases a VARDESC previously returned by GetVarDesc.
8234 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8235 VARDESC *pVarDesc)
8237 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8238 TRACE("(%p)->(%p)\n", This, pVarDesc);
8240 TLB_FreeVarDesc(pVarDesc);
8243 /* ITypeInfo2::GetTypeKind
8245 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8248 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8249 TYPEKIND *pTypeKind)
8251 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8252 *pTypeKind = This->typeattr.typekind;
8253 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8254 return S_OK;
8257 /* ITypeInfo2::GetTypeFlags
8259 * Returns the type flags without any allocations. This returns a DWORD type
8260 * flag, which expands the type flags without growing the TYPEATTR (type
8261 * attribute).
8264 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8266 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8267 *pTypeFlags=This->typeattr.wTypeFlags;
8268 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8269 return S_OK;
8272 /* ITypeInfo2::GetFuncIndexOfMemId
8273 * Binds to a specific member based on a known DISPID, where the member name
8274 * is not known (for example, when binding to a default member).
8277 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8278 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8280 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8281 UINT fdc;
8282 HRESULT result;
8284 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8285 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8286 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8287 break;
8289 if(fdc < This->typeattr.cFuncs) {
8290 *pFuncIndex = fdc;
8291 result = S_OK;
8292 } else
8293 result = TYPE_E_ELEMENTNOTFOUND;
8295 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8296 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8297 return result;
8300 /* TypeInfo2::GetVarIndexOfMemId
8302 * Binds to a specific member based on a known DISPID, where the member name
8303 * is not known (for example, when binding to a default member).
8306 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8307 MEMBERID memid, UINT *pVarIndex)
8309 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8310 TLBVarDesc *pVarInfo;
8312 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8314 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8315 if(!pVarInfo)
8316 return TYPE_E_ELEMENTNOTFOUND;
8318 *pVarIndex = (pVarInfo - This->vardescs);
8320 return S_OK;
8323 /* ITypeInfo2::GetCustData
8325 * Gets the custom data
8327 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8328 ITypeInfo2 * iface,
8329 REFGUID guid,
8330 VARIANT *pVarVal)
8332 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8333 TLBCustData *pCData;
8335 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8337 if(!guid || !pVarVal)
8338 return E_INVALIDARG;
8340 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8342 VariantInit( pVarVal);
8343 if (pCData)
8344 VariantCopy( pVarVal, &pCData->data);
8345 else
8346 VariantClear( pVarVal );
8347 return S_OK;
8350 /* ITypeInfo2::GetFuncCustData
8352 * Gets the custom data
8354 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8355 ITypeInfo2 * iface,
8356 UINT index,
8357 REFGUID guid,
8358 VARIANT *pVarVal)
8360 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8361 const TLBFuncDesc *desc;
8362 TLBCustData *data;
8363 UINT hrefoffset;
8364 HRESULT hr;
8366 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8368 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8369 if (FAILED(hr))
8371 WARN("description for function %d not found\n", index);
8372 return hr;
8375 VariantInit(pVarVal);
8376 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8377 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8380 /* ITypeInfo2::GetParamCustData
8382 * Gets the custom data
8384 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8385 ITypeInfo2 * iface,
8386 UINT indexFunc,
8387 UINT indexParam,
8388 REFGUID guid,
8389 VARIANT *pVarVal)
8391 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8392 const TLBFuncDesc *pFDesc;
8393 TLBCustData *pCData;
8394 UINT hrefoffset;
8395 HRESULT hr;
8397 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8398 debugstr_guid(guid), pVarVal);
8400 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8401 if (FAILED(hr))
8402 return hr;
8404 if(indexParam >= pFDesc->funcdesc.cParams)
8405 return TYPE_E_ELEMENTNOTFOUND;
8407 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8408 if(!pCData)
8409 return TYPE_E_ELEMENTNOTFOUND;
8411 VariantInit(pVarVal);
8412 VariantCopy(pVarVal, &pCData->data);
8414 return S_OK;
8417 /* ITypeInfo2::GetVarCustData
8419 * Gets the custom data
8421 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8422 ITypeInfo2 * iface,
8423 UINT index,
8424 REFGUID guid,
8425 VARIANT *pVarVal)
8427 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8428 TLBCustData *pCData;
8429 TLBVarDesc *pVDesc = &This->vardescs[index];
8431 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8433 if(index >= This->typeattr.cVars)
8434 return TYPE_E_ELEMENTNOTFOUND;
8436 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8437 if(!pCData)
8438 return TYPE_E_ELEMENTNOTFOUND;
8440 VariantInit(pVarVal);
8441 VariantCopy(pVarVal, &pCData->data);
8443 return S_OK;
8446 /* ITypeInfo2::GetImplCustData
8448 * Gets the custom data
8450 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8451 ITypeInfo2 * iface,
8452 UINT index,
8453 REFGUID guid,
8454 VARIANT *pVarVal)
8456 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8457 TLBCustData *pCData;
8458 TLBImplType *pRDesc = &This->impltypes[index];
8460 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8462 if(index >= This->typeattr.cImplTypes)
8463 return TYPE_E_ELEMENTNOTFOUND;
8465 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8466 if(!pCData)
8467 return TYPE_E_ELEMENTNOTFOUND;
8469 VariantInit(pVarVal);
8470 VariantCopy(pVarVal, &pCData->data);
8472 return S_OK;
8475 /* ITypeInfo2::GetDocumentation2
8477 * Retrieves the documentation string, the complete Help file name and path,
8478 * the localization context to use, and the context ID for the library Help
8479 * topic in the Help file.
8482 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8483 ITypeInfo2 * iface,
8484 MEMBERID memid,
8485 LCID lcid,
8486 BSTR *pbstrHelpString,
8487 DWORD *pdwHelpStringContext,
8488 BSTR *pbstrHelpStringDll)
8490 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8491 const TLBFuncDesc *pFDesc;
8492 const TLBVarDesc *pVDesc;
8493 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8494 "HelpStringContext(%p) HelpStringDll(%p)\n",
8495 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8496 pbstrHelpStringDll );
8497 /* the help string should be obtained from the helpstringdll,
8498 * using the _DLLGetDocumentation function, based on the supplied
8499 * lcid. Nice to do sometime...
8501 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8502 if(pbstrHelpString)
8503 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8504 if(pdwHelpStringContext)
8505 *pdwHelpStringContext=This->dwHelpStringContext;
8506 if(pbstrHelpStringDll)
8507 *pbstrHelpStringDll=
8508 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8509 return S_OK;
8510 }else {/* for a member */
8511 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8512 if(pFDesc){
8513 if(pbstrHelpString)
8514 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8515 if(pdwHelpStringContext)
8516 *pdwHelpStringContext=pFDesc->HelpStringContext;
8517 if(pbstrHelpStringDll)
8518 *pbstrHelpStringDll=
8519 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8520 return S_OK;
8522 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8523 if(pVDesc){
8524 if(pbstrHelpString)
8525 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8526 if(pdwHelpStringContext)
8527 *pdwHelpStringContext=pVDesc->HelpStringContext;
8528 if(pbstrHelpStringDll)
8529 *pbstrHelpStringDll=
8530 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8531 return S_OK;
8534 return TYPE_E_ELEMENTNOTFOUND;
8537 /* ITypeInfo2::GetAllCustData
8539 * Gets all custom data items for the Type info.
8542 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8543 ITypeInfo2 * iface,
8544 CUSTDATA *pCustData)
8546 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8548 TRACE("%p %p\n", This, pCustData);
8550 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8553 /* ITypeInfo2::GetAllFuncCustData
8555 * Gets all custom data items for the specified Function
8558 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8559 ITypeInfo2 * iface,
8560 UINT index,
8561 CUSTDATA *pCustData)
8563 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8564 const TLBFuncDesc *pFDesc;
8565 UINT hrefoffset;
8566 HRESULT hr;
8568 TRACE("%p %u %p\n", This, index, pCustData);
8570 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8571 if (FAILED(hr))
8572 return hr;
8574 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8577 /* ITypeInfo2::GetAllParamCustData
8579 * Gets all custom data items for the Functions
8582 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8583 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8585 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8586 const TLBFuncDesc *pFDesc;
8587 UINT hrefoffset;
8588 HRESULT hr;
8590 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8592 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8593 if (FAILED(hr))
8594 return hr;
8596 if(indexParam >= pFDesc->funcdesc.cParams)
8597 return TYPE_E_ELEMENTNOTFOUND;
8599 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8602 /* ITypeInfo2::GetAllVarCustData
8604 * Gets all custom data items for the specified Variable
8607 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8608 UINT index, CUSTDATA *pCustData)
8610 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8611 TLBVarDesc * pVDesc = &This->vardescs[index];
8613 TRACE("%p %u %p\n", This, index, pCustData);
8615 if(index >= This->typeattr.cVars)
8616 return TYPE_E_ELEMENTNOTFOUND;
8618 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8621 /* ITypeInfo2::GetAllImplCustData
8623 * Gets all custom data items for the specified implementation type
8626 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8627 ITypeInfo2 * iface,
8628 UINT index,
8629 CUSTDATA *pCustData)
8631 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8632 TLBImplType *pRDesc = &This->impltypes[index];
8634 TRACE("%p %u %p\n", This, index, pCustData);
8636 if(index >= This->typeattr.cImplTypes)
8637 return TYPE_E_ELEMENTNOTFOUND;
8639 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8642 static const ITypeInfo2Vtbl tinfvt =
8645 ITypeInfo_fnQueryInterface,
8646 ITypeInfo_fnAddRef,
8647 ITypeInfo_fnRelease,
8649 ITypeInfo_fnGetTypeAttr,
8650 ITypeInfo_fnGetTypeComp,
8651 ITypeInfo_fnGetFuncDesc,
8652 ITypeInfo_fnGetVarDesc,
8653 ITypeInfo_fnGetNames,
8654 ITypeInfo_fnGetRefTypeOfImplType,
8655 ITypeInfo_fnGetImplTypeFlags,
8656 ITypeInfo_fnGetIDsOfNames,
8657 ITypeInfo_fnInvoke,
8658 ITypeInfo_fnGetDocumentation,
8659 ITypeInfo_fnGetDllEntry,
8660 ITypeInfo_fnGetRefTypeInfo,
8661 ITypeInfo_fnAddressOfMember,
8662 ITypeInfo_fnCreateInstance,
8663 ITypeInfo_fnGetMops,
8664 ITypeInfo_fnGetContainingTypeLib,
8665 ITypeInfo_fnReleaseTypeAttr,
8666 ITypeInfo_fnReleaseFuncDesc,
8667 ITypeInfo_fnReleaseVarDesc,
8669 ITypeInfo2_fnGetTypeKind,
8670 ITypeInfo2_fnGetTypeFlags,
8671 ITypeInfo2_fnGetFuncIndexOfMemId,
8672 ITypeInfo2_fnGetVarIndexOfMemId,
8673 ITypeInfo2_fnGetCustData,
8674 ITypeInfo2_fnGetFuncCustData,
8675 ITypeInfo2_fnGetParamCustData,
8676 ITypeInfo2_fnGetVarCustData,
8677 ITypeInfo2_fnGetImplTypeCustData,
8678 ITypeInfo2_fnGetDocumentation2,
8679 ITypeInfo2_fnGetAllCustData,
8680 ITypeInfo2_fnGetAllFuncCustData,
8681 ITypeInfo2_fnGetAllParamCustData,
8682 ITypeInfo2_fnGetAllVarCustData,
8683 ITypeInfo2_fnGetAllImplTypeCustData,
8686 /******************************************************************************
8687 * CreateDispTypeInfo [OLEAUT32.31]
8689 * Build type information for an object so it can be called through an
8690 * IDispatch interface.
8692 * RETURNS
8693 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8694 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8696 * NOTES
8697 * This call allows an objects methods to be accessed through IDispatch, by
8698 * building an ITypeInfo object that IDispatch can use to call through.
8700 HRESULT WINAPI CreateDispTypeInfo(
8701 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8702 LCID lcid, /* [I] Locale Id */
8703 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8705 ITypeInfoImpl *pTIClass, *pTIIface;
8706 ITypeLibImpl *pTypeLibImpl;
8707 unsigned int param, func;
8708 TLBFuncDesc *pFuncDesc;
8709 TLBRefType *ref;
8711 TRACE("\n");
8712 pTypeLibImpl = TypeLibImpl_Constructor();
8713 if (!pTypeLibImpl) return E_FAIL;
8715 pTypeLibImpl->TypeInfoCount = 2;
8716 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8718 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8719 pTIIface->pTypeLib = pTypeLibImpl;
8720 pTIIface->index = 0;
8721 pTIIface->Name = NULL;
8722 pTIIface->dwHelpContext = -1;
8723 pTIIface->guid = NULL;
8724 pTIIface->typeattr.lcid = lcid;
8725 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8726 pTIIface->typeattr.wMajorVerNum = 0;
8727 pTIIface->typeattr.wMinorVerNum = 0;
8728 pTIIface->typeattr.cbAlignment = 2;
8729 pTIIface->typeattr.cbSizeInstance = -1;
8730 pTIIface->typeattr.cbSizeVft = -1;
8731 pTIIface->typeattr.cFuncs = 0;
8732 pTIIface->typeattr.cImplTypes = 0;
8733 pTIIface->typeattr.cVars = 0;
8734 pTIIface->typeattr.wTypeFlags = 0;
8735 pTIIface->hreftype = 0;
8737 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8738 pFuncDesc = pTIIface->funcdescs;
8739 for(func = 0; func < pidata->cMembers; func++) {
8740 METHODDATA *md = pidata->pmethdata + func;
8741 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8742 pFuncDesc->funcdesc.memid = md->dispid;
8743 pFuncDesc->funcdesc.lprgscode = NULL;
8744 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8745 pFuncDesc->funcdesc.invkind = md->wFlags;
8746 pFuncDesc->funcdesc.callconv = md->cc;
8747 pFuncDesc->funcdesc.cParams = md->cArgs;
8748 pFuncDesc->funcdesc.cParamsOpt = 0;
8749 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8750 pFuncDesc->funcdesc.cScodes = 0;
8751 pFuncDesc->funcdesc.wFuncFlags = 0;
8752 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8753 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8754 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8755 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8756 md->cArgs * sizeof(ELEMDESC));
8757 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8758 for(param = 0; param < md->cArgs; param++) {
8759 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8760 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8762 pFuncDesc->helpcontext = 0;
8763 pFuncDesc->HelpStringContext = 0;
8764 pFuncDesc->HelpString = NULL;
8765 pFuncDesc->Entry = NULL;
8766 list_init(&pFuncDesc->custdata_list);
8767 pTIIface->typeattr.cFuncs++;
8768 ++pFuncDesc;
8771 dump_TypeInfo(pTIIface);
8773 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8774 pTIClass->pTypeLib = pTypeLibImpl;
8775 pTIClass->index = 1;
8776 pTIClass->Name = NULL;
8777 pTIClass->dwHelpContext = -1;
8778 pTIClass->guid = NULL;
8779 pTIClass->typeattr.lcid = lcid;
8780 pTIClass->typeattr.typekind = TKIND_COCLASS;
8781 pTIClass->typeattr.wMajorVerNum = 0;
8782 pTIClass->typeattr.wMinorVerNum = 0;
8783 pTIClass->typeattr.cbAlignment = 2;
8784 pTIClass->typeattr.cbSizeInstance = -1;
8785 pTIClass->typeattr.cbSizeVft = -1;
8786 pTIClass->typeattr.cFuncs = 0;
8787 pTIClass->typeattr.cImplTypes = 1;
8788 pTIClass->typeattr.cVars = 0;
8789 pTIClass->typeattr.wTypeFlags = 0;
8790 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8792 pTIClass->impltypes = TLBImplType_Alloc(1);
8794 ref = heap_alloc_zero(sizeof(*ref));
8795 ref->pImpTLInfo = TLB_REF_INTERNAL;
8796 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8798 dump_TypeInfo(pTIClass);
8800 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8802 ITypeInfo_AddRef(*pptinfo);
8803 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8805 return S_OK;
8809 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8811 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8813 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8816 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8818 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8820 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8823 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8825 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8827 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8830 static HRESULT WINAPI ITypeComp_fnBind(
8831 ITypeComp * iface,
8832 OLECHAR * szName,
8833 ULONG lHash,
8834 WORD wFlags,
8835 ITypeInfo ** ppTInfo,
8836 DESCKIND * pDescKind,
8837 BINDPTR * pBindPtr)
8839 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8840 const TLBFuncDesc *pFDesc;
8841 const TLBVarDesc *pVDesc;
8842 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8843 UINT fdc;
8845 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8847 *pDescKind = DESCKIND_NONE;
8848 pBindPtr->lpfuncdesc = NULL;
8849 *ppTInfo = NULL;
8851 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8852 pFDesc = &This->funcdescs[fdc];
8853 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8854 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8855 break;
8856 else
8857 /* name found, but wrong flags */
8858 hr = TYPE_E_TYPEMISMATCH;
8862 if (fdc < This->typeattr.cFuncs)
8864 HRESULT hr = TLB_AllocAndInitFuncDesc(
8865 &pFDesc->funcdesc,
8866 &pBindPtr->lpfuncdesc,
8867 This->typeattr.typekind == TKIND_DISPATCH);
8868 if (FAILED(hr))
8869 return hr;
8870 *pDescKind = DESCKIND_FUNCDESC;
8871 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8872 ITypeInfo_AddRef(*ppTInfo);
8873 return S_OK;
8874 } else {
8875 pVDesc = TLB_get_vardesc_by_name(This, szName);
8876 if(pVDesc){
8877 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8878 if (FAILED(hr))
8879 return hr;
8880 *pDescKind = DESCKIND_VARDESC;
8881 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8882 ITypeInfo_AddRef(*ppTInfo);
8883 return S_OK;
8887 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8888 /* recursive search */
8889 ITypeInfo *pTInfo;
8890 ITypeComp *pTComp;
8891 HRESULT hr;
8892 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8893 if (SUCCEEDED(hr))
8895 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8896 ITypeInfo_Release(pTInfo);
8898 if (SUCCEEDED(hr))
8900 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8901 ITypeComp_Release(pTComp);
8902 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8903 This->typeattr.typekind == TKIND_DISPATCH)
8905 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8906 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8907 SysFreeString((BSTR)tmp);
8909 return hr;
8911 WARN("Could not search inherited interface!\n");
8913 if (hr == DISP_E_MEMBERNOTFOUND)
8914 hr = S_OK;
8915 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8916 return hr;
8919 static HRESULT WINAPI ITypeComp_fnBindType(
8920 ITypeComp * iface,
8921 OLECHAR * szName,
8922 ULONG lHash,
8923 ITypeInfo ** ppTInfo,
8924 ITypeComp ** ppTComp)
8926 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8928 /* strange behaviour (does nothing) but like the
8929 * original */
8931 if (!ppTInfo || !ppTComp)
8932 return E_POINTER;
8934 *ppTInfo = NULL;
8935 *ppTComp = NULL;
8937 return S_OK;
8940 static const ITypeCompVtbl tcompvt =
8943 ITypeComp_fnQueryInterface,
8944 ITypeComp_fnAddRef,
8945 ITypeComp_fnRelease,
8947 ITypeComp_fnBind,
8948 ITypeComp_fnBindType
8951 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8952 ICreateTypeLib2** ppctlib)
8954 ITypeLibImpl *This;
8955 HRESULT hres;
8957 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8959 if (!szFile) return E_INVALIDARG;
8961 This = TypeLibImpl_Constructor();
8962 if (!This)
8963 return E_OUTOFMEMORY;
8965 This->lcid = GetSystemDefaultLCID();
8966 This->syskind = syskind;
8967 This->ptr_size = get_ptr_size(syskind);
8969 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8970 if (!This->path) {
8971 ITypeLib2_Release(&This->ITypeLib2_iface);
8972 return E_OUTOFMEMORY;
8974 lstrcpyW(This->path, szFile);
8976 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8977 ITypeLib2_Release(&This->ITypeLib2_iface);
8978 return hres;
8981 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8982 REFIID riid, void **object)
8984 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8986 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8989 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8991 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8993 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8996 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8998 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9000 return ITypeLib2_Release(&This->ITypeLib2_iface);
9003 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
9004 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
9006 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9007 ITypeInfoImpl *info;
9008 HRESULT hres;
9010 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
9012 if (!ctinfo || !name)
9013 return E_INVALIDARG;
9015 info = TLB_get_typeinfo_by_name(This, name);
9016 if (info)
9017 return TYPE_E_NAMECONFLICT;
9019 if (This->typeinfos)
9020 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
9021 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
9022 else
9023 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
9025 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
9027 info->pTypeLib = This;
9028 info->Name = TLB_append_str(&This->name_list, name);
9029 info->index = This->TypeInfoCount;
9030 info->typeattr.typekind = kind;
9031 info->typeattr.cbAlignment = 4;
9033 switch (info->typeattr.typekind) {
9034 case TKIND_ENUM:
9035 case TKIND_INTERFACE:
9036 case TKIND_DISPATCH:
9037 case TKIND_COCLASS:
9038 info->typeattr.cbSizeInstance = This->ptr_size;
9039 break;
9040 case TKIND_RECORD:
9041 case TKIND_UNION:
9042 info->typeattr.cbSizeInstance = 0;
9043 break;
9044 case TKIND_MODULE:
9045 info->typeattr.cbSizeInstance = 2;
9046 break;
9047 case TKIND_ALIAS:
9048 info->typeattr.cbSizeInstance = -0x75;
9049 break;
9050 default:
9051 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9052 info->typeattr.cbSizeInstance = 0xdeadbeef;
9053 break;
9056 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9057 &IID_ICreateTypeInfo, (void **)ctinfo);
9058 if (FAILED(hres)) {
9059 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9060 return hres;
9063 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9065 ++This->TypeInfoCount;
9067 return S_OK;
9070 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9071 LPOLESTR name)
9073 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9075 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9077 if (!name)
9078 return E_INVALIDARG;
9080 This->Name = TLB_append_str(&This->name_list, name);
9082 return S_OK;
9085 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9086 WORD majorVerNum, WORD minorVerNum)
9088 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9090 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9092 This->ver_major = majorVerNum;
9093 This->ver_minor = minorVerNum;
9095 return S_OK;
9098 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9099 REFGUID guid)
9101 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9103 TRACE("%p %s\n", This, debugstr_guid(guid));
9105 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9107 return S_OK;
9110 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9111 LPOLESTR doc)
9113 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9115 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9117 if (!doc)
9118 return E_INVALIDARG;
9120 This->DocString = TLB_append_str(&This->string_list, doc);
9122 return S_OK;
9125 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9126 LPOLESTR helpFileName)
9128 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9130 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9132 if (!helpFileName)
9133 return E_INVALIDARG;
9135 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9137 return S_OK;
9140 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9141 DWORD helpContext)
9143 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9145 TRACE("%p %d\n", This, helpContext);
9147 This->dwHelpContext = helpContext;
9149 return S_OK;
9152 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9153 LCID lcid)
9155 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9157 TRACE("%p %x\n", This, lcid);
9159 This->set_lcid = lcid;
9161 return S_OK;
9164 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9165 UINT libFlags)
9167 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9169 TRACE("%p %x\n", This, libFlags);
9171 This->libflags = libFlags;
9173 return S_OK;
9176 typedef struct tagWMSFT_SegContents {
9177 DWORD len;
9178 void *data;
9179 } WMSFT_SegContents;
9181 typedef struct tagWMSFT_TLBFile {
9182 MSFT_Header header;
9183 WMSFT_SegContents typeinfo_seg;
9184 WMSFT_SegContents impfile_seg;
9185 WMSFT_SegContents impinfo_seg;
9186 WMSFT_SegContents ref_seg;
9187 WMSFT_SegContents guidhash_seg;
9188 WMSFT_SegContents guid_seg;
9189 WMSFT_SegContents namehash_seg;
9190 WMSFT_SegContents name_seg;
9191 WMSFT_SegContents string_seg;
9192 WMSFT_SegContents typdesc_seg;
9193 WMSFT_SegContents arraydesc_seg;
9194 WMSFT_SegContents custdata_seg;
9195 WMSFT_SegContents cdguids_seg;
9196 MSFT_SegDir segdir;
9197 WMSFT_SegContents aux_seg;
9198 } WMSFT_TLBFile;
9200 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9201 WMSFT_TLBFile *file)
9203 TLBString *str;
9204 UINT last_offs;
9205 char *data;
9207 file->string_seg.len = 0;
9208 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9209 int size;
9211 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9212 if (size == 0)
9213 return E_UNEXPECTED;
9215 size += sizeof(INT16);
9216 if (size % 4)
9217 size = (size + 4) & ~0x3;
9218 if (size < 8)
9219 size = 8;
9221 file->string_seg.len += size;
9223 /* temporarily use str->offset to store the length of the aligned,
9224 * converted string */
9225 str->offset = size;
9228 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9230 last_offs = 0;
9231 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9232 int size;
9234 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9235 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9236 if (size == 0) {
9237 heap_free(file->string_seg.data);
9238 return E_UNEXPECTED;
9241 *((INT16*)data) = size;
9243 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9245 size = str->offset;
9246 data += size;
9247 str->offset = last_offs;
9248 last_offs += size;
9251 return S_OK;
9254 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9255 WMSFT_TLBFile *file)
9257 TLBString *str;
9258 UINT last_offs;
9259 char *data;
9260 MSFT_NameIntro *last_intro = NULL;
9262 file->header.nametablecount = 0;
9263 file->header.nametablechars = 0;
9265 file->name_seg.len = 0;
9266 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9267 int size;
9269 size = lstrlenW(str->str);
9270 file->header.nametablechars += size;
9271 file->header.nametablecount++;
9273 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9274 if (size == 0)
9275 return E_UNEXPECTED;
9277 size += sizeof(MSFT_NameIntro);
9278 if (size % 4)
9279 size = (size + 4) & ~0x3;
9280 if (size < 8)
9281 size = 8;
9283 file->name_seg.len += size;
9285 /* temporarily use str->offset to store the length of the aligned,
9286 * converted string */
9287 str->offset = size;
9290 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9291 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9293 last_offs = 0;
9294 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9295 int size, hash;
9296 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9298 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9299 data + sizeof(MSFT_NameIntro),
9300 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9301 if (size == 0) {
9302 heap_free(file->name_seg.data);
9303 return E_UNEXPECTED;
9305 data[sizeof(MSFT_NameIntro) + size] = '\0';
9307 intro->hreftype = -1; /* TODO? */
9308 intro->namelen = size & 0xFF;
9309 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9310 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9311 intro->namelen |= hash << 16;
9312 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9313 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9315 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9316 str->offset - size - sizeof(MSFT_NameIntro));
9318 /* update str->offset to actual value to use in other
9319 * compilation functions that require positions within
9320 * the string table */
9321 last_intro = intro;
9322 size = str->offset;
9323 data += size;
9324 str->offset = last_offs;
9325 last_offs += size;
9328 if(last_intro)
9329 last_intro->hreftype = 0; /* last one is 0? */
9331 return S_OK;
9334 static inline int hash_guid(GUID *guid)
9336 int i, hash = 0;
9338 for (i = 0; i < 8; i ++)
9339 hash ^= ((const short *)guid)[i];
9341 return hash & 0x1f;
9344 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9346 TLBGuid *guid;
9347 MSFT_GuidEntry *entry;
9348 DWORD offs;
9349 int hash_key, *guidhashtab;
9351 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9352 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9354 entry = file->guid_seg.data;
9355 offs = 0;
9356 guidhashtab = file->guidhash_seg.data;
9357 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9358 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9359 entry->hreftype = guid->hreftype;
9361 hash_key = hash_guid(&guid->guid);
9362 entry->next_hash = guidhashtab[hash_key];
9363 guidhashtab[hash_key] = offs;
9365 guid->offset = offs;
9366 offs += sizeof(MSFT_GuidEntry);
9367 ++entry;
9370 return S_OK;
9373 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9375 VARIANT v = *value;
9376 VARTYPE arg_type = V_VT(value);
9377 int mask = 0;
9378 HRESULT hres;
9379 DWORD ret = file->custdata_seg.len;
9381 if(arg_type == VT_INT)
9382 arg_type = VT_I4;
9383 if(arg_type == VT_UINT)
9384 arg_type = VT_UI4;
9386 v = *value;
9387 if(V_VT(value) != arg_type) {
9388 hres = VariantChangeType(&v, value, 0, arg_type);
9389 if(FAILED(hres)){
9390 ERR("VariantChangeType failed: %08x\n", hres);
9391 return -1;
9395 /* Check if default value can be stored in-place */
9396 switch(arg_type){
9397 case VT_I4:
9398 case VT_UI4:
9399 mask = 0x3ffffff;
9400 if(V_UI4(&v) > 0x3ffffff)
9401 break;
9402 /* fall through */
9403 case VT_I1:
9404 case VT_UI1:
9405 case VT_BOOL:
9406 if(!mask)
9407 mask = 0xff;
9408 /* fall through */
9409 case VT_I2:
9410 case VT_UI2:
9411 if(!mask)
9412 mask = 0xffff;
9413 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9416 /* have to allocate space in custdata_seg */
9417 switch(arg_type) {
9418 case VT_I4:
9419 case VT_R4:
9420 case VT_UI4:
9421 case VT_INT:
9422 case VT_UINT:
9423 case VT_HRESULT:
9424 case VT_PTR: {
9425 /* Construct the data to be allocated */
9426 int *data;
9428 if(file->custdata_seg.data){
9429 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9430 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9431 file->custdata_seg.len += sizeof(int) * 2;
9432 }else{
9433 file->custdata_seg.len = sizeof(int) * 2;
9434 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9437 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9438 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9440 /* TODO: Check if the encoded data is already present in custdata_seg */
9442 return ret;
9445 case VT_BSTR: {
9446 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9447 char *data;
9449 if(file->custdata_seg.data){
9450 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9451 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9452 file->custdata_seg.len += len;
9453 }else{
9454 file->custdata_seg.len = len;
9455 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9458 *((unsigned short *)data) = V_VT(value);
9459 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9460 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9461 if(V_BSTR(&v)[i] <= 0x7f)
9462 data[i+6] = V_BSTR(&v)[i];
9463 else
9464 data[i+6] = '?';
9466 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9467 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9468 data[i] = 0x57;
9470 /* TODO: Check if the encoded data is already present in custdata_seg */
9472 return ret;
9474 default:
9475 FIXME("Argument type not yet handled\n");
9476 return -1;
9480 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9482 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9484 DWORD offs = file->arraydesc_seg.len;
9485 DWORD *encoded;
9486 USHORT i;
9488 /* TODO: we should check for duplicates, but that's harder because each
9489 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9490 * at the library-level) */
9492 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9493 if(!file->arraydesc_seg.data)
9494 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9495 else
9496 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9497 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9499 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9500 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9501 for(i = 0; i < desc->cDims; ++i){
9502 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9503 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9506 return offs;
9509 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9511 DWORD junk;
9512 INT16 junk2;
9513 DWORD offs = 0;
9514 DWORD encoded[2];
9515 VARTYPE vt, subtype;
9516 char *data;
9518 if(!desc)
9519 return -1;
9521 if(!out_mix)
9522 out_mix = &junk;
9523 if(!out_size)
9524 out_size = &junk2;
9526 vt = desc->vt & VT_TYPEMASK;
9528 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9529 DWORD mix;
9530 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9531 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9532 *out_mix = 0x7FFF;
9533 *out_size += 2 * sizeof(DWORD);
9534 }else if(vt == VT_CARRAY){
9535 encoded[0] = desc->vt | (0x7FFE << 16);
9536 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9537 *out_mix = 0x7FFE;
9538 }else if(vt == VT_USERDEFINED){
9539 encoded[0] = desc->vt | (0x7FFF << 16);
9540 encoded[1] = desc->u.hreftype;
9541 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9542 }else{
9543 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9545 switch(vt){
9546 case VT_INT:
9547 subtype = VT_I4;
9548 break;
9549 case VT_UINT:
9550 subtype = VT_UI4;
9551 break;
9552 case VT_VOID:
9553 subtype = VT_EMPTY;
9554 break;
9555 default:
9556 subtype = vt;
9557 break;
9560 *out_mix = subtype;
9561 return 0x80000000 | (subtype << 16) | desc->vt;
9564 data = file->typdesc_seg.data;
9565 while(offs < file->typdesc_seg.len){
9566 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9567 return offs;
9568 offs += sizeof(encoded);
9571 file->typdesc_seg.len += sizeof(encoded);
9572 if(!file->typdesc_seg.data)
9573 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9574 else
9575 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9577 memcpy(&data[offs], encoded, sizeof(encoded));
9579 return offs;
9582 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9584 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9585 DWORD ret = cdguids_seg->len, offs;
9586 MSFT_CDGuid *cdguid;
9587 TLBCustData *cd;
9589 if(list_empty(custdata_list))
9590 return -1;
9592 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9593 if(!cdguids_seg->data){
9594 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9595 }else {
9596 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9597 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9600 offs = ret + sizeof(MSFT_CDGuid);
9601 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9602 cdguid->GuidOffset = cd->guid->offset;
9603 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9604 cdguid->next = offs;
9605 offs += sizeof(MSFT_CDGuid);
9606 ++cdguid;
9609 --cdguid;
9610 cdguid->next = -1;
9612 return ret;
9615 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9616 WMSFT_TLBFile *file)
9618 WMSFT_SegContents *aux_seg = &file->aux_seg;
9619 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9620 MSFT_VarRecord *varrecord;
9621 MSFT_FuncRecord *funcrecord;
9622 MEMBERID *memid;
9623 DWORD *name, *offsets, offs;
9625 for(i = 0; i < info->typeattr.cFuncs; ++i){
9626 TLBFuncDesc *desc = &info->funcdescs[i];
9628 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9630 /* optional fields */
9631 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9632 if(!list_empty(&desc->custdata_list))
9633 recorded_size += 7 * sizeof(INT);
9634 else if(desc->HelpStringContext != 0)
9635 recorded_size += 6 * sizeof(INT);
9636 /* res9? resA? */
9637 else if(desc->Entry)
9638 recorded_size += 3 * sizeof(INT);
9639 else if(desc->HelpString)
9640 recorded_size += 2 * sizeof(INT);
9641 else if(desc->helpcontext)
9642 recorded_size += sizeof(INT);
9644 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9646 for(j = 0; j < desc->funcdesc.cParams; ++j){
9647 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9648 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9649 break;
9653 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9656 for(i = 0; i < info->typeattr.cVars; ++i){
9657 TLBVarDesc *desc = &info->vardescs[i];
9659 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9661 /* optional fields */
9662 if(desc->HelpStringContext != 0)
9663 recorded_size += 5 * sizeof(INT);
9664 else if(!list_empty(&desc->custdata_list))
9665 recorded_size += 4 * sizeof(INT);
9666 /* res9? */
9667 else if(desc->HelpString)
9668 recorded_size += 2 * sizeof(INT);
9669 else if(desc->HelpContext != 0)
9670 recorded_size += sizeof(INT);
9672 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9675 if(!recorded_size && !extra_size)
9676 return ret;
9678 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9680 aux_seg->len += recorded_size + extra_size;
9682 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9684 if(aux_seg->data)
9685 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9686 else
9687 aux_seg->data = heap_alloc(aux_seg->len);
9689 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9691 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9692 offs = 0;
9694 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9695 for(i = 0; i < info->typeattr.cFuncs; ++i){
9696 TLBFuncDesc *desc = &info->funcdescs[i];
9697 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9699 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9700 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9701 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9702 funcrecord->VtableOffset = desc->funcdesc.oVft;
9704 /* FKCCIC:
9705 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9706 * ^^^funckind
9707 * ^^^ ^invkind
9708 * ^has_cust_data
9709 * ^^^^callconv
9710 * ^has_param_defaults
9711 * ^oEntry_is_intresource
9713 funcrecord->FKCCIC =
9714 desc->funcdesc.funckind |
9715 (desc->funcdesc.invkind << 3) |
9716 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9717 (desc->funcdesc.callconv << 8);
9719 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9720 funcrecord->FKCCIC |= 0x2000;
9722 for(j = 0; j < desc->funcdesc.cParams; ++j){
9723 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9724 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9725 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9728 if(paramdefault_size > 0)
9729 funcrecord->FKCCIC |= 0x1000;
9731 funcrecord->nrargs = desc->funcdesc.cParams;
9732 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9734 /* optional fields */
9735 /* res9? resA? */
9736 if(!list_empty(&desc->custdata_list)){
9737 size += 7 * sizeof(INT);
9738 funcrecord->HelpContext = desc->helpcontext;
9739 if(desc->HelpString)
9740 funcrecord->oHelpString = desc->HelpString->offset;
9741 else
9742 funcrecord->oHelpString = -1;
9743 if(!desc->Entry)
9744 funcrecord->oEntry = -1;
9745 else if(IS_INTRESOURCE(desc->Entry))
9746 funcrecord->oEntry = LOWORD(desc->Entry);
9747 else
9748 funcrecord->oEntry = desc->Entry->offset;
9749 funcrecord->res9 = -1;
9750 funcrecord->resA = -1;
9751 funcrecord->HelpStringContext = desc->HelpStringContext;
9752 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9753 }else if(desc->HelpStringContext != 0){
9754 size += 6 * sizeof(INT);
9755 funcrecord->HelpContext = desc->helpcontext;
9756 if(desc->HelpString)
9757 funcrecord->oHelpString = desc->HelpString->offset;
9758 else
9759 funcrecord->oHelpString = -1;
9760 if(!desc->Entry)
9761 funcrecord->oEntry = -1;
9762 else if(IS_INTRESOURCE(desc->Entry))
9763 funcrecord->oEntry = LOWORD(desc->Entry);
9764 else
9765 funcrecord->oEntry = desc->Entry->offset;
9766 funcrecord->res9 = -1;
9767 funcrecord->resA = -1;
9768 funcrecord->HelpStringContext = desc->HelpStringContext;
9769 }else if(desc->Entry){
9770 size += 3 * sizeof(INT);
9771 funcrecord->HelpContext = desc->helpcontext;
9772 if(desc->HelpString)
9773 funcrecord->oHelpString = desc->HelpString->offset;
9774 else
9775 funcrecord->oHelpString = -1;
9776 if(!desc->Entry)
9777 funcrecord->oEntry = -1;
9778 else if(IS_INTRESOURCE(desc->Entry))
9779 funcrecord->oEntry = LOWORD(desc->Entry);
9780 else
9781 funcrecord->oEntry = desc->Entry->offset;
9782 }else if(desc->HelpString){
9783 size += 2 * sizeof(INT);
9784 funcrecord->HelpContext = desc->helpcontext;
9785 funcrecord->oHelpString = desc->HelpString->offset;
9786 }else if(desc->helpcontext){
9787 size += sizeof(INT);
9788 funcrecord->HelpContext = desc->helpcontext;
9791 paramdefault = (DWORD*)((char *)funcrecord + size);
9792 size += paramdefault_size;
9794 for(j = 0; j < desc->funcdesc.cParams; ++j){
9795 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9797 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9798 if(desc->pParamDesc[j].Name)
9799 info->oName = desc->pParamDesc[j].Name->offset;
9800 else
9801 info->oName = -1;
9802 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9804 if(paramdefault_size){
9805 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9806 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9807 else if(paramdefault_size)
9808 *paramdefault = -1;
9809 ++paramdefault;
9812 size += sizeof(MSFT_ParameterInfo);
9815 funcrecord->Info = size | (i << 16); /* is it just the index? */
9817 *offsets = offs;
9818 offs += size;
9819 ++offsets;
9821 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9824 varrecord = (MSFT_VarRecord*)funcrecord;
9825 for(i = 0; i < info->typeattr.cVars; ++i){
9826 TLBVarDesc *desc = &info->vardescs[i];
9827 DWORD size = 5 * sizeof(INT);
9829 varrecord->vardescsize = sizeof(desc->vardesc);
9830 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9831 varrecord->Flags = desc->vardesc.wVarFlags;
9832 varrecord->VarKind = desc->vardesc.varkind;
9834 if(desc->vardesc.varkind == VAR_CONST){
9835 varrecord->vardescsize += sizeof(VARIANT);
9836 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9837 }else
9838 varrecord->OffsValue = desc->vardesc.u.oInst;
9840 /* res9? */
9841 if(desc->HelpStringContext != 0){
9842 size += 5 * sizeof(INT);
9843 varrecord->HelpContext = desc->HelpContext;
9844 if(desc->HelpString)
9845 varrecord->HelpString = desc->HelpString->offset;
9846 else
9847 varrecord->HelpString = -1;
9848 varrecord->res9 = -1;
9849 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9850 varrecord->HelpStringContext = desc->HelpStringContext;
9851 }else if(!list_empty(&desc->custdata_list)){
9852 size += 4 * sizeof(INT);
9853 varrecord->HelpContext = desc->HelpContext;
9854 if(desc->HelpString)
9855 varrecord->HelpString = desc->HelpString->offset;
9856 else
9857 varrecord->HelpString = -1;
9858 varrecord->res9 = -1;
9859 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9860 }else if(desc->HelpString){
9861 size += 2 * sizeof(INT);
9862 varrecord->HelpContext = desc->HelpContext;
9863 if(desc->HelpString)
9864 varrecord->HelpString = desc->HelpString->offset;
9865 else
9866 varrecord->HelpString = -1;
9867 }else if(desc->HelpContext != 0){
9868 size += sizeof(INT);
9869 varrecord->HelpContext = desc->HelpContext;
9872 varrecord->Info = size | (i << 16);
9874 *offsets = offs;
9875 offs += size;
9876 ++offsets;
9878 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9881 memid = (MEMBERID*)varrecord;
9882 for(i = 0; i < info->typeattr.cFuncs; ++i){
9883 TLBFuncDesc *desc = &info->funcdescs[i];
9884 *memid = desc->funcdesc.memid;
9885 ++memid;
9887 for(i = 0; i < info->typeattr.cVars; ++i){
9888 TLBVarDesc *desc = &info->vardescs[i];
9889 *memid = desc->vardesc.memid;
9890 ++memid;
9893 name = (DWORD*)memid;
9894 for(i = 0; i < info->typeattr.cFuncs; ++i){
9895 TLBFuncDesc *desc = &info->funcdescs[i];
9896 if(desc->Name)
9897 *name = desc->Name->offset;
9898 else
9899 *name = -1;
9900 ++name;
9902 for(i = 0; i < info->typeattr.cVars; ++i){
9903 TLBVarDesc *desc = &info->vardescs[i];
9904 if(desc->Name)
9905 *name = desc->Name->offset;
9906 else
9907 *name = -1;
9908 ++name;
9911 return ret;
9914 typedef struct tagWMSFT_RefChunk {
9915 DWORD href;
9916 DWORD res04;
9917 DWORD res08;
9918 DWORD next;
9919 } WMSFT_RefChunk;
9921 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9923 DWORD offs = file->ref_seg.len, i;
9924 WMSFT_RefChunk *chunk;
9926 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9927 if(!file->ref_seg.data)
9928 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9929 else
9930 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9932 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9934 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9935 chunk->href = info->impltypes[i].hRef;
9936 chunk->res04 = info->impltypes[i].implflags;
9937 chunk->res08 = -1;
9938 if(i < info->typeattr.cImplTypes - 1)
9939 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9940 else
9941 chunk->next = -1;
9942 ++chunk;
9945 return offs;
9948 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9950 DWORD size;
9952 size = sizeof(MSFT_TypeInfoBase);
9954 if(data){
9955 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9956 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9957 base->typekind = TKIND_DISPATCH;
9958 else
9959 base->typekind = info->typeattr.typekind;
9960 base->typekind |= index << 16; /* TODO: There are some other flags here */
9961 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9962 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9963 base->res2 = 0;
9964 base->res3 = 0;
9965 base->res4 = 3;
9966 base->res5 = 0;
9967 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9968 base->res7 = 0;
9969 base->res8 = 0;
9970 base->res9 = 0;
9971 base->resA = 0;
9972 if(info->guid)
9973 base->posguid = info->guid->offset;
9974 else
9975 base->posguid = -1;
9976 base->flags = info->typeattr.wTypeFlags;
9977 if(info->Name) {
9978 base->NameOffset = info->Name->offset;
9980 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9981 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9982 }else {
9983 base->NameOffset = -1;
9985 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9986 if(info->DocString)
9987 base->docstringoffs = info->DocString->offset;
9988 else
9989 base->docstringoffs = -1;
9990 base->helpstringcontext = info->dwHelpStringContext;
9991 base->helpcontext = info->dwHelpContext;
9992 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9993 base->cImplTypes = info->typeattr.cImplTypes;
9994 base->cbSizeVft = info->typeattr.cbSizeVft;
9995 base->size = info->typeattr.cbSizeInstance;
9996 if(info->typeattr.typekind == TKIND_COCLASS){
9997 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9998 }else if(info->typeattr.typekind == TKIND_ALIAS){
9999 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
10000 }else if(info->typeattr.typekind == TKIND_MODULE){
10001 if(info->DllName)
10002 base->datatype1 = info->DllName->offset;
10003 else
10004 base->datatype1 = -1;
10005 }else{
10006 if(info->typeattr.cImplTypes > 0)
10007 base->datatype1 = info->impltypes[0].hRef;
10008 else
10009 base->datatype1 = -1;
10011 base->datatype2 = index; /* FIXME: i think there's more here */
10012 base->res18 = 0;
10013 base->res19 = -1;
10016 return size;
10019 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
10021 UINT i;
10023 file->typeinfo_seg.len = 0;
10024 for(i = 0; i < This->TypeInfoCount; ++i){
10025 ITypeInfoImpl *info = This->typeinfos[i];
10026 *junk = file->typeinfo_seg.len;
10027 ++junk;
10028 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
10031 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
10032 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
10034 file->aux_seg.len = 0;
10035 file->aux_seg.data = NULL;
10037 file->typeinfo_seg.len = 0;
10038 for(i = 0; i < This->TypeInfoCount; ++i){
10039 ITypeInfoImpl *info = This->typeinfos[i];
10040 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
10041 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
10045 typedef struct tagWMSFT_ImpFile {
10046 INT guid_offs;
10047 LCID lcid;
10048 DWORD version;
10049 } WMSFT_ImpFile;
10051 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
10053 TLBImpLib *implib;
10054 WMSFT_ImpFile *impfile;
10055 char *data;
10056 DWORD last_offs = 0;
10058 file->impfile_seg.len = 0;
10059 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10060 int size = 0;
10062 if(implib->name){
10063 WCHAR *path = wcsrchr(implib->name, '\\');
10064 if(path)
10065 ++path;
10066 else
10067 path = implib->name;
10068 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10069 if (size == 0)
10070 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10073 size += sizeof(INT16);
10074 if (size % 4)
10075 size = (size + 4) & ~0x3;
10076 if (size < 8)
10077 size = 8;
10079 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10082 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
10084 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10085 int strlen = 0, size;
10087 impfile = (WMSFT_ImpFile*)data;
10088 impfile->guid_offs = implib->guid->offset;
10089 impfile->lcid = implib->lcid;
10090 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10092 data += sizeof(WMSFT_ImpFile);
10094 if(implib->name){
10095 WCHAR *path= wcsrchr(implib->name, '\\');
10096 if(path)
10097 ++path;
10098 else
10099 path = implib->name;
10100 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10101 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10102 if (strlen == 0)
10103 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10106 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10108 size = strlen + sizeof(INT16);
10109 if (size % 4)
10110 size = (size + 4) & ~0x3;
10111 if (size < 8)
10112 size = 8;
10113 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10115 data += size;
10116 implib->offset = last_offs;
10117 last_offs += size + sizeof(WMSFT_ImpFile);
10121 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10123 MSFT_ImpInfo *info;
10124 TLBRefType *ref_type;
10125 UINT i = 0;
10127 WMSFT_compile_impfile(This, file);
10129 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10130 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10132 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10133 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10134 if(ref_type->index == TLB_REF_USE_GUID){
10135 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10136 info->oGuid = ref_type->guid->offset;
10137 }else
10138 info->oGuid = ref_type->index;
10139 info->oImpFile = ref_type->pImpTLInfo->offset;
10140 ++i;
10141 ++info;
10145 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10147 file->guidhash_seg.len = 0x80;
10148 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10149 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10152 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10154 file->namehash_seg.len = 0x200;
10155 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10156 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10159 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10161 if(contents && contents->len){
10162 segdir->offset = *running_offset;
10163 segdir->length = contents->len;
10164 *running_offset += segdir->length;
10165 }else{
10166 segdir->offset = -1;
10167 segdir->length = 0;
10170 /* TODO: do these ever change? */
10171 segdir->res08 = -1;
10172 segdir->res0c = 0xf;
10175 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10177 DWORD written;
10178 if(segment)
10179 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10182 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10183 DWORD file_len)
10185 DWORD i;
10186 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10188 for(i = 0; i < This->TypeInfoCount; ++i){
10189 base->memoffset += file_len;
10190 ++base;
10193 return S_OK;
10196 static void WMSFT_free_file(WMSFT_TLBFile *file)
10198 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10199 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10200 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10201 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10202 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10203 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10204 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10205 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10206 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10207 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10208 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10209 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10210 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10211 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10214 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10216 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10217 WMSFT_TLBFile file;
10218 DWORD written, junk_size, junk_offs, running_offset;
10219 BOOL br;
10220 HANDLE outfile;
10221 HRESULT hres;
10222 DWORD *junk;
10223 UINT i;
10225 TRACE("%p\n", This);
10227 for(i = 0; i < This->TypeInfoCount; ++i)
10228 if(This->typeinfos[i]->needs_layout)
10229 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10231 memset(&file, 0, sizeof(file));
10233 file.header.magic1 = 0x5446534D;
10234 file.header.magic2 = 0x00010002;
10235 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10236 file.header.lcid2 = This->set_lcid;
10237 file.header.varflags = 0x40 | This->syskind;
10238 if (This->HelpFile)
10239 file.header.varflags |= 0x10;
10240 if (This->HelpStringDll)
10241 file.header.varflags |= HELPDLLFLAG;
10242 file.header.version = (This->ver_minor << 16) | This->ver_major;
10243 file.header.flags = This->libflags;
10244 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10245 file.header.helpcontext = This->dwHelpContext;
10246 file.header.res44 = 0x20;
10247 file.header.res48 = 0x80;
10248 file.header.dispatchpos = This->dispatch_href;
10250 WMSFT_compile_namehash(This, &file);
10251 /* do name and string compilation to get offsets for other compilations */
10252 hres = WMSFT_compile_names(This, &file);
10253 if (FAILED(hres)){
10254 WMSFT_free_file(&file);
10255 return hres;
10258 hres = WMSFT_compile_strings(This, &file);
10259 if (FAILED(hres)){
10260 WMSFT_free_file(&file);
10261 return hres;
10264 WMSFT_compile_guidhash(This, &file);
10265 hres = WMSFT_compile_guids(This, &file);
10266 if (FAILED(hres)){
10267 WMSFT_free_file(&file);
10268 return hres;
10271 if(This->HelpFile)
10272 file.header.helpfile = This->HelpFile->offset;
10273 else
10274 file.header.helpfile = -1;
10276 if(This->DocString)
10277 file.header.helpstring = This->DocString->offset;
10278 else
10279 file.header.helpstring = -1;
10281 /* do some more segment compilation */
10282 file.header.nimpinfos = list_count(&This->ref_list);
10283 file.header.nrtypeinfos = This->TypeInfoCount;
10285 if(This->Name)
10286 file.header.NameOffset = This->Name->offset;
10287 else
10288 file.header.NameOffset = -1;
10290 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10292 if(This->guid)
10293 file.header.posguid = This->guid->offset;
10294 else
10295 file.header.posguid = -1;
10297 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10298 if(file.header.varflags & HELPDLLFLAG)
10299 junk_size += sizeof(DWORD);
10300 if(junk_size){
10301 junk = heap_alloc_zero(junk_size);
10302 if(file.header.varflags & HELPDLLFLAG){
10303 *junk = This->HelpStringDll->offset;
10304 junk_offs = 1;
10305 }else
10306 junk_offs = 0;
10307 }else{
10308 junk = NULL;
10309 junk_offs = 0;
10312 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10313 WMSFT_compile_impinfo(This, &file);
10315 running_offset = 0;
10317 TRACE("header at: 0x%x\n", running_offset);
10318 running_offset += sizeof(file.header);
10320 TRACE("junk at: 0x%x\n", running_offset);
10321 running_offset += junk_size;
10323 TRACE("segdir at: 0x%x\n", running_offset);
10324 running_offset += sizeof(file.segdir);
10326 TRACE("typeinfo at: 0x%x\n", running_offset);
10327 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10329 TRACE("guidhashtab at: 0x%x\n", running_offset);
10330 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10332 TRACE("guidtab at: 0x%x\n", running_offset);
10333 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10335 TRACE("reftab at: 0x%x\n", running_offset);
10336 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10338 TRACE("impinfo at: 0x%x\n", running_offset);
10339 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10341 TRACE("impfiles at: 0x%x\n", running_offset);
10342 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10344 TRACE("namehashtab at: 0x%x\n", running_offset);
10345 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10347 TRACE("nametab at: 0x%x\n", running_offset);
10348 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10350 TRACE("stringtab at: 0x%x\n", running_offset);
10351 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10353 TRACE("typdesc at: 0x%x\n", running_offset);
10354 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10356 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10357 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10359 TRACE("custdata at: 0x%x\n", running_offset);
10360 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10362 TRACE("cdguids at: 0x%x\n", running_offset);
10363 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10365 TRACE("res0e at: 0x%x\n", running_offset);
10366 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10368 TRACE("res0f at: 0x%x\n", running_offset);
10369 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10371 TRACE("aux_seg at: 0x%x\n", running_offset);
10373 WMSFT_fixup_typeinfos(This, &file, running_offset);
10375 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10376 FILE_ATTRIBUTE_NORMAL, 0);
10377 if (outfile == INVALID_HANDLE_VALUE){
10378 WMSFT_free_file(&file);
10379 heap_free(junk);
10380 return TYPE_E_IOERROR;
10383 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10384 if (!br) {
10385 WMSFT_free_file(&file);
10386 CloseHandle(outfile);
10387 heap_free(junk);
10388 return TYPE_E_IOERROR;
10391 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10392 heap_free(junk);
10393 if (!br) {
10394 WMSFT_free_file(&file);
10395 CloseHandle(outfile);
10396 return TYPE_E_IOERROR;
10399 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10400 if (!br) {
10401 WMSFT_free_file(&file);
10402 CloseHandle(outfile);
10403 return TYPE_E_IOERROR;
10406 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10407 WMSFT_write_segment(outfile, &file.guidhash_seg);
10408 WMSFT_write_segment(outfile, &file.guid_seg);
10409 WMSFT_write_segment(outfile, &file.ref_seg);
10410 WMSFT_write_segment(outfile, &file.impinfo_seg);
10411 WMSFT_write_segment(outfile, &file.impfile_seg);
10412 WMSFT_write_segment(outfile, &file.namehash_seg);
10413 WMSFT_write_segment(outfile, &file.name_seg);
10414 WMSFT_write_segment(outfile, &file.string_seg);
10415 WMSFT_write_segment(outfile, &file.typdesc_seg);
10416 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10417 WMSFT_write_segment(outfile, &file.custdata_seg);
10418 WMSFT_write_segment(outfile, &file.cdguids_seg);
10419 WMSFT_write_segment(outfile, &file.aux_seg);
10421 WMSFT_free_file(&file);
10423 CloseHandle(outfile);
10425 return S_OK;
10428 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10429 LPOLESTR name)
10431 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10432 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10433 return E_NOTIMPL;
10436 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10437 REFGUID guid, VARIANT *varVal)
10439 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10440 TLBGuid *tlbguid;
10442 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10444 if (!guid || !varVal)
10445 return E_INVALIDARG;
10447 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10449 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10452 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10453 ULONG helpStringContext)
10455 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10456 FIXME("%p %u - stub\n", This, helpStringContext);
10457 return E_NOTIMPL;
10460 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10461 LPOLESTR filename)
10463 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10464 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10466 if (!filename)
10467 return E_INVALIDARG;
10469 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10471 return S_OK;
10474 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10475 ICreateTypeLib2_fnQueryInterface,
10476 ICreateTypeLib2_fnAddRef,
10477 ICreateTypeLib2_fnRelease,
10478 ICreateTypeLib2_fnCreateTypeInfo,
10479 ICreateTypeLib2_fnSetName,
10480 ICreateTypeLib2_fnSetVersion,
10481 ICreateTypeLib2_fnSetGuid,
10482 ICreateTypeLib2_fnSetDocString,
10483 ICreateTypeLib2_fnSetHelpFileName,
10484 ICreateTypeLib2_fnSetHelpContext,
10485 ICreateTypeLib2_fnSetLcid,
10486 ICreateTypeLib2_fnSetLibFlags,
10487 ICreateTypeLib2_fnSaveAllChanges,
10488 ICreateTypeLib2_fnDeleteTypeInfo,
10489 ICreateTypeLib2_fnSetCustData,
10490 ICreateTypeLib2_fnSetHelpStringContext,
10491 ICreateTypeLib2_fnSetHelpStringDll
10494 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10495 REFIID riid, void **object)
10497 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10499 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10502 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10504 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10506 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10509 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10511 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10513 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10516 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10517 REFGUID guid)
10519 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10521 TRACE("%p %s\n", This, debugstr_guid(guid));
10523 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10525 return S_OK;
10528 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10529 UINT typeFlags)
10531 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10532 WORD old_flags;
10533 HRESULT hres;
10535 TRACE("%p %x\n", This, typeFlags);
10537 if (typeFlags & TYPEFLAG_FDUAL) {
10538 ITypeLib *stdole;
10539 ITypeInfo *dispatch;
10540 HREFTYPE hreftype;
10541 HRESULT hres;
10543 hres = LoadTypeLib(L"stdole2.tlb", &stdole);
10544 if(FAILED(hres))
10545 return hres;
10547 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10548 ITypeLib_Release(stdole);
10549 if(FAILED(hres))
10550 return hres;
10552 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10553 ITypeInfo_Release(dispatch);
10554 if(FAILED(hres))
10555 return hres;
10558 old_flags = This->typeattr.wTypeFlags;
10559 This->typeattr.wTypeFlags = typeFlags;
10561 hres = ICreateTypeInfo2_LayOut(iface);
10562 if (FAILED(hres)) {
10563 This->typeattr.wTypeFlags = old_flags;
10564 return hres;
10567 return S_OK;
10570 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10571 LPOLESTR doc)
10573 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10575 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10577 if (!doc)
10578 return E_INVALIDARG;
10580 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10582 return S_OK;
10585 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10586 DWORD helpContext)
10588 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10590 TRACE("%p %d\n", This, helpContext);
10592 This->dwHelpContext = helpContext;
10594 return S_OK;
10597 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10598 WORD majorVerNum, WORD minorVerNum)
10600 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10602 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10604 This->typeattr.wMajorVerNum = majorVerNum;
10605 This->typeattr.wMinorVerNum = minorVerNum;
10607 return S_OK;
10610 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10611 ITypeInfo *typeInfo, HREFTYPE *refType)
10613 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10614 UINT index;
10615 ITypeLib *container;
10616 TLBRefType *ref_type;
10617 TLBImpLib *implib;
10618 TYPEATTR *typeattr;
10619 TLIBATTR *libattr;
10620 HRESULT hres;
10622 TRACE("%p %p %p\n", This, typeInfo, refType);
10624 if (!typeInfo || !refType)
10625 return E_INVALIDARG;
10627 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10628 if (FAILED(hres))
10629 return hres;
10631 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10632 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10634 ITypeLib_Release(container);
10636 *refType = target->hreftype;
10638 return S_OK;
10641 hres = ITypeLib_GetLibAttr(container, &libattr);
10642 if (FAILED(hres)) {
10643 ITypeLib_Release(container);
10644 return hres;
10647 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10648 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10649 implib->lcid == libattr->lcid &&
10650 implib->wVersionMajor == libattr->wMajorVerNum &&
10651 implib->wVersionMinor == libattr->wMinorVerNum)
10652 break;
10655 if(&implib->entry == &This->pTypeLib->implib_list){
10656 implib = heap_alloc_zero(sizeof(TLBImpLib));
10658 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10659 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10660 implib->name = SysAllocString(our_container->path);
10661 }else{
10662 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10663 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10664 if(FAILED(hres)){
10665 implib->name = NULL;
10666 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10670 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10671 implib->lcid = libattr->lcid;
10672 implib->wVersionMajor = libattr->wMajorVerNum;
10673 implib->wVersionMinor = libattr->wMinorVerNum;
10675 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10678 ITypeLib_ReleaseTLibAttr(container, libattr);
10679 ITypeLib_Release(container);
10681 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10682 if (FAILED(hres))
10683 return hres;
10685 index = 0;
10686 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10687 if(ref_type->index == TLB_REF_USE_GUID &&
10688 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10689 ref_type->tkind == typeattr->typekind)
10690 break;
10691 ++index;
10694 if(&ref_type->entry == &This->pTypeLib->ref_list){
10695 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10697 ref_type->tkind = typeattr->typekind;
10698 ref_type->pImpTLInfo = implib;
10699 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10701 ref_type->index = TLB_REF_USE_GUID;
10703 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10705 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10708 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10710 *refType = ref_type->reference | 0x1;
10712 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10713 This->pTypeLib->dispatch_href = *refType;
10715 return S_OK;
10718 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10719 UINT index, FUNCDESC *funcDesc)
10721 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10722 TLBFuncDesc tmp_func_desc, *func_desc;
10723 int buf_size, i;
10724 char *buffer;
10725 HRESULT hres;
10727 TRACE("%p %u %p\n", This, index, funcDesc);
10729 if (!funcDesc || funcDesc->oVft & 3)
10730 return E_INVALIDARG;
10732 switch (This->typeattr.typekind) {
10733 case TKIND_MODULE:
10734 if (funcDesc->funckind != FUNC_STATIC)
10735 return TYPE_E_BADMODULEKIND;
10736 break;
10737 case TKIND_DISPATCH:
10738 if (funcDesc->funckind != FUNC_DISPATCH)
10739 return TYPE_E_BADMODULEKIND;
10740 break;
10741 default:
10742 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10743 return TYPE_E_BADMODULEKIND;
10746 if (index > This->typeattr.cFuncs)
10747 return TYPE_E_ELEMENTNOTFOUND;
10749 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10750 !funcDesc->cParams)
10751 return TYPE_E_INCONSISTENTPROPFUNCS;
10753 #ifdef _WIN64
10754 if(This->pTypeLib->syskind == SYS_WIN64 &&
10755 funcDesc->oVft % 8 != 0)
10756 return E_INVALIDARG;
10757 #endif
10759 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10760 TLBFuncDesc_Constructor(&tmp_func_desc);
10762 tmp_func_desc.funcdesc = *funcDesc;
10764 if (tmp_func_desc.funcdesc.oVft != 0)
10765 tmp_func_desc.funcdesc.oVft |= 1;
10767 if (funcDesc->cScodes && funcDesc->lprgscode) {
10768 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10769 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10770 } else {
10771 tmp_func_desc.funcdesc.lprgscode = NULL;
10772 tmp_func_desc.funcdesc.cScodes = 0;
10775 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10776 for (i = 0; i < funcDesc->cParams; ++i) {
10777 buf_size += sizeof(ELEMDESC);
10778 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10780 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10781 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10783 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10784 if (FAILED(hres)) {
10785 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10786 heap_free(tmp_func_desc.funcdesc.lprgscode);
10787 return hres;
10790 for (i = 0; i < funcDesc->cParams; ++i) {
10791 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10792 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10793 if (FAILED(hres)) {
10794 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10795 heap_free(tmp_func_desc.funcdesc.lprgscode);
10796 return hres;
10798 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10799 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10800 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10801 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10802 if (FAILED(hres)) {
10803 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10804 heap_free(tmp_func_desc.funcdesc.lprgscode);
10805 return hres;
10810 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10812 if (This->funcdescs) {
10813 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10814 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10816 if (index < This->typeattr.cFuncs) {
10817 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10818 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10819 func_desc = This->funcdescs + index;
10820 } else
10821 func_desc = This->funcdescs + This->typeattr.cFuncs;
10823 /* move custdata lists to the new memory location */
10824 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10825 if(index != i)
10826 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10828 } else
10829 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10831 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10832 list_init(&func_desc->custdata_list);
10834 ++This->typeattr.cFuncs;
10836 This->needs_layout = TRUE;
10838 return S_OK;
10841 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10842 UINT index, HREFTYPE refType)
10844 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10845 TLBImplType *impl_type;
10846 HRESULT hres;
10848 TRACE("%p %u %d\n", This, index, refType);
10850 switch(This->typeattr.typekind){
10851 case TKIND_COCLASS: {
10852 if (index == -1) {
10853 FIXME("Unhandled index: -1\n");
10854 return E_NOTIMPL;
10857 if(index != This->typeattr.cImplTypes)
10858 return TYPE_E_ELEMENTNOTFOUND;
10860 break;
10862 case TKIND_INTERFACE:
10863 case TKIND_DISPATCH:
10864 if (index != 0 || This->typeattr.cImplTypes)
10865 return TYPE_E_ELEMENTNOTFOUND;
10866 break;
10867 default:
10868 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10869 return E_NOTIMPL;
10872 if (This->impltypes){
10873 UINT i;
10875 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10876 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10878 if (index < This->typeattr.cImplTypes) {
10879 memmove(This->impltypes + index + 1, This->impltypes + index,
10880 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10881 impl_type = This->impltypes + index;
10882 } else
10883 impl_type = This->impltypes + This->typeattr.cImplTypes;
10885 /* move custdata lists to the new memory location */
10886 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10887 if(index != i)
10888 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10890 } else
10891 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10893 memset(impl_type, 0, sizeof(TLBImplType));
10894 TLBImplType_Constructor(impl_type);
10895 impl_type->hRef = refType;
10897 ++This->typeattr.cImplTypes;
10899 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10900 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10902 hres = ICreateTypeInfo2_LayOut(iface);
10903 if (FAILED(hres))
10904 return hres;
10906 return S_OK;
10909 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10910 UINT index, INT implTypeFlags)
10912 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10913 TLBImplType *impl_type = &This->impltypes[index];
10915 TRACE("%p %u %x\n", This, index, implTypeFlags);
10917 if (This->typeattr.typekind != TKIND_COCLASS)
10918 return TYPE_E_BADMODULEKIND;
10920 if (index >= This->typeattr.cImplTypes)
10921 return TYPE_E_ELEMENTNOTFOUND;
10923 impl_type->implflags = implTypeFlags;
10925 return S_OK;
10928 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10929 WORD alignment)
10931 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10933 TRACE("%p %d\n", This, alignment);
10935 This->typeattr.cbAlignment = alignment;
10937 return S_OK;
10940 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10941 LPOLESTR schema)
10943 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10945 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10947 if (!schema)
10948 return E_INVALIDARG;
10950 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10952 This->typeattr.lpstrSchema = This->Schema->str;
10954 return S_OK;
10957 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10958 UINT index, VARDESC *varDesc)
10960 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10961 TLBVarDesc *var_desc;
10962 HRESULT hr;
10964 TRACE("%p %u %p\n", This, index, varDesc);
10966 if (This->vardescs){
10967 UINT i;
10969 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10970 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10972 if (index < This->typeattr.cVars) {
10973 memmove(This->vardescs + index + 1, This->vardescs + index,
10974 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10975 var_desc = This->vardescs + index;
10976 } else
10977 var_desc = This->vardescs + This->typeattr.cVars;
10979 /* move custdata lists to the new memory location */
10980 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10981 if(index != i)
10982 TLB_relink_custdata(&This->vardescs[i].custdata_list);
10984 } else
10985 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10987 TLBVarDesc_Constructor(var_desc);
10988 hr = TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10989 if (FAILED(hr))
10990 return hr;
10991 var_desc->vardesc = *var_desc->vardesc_create;
10993 ++This->typeattr.cVars;
10995 This->needs_layout = TRUE;
10997 return S_OK;
11000 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
11001 UINT index, LPOLESTR *names, UINT numNames)
11003 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11004 TLBFuncDesc *func_desc = &This->funcdescs[index];
11005 int i;
11007 TRACE("%p %u %p %u\n", This, index, names, numNames);
11009 if (!names)
11010 return E_INVALIDARG;
11012 if (index >= This->typeattr.cFuncs || numNames == 0)
11013 return TYPE_E_ELEMENTNOTFOUND;
11015 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
11016 if(numNames > func_desc->funcdesc.cParams)
11017 return TYPE_E_ELEMENTNOTFOUND;
11018 } else
11019 if(numNames > func_desc->funcdesc.cParams + 1)
11020 return TYPE_E_ELEMENTNOTFOUND;
11022 for(i = 0; i < This->typeattr.cFuncs; ++i) {
11023 TLBFuncDesc *iter = &This->funcdescs[i];
11024 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
11025 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11026 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11027 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
11028 continue;
11029 return TYPE_E_AMBIGUOUSNAME;
11033 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
11035 for (i = 1; i < numNames; ++i) {
11036 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
11037 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
11040 return S_OK;
11043 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
11044 UINT index, LPOLESTR name)
11046 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11048 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
11050 if(!name)
11051 return E_INVALIDARG;
11053 if(index >= This->typeattr.cVars)
11054 return TYPE_E_ELEMENTNOTFOUND;
11056 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
11057 return S_OK;
11060 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
11061 TYPEDESC *tdescAlias)
11063 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11064 HRESULT hr;
11066 TRACE("%p %p\n", This, tdescAlias);
11068 if(!tdescAlias)
11069 return E_INVALIDARG;
11071 if(This->typeattr.typekind != TKIND_ALIAS)
11072 return TYPE_E_BADMODULEKIND;
11074 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11075 if(FAILED(hr))
11076 return hr;
11078 heap_free(This->tdescAlias);
11079 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11080 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11082 return S_OK;
11085 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11086 UINT index, LPOLESTR dllName, LPOLESTR procName)
11088 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11089 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11090 return E_NOTIMPL;
11093 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11094 UINT index, LPOLESTR docString)
11096 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11097 TLBFuncDesc *func_desc = &This->funcdescs[index];
11099 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11101 if(!docString)
11102 return E_INVALIDARG;
11104 if(index >= This->typeattr.cFuncs)
11105 return TYPE_E_ELEMENTNOTFOUND;
11107 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11109 return S_OK;
11112 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11113 UINT index, LPOLESTR docString)
11115 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11116 TLBVarDesc *var_desc = &This->vardescs[index];
11118 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11120 if(!docString)
11121 return E_INVALIDARG;
11123 if(index >= This->typeattr.cVars)
11124 return TYPE_E_ELEMENTNOTFOUND;
11126 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11128 return S_OK;
11131 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11132 UINT index, DWORD helpContext)
11134 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11135 TLBFuncDesc *func_desc = &This->funcdescs[index];
11137 TRACE("%p %u %d\n", This, index, helpContext);
11139 if(index >= This->typeattr.cFuncs)
11140 return TYPE_E_ELEMENTNOTFOUND;
11142 func_desc->helpcontext = helpContext;
11144 return S_OK;
11147 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11148 UINT index, DWORD helpContext)
11150 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11151 TLBVarDesc *var_desc = &This->vardescs[index];
11153 TRACE("%p %u %d\n", This, index, helpContext);
11155 if(index >= This->typeattr.cVars)
11156 return TYPE_E_ELEMENTNOTFOUND;
11158 var_desc->HelpContext = helpContext;
11160 return S_OK;
11163 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11164 UINT index, BSTR bstrMops)
11166 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11167 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11168 return E_NOTIMPL;
11171 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11172 IDLDESC *idlDesc)
11174 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11176 TRACE("%p %p\n", This, idlDesc);
11178 if (!idlDesc)
11179 return E_INVALIDARG;
11181 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11182 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11184 return S_OK;
11187 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11189 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11190 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11191 TLBFuncDesc *func_desc;
11192 UINT user_vft = 0, i, depth = 0;
11193 HRESULT hres = S_OK;
11195 TRACE("%p\n", This);
11197 This->needs_layout = FALSE;
11199 if (This->typeattr.typekind == TKIND_INTERFACE) {
11200 ITypeInfo *inh;
11201 TYPEATTR *attr;
11202 HREFTYPE inh_href;
11204 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11206 if (SUCCEEDED(hres)) {
11207 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11209 if (SUCCEEDED(hres)) {
11210 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11211 if (FAILED(hres)) {
11212 ITypeInfo_Release(inh);
11213 return hres;
11215 This->typeattr.cbSizeVft = attr->cbSizeVft;
11216 ITypeInfo_ReleaseTypeAttr(inh, attr);
11219 ++depth;
11220 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11221 if(SUCCEEDED(hres)){
11222 ITypeInfo *next;
11223 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11224 if(SUCCEEDED(hres)){
11225 ITypeInfo_Release(inh);
11226 inh = next;
11229 }while(SUCCEEDED(hres));
11230 hres = S_OK;
11232 ITypeInfo_Release(inh);
11233 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11234 This->typeattr.cbSizeVft = 0;
11235 hres = S_OK;
11236 } else
11237 return hres;
11238 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11239 This->typeattr.cbSizeVft = 0;
11240 hres = S_OK;
11241 } else
11242 return hres;
11243 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11244 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11245 else
11246 This->typeattr.cbSizeVft = 0;
11248 func_desc = This->funcdescs;
11249 i = 0;
11250 while (i < This->typeattr.cFuncs) {
11251 if (!(func_desc->funcdesc.oVft & 0x1))
11252 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11254 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11255 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11257 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11259 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11260 TLBFuncDesc *iter;
11261 UINT j = 0;
11262 BOOL reset = FALSE;
11264 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11266 iter = This->funcdescs;
11267 while (j < This->typeattr.cFuncs) {
11268 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11269 if (!reset) {
11270 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11271 reset = TRUE;
11272 } else
11273 ++func_desc->funcdesc.memid;
11274 iter = This->funcdescs;
11275 j = 0;
11276 } else {
11277 ++iter;
11278 ++j;
11283 ++func_desc;
11284 ++i;
11287 if (user_vft > This->typeattr.cbSizeVft)
11288 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11290 for(i = 0; i < This->typeattr.cVars; ++i){
11291 TLBVarDesc *var_desc = &This->vardescs[i];
11292 if(var_desc->vardesc.memid == MEMBERID_NIL){
11293 UINT j = 0;
11294 BOOL reset = FALSE;
11295 TLBVarDesc *iter;
11297 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11299 iter = This->vardescs;
11300 while (j < This->typeattr.cVars) {
11301 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11302 if (!reset) {
11303 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11304 reset = TRUE;
11305 } else
11306 ++var_desc->vardesc.memid;
11307 iter = This->vardescs;
11308 j = 0;
11309 } else {
11310 ++iter;
11311 ++j;
11317 return hres;
11320 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11321 UINT index)
11323 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11324 unsigned int i;
11326 TRACE("%p %u\n", This, index);
11328 if (index >= This->typeattr.cFuncs)
11329 return TYPE_E_ELEMENTNOTFOUND;
11331 typeinfo_release_funcdesc(&This->funcdescs[index]);
11333 --This->typeattr.cFuncs;
11334 if (index != This->typeattr.cFuncs)
11336 memmove(This->funcdescs + index, This->funcdescs + index + 1,
11337 sizeof(*This->funcdescs) * (This->typeattr.cFuncs - index));
11338 for (i = index; i < This->typeattr.cFuncs; ++i)
11339 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
11342 This->needs_layout = TRUE;
11344 return S_OK;
11347 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11348 MEMBERID memid, INVOKEKIND invKind)
11350 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11351 FIXME("%p %x %d - stub\n", This, memid, invKind);
11352 return E_NOTIMPL;
11355 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11356 UINT index)
11358 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11359 FIXME("%p %u - stub\n", This, index);
11360 return E_NOTIMPL;
11363 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11364 MEMBERID memid)
11366 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11367 FIXME("%p %x - stub\n", This, memid);
11368 return E_NOTIMPL;
11371 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11372 UINT index)
11374 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11375 int i;
11377 TRACE("%p %u\n", This, index);
11379 if (index >= This->typeattr.cImplTypes)
11380 return TYPE_E_ELEMENTNOTFOUND;
11382 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11383 --This->typeattr.cImplTypes;
11385 if (index < This->typeattr.cImplTypes)
11387 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11388 sizeof(*This->impltypes));
11389 for (i = index; i < This->typeattr.cImplTypes; ++i)
11390 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11393 return S_OK;
11396 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11397 REFGUID guid, VARIANT *varVal)
11399 TLBGuid *tlbguid;
11401 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11403 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11405 if (!guid || !varVal)
11406 return E_INVALIDARG;
11408 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11410 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11413 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11414 UINT index, REFGUID guid, VARIANT *varVal)
11416 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11417 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11418 return E_NOTIMPL;
11421 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11422 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11424 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11425 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11426 return E_NOTIMPL;
11429 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11430 UINT index, REFGUID guid, VARIANT *varVal)
11432 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11433 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11434 return E_NOTIMPL;
11437 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11438 UINT index, REFGUID guid, VARIANT *varVal)
11440 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11441 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11442 return E_NOTIMPL;
11445 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11446 ULONG helpStringContext)
11448 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11450 TRACE("%p %u\n", This, helpStringContext);
11452 This->dwHelpStringContext = helpStringContext;
11454 return S_OK;
11457 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11458 UINT index, ULONG helpStringContext)
11460 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11461 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11462 return E_NOTIMPL;
11465 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11466 UINT index, ULONG helpStringContext)
11468 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11469 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11470 return E_NOTIMPL;
11473 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11475 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11476 FIXME("%p - stub\n", This);
11477 return E_NOTIMPL;
11480 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11481 LPOLESTR name)
11483 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11485 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11487 if (!name)
11488 return E_INVALIDARG;
11490 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11492 return S_OK;
11495 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11496 ICreateTypeInfo2_fnQueryInterface,
11497 ICreateTypeInfo2_fnAddRef,
11498 ICreateTypeInfo2_fnRelease,
11499 ICreateTypeInfo2_fnSetGuid,
11500 ICreateTypeInfo2_fnSetTypeFlags,
11501 ICreateTypeInfo2_fnSetDocString,
11502 ICreateTypeInfo2_fnSetHelpContext,
11503 ICreateTypeInfo2_fnSetVersion,
11504 ICreateTypeInfo2_fnAddRefTypeInfo,
11505 ICreateTypeInfo2_fnAddFuncDesc,
11506 ICreateTypeInfo2_fnAddImplType,
11507 ICreateTypeInfo2_fnSetImplTypeFlags,
11508 ICreateTypeInfo2_fnSetAlignment,
11509 ICreateTypeInfo2_fnSetSchema,
11510 ICreateTypeInfo2_fnAddVarDesc,
11511 ICreateTypeInfo2_fnSetFuncAndParamNames,
11512 ICreateTypeInfo2_fnSetVarName,
11513 ICreateTypeInfo2_fnSetTypeDescAlias,
11514 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11515 ICreateTypeInfo2_fnSetFuncDocString,
11516 ICreateTypeInfo2_fnSetVarDocString,
11517 ICreateTypeInfo2_fnSetFuncHelpContext,
11518 ICreateTypeInfo2_fnSetVarHelpContext,
11519 ICreateTypeInfo2_fnSetMops,
11520 ICreateTypeInfo2_fnSetTypeIdldesc,
11521 ICreateTypeInfo2_fnLayOut,
11522 ICreateTypeInfo2_fnDeleteFuncDesc,
11523 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11524 ICreateTypeInfo2_fnDeleteVarDesc,
11525 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11526 ICreateTypeInfo2_fnDeleteImplType,
11527 ICreateTypeInfo2_fnSetCustData,
11528 ICreateTypeInfo2_fnSetFuncCustData,
11529 ICreateTypeInfo2_fnSetParamCustData,
11530 ICreateTypeInfo2_fnSetVarCustData,
11531 ICreateTypeInfo2_fnSetImplTypeCustData,
11532 ICreateTypeInfo2_fnSetHelpStringContext,
11533 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11534 ICreateTypeInfo2_fnSetVarHelpStringContext,
11535 ICreateTypeInfo2_fnInvalidate,
11536 ICreateTypeInfo2_fnSetName
11539 /******************************************************************************
11540 * ClearCustData (OLEAUT32.171)
11542 * Clear a custom data type's data.
11544 * PARAMS
11545 * lpCust [I] The custom data type instance
11547 * RETURNS
11548 * Nothing.
11550 void WINAPI ClearCustData(CUSTDATA *lpCust)
11552 if (lpCust && lpCust->cCustData)
11554 if (lpCust->prgCustData)
11556 DWORD i;
11558 for (i = 0; i < lpCust->cCustData; i++)
11559 VariantClear(&lpCust->prgCustData[i].varValue);
11561 CoTaskMemFree(lpCust->prgCustData);
11562 lpCust->prgCustData = NULL;
11564 lpCust->cCustData = 0;