imm32: Ignore some messages in ImmTranslateMessage.
[wine.git] / dlls / oleaut32 / typelib.c
blobd92d0234c6c949df31e0ff049b39c1eb02668e08
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 >= *wMin && 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, %#lx, %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)("-- %#lx\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 %#lx\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, %#lx, %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 = %lx", pTD->u.hreftype); break;
1356 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1357 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1358 case VT_PTR: sprintf(szVarType, "ptr to ");
1359 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1360 break;
1361 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1362 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1363 break;
1364 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1365 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1366 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1367 break;
1369 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1373 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1374 char buf[200];
1375 USHORT flags = edesc->u.paramdesc.wParamFlags;
1376 dump_TypeDesc(&edesc->tdesc,buf);
1377 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1378 MESSAGE("\t\tu.paramdesc.wParamFlags");
1379 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1380 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1381 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1382 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1383 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1384 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1385 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1386 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1387 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1389 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1390 int i;
1391 MESSAGE("memid is %#lx\n", funcdesc->memid);
1392 for (i=0;i<funcdesc->cParams;i++) {
1393 MESSAGE("Param %d:\n",i);
1394 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1396 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1397 switch (funcdesc->funckind) {
1398 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1399 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1400 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1401 case FUNC_STATIC: MESSAGE("static");break;
1402 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1403 default: MESSAGE("unknown");break;
1405 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1406 switch (funcdesc->invkind) {
1407 case INVOKE_FUNC: MESSAGE("func");break;
1408 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1409 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1410 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1412 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1413 switch (funcdesc->callconv) {
1414 case CC_CDECL: MESSAGE("cdecl");break;
1415 case CC_PASCAL: MESSAGE("pascal");break;
1416 case CC_STDCALL: MESSAGE("stdcall");break;
1417 case CC_SYSCALL: MESSAGE("syscall");break;
1418 default:break;
1420 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1421 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1422 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1424 MESSAGE("\telemdescFunc (return value type):\n");
1425 dump_ELEMDESC(&funcdesc->elemdescFunc);
1428 static const char * const typekind_desc[] =
1430 "TKIND_ENUM",
1431 "TKIND_RECORD",
1432 "TKIND_MODULE",
1433 "TKIND_INTERFACE",
1434 "TKIND_DISPATCH",
1435 "TKIND_COCLASS",
1436 "TKIND_ALIAS",
1437 "TKIND_UNION",
1438 "TKIND_MAX"
1441 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1443 int i;
1444 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1445 for (i=0;i<pfd->funcdesc.cParams;i++)
1446 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1449 dump_FUNCDESC(&(pfd->funcdesc));
1451 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1452 if(pfd->Entry == NULL)
1453 MESSAGE("\tentry: (null)\n");
1454 else if(pfd->Entry == (void*)-1)
1455 MESSAGE("\tentry: invalid\n");
1456 else if(IS_INTRESOURCE(pfd->Entry))
1457 MESSAGE("\tentry: %p\n", pfd->Entry);
1458 else
1459 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1461 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1463 while (n)
1465 dump_TLBFuncDescOne(pfd);
1466 ++pfd;
1467 --n;
1470 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1472 while (n)
1474 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1475 ++pvd;
1476 --n;
1480 static void dump_TLBImpLib(const TLBImpLib *import)
1482 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1483 debugstr_w(import->name));
1484 TRACE_(typelib)("v%d.%d lcid %#lx offset=%x\n", import->wVersionMajor, import->wVersionMinor, import->lcid, import->offset);
1487 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1489 TLBRefType *ref;
1491 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1493 TRACE_(typelib)("href:%#lx\n", ref->reference);
1494 if(ref->index == -1)
1495 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1496 else
1497 TRACE_(typelib)("type no: %d\n", ref->index);
1499 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1501 TRACE_(typelib)("in lib\n");
1502 dump_TLBImpLib(ref->pImpTLInfo);
1507 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1509 if(!impl)
1510 return;
1511 while (n) {
1512 TRACE_(typelib)("implementing/inheriting interface hRef = %lx implflags %x\n",
1513 impl->hRef, impl->implflags);
1514 ++impl;
1515 --n;
1519 static void dump_DispParms(const DISPPARAMS * pdp)
1521 unsigned int index;
1523 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1525 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1527 TRACE("named args:\n");
1528 for (index = 0; index < pdp->cNamedArgs; index++)
1529 TRACE( "\t0x%lx\n", pdp->rgdispidNamedArgs[index] );
1532 if (pdp->cArgs && pdp->rgvarg)
1534 TRACE("args:\n");
1535 for (index = 0; index < pdp->cArgs; index++)
1536 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1540 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1542 TRACE("%p ref %lu\n", pty, pty->ref);
1543 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1544 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1545 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1546 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1547 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1548 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1549 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1550 if (TRACE_ON(ole))
1551 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1552 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1553 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1556 static void dump_VARDESC(const VARDESC *v)
1558 MESSAGE("memid %ld\n",v->memid);
1559 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1560 MESSAGE("oInst %ld\n", v->u.oInst);
1561 dump_ELEMDESC(&(v->elemdescVar));
1562 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1563 MESSAGE("varkind %d\n",v->varkind);
1566 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1568 /* VT_LPWSTR is largest type that, may appear in type description */
1569 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1570 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1571 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1572 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1573 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1574 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1575 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1576 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1579 static void TLB_abort(void)
1581 DebugBreak();
1584 /* returns the size required for a deep copy of a typedesc into a
1585 * flat buffer */
1586 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1588 SIZE_T size = 0;
1590 if (alloc_initial_space)
1591 size += sizeof(TYPEDESC);
1593 switch (tdesc->vt)
1595 case VT_PTR:
1596 case VT_SAFEARRAY:
1597 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1598 break;
1599 case VT_CARRAY:
1600 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1601 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1602 break;
1604 return size;
1607 /* deep copy a typedesc into a flat buffer */
1608 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1610 if (!dest)
1612 dest = buffer;
1613 buffer = (char *)buffer + sizeof(TYPEDESC);
1616 *dest = *src;
1618 switch (src->vt)
1620 case VT_PTR:
1621 case VT_SAFEARRAY:
1622 dest->u.lptdesc = buffer;
1623 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1624 break;
1625 case VT_CARRAY:
1626 dest->u.lpadesc = buffer;
1627 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1628 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1629 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1630 break;
1632 return buffer;
1635 /* free custom data allocated by MSFT_CustData */
1636 static inline void TLB_FreeCustData(struct list *custdata_list)
1638 TLBCustData *cd, *cdn;
1639 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1641 list_remove(&cd->entry);
1642 VariantClear(&cd->data);
1643 heap_free(cd);
1647 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1649 DWORD len;
1650 BSTR ret;
1652 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1653 ret = SysAllocStringLen(NULL, len - 1);
1654 if (!ret) return ret;
1655 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1656 return ret;
1659 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1661 int i;
1663 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1665 if (typeinfo->funcdescs[i].funcdesc.memid == memid)
1666 return &typeinfo->funcdescs[i];
1669 return NULL;
1672 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl *typeinfo, MEMBERID memid, INVOKEKIND invkind)
1674 int i;
1676 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1678 if (typeinfo->funcdescs[i].funcdesc.memid == memid && typeinfo->funcdescs[i].funcdesc.invkind == invkind)
1679 return &typeinfo->funcdescs[i];
1682 return NULL;
1685 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1687 int i;
1689 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1691 if (typeinfo->vardescs[i].vardesc.memid == memid)
1692 return &typeinfo->vardescs[i];
1695 return NULL;
1698 static inline TLBVarDesc *TLB_get_vardesc_by_name(ITypeInfoImpl *typeinfo, const OLECHAR *name)
1700 int i;
1702 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1704 if (!lstrcmpiW(TLB_get_bstr(typeinfo->vardescs[i].Name), name))
1705 return &typeinfo->vardescs[i];
1708 return NULL;
1711 static inline TLBCustData *TLB_get_custdata_by_guid(const struct list *custdata_list, REFGUID guid)
1713 TLBCustData *cust_data;
1714 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1715 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1716 return cust_data;
1717 return NULL;
1720 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeLibImpl *typelib, const OLECHAR *name)
1722 int i;
1724 for (i = 0; i < typelib->TypeInfoCount; ++i)
1726 if (!lstrcmpiW(TLB_get_bstr(typelib->typeinfos[i]->Name), name))
1727 return typelib->typeinfos[i];
1730 return NULL;
1733 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1735 list_init(&var_desc->custdata_list);
1738 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1740 TLBVarDesc *ret;
1742 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1743 if(!ret)
1744 return NULL;
1746 while(n){
1747 TLBVarDesc_Constructor(&ret[n-1]);
1748 --n;
1751 return ret;
1754 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1756 TLBParDesc *ret;
1758 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1759 if(!ret)
1760 return NULL;
1762 while(n){
1763 list_init(&ret[n-1].custdata_list);
1764 --n;
1767 return ret;
1770 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1772 list_init(&func_desc->custdata_list);
1775 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1777 TLBFuncDesc *ret;
1779 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1780 if(!ret)
1781 return NULL;
1783 while(n){
1784 TLBFuncDesc_Constructor(&ret[n-1]);
1785 --n;
1788 return ret;
1791 static void TLBImplType_Constructor(TLBImplType *impl)
1793 list_init(&impl->custdata_list);
1796 static TLBImplType *TLBImplType_Alloc(UINT n)
1798 TLBImplType *ret;
1800 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1801 if(!ret)
1802 return NULL;
1804 while(n){
1805 TLBImplType_Constructor(&ret[n-1]);
1806 --n;
1809 return ret;
1812 static TLBGuid *TLB_append_guid(struct list *guid_list,
1813 const GUID *new_guid, HREFTYPE hreftype)
1815 TLBGuid *guid;
1817 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1818 if (IsEqualGUID(&guid->guid, new_guid))
1819 return guid;
1822 guid = heap_alloc(sizeof(TLBGuid));
1823 if (!guid)
1824 return NULL;
1826 memcpy(&guid->guid, new_guid, sizeof(GUID));
1827 guid->hreftype = hreftype;
1829 list_add_tail(guid_list, &guid->entry);
1831 return guid;
1834 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1836 TLBCustData *cust_data;
1838 switch(V_VT(var)){
1839 case VT_I4:
1840 case VT_R4:
1841 case VT_UI4:
1842 case VT_INT:
1843 case VT_UINT:
1844 case VT_HRESULT:
1845 case VT_BSTR:
1846 break;
1847 default:
1848 return DISP_E_BADVARTYPE;
1851 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1853 if (!cust_data) {
1854 cust_data = heap_alloc(sizeof(TLBCustData));
1855 if (!cust_data)
1856 return E_OUTOFMEMORY;
1858 cust_data->guid = tlbguid;
1859 VariantInit(&cust_data->data);
1861 list_add_tail(custdata_list, &cust_data->entry);
1862 }else
1863 VariantClear(&cust_data->data);
1865 return VariantCopy(&cust_data->data, var);
1868 /* Used to update list pointers after list itself was moved. */
1869 static void TLB_relink_custdata(struct list *custdata_list)
1871 if (custdata_list->prev == custdata_list->next)
1872 list_init(custdata_list);
1873 else
1875 custdata_list->prev->next = custdata_list;
1876 custdata_list->next->prev = custdata_list;
1880 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1882 TLBString *str;
1884 if(!new_str)
1885 return NULL;
1887 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1888 if (wcscmp(str->str, new_str) == 0)
1889 return str;
1892 str = heap_alloc(sizeof(TLBString));
1893 if (!str)
1894 return NULL;
1896 str->str = SysAllocString(new_str);
1897 if (!str->str) {
1898 heap_free(str);
1899 return NULL;
1902 list_add_tail(string_list, &str->entry);
1904 return str;
1907 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1908 ULONG *size, WORD *align)
1910 ITypeInfo *other;
1911 TYPEATTR *attr;
1912 HRESULT hr;
1914 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1915 if(FAILED(hr))
1916 return hr;
1918 hr = ITypeInfo_GetTypeAttr(other, &attr);
1919 if(FAILED(hr)){
1920 ITypeInfo_Release(other);
1921 return hr;
1924 if(size)
1925 *size = attr->cbSizeInstance;
1926 if(align)
1927 *align = attr->cbAlignment;
1929 ITypeInfo_ReleaseTypeAttr(other, attr);
1930 ITypeInfo_Release(other);
1932 return S_OK;
1935 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1936 TYPEDESC *tdesc, ULONG *size, WORD *align)
1938 ULONG i, sub, ptr_size;
1939 HRESULT hr;
1941 ptr_size = get_ptr_size(sys);
1943 switch(tdesc->vt){
1944 case VT_VOID:
1945 *size = 0;
1946 break;
1947 case VT_I1:
1948 case VT_UI1:
1949 *size = 1;
1950 break;
1951 case VT_I2:
1952 case VT_BOOL:
1953 case VT_UI2:
1954 *size = 2;
1955 break;
1956 case VT_I4:
1957 case VT_R4:
1958 case VT_ERROR:
1959 case VT_UI4:
1960 case VT_INT:
1961 case VT_UINT:
1962 case VT_HRESULT:
1963 *size = 4;
1964 break;
1965 case VT_R8:
1966 case VT_I8:
1967 case VT_UI8:
1968 *size = 8;
1969 break;
1970 case VT_BSTR:
1971 case VT_DISPATCH:
1972 case VT_UNKNOWN:
1973 case VT_PTR:
1974 case VT_SAFEARRAY:
1975 case VT_LPSTR:
1976 case VT_LPWSTR:
1977 *size = ptr_size;
1978 break;
1979 case VT_DATE:
1980 *size = sizeof(DATE);
1981 break;
1982 case VT_VARIANT:
1983 *size = sizeof(VARIANT);
1984 #ifdef _WIN64
1985 if(sys == SYS_WIN32)
1986 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1987 #endif
1988 break;
1989 case VT_DECIMAL:
1990 *size = sizeof(DECIMAL);
1991 break;
1992 case VT_CY:
1993 *size = sizeof(CY);
1994 break;
1995 case VT_CARRAY:
1996 *size = 0;
1997 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
1998 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
1999 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2000 if(FAILED(hr))
2001 return hr;
2002 *size *= sub;
2003 return S_OK;
2004 case VT_USERDEFINED:
2005 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2006 default:
2007 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2008 return E_FAIL;
2011 if(align){
2012 if(*size < 4)
2013 *align = *size;
2014 else
2015 *align = 4;
2018 return S_OK;
2021 /**********************************************************************
2023 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2026 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2028 if (where != DO_NOT_SEEK)
2030 where += pcx->oStart;
2031 if (where > pcx->length)
2033 /* FIXME */
2034 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
2035 TLB_abort();
2037 pcx->pos = where;
2041 /* read function */
2042 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2044 TRACE_(typelib)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2045 pcx->pos, count, pcx->oStart, pcx->length, where);
2047 MSFT_Seek(pcx, where);
2048 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2049 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2050 pcx->pos += count;
2051 return count;
2054 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2055 LONG where )
2057 DWORD ret;
2059 ret = MSFT_Read(buffer, count, pcx, where);
2060 FromLEDWords(buffer, ret);
2062 return ret;
2065 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2066 LONG where )
2068 DWORD ret;
2070 ret = MSFT_Read(buffer, count, pcx, where);
2071 FromLEWords(buffer, ret);
2073 return ret;
2076 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2078 TLBGuid *guid;
2079 MSFT_GuidEntry entry;
2080 int offs = 0;
2082 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2083 while (1) {
2084 if (offs >= pcx->pTblDir->pGuidTab.length)
2085 return S_OK;
2087 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2089 guid = heap_alloc(sizeof(TLBGuid));
2091 guid->offset = offs;
2092 guid->guid = entry.guid;
2093 guid->hreftype = entry.hreftype;
2095 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2097 offs += sizeof(MSFT_GuidEntry);
2101 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2103 TLBGuid *ret;
2105 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2106 if(ret->offset == offset){
2107 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2108 return ret;
2112 return NULL;
2115 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2117 MSFT_NameIntro niName;
2119 if (offset < 0)
2121 ERR_(typelib)("bad offset %d\n", offset);
2122 return -1;
2125 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2126 pcx->pTblDir->pNametab.offset+offset);
2128 return niName.hreftype;
2131 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2133 char *string;
2134 MSFT_NameIntro intro;
2135 INT16 len_piece;
2136 int offs = 0, lengthInChars;
2138 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2139 while (1) {
2140 TLBString *tlbstr;
2142 if (offs >= pcx->pTblDir->pNametab.length)
2143 return S_OK;
2145 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2146 intro.namelen &= 0xFF;
2147 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2148 if(len_piece % 4)
2149 len_piece = (len_piece + 4) & ~0x3;
2150 if(len_piece < 8)
2151 len_piece = 8;
2153 string = heap_alloc(len_piece + 1);
2154 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2155 string[intro.namelen] = '\0';
2157 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2158 string, -1, NULL, 0);
2159 if (!lengthInChars) {
2160 heap_free(string);
2161 return E_UNEXPECTED;
2164 tlbstr = heap_alloc(sizeof(TLBString));
2166 tlbstr->offset = offs;
2167 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2168 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2170 heap_free(string);
2172 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2174 offs += len_piece;
2178 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2180 TLBString *tlbstr;
2182 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2183 if (tlbstr->offset == offset) {
2184 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2185 return tlbstr;
2189 return NULL;
2192 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2194 TLBString *tlbstr;
2196 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2197 if (tlbstr->offset == offset) {
2198 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2199 return tlbstr;
2203 return NULL;
2207 * read a value and fill a VARIANT structure
2209 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2211 int size;
2213 TRACE_(typelib)("\n");
2215 if(offset <0) { /* data are packed in here */
2216 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2217 V_I4(pVar) = offset & 0x3ffffff;
2218 return;
2220 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2221 pcx->pTblDir->pCustData.offset + offset );
2222 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2223 switch (V_VT(pVar)){
2224 case VT_EMPTY: /* FIXME: is this right? */
2225 case VT_NULL: /* FIXME: is this right? */
2226 case VT_I2 : /* this should not happen */
2227 case VT_I4 :
2228 case VT_R4 :
2229 case VT_ERROR :
2230 case VT_BOOL :
2231 case VT_I1 :
2232 case VT_UI1 :
2233 case VT_UI2 :
2234 case VT_UI4 :
2235 case VT_INT :
2236 case VT_UINT :
2237 case VT_VOID : /* FIXME: is this right? */
2238 case VT_HRESULT :
2239 size=4; break;
2240 case VT_R8 :
2241 case VT_CY :
2242 case VT_DATE :
2243 case VT_I8 :
2244 case VT_UI8 :
2245 case VT_DECIMAL : /* FIXME: is this right? */
2246 case VT_FILETIME :
2247 size=8;break;
2248 /* pointer types with known behaviour */
2249 case VT_BSTR :{
2250 char * ptr;
2251 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2252 if(size == -1){
2253 V_BSTR(pVar) = NULL;
2254 }else{
2255 int len;
2256 ptr = heap_alloc_zero(size);
2257 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2258 len = MultiByteToWideChar(CP_ACP, 0, ptr, size, NULL, 0 );
2259 V_BSTR(pVar)=SysAllocStringLen(NULL,len);
2260 MultiByteToWideChar(CP_ACP, 0, ptr, size, V_BSTR(pVar), len );
2261 heap_free(ptr);
2264 size=-4; break;
2265 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2266 case VT_DISPATCH :
2267 case VT_VARIANT :
2268 case VT_UNKNOWN :
2269 case VT_PTR :
2270 case VT_SAFEARRAY :
2271 case VT_CARRAY :
2272 case VT_USERDEFINED :
2273 case VT_LPSTR :
2274 case VT_LPWSTR :
2275 case VT_BLOB :
2276 case VT_STREAM :
2277 case VT_STORAGE :
2278 case VT_STREAMED_OBJECT :
2279 case VT_STORED_OBJECT :
2280 case VT_BLOB_OBJECT :
2281 case VT_CF :
2282 case VT_CLSID :
2283 default:
2284 size=0;
2285 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2286 V_VT(pVar));
2289 if(size>0) /* (big|small) endian correct? */
2290 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2291 return;
2294 * create a linked list with custom data
2296 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2298 MSFT_CDGuid entry;
2299 TLBCustData* pNew;
2300 int count=0;
2302 TRACE_(typelib)("\n");
2304 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2306 while(offset >=0){
2307 count++;
2308 pNew=heap_alloc_zero(sizeof(TLBCustData));
2309 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2310 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2311 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2312 list_add_head(custdata_list, &pNew->entry);
2313 offset = entry.next;
2315 return count;
2318 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2320 if(type <0)
2321 pTd->vt=type & VT_TYPEMASK;
2322 else
2323 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2325 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2328 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2330 return (invkind == INVOKE_PROPERTYGET ||
2331 invkind == INVOKE_PROPERTYPUT ||
2332 invkind == INVOKE_PROPERTYPUTREF);
2335 static void
2336 MSFT_DoFuncs(TLBContext* pcx,
2337 ITypeInfoImpl* pTI,
2338 int cFuncs,
2339 int cVars,
2340 int offset,
2341 TLBFuncDesc** pptfd)
2344 * member information is stored in a data structure at offset
2345 * indicated by the memoffset field of the typeinfo structure
2346 * There are several distinctive parts.
2347 * The first part starts with a field that holds the total length
2348 * of this (first) part excluding this field. Then follow the records,
2349 * for each member there is one record.
2351 * The first entry is always the length of the record (including this
2352 * length word).
2353 * The rest of the record depends on the type of the member. If there is
2354 * a field indicating the member type (function, variable, interface, etc)
2355 * I have not found it yet. At this time we depend on the information
2356 * in the type info and the usual order how things are stored.
2358 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2359 * for each member;
2361 * Third is an equal sized array with file offsets to the name entry
2362 * of each member.
2364 * The fourth and last (?) part is an array with offsets to the records
2365 * in the first part of this file segment.
2368 int infolen, nameoffset, reclength, i;
2369 int recoffset = offset + sizeof(INT);
2371 char *recbuf = heap_alloc(0xffff);
2372 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2373 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2375 TRACE_(typelib)("\n");
2377 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2379 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2380 ptfd = *pptfd;
2381 for ( i = 0; i < cFuncs ; i++ )
2383 int optional;
2385 /* name, eventually add to a hash table */
2386 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2387 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2389 /* read the function information record */
2390 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2392 reclength &= 0xffff;
2394 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2396 /* size without argument data */
2397 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2398 if (pFuncRec->FKCCIC & 0x1000)
2399 optional -= pFuncRec->nrargs * sizeof(INT);
2401 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2402 ptfd->helpcontext = pFuncRec->HelpContext;
2404 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2405 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2407 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2409 if (pFuncRec->FKCCIC & 0x2000 )
2411 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2412 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2413 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2415 else
2416 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2418 else
2419 ptfd->Entry = (TLBString*)-1;
2421 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2422 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2424 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2425 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2427 /* fill the FuncDesc Structure */
2428 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2429 offset + infolen + ( i + 1) * sizeof(INT));
2431 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2432 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2433 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2434 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2435 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2436 if (ptfd->funcdesc.funckind == FUNC_DISPATCH)
2437 ptfd->funcdesc.oVft = 0;
2438 else
2439 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2440 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2442 /* nameoffset is sometimes -1 on the second half of a propget/propput
2443 * pair of functions */
2444 if ((nameoffset == -1) && (i > 0) &&
2445 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2446 TLB_is_propgetput(ptfd->funcdesc.invkind))
2447 ptfd->Name = ptfd_prev->Name;
2448 else
2449 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2451 MSFT_GetTdesc(pcx,
2452 pFuncRec->DataType,
2453 &ptfd->funcdesc.elemdescFunc.tdesc);
2455 /* do the parameters/arguments */
2456 if(pFuncRec->nrargs)
2458 int j = 0;
2459 MSFT_ParameterInfo paraminfo;
2461 ptfd->funcdesc.lprgelemdescParam =
2462 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2464 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2466 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2467 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2469 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2471 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2473 MSFT_GetTdesc(pcx,
2474 paraminfo.DataType,
2475 &elemdesc->tdesc);
2477 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2479 /* name */
2480 if (paraminfo.oName != -1)
2481 ptfd->pParamDesc[j].Name =
2482 MSFT_ReadName( pcx, paraminfo.oName );
2483 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2485 /* default value */
2486 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2487 (pFuncRec->FKCCIC & 0x1000) )
2489 INT* pInt = (INT *)((char *)pFuncRec +
2490 reclength -
2491 (pFuncRec->nrargs * 4) * sizeof(INT) );
2493 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2495 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2496 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2498 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2499 pInt[j], pcx);
2501 else
2502 elemdesc->u.paramdesc.pparamdescex = NULL;
2504 /* custom info */
2505 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2506 j*sizeof(pFuncRec->oArgCustData[0])) &&
2507 pFuncRec->FKCCIC & 0x80 )
2509 MSFT_CustData(pcx,
2510 pFuncRec->oArgCustData[j],
2511 &ptfd->pParamDesc[j].custdata_list);
2514 /* SEEK value = jump to offset,
2515 * from there jump to the end of record,
2516 * go back by (j-1) arguments
2518 MSFT_ReadLEDWords( &paraminfo ,
2519 sizeof(MSFT_ParameterInfo), pcx,
2520 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2521 * sizeof(MSFT_ParameterInfo)));
2525 /* scode is not used: archaic win16 stuff FIXME: right? */
2526 ptfd->funcdesc.cScodes = 0 ;
2527 ptfd->funcdesc.lprgscode = NULL ;
2529 ptfd_prev = ptfd;
2530 ++ptfd;
2531 recoffset += reclength;
2533 heap_free(recbuf);
2536 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2537 int cVars, int offset, TLBVarDesc ** pptvd)
2539 int infolen, nameoffset, reclength;
2540 char recbuf[256];
2541 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2542 TLBVarDesc *ptvd;
2543 int i;
2544 int recoffset;
2546 TRACE_(typelib)("\n");
2548 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2549 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2550 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2551 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2552 recoffset += offset+sizeof(INT);
2553 for(i=0;i<cVars;i++, ++ptvd){
2554 /* name, eventually add to a hash table */
2555 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2556 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2557 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2558 /* read the variable information record */
2559 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2560 reclength &= 0xff;
2561 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2563 /* optional data */
2564 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2565 ptvd->HelpContext = pVarRec->HelpContext;
2567 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2568 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2570 if (reclength > FIELD_OFFSET(MSFT_VarRecord, oCustData))
2571 MSFT_CustData(pcx, pVarRec->oCustData, &ptvd->custdata_list);
2573 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2574 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2576 /* fill the VarDesc Structure */
2577 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2578 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2579 ptvd->vardesc.varkind = pVarRec->VarKind;
2580 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2581 MSFT_GetTdesc(pcx, pVarRec->DataType,
2582 &ptvd->vardesc.elemdescVar.tdesc);
2583 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2584 if(pVarRec->VarKind == VAR_CONST ){
2585 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2586 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2587 pVarRec->OffsValue, pcx);
2588 } else
2589 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2590 recoffset += reclength;
2594 /* process Implemented Interfaces of a com class */
2595 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2596 int offset)
2598 int i;
2599 MSFT_RefRecord refrec;
2600 TLBImplType *pImpl;
2602 TRACE_(typelib)("\n");
2604 pTI->impltypes = TLBImplType_Alloc(count);
2605 pImpl = pTI->impltypes;
2606 for(i=0;i<count;i++){
2607 if(offset<0) break; /* paranoia */
2608 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2609 pImpl->hRef = refrec.reftype;
2610 pImpl->implflags=refrec.flags;
2611 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2612 offset=refrec.onext;
2613 ++pImpl;
2617 #ifdef _WIN64
2618 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2619 * and some structures, and fix the alignment */
2620 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2622 if(info->typeattr.typekind == TKIND_ALIAS){
2623 switch(info->tdescAlias->vt){
2624 case VT_BSTR:
2625 case VT_DISPATCH:
2626 case VT_UNKNOWN:
2627 case VT_PTR:
2628 case VT_SAFEARRAY:
2629 case VT_LPSTR:
2630 case VT_LPWSTR:
2631 info->typeattr.cbSizeInstance = sizeof(void*);
2632 info->typeattr.cbAlignment = sizeof(void*);
2633 break;
2634 case VT_CARRAY:
2635 case VT_USERDEFINED:
2636 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2637 break;
2638 case VT_VARIANT:
2639 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2640 info->typeattr.cbAlignment = 8;
2641 default:
2642 if(info->typeattr.cbSizeInstance < sizeof(void*))
2643 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2644 else
2645 info->typeattr.cbAlignment = sizeof(void*);
2646 break;
2648 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2649 info->typeattr.typekind == TKIND_DISPATCH ||
2650 info->typeattr.typekind == TKIND_COCLASS){
2651 info->typeattr.cbSizeInstance = sizeof(void*);
2652 info->typeattr.cbAlignment = sizeof(void*);
2655 #endif
2658 * process a typeinfo record
2660 static ITypeInfoImpl * MSFT_DoTypeInfo(
2661 TLBContext *pcx,
2662 int count,
2663 ITypeLibImpl * pLibInfo)
2665 MSFT_TypeInfoBase tiBase;
2666 ITypeInfoImpl *ptiRet;
2668 TRACE_(typelib)("count=%u\n", count);
2670 ptiRet = ITypeInfoImpl_Constructor();
2671 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2672 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2674 /* this is where we are coming from */
2675 ptiRet->pTypeLib = pLibInfo;
2676 ptiRet->index=count;
2678 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2679 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2680 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2681 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2682 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2683 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2684 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2685 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2686 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2687 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2688 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2689 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2690 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2691 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2692 TYPEDESC tmp;
2693 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2694 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2695 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2698 /* FIXME: */
2699 /* IDLDESC idldescType; *//* never saw this one != zero */
2701 /* name, eventually add to a hash table */
2702 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2703 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2704 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2705 /* help info */
2706 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2707 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2708 ptiRet->dwHelpContext=tiBase.helpcontext;
2710 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2711 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2713 /* note: InfoType's Help file and HelpStringDll come from the containing
2714 * library. Further HelpString and Docstring appear to be the same thing :(
2716 /* functions */
2717 if(ptiRet->typeattr.cFuncs >0 )
2718 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2719 ptiRet->typeattr.cVars,
2720 tiBase.memoffset, &ptiRet->funcdescs);
2721 /* variables */
2722 if(ptiRet->typeattr.cVars >0 )
2723 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2724 ptiRet->typeattr.cVars,
2725 tiBase.memoffset, &ptiRet->vardescs);
2726 if(ptiRet->typeattr.cImplTypes >0 ) {
2727 switch(ptiRet->typeattr.typekind)
2729 case TKIND_COCLASS:
2730 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2731 tiBase.datatype1);
2732 break;
2733 case TKIND_DISPATCH:
2734 /* This is not -1 when the interface is a non-base dual interface or
2735 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2736 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2737 not this interface.
2740 if (tiBase.datatype1 != -1)
2742 ptiRet->impltypes = TLBImplType_Alloc(1);
2743 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2745 break;
2746 default:
2747 ptiRet->impltypes = TLBImplType_Alloc(1);
2748 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2749 break;
2752 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2754 TRACE_(typelib)("%s guid: %s kind:%s\n",
2755 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2756 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2757 typekind_desc[ptiRet->typeattr.typekind]);
2758 if (TRACE_ON(typelib))
2759 dump_TypeInfo(ptiRet);
2761 return ptiRet;
2764 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2766 char *string;
2767 INT16 len_str, len_piece;
2768 int offs = 0, lengthInChars;
2770 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2771 while (1) {
2772 TLBString *tlbstr;
2774 if (offs >= pcx->pTblDir->pStringtab.length)
2775 return S_OK;
2777 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2778 len_piece = len_str + sizeof(INT16);
2779 if(len_piece % 4)
2780 len_piece = (len_piece + 4) & ~0x3;
2781 if(len_piece < 8)
2782 len_piece = 8;
2784 string = heap_alloc(len_piece + 1);
2785 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2786 string[len_str] = '\0';
2788 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2789 string, -1, NULL, 0);
2790 if (!lengthInChars) {
2791 heap_free(string);
2792 return E_UNEXPECTED;
2795 tlbstr = heap_alloc(sizeof(TLBString));
2797 tlbstr->offset = offs;
2798 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2799 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2801 heap_free(string);
2803 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2805 offs += len_piece;
2809 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2811 TLBRefType *ref;
2812 int offs = 0;
2814 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2815 while (offs < pcx->pTblDir->pImpInfo.length) {
2816 MSFT_ImpInfo impinfo;
2817 TLBImpLib *pImpLib;
2819 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2821 ref = heap_alloc_zero(sizeof(TLBRefType));
2822 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2824 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2825 if(pImpLib->offset==impinfo.oImpFile)
2826 break;
2828 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2829 ref->reference = offs;
2830 ref->pImpTLInfo = pImpLib;
2831 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2832 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2833 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2834 ref->index = TLB_REF_USE_GUID;
2835 } else
2836 ref->index = impinfo.oGuid;
2837 }else{
2838 ERR("Cannot find a reference\n");
2839 ref->reference = -1;
2840 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2843 offs += sizeof(impinfo);
2846 return S_OK;
2849 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2850 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2851 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2852 * tradeoff here.
2854 static struct list tlb_cache = LIST_INIT(tlb_cache);
2855 static CRITICAL_SECTION cache_section;
2856 static CRITICAL_SECTION_DEBUG cache_section_debug =
2858 0, 0, &cache_section,
2859 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2860 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2862 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2865 typedef struct TLB_PEFile
2867 IUnknown IUnknown_iface;
2868 LONG refs;
2869 HMODULE dll;
2870 HRSRC typelib_resource;
2871 HGLOBAL typelib_global;
2872 LPVOID typelib_base;
2873 } TLB_PEFile;
2875 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2877 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2880 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2882 if (IsEqualIID(riid, &IID_IUnknown))
2884 *ppv = iface;
2885 IUnknown_AddRef(iface);
2886 return S_OK;
2888 *ppv = NULL;
2889 return E_NOINTERFACE;
2892 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2894 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2895 return InterlockedIncrement(&This->refs);
2898 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2900 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2901 ULONG refs = InterlockedDecrement(&This->refs);
2902 if (!refs)
2904 if (This->typelib_global)
2905 FreeResource(This->typelib_global);
2906 if (This->dll)
2907 FreeLibrary(This->dll);
2908 heap_free(This);
2910 return refs;
2913 static const IUnknownVtbl TLB_PEFile_Vtable =
2915 TLB_PEFile_QueryInterface,
2916 TLB_PEFile_AddRef,
2917 TLB_PEFile_Release
2920 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2922 TLB_PEFile *This;
2923 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2925 This = heap_alloc(sizeof(TLB_PEFile));
2926 if (!This)
2927 return E_OUTOFMEMORY;
2929 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2930 This->refs = 1;
2931 This->dll = NULL;
2932 This->typelib_resource = NULL;
2933 This->typelib_global = NULL;
2934 This->typelib_base = NULL;
2936 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2937 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2939 if (This->dll)
2941 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), L"TYPELIB");
2942 if (This->typelib_resource)
2944 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2945 if (This->typelib_global)
2947 This->typelib_base = LockResource(This->typelib_global);
2949 if (This->typelib_base)
2951 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2952 *ppBase = This->typelib_base;
2953 *ppFile = &This->IUnknown_iface;
2954 return S_OK;
2959 TRACE("No TYPELIB resource found\n");
2960 hr = E_FAIL;
2963 TLB_PEFile_Release(&This->IUnknown_iface);
2964 return hr;
2967 typedef struct TLB_NEFile
2969 IUnknown IUnknown_iface;
2970 LONG refs;
2971 LPVOID typelib_base;
2972 } TLB_NEFile;
2974 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2976 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2979 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2981 if (IsEqualIID(riid, &IID_IUnknown))
2983 *ppv = iface;
2984 IUnknown_AddRef(iface);
2985 return S_OK;
2987 *ppv = NULL;
2988 return E_NOINTERFACE;
2991 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2993 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2994 return InterlockedIncrement(&This->refs);
2997 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2999 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3000 ULONG refs = InterlockedDecrement(&This->refs);
3001 if (!refs)
3003 heap_free(This->typelib_base);
3004 heap_free(This);
3006 return refs;
3009 static const IUnknownVtbl TLB_NEFile_Vtable =
3011 TLB_NEFile_QueryInterface,
3012 TLB_NEFile_AddRef,
3013 TLB_NEFile_Release
3016 /***********************************************************************
3017 * read_xx_header [internal]
3019 static int read_xx_header( HFILE lzfd )
3021 IMAGE_DOS_HEADER mzh;
3022 char magic[3];
3024 LZSeek( lzfd, 0, SEEK_SET );
3025 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3026 return 0;
3027 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3028 return 0;
3030 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3031 if ( 2 != LZRead( lzfd, magic, 2 ) )
3032 return 0;
3034 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3036 if ( magic[0] == 'N' && magic[1] == 'E' )
3037 return IMAGE_OS2_SIGNATURE;
3038 if ( magic[0] == 'P' && magic[1] == 'E' )
3039 return IMAGE_NT_SIGNATURE;
3041 magic[2] = '\0';
3042 WARN("Can't handle %s files.\n", magic );
3043 return 0;
3047 /***********************************************************************
3048 * find_ne_resource [internal]
3050 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3051 DWORD *resLen, DWORD *resOff )
3053 IMAGE_OS2_HEADER nehd;
3054 NE_TYPEINFO *typeInfo;
3055 NE_NAMEINFO *nameInfo;
3056 DWORD nehdoffset;
3057 LPBYTE resTab;
3058 DWORD resTabSize;
3059 int count;
3061 /* Read in NE header */
3062 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3063 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3065 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3066 if ( !resTabSize )
3068 TRACE("No resources in NE dll\n" );
3069 return FALSE;
3072 /* Read in resource table */
3073 resTab = heap_alloc( resTabSize );
3074 if ( !resTab ) return FALSE;
3076 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3077 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3079 heap_free( resTab );
3080 return FALSE;
3083 /* Find resource */
3084 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3086 if (!IS_INTRESOURCE(typeid)) /* named type */
3088 BYTE len = strlen( typeid );
3089 while (typeInfo->type_id)
3091 if (!(typeInfo->type_id & 0x8000))
3093 BYTE *p = resTab + typeInfo->type_id;
3094 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3096 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3097 typeInfo->count * sizeof(NE_NAMEINFO));
3100 else /* numeric type id */
3102 WORD id = LOWORD(typeid) | 0x8000;
3103 while (typeInfo->type_id)
3105 if (typeInfo->type_id == id) goto found_type;
3106 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3107 typeInfo->count * sizeof(NE_NAMEINFO));
3110 TRACE("No typeid entry found for %p\n", typeid );
3111 heap_free( resTab );
3112 return FALSE;
3114 found_type:
3115 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3117 if (!IS_INTRESOURCE(resid)) /* named resource */
3119 BYTE len = strlen( resid );
3120 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3122 BYTE *p = resTab + nameInfo->id;
3123 if (nameInfo->id & 0x8000) continue;
3124 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3127 else /* numeric resource id */
3129 WORD id = LOWORD(resid) | 0x8000;
3130 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3131 if (nameInfo->id == id) goto found_name;
3133 TRACE("No resid entry found for %p\n", typeid );
3134 heap_free( resTab );
3135 return FALSE;
3137 found_name:
3138 /* Return resource data */
3139 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3140 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3142 heap_free( resTab );
3143 return TRUE;
3146 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3148 HFILE lzfd = -1;
3149 OFSTRUCT ofs;
3150 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3151 TLB_NEFile *This;
3153 This = heap_alloc(sizeof(TLB_NEFile));
3154 if (!This) return E_OUTOFMEMORY;
3156 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3157 This->refs = 1;
3158 This->typelib_base = NULL;
3160 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3161 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3163 DWORD reslen, offset;
3164 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3166 This->typelib_base = heap_alloc(reslen);
3167 if( !This->typelib_base )
3168 hr = E_OUTOFMEMORY;
3169 else
3171 LZSeek( lzfd, offset, SEEK_SET );
3172 reslen = LZRead( lzfd, This->typelib_base, reslen );
3173 LZClose( lzfd );
3174 *ppBase = This->typelib_base;
3175 *pdwTLBLength = reslen;
3176 *ppFile = &This->IUnknown_iface;
3177 return S_OK;
3182 if( lzfd >= 0) LZClose( lzfd );
3183 TLB_NEFile_Release(&This->IUnknown_iface);
3184 return hr;
3187 typedef struct TLB_Mapping
3189 IUnknown IUnknown_iface;
3190 LONG refs;
3191 HANDLE file;
3192 HANDLE mapping;
3193 LPVOID typelib_base;
3194 } TLB_Mapping;
3196 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3198 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3201 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3203 if (IsEqualIID(riid, &IID_IUnknown))
3205 *ppv = iface;
3206 IUnknown_AddRef(iface);
3207 return S_OK;
3209 *ppv = NULL;
3210 return E_NOINTERFACE;
3213 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3215 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3216 return InterlockedIncrement(&This->refs);
3219 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3221 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3222 ULONG refs = InterlockedDecrement(&This->refs);
3223 if (!refs)
3225 if (This->typelib_base)
3226 UnmapViewOfFile(This->typelib_base);
3227 if (This->mapping)
3228 CloseHandle(This->mapping);
3229 if (This->file != INVALID_HANDLE_VALUE)
3230 CloseHandle(This->file);
3231 heap_free(This);
3233 return refs;
3236 static const IUnknownVtbl TLB_Mapping_Vtable =
3238 TLB_Mapping_QueryInterface,
3239 TLB_Mapping_AddRef,
3240 TLB_Mapping_Release
3243 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3245 TLB_Mapping *This;
3247 This = heap_alloc(sizeof(TLB_Mapping));
3248 if (!This)
3249 return E_OUTOFMEMORY;
3251 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3252 This->refs = 1;
3253 This->file = INVALID_HANDLE_VALUE;
3254 This->mapping = NULL;
3255 This->typelib_base = NULL;
3257 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3258 if (INVALID_HANDLE_VALUE != This->file)
3260 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3261 if (This->mapping)
3263 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3264 if(This->typelib_base)
3266 /* retrieve file size */
3267 *pdwTLBLength = GetFileSize(This->file, NULL);
3268 *ppBase = This->typelib_base;
3269 *ppFile = &This->IUnknown_iface;
3270 return S_OK;
3275 IUnknown_Release(&This->IUnknown_iface);
3276 return TYPE_E_CANTLOADLIBRARY;
3279 /****************************************************************************
3280 * TLB_ReadTypeLib
3282 * find the type of the typelib file and map the typelib resource into
3283 * the memory
3286 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3289 ITypeLibImpl *entry;
3290 HRESULT ret;
3291 INT index = 1;
3292 LPWSTR index_str, file = (LPWSTR)pszFileName;
3293 LPVOID pBase = NULL;
3294 DWORD dwTLBLength = 0;
3295 IUnknown *pFile = NULL;
3296 HANDLE h;
3298 *ppTypeLib = NULL;
3300 index_str = wcsrchr(pszFileName, '\\');
3301 if(index_str && *++index_str != '\0')
3303 LPWSTR end_ptr;
3304 LONG idx = wcstol(index_str, &end_ptr, 10);
3305 if(*end_ptr == '\0')
3307 int str_len = index_str - pszFileName - 1;
3308 index = idx;
3309 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3310 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3311 file[str_len] = 0;
3315 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3317 if(wcschr(file, '\\'))
3319 lstrcpyW(pszPath, file);
3321 else
3323 int len = GetSystemDirectoryW(pszPath, cchPath);
3324 pszPath[len] = '\\';
3325 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3329 if(file != pszFileName) heap_free(file);
3331 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3332 if(h != INVALID_HANDLE_VALUE){
3333 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3334 CloseHandle(h);
3337 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3339 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3340 EnterCriticalSection(&cache_section);
3341 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3343 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3345 TRACE("cache hit\n");
3346 *ppTypeLib = &entry->ITypeLib2_iface;
3347 ITypeLib2_AddRef(*ppTypeLib);
3348 LeaveCriticalSection(&cache_section);
3349 return S_OK;
3352 LeaveCriticalSection(&cache_section);
3354 /* now actually load and parse the typelib */
3356 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3357 if (ret == TYPE_E_CANTLOADLIBRARY)
3358 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3359 if (ret == TYPE_E_CANTLOADLIBRARY)
3360 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3361 if (SUCCEEDED(ret))
3363 if (dwTLBLength >= 4)
3365 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3366 if (dwSignature == MSFT_SIGNATURE)
3367 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3368 else if (dwSignature == SLTG_SIGNATURE)
3369 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3370 else
3372 FIXME("Header type magic %#lx not supported.\n", dwSignature);
3373 ret = TYPE_E_CANTLOADLIBRARY;
3376 else
3377 ret = TYPE_E_CANTLOADLIBRARY;
3378 IUnknown_Release(pFile);
3381 if(*ppTypeLib) {
3382 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3384 TRACE("adding to cache\n");
3385 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3386 lstrcpyW(impl->path, pszPath);
3387 /* We should really canonicalise the path here. */
3388 impl->index = index;
3390 /* FIXME: check if it has added already in the meantime */
3391 EnterCriticalSection(&cache_section);
3392 list_add_head(&tlb_cache, &impl->entry);
3393 LeaveCriticalSection(&cache_section);
3394 ret = S_OK;
3396 else
3398 if(ret != E_FAIL)
3399 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
3401 ret = TYPE_E_CANTLOADLIBRARY;
3405 return ret;
3408 /*================== ITypeLib(2) Methods ===================================*/
3410 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3412 ITypeLibImpl* pTypeLibImpl;
3414 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3415 if (!pTypeLibImpl) return NULL;
3417 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3418 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3419 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3420 pTypeLibImpl->ref = 1;
3422 list_init(&pTypeLibImpl->implib_list);
3423 list_init(&pTypeLibImpl->custdata_list);
3424 list_init(&pTypeLibImpl->name_list);
3425 list_init(&pTypeLibImpl->string_list);
3426 list_init(&pTypeLibImpl->guid_list);
3427 list_init(&pTypeLibImpl->ref_list);
3428 pTypeLibImpl->dispatch_href = -1;
3430 return pTypeLibImpl;
3433 /****************************************************************************
3434 * ITypeLib2_Constructor_MSFT
3436 * loading an MSFT typelib from an in-memory image
3438 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3440 TLBContext cx;
3441 LONG lPSegDir;
3442 MSFT_Header tlbHeader;
3443 MSFT_SegDir tlbSegDir;
3444 ITypeLibImpl * pTypeLibImpl;
3445 int i;
3447 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3449 pTypeLibImpl = TypeLibImpl_Constructor();
3450 if (!pTypeLibImpl) return NULL;
3452 /* get pointer to beginning of typelib data */
3453 cx.pos = 0;
3454 cx.oStart=0;
3455 cx.mapping = pLib;
3456 cx.pLibInfo = pTypeLibImpl;
3457 cx.length = dwTLBLength;
3459 /* read header */
3460 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3461 TRACE_(typelib)("header:\n");
3462 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3463 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3464 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3465 return NULL;
3467 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3469 /* there is a small amount of information here until the next important
3470 * part:
3471 * the segment directory . Try to calculate the amount of data */
3472 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3474 /* now read the segment directory */
3475 TRACE("read segment directory (at %ld)\n",lPSegDir);
3476 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3477 cx.pTblDir = &tlbSegDir;
3479 /* just check two entries */
3480 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3482 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir);
3483 heap_free(pTypeLibImpl);
3484 return NULL;
3487 MSFT_ReadAllNames(&cx);
3488 MSFT_ReadAllStrings(&cx);
3489 MSFT_ReadAllGuids(&cx);
3491 /* now fill our internal data */
3492 /* TLIBATTR fields */
3493 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3495 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3496 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3497 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3498 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3499 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3501 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3502 pTypeLibImpl->lcid = tlbHeader.lcid;
3504 /* name, eventually add to a hash table */
3505 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3507 /* help info */
3508 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3509 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3511 if( tlbHeader.varflags & HELPDLLFLAG)
3513 int offset;
3514 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3515 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3518 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3520 /* custom data */
3521 if(tlbHeader.CustomDataOffset >= 0)
3523 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3526 /* fill in type descriptions */
3527 if(tlbSegDir.pTypdescTab.length > 0)
3529 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3530 INT16 td[4];
3531 pTypeLibImpl->ctTypeDesc = cTD;
3532 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3533 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3534 for(i=0; i<cTD; )
3536 /* FIXME: add several sanity checks here */
3537 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3538 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3540 /* FIXME: check safearray */
3541 if(td[3] < 0)
3542 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3543 else
3544 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3546 else if(td[0] == VT_CARRAY)
3548 /* array descr table here */
3549 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3551 else if(td[0] == VT_USERDEFINED)
3553 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3555 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3558 /* second time around to fill the array subscript info */
3559 for(i=0;i<cTD;i++)
3561 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3562 if(tlbSegDir.pArrayDescriptions.offset>0)
3564 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3565 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3567 if(td[1]<0)
3568 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3569 else
3570 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3572 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3574 for(j = 0; j<td[2]; j++)
3576 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3577 sizeof(INT), &cx, DO_NOT_SEEK);
3578 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3579 sizeof(INT), &cx, DO_NOT_SEEK);
3582 else
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3585 ERR("didn't find array description data\n");
3590 /* imported type libs */
3591 if(tlbSegDir.pImpFiles.offset>0)
3593 TLBImpLib *pImpLib;
3594 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3595 UINT16 size;
3597 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3599 char *name;
3601 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3602 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3603 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3605 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3606 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3607 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3608 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3610 size >>= 2;
3611 name = heap_alloc_zero(size+1);
3612 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3613 pImpLib->name = TLB_MultiByteToBSTR(name);
3614 heap_free(name);
3616 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3617 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3619 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3623 MSFT_ReadAllRefs(&cx);
3625 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3627 /* type infos */
3628 if(tlbHeader.nrtypeinfos >= 0 )
3630 ITypeInfoImpl **ppTI;
3632 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3634 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3636 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3638 ++ppTI;
3639 (pTypeLibImpl->TypeInfoCount)++;
3643 #ifdef _WIN64
3644 if(pTypeLibImpl->syskind == SYS_WIN32){
3645 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3646 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3648 #endif
3650 TRACE("(%p)\n", pTypeLibImpl);
3651 return &pTypeLibImpl->ITypeLib2_iface;
3655 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3657 char b[3];
3658 int i;
3659 short s;
3661 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3662 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3663 return FALSE;
3666 guid->Data4[0] = s >> 8;
3667 guid->Data4[1] = s & 0xff;
3669 b[2] = '\0';
3670 for(i = 0; i < 6; i++) {
3671 memcpy(b, str + 24 + 2 * i, 2);
3672 guid->Data4[i + 2] = strtol(b, NULL, 16);
3674 return TRUE;
3677 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3679 WORD bytelen;
3680 DWORD len;
3681 BSTR tmp_str;
3683 *pStr = NULL;
3684 bytelen = *(const WORD*)ptr;
3685 if(bytelen == 0xffff) return 2;
3687 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3688 tmp_str = SysAllocStringLen(NULL, len);
3689 if (tmp_str) {
3690 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3691 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3692 SysFreeString(tmp_str);
3694 return bytelen + 2;
3697 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3699 WORD bytelen;
3701 *str = NULL;
3702 bytelen = *(const WORD*)ptr;
3703 if(bytelen == 0xffff) return 2;
3704 *str = heap_alloc(bytelen + 1);
3705 memcpy(*str, ptr + 2, bytelen);
3706 (*str)[bytelen] = '\0';
3707 return bytelen + 2;
3710 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3712 BSTR tmp_str;
3713 TLBString *tlbstr;
3715 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3716 if (tlbstr->offset == offset)
3717 return tlbstr;
3720 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3721 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3722 SysFreeString(tmp_str);
3724 return tlbstr;
3727 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3729 char *ptr = pLibBlk;
3730 WORD w;
3732 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3733 FIXME("libblk magic = %04x\n", w);
3734 return 0;
3737 ptr += 6;
3738 if((w = *(WORD*)ptr) != 0xffff) {
3739 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3740 ptr += w;
3742 ptr += 2;
3744 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3746 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3748 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3749 ptr += 4;
3751 pTypeLibImpl->syskind = *(WORD*)ptr;
3752 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3753 ptr += 2;
3755 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3756 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3757 else
3758 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3759 ptr += 2;
3761 ptr += 4; /* skip res12 */
3763 pTypeLibImpl->libflags = *(WORD*)ptr;
3764 ptr += 2;
3766 pTypeLibImpl->ver_major = *(WORD*)ptr;
3767 ptr += 2;
3769 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3770 ptr += 2;
3772 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3773 ptr += sizeof(GUID);
3775 return ptr - (char*)pLibBlk;
3778 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3779 typedef struct
3781 unsigned int num;
3782 HREFTYPE refs[1];
3783 } sltg_ref_lookup_t;
3785 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3786 HREFTYPE *typelib_ref)
3788 if(table && typeinfo_ref < table->num)
3790 *typelib_ref = table->refs[typeinfo_ref];
3791 return S_OK;
3794 ERR_(typelib)("Unable to find reference\n");
3795 *typelib_ref = -1;
3796 return E_FAIL;
3799 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3801 BOOL done = FALSE;
3803 while(!done) {
3804 if((*pType & 0xe00) == 0xe00) {
3805 pTD->vt = VT_PTR;
3806 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3807 pTD = pTD->u.lptdesc;
3809 switch(*pType & 0x3f) {
3810 case VT_PTR:
3811 pTD->vt = VT_PTR;
3812 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3813 pTD = pTD->u.lptdesc;
3814 break;
3816 case VT_USERDEFINED:
3817 pTD->vt = VT_USERDEFINED;
3818 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3819 done = TRUE;
3820 break;
3822 case VT_CARRAY:
3824 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3825 array */
3827 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3829 pTD->vt = VT_CARRAY;
3830 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3831 pTD->u.lpadesc->cDims = pSA->cDims;
3832 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3833 pSA->cDims * sizeof(SAFEARRAYBOUND));
3835 pTD = &pTD->u.lpadesc->tdescElem;
3836 break;
3839 case VT_SAFEARRAY:
3841 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3842 useful? */
3844 pType++;
3845 pTD->vt = VT_SAFEARRAY;
3846 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3847 pTD = pTD->u.lptdesc;
3848 break;
3850 default:
3851 pTD->vt = *pType & 0x3f;
3852 done = TRUE;
3853 break;
3855 pType++;
3857 return pType;
3860 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3861 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3863 /* Handle [in/out] first */
3864 if((*pType & 0xc000) == 0xc000)
3865 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3866 else if(*pType & 0x8000)
3867 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3868 else if(*pType & 0x4000)
3869 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3870 else
3871 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3873 if(*pType & 0x2000)
3874 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3876 if(*pType & 0x80)
3877 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3879 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3883 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3884 char *pNameTable)
3886 unsigned int ref;
3887 char *name;
3888 TLBRefType *ref_type;
3889 sltg_ref_lookup_t *table;
3890 HREFTYPE typelib_ref;
3892 if(pRef->magic != SLTG_REF_MAGIC) {
3893 FIXME("Ref magic = %x\n", pRef->magic);
3894 return NULL;
3896 name = ( (char*)pRef->names + pRef->number);
3898 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3899 table->num = pRef->number >> 3;
3901 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3903 /* We don't want the first href to be 0 */
3904 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3906 for(ref = 0; ref < pRef->number >> 3; ref++) {
3907 char *refname;
3908 unsigned int lib_offs, type_num;
3910 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3912 name += SLTG_ReadStringA(name, &refname);
3913 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3914 FIXME_(typelib)("Can't sscanf ref\n");
3915 if(lib_offs != 0xffff) {
3916 TLBImpLib *import;
3918 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3919 if(import->offset == lib_offs)
3920 break;
3922 if(&import->entry == &pTL->implib_list) {
3923 char fname[MAX_PATH+1];
3924 int len;
3925 GUID tmpguid;
3927 import = heap_alloc_zero(sizeof(*import));
3928 import->offset = lib_offs;
3929 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3930 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3931 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
3932 &import->wVersionMajor,
3933 &import->wVersionMinor,
3934 &import->lcid, fname) != 4) {
3935 FIXME_(typelib)("can't sscanf ref %s\n",
3936 pNameTable + lib_offs + 40);
3938 len = strlen(fname);
3939 if(fname[len-1] != '#')
3940 FIXME("fname = %s\n", fname);
3941 fname[len-1] = '\0';
3942 import->name = TLB_MultiByteToBSTR(fname);
3943 list_add_tail(&pTL->implib_list, &import->entry);
3945 ref_type->pImpTLInfo = import;
3947 /* Store a reference to IDispatch */
3948 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3949 pTL->dispatch_href = typelib_ref;
3951 } else { /* internal ref */
3952 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3954 ref_type->reference = typelib_ref;
3955 ref_type->index = type_num;
3957 heap_free(refname);
3958 list_add_tail(&pTL->ref_list, &ref_type->entry);
3960 table->refs[ref] = typelib_ref;
3961 typelib_ref += 4;
3963 if((BYTE)*name != SLTG_REF_MAGIC)
3964 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3965 dump_TLBRefType(pTL);
3966 return table;
3969 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3970 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3972 SLTG_ImplInfo *info;
3973 TLBImplType *pImplType;
3974 /* I don't really get this structure, usually it's 0x16 bytes
3975 long, but iuser.tlb contains some that are 0x18 bytes long.
3976 That's ok because we can use the next ptr to jump to the next
3977 one. But how do we know the length of the last one? The WORD
3978 at offs 0x8 might be the clue. For now I'm just assuming that
3979 the last one is the regular 0x16 bytes. */
3981 info = (SLTG_ImplInfo*)pBlk;
3982 while(1){
3983 pTI->typeattr.cImplTypes++;
3984 if(info->next == 0xffff)
3985 break;
3986 info = (SLTG_ImplInfo*)(pBlk + info->next);
3989 info = (SLTG_ImplInfo*)pBlk;
3990 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3991 pImplType = pTI->impltypes;
3992 while(1) {
3993 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3994 pImplType->implflags = info->impltypeflags;
3995 ++pImplType;
3997 if(info->next == 0xffff)
3998 break;
3999 if(OneOnly)
4000 FIXME_(typelib)("Interface inheriting more than one interface\n");
4001 info = (SLTG_ImplInfo*)(pBlk + info->next);
4003 info++; /* see comment at top of function */
4004 return (char*)info;
4007 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4008 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4010 TLBVarDesc *pVarDesc;
4011 const TLBString *prevName = NULL;
4012 SLTG_Variable *pItem;
4013 unsigned short i;
4014 WORD *pType;
4016 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4018 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4019 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4021 pVarDesc->vardesc.memid = pItem->memid;
4023 if (pItem->magic != SLTG_VAR_MAGIC &&
4024 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4025 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4026 return;
4029 if (pItem->name == 0xfffe)
4030 pVarDesc->Name = prevName;
4031 else
4032 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4034 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4035 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4036 TRACE_(typelib)("memid = %#lx\n", pItem->memid);
4038 if(pItem->flags & 0x02)
4039 pType = &pItem->type;
4040 else
4041 pType = (WORD*)(pBlk + pItem->type);
4043 if (pItem->flags & ~0xda)
4044 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4046 SLTG_DoElem(pType, pBlk,
4047 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4049 if (TRACE_ON(typelib)) {
4050 char buf[300];
4051 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4052 TRACE_(typelib)("elemdescVar: %s\n", buf);
4055 if (pItem->flags & 0x40) {
4056 TRACE_(typelib)("VAR_DISPATCH\n");
4057 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4059 else if (pItem->flags & 0x10) {
4060 TRACE_(typelib)("VAR_CONST\n");
4061 pVarDesc->vardesc.varkind = VAR_CONST;
4062 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4063 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4064 if (pItem->flags & 0x08)
4065 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4066 else {
4067 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4069 case VT_LPSTR:
4070 case VT_LPWSTR:
4071 case VT_BSTR:
4073 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4074 BSTR str;
4075 TRACE_(typelib)("len = %u\n", len);
4076 if (len == 0xffff) {
4077 str = NULL;
4078 } else {
4079 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4080 str = SysAllocStringLen(NULL, alloc_len);
4081 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4083 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4084 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4085 break;
4087 case VT_I2:
4088 case VT_UI2:
4089 case VT_I4:
4090 case VT_UI4:
4091 case VT_INT:
4092 case VT_UINT:
4093 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4094 *(INT*)(pBlk + pItem->byte_offs);
4095 break;
4096 default:
4097 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4101 else {
4102 TRACE_(typelib)("VAR_PERINSTANCE\n");
4103 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4104 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4107 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4108 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4110 if (pItem->flags & 0x80)
4111 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4113 prevName = pVarDesc->Name;
4115 pTI->typeattr.cVars = cVars;
4118 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4119 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4121 SLTG_Function *pFunc;
4122 unsigned short i;
4123 TLBFuncDesc *pFuncDesc;
4125 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4127 pFuncDesc = pTI->funcdescs;
4128 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4129 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4131 int param;
4132 WORD *pType, *pArg;
4134 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4135 case SLTG_FUNCTION_MAGIC:
4136 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4137 break;
4138 case SLTG_DISPATCH_FUNCTION_MAGIC:
4139 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4140 break;
4141 case SLTG_STATIC_FUNCTION_MAGIC:
4142 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4143 break;
4144 default:
4145 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4146 continue;
4148 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4150 pFuncDesc->funcdesc.memid = pFunc->dispid;
4151 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4152 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4153 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4154 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4155 if (pFuncDesc->funcdesc.funckind == FUNC_DISPATCH)
4156 pFuncDesc->funcdesc.oVft = 0;
4157 else
4158 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4160 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4161 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4163 if(pFunc->retnextopt & 0x80)
4164 pType = &pFunc->rettype;
4165 else
4166 pType = (WORD*)(pBlk + pFunc->rettype);
4168 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4170 pFuncDesc->funcdesc.lprgelemdescParam =
4171 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4172 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4174 pArg = (WORD*)(pBlk + pFunc->arg_off);
4176 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4177 char *paramName = pNameTable + *pArg;
4178 BOOL HaveOffs;
4179 /* If arg type follows then paramName points to the 2nd
4180 letter of the name, else the next WORD is an offset to
4181 the arg type and paramName points to the first letter.
4182 So let's take one char off paramName and see if we're
4183 pointing at an alphanumeric char. However if *pArg is
4184 0xffff or 0xfffe then the param has no name, the former
4185 meaning that the next WORD is the type, the latter
4186 meaning that the next WORD is an offset to the type. */
4188 HaveOffs = FALSE;
4189 if(*pArg == 0xffff)
4190 paramName = NULL;
4191 else if(*pArg == 0xfffe) {
4192 paramName = NULL;
4193 HaveOffs = TRUE;
4195 else if(paramName[-1] && !isalnum(paramName[-1]))
4196 HaveOffs = TRUE;
4198 pArg++;
4200 if(HaveOffs) { /* the next word is an offset to type */
4201 pType = (WORD*)(pBlk + *pArg);
4202 SLTG_DoElem(pType, pBlk,
4203 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4204 pArg++;
4205 } else {
4206 if(paramName)
4207 paramName--;
4208 pArg = SLTG_DoElem(pArg, pBlk,
4209 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4212 /* Are we an optional param ? */
4213 if(pFuncDesc->funcdesc.cParams - param <=
4214 pFuncDesc->funcdesc.cParamsOpt)
4215 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4217 if(paramName) {
4218 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4219 paramName - pNameTable, pTI->pTypeLib);
4220 } else {
4221 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4225 pTI->typeattr.cFuncs = cFuncs;
4228 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4229 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4230 SLTG_TypeInfoTail *pTITail)
4232 char *pFirstItem;
4233 sltg_ref_lookup_t *ref_lookup = NULL;
4235 if(pTIHeader->href_table != 0xffffffff) {
4236 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4237 pNameTable);
4240 pFirstItem = pBlk;
4242 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4243 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4245 heap_free(ref_lookup);
4249 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4250 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4251 const SLTG_TypeInfoTail *pTITail)
4253 char *pFirstItem;
4254 sltg_ref_lookup_t *ref_lookup = NULL;
4256 if(pTIHeader->href_table != 0xffffffff) {
4257 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4258 pNameTable);
4261 pFirstItem = pBlk;
4263 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4264 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4267 if (pTITail->funcs_off != 0xffff)
4268 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4270 heap_free(ref_lookup);
4272 if (TRACE_ON(typelib))
4273 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4276 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4277 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4278 const SLTG_TypeInfoTail *pTITail)
4280 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4283 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4284 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4285 const SLTG_TypeInfoTail *pTITail)
4287 WORD *pType;
4288 sltg_ref_lookup_t *ref_lookup = NULL;
4290 if (pTITail->simple_alias) {
4291 /* if simple alias, no more processing required */
4292 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4293 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4294 return;
4297 if(pTIHeader->href_table != 0xffffffff) {
4298 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4299 pNameTable);
4302 /* otherwise it is an offset to a type */
4303 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4305 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4306 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4308 heap_free(ref_lookup);
4311 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4312 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4313 const SLTG_TypeInfoTail *pTITail)
4315 sltg_ref_lookup_t *ref_lookup = NULL;
4316 if (pTIHeader->href_table != 0xffffffff)
4317 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4318 pNameTable);
4320 if (pTITail->vars_off != 0xffff)
4321 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4323 if (pTITail->funcs_off != 0xffff)
4324 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4326 if (pTITail->impls_off != 0xffff)
4327 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4329 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4330 * of dispinterface functions including the IDispatch ones, so
4331 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4332 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4334 heap_free(ref_lookup);
4335 if (TRACE_ON(typelib))
4336 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4339 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4340 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4341 const SLTG_TypeInfoTail *pTITail)
4343 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4346 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4347 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4348 const SLTG_TypeInfoTail *pTITail)
4350 sltg_ref_lookup_t *ref_lookup = NULL;
4351 if (pTIHeader->href_table != 0xffffffff)
4352 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4353 pNameTable);
4355 if (pTITail->vars_off != 0xffff)
4356 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4358 if (pTITail->funcs_off != 0xffff)
4359 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4360 heap_free(ref_lookup);
4361 if (TRACE_ON(typelib))
4362 dump_TypeInfo(pTI);
4365 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4366 manageable copy of it into this */
4367 typedef struct {
4368 WORD small_no;
4369 char *index_name;
4370 char *other_name;
4371 WORD res1a;
4372 WORD name_offs;
4373 WORD more_bytes;
4374 char *extra;
4375 WORD res20;
4376 DWORD helpcontext;
4377 WORD res26;
4378 GUID uuid;
4379 } SLTG_InternalOtherTypeInfo;
4381 /****************************************************************************
4382 * ITypeLib2_Constructor_SLTG
4384 * loading a SLTG typelib from an in-memory image
4386 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4388 ITypeLibImpl *pTypeLibImpl;
4389 SLTG_Header *pHeader;
4390 SLTG_BlkEntry *pBlkEntry;
4391 SLTG_Magic *pMagic;
4392 SLTG_Index *pIndex;
4393 SLTG_Pad9 *pPad9;
4394 LPVOID pBlk, pFirstBlk;
4395 SLTG_LibBlk *pLibBlk;
4396 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4397 char *pAfterOTIBlks = NULL;
4398 char *pNameTable, *ptr;
4399 int i;
4400 DWORD len, order;
4401 ITypeInfoImpl **ppTypeInfoImpl;
4403 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
4406 pTypeLibImpl = TypeLibImpl_Constructor();
4407 if (!pTypeLibImpl) return NULL;
4409 pHeader = pLib;
4411 TRACE_(typelib)("header:\n");
4412 TRACE_(typelib)("\tmagic %#lx, file blocks = %d\n", pHeader->SLTG_magic,
4413 pHeader->nrOfFileBlks );
4414 if (pHeader->SLTG_magic != SLTG_SIGNATURE)
4416 FIXME_(typelib)("Header type magic %#lx not supported.\n", pHeader->SLTG_magic);
4417 return NULL;
4420 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4421 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4423 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4424 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4426 /* Next we have a magic block */
4427 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4429 /* Let's see if we're still in sync */
4430 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4431 sizeof(SLTG_COMPOBJ_MAGIC))) {
4432 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4433 return NULL;
4435 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4436 sizeof(SLTG_DIR_MAGIC))) {
4437 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4438 return NULL;
4441 pIndex = (SLTG_Index*)(pMagic+1);
4443 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4445 pFirstBlk = pPad9 + 1;
4447 /* We'll set up a ptr to the main library block, which is the last one. */
4449 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4450 pBlkEntry[order].next != 0;
4451 order = pBlkEntry[order].next - 1) {
4452 pBlk = (char*)pBlk + pBlkEntry[order].len;
4454 pLibBlk = pBlk;
4456 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4458 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4459 interspersed */
4461 len += 0x40;
4463 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4465 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4468 ptr = (char*)pLibBlk + len;
4470 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4471 WORD w, extra;
4472 len = 0;
4474 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4476 w = *(WORD*)(ptr + 2);
4477 if(w != 0xffff) {
4478 len += w;
4479 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4480 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4481 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4483 w = *(WORD*)(ptr + 4 + len);
4484 if(w != 0xffff) {
4485 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4486 len += w;
4487 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4488 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4489 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4491 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4492 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4493 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4494 if(extra) {
4495 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4496 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4497 len += extra;
4499 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4500 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4501 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4502 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4503 len += sizeof(SLTG_OtherTypeInfo);
4504 ptr += len;
4507 pAfterOTIBlks = ptr;
4509 /* Skip this WORD and get the next DWORD */
4510 len = *(DWORD*)(pAfterOTIBlks + 2);
4512 /* Now add this to pLibBLk look at what we're pointing at and
4513 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4514 dust and we should be pointing at the beginning of the name
4515 table */
4517 pNameTable = (char*)pLibBlk + len;
4519 switch(*(WORD*)pNameTable) {
4520 case 0xffff:
4521 break;
4522 case 0x0200:
4523 pNameTable += 0x20;
4524 break;
4525 default:
4526 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4527 break;
4530 pNameTable += 0x216;
4532 pNameTable += 2;
4534 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4536 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4539 /* Hopefully we now have enough ptrs set up to actually read in
4540 some TypeInfos. It's not clear which order to do them in, so
4541 I'll just follow the links along the BlkEntry chain and read
4542 them in the order in which they are in the file */
4544 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4545 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4547 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4548 pBlkEntry[order].next != 0;
4549 order = pBlkEntry[order].next - 1, i++) {
4551 SLTG_TypeInfoHeader *pTIHeader;
4552 SLTG_TypeInfoTail *pTITail;
4553 SLTG_MemberHeader *pMemHeader;
4555 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4556 FIXME_(typelib)("Index strings don't match\n");
4557 heap_free(pOtherTypeInfoBlks);
4558 return NULL;
4561 pTIHeader = pBlk;
4562 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4563 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4564 heap_free(pOtherTypeInfoBlks);
4565 return NULL;
4567 TRACE_(typelib)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4568 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4569 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4571 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4572 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4573 (*ppTypeInfoImpl)->index = i;
4574 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4575 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4576 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4577 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4578 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4579 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4580 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4581 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4583 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4584 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4586 if((pTIHeader->typeflags1 & 7) != 2)
4587 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4588 if(pTIHeader->typeflags3 != 2)
4589 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4591 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4592 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4593 typekind_desc[pTIHeader->typekind],
4594 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4595 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4597 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4599 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4601 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4602 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4603 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4605 switch(pTIHeader->typekind) {
4606 case TKIND_ENUM:
4607 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4608 pTIHeader, pTITail);
4609 break;
4611 case TKIND_RECORD:
4612 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4613 pTIHeader, pTITail);
4614 break;
4616 case TKIND_INTERFACE:
4617 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4618 pTIHeader, pTITail);
4619 break;
4621 case TKIND_COCLASS:
4622 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4623 pTIHeader, pTITail);
4624 break;
4626 case TKIND_ALIAS:
4627 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4628 pTIHeader, pTITail);
4629 break;
4631 case TKIND_DISPATCH:
4632 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4633 pTIHeader, pTITail);
4634 break;
4636 case TKIND_MODULE:
4637 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4638 pTIHeader, pTITail);
4639 break;
4641 default:
4642 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4643 break;
4647 /* could get cFuncs, cVars and cImplTypes from here
4648 but we've already set those */
4649 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4650 X(06);
4651 X(16);
4652 X(18);
4653 X(1a);
4654 X(1e);
4655 X(24);
4656 X(26);
4657 X(2a);
4658 X(2c);
4659 X(2e);
4660 X(30);
4661 X(32);
4662 X(34);
4663 #undef X
4664 ++ppTypeInfoImpl;
4665 pBlk = (char*)pBlk + pBlkEntry[order].len;
4668 if(i != pTypeLibImpl->TypeInfoCount) {
4669 FIXME("Somehow processed %d TypeInfos\n", i);
4670 heap_free(pOtherTypeInfoBlks);
4671 return NULL;
4674 heap_free(pOtherTypeInfoBlks);
4675 return &pTypeLibImpl->ITypeLib2_iface;
4678 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4680 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4682 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4684 if(IsEqualIID(riid, &IID_IUnknown) ||
4685 IsEqualIID(riid,&IID_ITypeLib)||
4686 IsEqualIID(riid,&IID_ITypeLib2))
4688 *ppv = &This->ITypeLib2_iface;
4690 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4691 IsEqualIID(riid, &IID_ICreateTypeLib2))
4693 *ppv = &This->ICreateTypeLib2_iface;
4695 else
4697 *ppv = NULL;
4698 TRACE("-- Interface: E_NOINTERFACE\n");
4699 return E_NOINTERFACE;
4702 IUnknown_AddRef((IUnknown*)*ppv);
4703 return S_OK;
4706 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4708 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4709 ULONG ref = InterlockedIncrement(&This->ref);
4711 TRACE("%p, refcount %lu.\n", iface, ref);
4713 return ref;
4716 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4718 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4719 ULONG ref = InterlockedDecrement(&This->ref);
4721 TRACE("%p, refcount %lu.\n", iface, ref);
4723 if (!ref)
4725 TLBImpLib *pImpLib, *pImpLibNext;
4726 TLBRefType *ref_type, *ref_type_next;
4727 TLBString *tlbstr, *tlbstr_next;
4728 TLBGuid *tlbguid, *tlbguid_next;
4729 int i;
4731 /* remove cache entry */
4732 if(This->path)
4734 TRACE("removing from cache list\n");
4735 EnterCriticalSection(&cache_section);
4736 if(This->entry.next)
4737 list_remove(&This->entry);
4738 LeaveCriticalSection(&cache_section);
4739 heap_free(This->path);
4741 TRACE(" destroying ITypeLib(%p)\n",This);
4743 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4744 list_remove(&tlbstr->entry);
4745 SysFreeString(tlbstr->str);
4746 heap_free(tlbstr);
4749 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4750 list_remove(&tlbstr->entry);
4751 SysFreeString(tlbstr->str);
4752 heap_free(tlbstr);
4755 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4756 list_remove(&tlbguid->entry);
4757 heap_free(tlbguid);
4760 TLB_FreeCustData(&This->custdata_list);
4762 for (i = 0; i < This->ctTypeDesc; i++)
4763 if (This->pTypeDesc[i].vt == VT_CARRAY)
4764 heap_free(This->pTypeDesc[i].u.lpadesc);
4766 heap_free(This->pTypeDesc);
4768 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4770 if (pImpLib->pImpTypeLib)
4771 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4772 SysFreeString(pImpLib->name);
4774 list_remove(&pImpLib->entry);
4775 heap_free(pImpLib);
4778 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4780 list_remove(&ref_type->entry);
4781 heap_free(ref_type);
4784 for (i = 0; i < This->TypeInfoCount; ++i){
4785 heap_free(This->typeinfos[i]->tdescAlias);
4786 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4788 heap_free(This->typeinfos);
4789 heap_free(This);
4790 return 0;
4793 return ref;
4796 /* ITypeLib::GetTypeInfoCount
4798 * Returns the number of type descriptions in the type library
4800 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4802 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4803 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4804 return This->TypeInfoCount;
4807 /* ITypeLib::GetTypeInfo
4809 * retrieves the specified type description in the library.
4811 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4812 ITypeLib2 *iface,
4813 UINT index,
4814 ITypeInfo **ppTInfo)
4816 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4818 TRACE("%p %u %p\n", This, index, ppTInfo);
4820 if(!ppTInfo)
4821 return E_INVALIDARG;
4823 if(index >= This->TypeInfoCount)
4824 return TYPE_E_ELEMENTNOTFOUND;
4826 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4827 ITypeInfo_AddRef(*ppTInfo);
4829 return S_OK;
4833 /* ITypeLibs::GetTypeInfoType
4835 * Retrieves the type of a type description.
4837 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4838 ITypeLib2 *iface,
4839 UINT index,
4840 TYPEKIND *pTKind)
4842 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4844 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4846 if(!pTKind)
4847 return E_INVALIDARG;
4849 if(index >= This->TypeInfoCount)
4850 return TYPE_E_ELEMENTNOTFOUND;
4852 *pTKind = This->typeinfos[index]->typeattr.typekind;
4854 return S_OK;
4857 /* ITypeLib::GetTypeInfoOfGuid
4859 * Retrieves the type description that corresponds to the specified GUID.
4862 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4863 ITypeLib2 *iface,
4864 REFGUID guid,
4865 ITypeInfo **ppTInfo)
4867 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4868 int i;
4870 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4872 for(i = 0; i < This->TypeInfoCount; ++i){
4873 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4874 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4875 ITypeInfo_AddRef(*ppTInfo);
4876 return S_OK;
4880 return TYPE_E_ELEMENTNOTFOUND;
4883 /* ITypeLib::GetLibAttr
4885 * Retrieves the structure that contains the library's attributes.
4888 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4889 ITypeLib2 *iface,
4890 LPTLIBATTR *attr)
4892 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4894 TRACE("(%p, %p)\n", This, attr);
4896 if (!attr) return E_INVALIDARG;
4898 *attr = heap_alloc(sizeof(**attr));
4899 if (!*attr) return E_OUTOFMEMORY;
4901 (*attr)->guid = *TLB_get_guid_null(This->guid);
4902 (*attr)->lcid = This->set_lcid;
4903 (*attr)->syskind = This->syskind;
4904 (*attr)->wMajorVerNum = This->ver_major;
4905 (*attr)->wMinorVerNum = This->ver_minor;
4906 (*attr)->wLibFlags = This->libflags;
4908 return S_OK;
4911 /* ITypeLib::GetTypeComp
4913 * Enables a client compiler to bind to a library's types, variables,
4914 * constants, and global functions.
4917 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4918 ITypeLib2 *iface,
4919 ITypeComp **ppTComp)
4921 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4923 TRACE("(%p)->(%p)\n",This,ppTComp);
4924 *ppTComp = &This->ITypeComp_iface;
4925 ITypeComp_AddRef(*ppTComp);
4927 return S_OK;
4930 /* ITypeLib::GetDocumentation
4932 * Retrieves the library's documentation string, the complete Help file name
4933 * and path, and the context identifier for the library Help topic in the Help
4934 * file.
4936 * On a successful return all non-null BSTR pointers will have been set,
4937 * possibly to NULL.
4939 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4940 ITypeLib2 *iface,
4941 INT index,
4942 BSTR *pBstrName,
4943 BSTR *pBstrDocString,
4944 DWORD *pdwHelpContext,
4945 BSTR *pBstrHelpFile)
4947 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4948 HRESULT result = E_INVALIDARG;
4949 ITypeInfo *pTInfo;
4951 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4952 This, index,
4953 pBstrName, pBstrDocString,
4954 pdwHelpContext, pBstrHelpFile);
4956 if(index<0)
4958 /* documentation for the typelib */
4959 if(pBstrName)
4961 if (This->Name)
4963 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4964 goto memerr1;
4966 else
4967 *pBstrName = NULL;
4969 if(pBstrDocString)
4971 if (This->DocString)
4973 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4974 goto memerr2;
4976 else
4977 *pBstrDocString = NULL;
4979 if(pdwHelpContext)
4981 *pdwHelpContext = This->dwHelpContext;
4983 if(pBstrHelpFile)
4985 if (This->HelpFile)
4987 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4988 goto memerr3;
4990 else
4991 *pBstrHelpFile = NULL;
4994 result = S_OK;
4996 else
4998 /* for a typeinfo */
4999 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5001 if(SUCCEEDED(result))
5003 result = ITypeInfo_GetDocumentation(pTInfo,
5004 MEMBERID_NIL,
5005 pBstrName,
5006 pBstrDocString,
5007 pdwHelpContext, pBstrHelpFile);
5009 ITypeInfo_Release(pTInfo);
5012 return result;
5013 memerr3:
5014 if (pBstrDocString) SysFreeString (*pBstrDocString);
5015 memerr2:
5016 if (pBstrName) SysFreeString (*pBstrName);
5017 memerr1:
5018 return STG_E_INSUFFICIENTMEMORY;
5021 /* ITypeLib::IsName
5023 * Indicates whether a passed-in string contains the name of a type or member
5024 * described in the library.
5027 static HRESULT WINAPI ITypeLib2_fnIsName(
5028 ITypeLib2 *iface,
5029 LPOLESTR szNameBuf,
5030 ULONG lHashVal,
5031 BOOL *pfName)
5033 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5034 int tic;
5035 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5037 TRACE("%p, %s, %#lx, %p.\n", iface, debugstr_w(szNameBuf), lHashVal, pfName);
5039 *pfName=TRUE;
5040 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5041 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5042 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5043 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5044 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5045 int pc;
5046 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5047 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5048 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5049 goto ITypeLib2_fnIsName_exit;
5052 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5053 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5054 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5058 *pfName=FALSE;
5060 ITypeLib2_fnIsName_exit:
5061 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5062 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5064 return S_OK;
5067 /* ITypeLib::FindName
5069 * Finds occurrences of a type description in a type library. This may be used
5070 * to quickly verify that a name exists in a type library.
5073 static HRESULT WINAPI ITypeLib2_fnFindName(
5074 ITypeLib2 *iface,
5075 LPOLESTR name,
5076 ULONG hash,
5077 ITypeInfo **ppTInfo,
5078 MEMBERID *memid,
5079 UINT16 *found)
5081 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5082 int tic;
5083 UINT count = 0;
5084 UINT len;
5086 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface, debugstr_w(name), hash, ppTInfo, memid, found);
5088 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5089 return E_INVALIDARG;
5091 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5092 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5093 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5094 TLBVarDesc *var;
5095 UINT fdc;
5097 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5098 memid[count] = MEMBERID_NIL;
5099 goto ITypeLib2_fnFindName_exit;
5102 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5103 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5105 if(!TLB_str_memcmp(name, func->Name, len)) {
5106 memid[count] = func->funcdesc.memid;
5107 goto ITypeLib2_fnFindName_exit;
5111 var = TLB_get_vardesc_by_name(pTInfo, name);
5112 if (var) {
5113 memid[count] = var->vardesc.memid;
5114 goto ITypeLib2_fnFindName_exit;
5117 continue;
5118 ITypeLib2_fnFindName_exit:
5119 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5120 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5121 count++;
5123 TRACE("found %d typeinfos\n", count);
5125 *found = count;
5127 return S_OK;
5130 /* ITypeLib::ReleaseTLibAttr
5132 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5135 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5136 ITypeLib2 *iface,
5137 TLIBATTR *pTLibAttr)
5139 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5140 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5141 heap_free(pTLibAttr);
5144 /* ITypeLib2::GetCustData
5146 * gets the custom data
5148 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5149 ITypeLib2 * iface,
5150 REFGUID guid,
5151 VARIANT *pVarVal)
5153 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5154 TLBCustData *pCData;
5156 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5158 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5159 if(!pCData)
5160 return TYPE_E_ELEMENTNOTFOUND;
5162 VariantInit(pVarVal);
5163 VariantCopy(pVarVal, &pCData->data);
5165 return S_OK;
5168 /* ITypeLib2::GetLibStatistics
5170 * Returns statistics about a type library that are required for efficient
5171 * sizing of hash tables.
5174 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5175 ITypeLib2 * iface,
5176 ULONG *pcUniqueNames,
5177 ULONG *pcchUniqueNames)
5179 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5181 FIXME("(%p): stub!\n", This);
5183 if(pcUniqueNames) *pcUniqueNames=1;
5184 if(pcchUniqueNames) *pcchUniqueNames=1;
5185 return S_OK;
5188 /* ITypeLib2::GetDocumentation2
5190 * Retrieves the library's documentation string, the complete Help file name
5191 * and path, the localization context to use, and the context ID for the
5192 * library Help topic in the Help file.
5195 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5196 ITypeLib2 * iface,
5197 INT index,
5198 LCID lcid,
5199 BSTR *pbstrHelpString,
5200 DWORD *pdwHelpStringContext,
5201 BSTR *pbstrHelpStringDll)
5203 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5204 HRESULT result;
5205 ITypeInfo *pTInfo;
5207 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface, index, lcid);
5209 /* the help string should be obtained from the helpstringdll,
5210 * using the _DLLGetDocumentation function, based on the supplied
5211 * lcid. Nice to do sometime...
5213 if(index<0)
5215 /* documentation for the typelib */
5216 if(pbstrHelpString)
5217 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5218 if(pdwHelpStringContext)
5219 *pdwHelpStringContext=This->dwHelpContext;
5220 if(pbstrHelpStringDll)
5221 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5223 result = S_OK;
5225 else
5227 /* for a typeinfo */
5228 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5230 if(SUCCEEDED(result))
5232 ITypeInfo2 * pTInfo2;
5233 result = ITypeInfo_QueryInterface(pTInfo,
5234 &IID_ITypeInfo2,
5235 (LPVOID*) &pTInfo2);
5237 if(SUCCEEDED(result))
5239 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5240 MEMBERID_NIL,
5241 lcid,
5242 pbstrHelpString,
5243 pdwHelpStringContext,
5244 pbstrHelpStringDll);
5246 ITypeInfo2_Release(pTInfo2);
5249 ITypeInfo_Release(pTInfo);
5252 return result;
5255 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5257 TLBCustData *pCData;
5258 unsigned int ct;
5259 CUSTDATAITEM *cdi;
5260 HRESULT hr = S_OK;
5262 ct = list_count(custdata_list);
5264 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5265 if(!pCustData->prgCustData)
5266 return E_OUTOFMEMORY;
5268 pCustData->cCustData = ct;
5270 cdi = pCustData->prgCustData;
5271 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5272 cdi->guid = *TLB_get_guid_null(pCData->guid);
5273 VariantInit(&cdi->varValue);
5274 hr = VariantCopy(&cdi->varValue, &pCData->data);
5275 if(FAILED(hr)) break;
5276 ++cdi;
5279 return hr;
5283 /* ITypeLib2::GetAllCustData
5285 * Gets all custom data items for the library.
5288 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5289 ITypeLib2 * iface,
5290 CUSTDATA *pCustData)
5292 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5293 TRACE("(%p)->(%p)\n", This, pCustData);
5294 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5297 static const ITypeLib2Vtbl tlbvt = {
5298 ITypeLib2_fnQueryInterface,
5299 ITypeLib2_fnAddRef,
5300 ITypeLib2_fnRelease,
5301 ITypeLib2_fnGetTypeInfoCount,
5302 ITypeLib2_fnGetTypeInfo,
5303 ITypeLib2_fnGetTypeInfoType,
5304 ITypeLib2_fnGetTypeInfoOfGuid,
5305 ITypeLib2_fnGetLibAttr,
5306 ITypeLib2_fnGetTypeComp,
5307 ITypeLib2_fnGetDocumentation,
5308 ITypeLib2_fnIsName,
5309 ITypeLib2_fnFindName,
5310 ITypeLib2_fnReleaseTLibAttr,
5312 ITypeLib2_fnGetCustData,
5313 ITypeLib2_fnGetLibStatistics,
5314 ITypeLib2_fnGetDocumentation2,
5315 ITypeLib2_fnGetAllCustData
5319 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5321 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5323 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5326 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5328 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5330 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5333 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5335 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5337 return ITypeLib2_Release(&This->ITypeLib2_iface);
5340 static HRESULT WINAPI ITypeLibComp_fnBind(
5341 ITypeComp * iface,
5342 OLECHAR * szName,
5343 ULONG lHash,
5344 WORD wFlags,
5345 ITypeInfo ** ppTInfo,
5346 DESCKIND * pDescKind,
5347 BINDPTR * pBindPtr)
5349 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5350 BOOL typemismatch = FALSE;
5351 int i;
5353 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5355 *pDescKind = DESCKIND_NONE;
5356 pBindPtr->lptcomp = NULL;
5357 *ppTInfo = NULL;
5359 for(i = 0; i < This->TypeInfoCount; ++i){
5360 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5361 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5363 /* FIXME: check wFlags here? */
5364 /* FIXME: we should use a hash table to look this info up using lHash
5365 * instead of an O(n) search */
5366 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5367 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5369 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5371 *pDescKind = DESCKIND_TYPECOMP;
5372 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5373 ITypeComp_AddRef(pBindPtr->lptcomp);
5374 TRACE("module or enum: %s\n", debugstr_w(szName));
5375 return S_OK;
5379 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5380 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5382 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5383 HRESULT hr;
5385 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5386 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5388 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5389 return S_OK;
5391 else if (hr == TYPE_E_TYPEMISMATCH)
5392 typemismatch = TRUE;
5395 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5396 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5398 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5399 HRESULT hr;
5400 ITypeInfo *subtypeinfo;
5401 BINDPTR subbindptr;
5402 DESCKIND subdesckind;
5404 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5405 &subtypeinfo, &subdesckind, &subbindptr);
5406 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5408 TYPEDESC tdesc_appobject;
5409 const VARDESC vardesc_appobject =
5411 -2, /* memid */
5412 NULL, /* lpstrSchema */
5414 0 /* oInst */
5417 /* ELEMDESC */
5419 /* TYPEDESC */
5421 &tdesc_appobject
5423 VT_PTR
5426 0, /* wVarFlags */
5427 VAR_STATIC /* varkind */
5430 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5431 tdesc_appobject.vt = VT_USERDEFINED;
5433 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5435 /* cleanup things filled in by Bind call so we can put our
5436 * application object data in there instead */
5437 switch (subdesckind)
5439 case DESCKIND_FUNCDESC:
5440 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5441 break;
5442 case DESCKIND_VARDESC:
5443 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5444 break;
5445 default:
5446 break;
5448 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5450 if (pTypeInfo->hreftype == -1)
5451 FIXME("no hreftype for interface %p\n", pTypeInfo);
5453 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5454 if (FAILED(hr))
5455 return hr;
5457 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5458 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5459 ITypeInfo_AddRef(*ppTInfo);
5460 return S_OK;
5462 else if (hr == TYPE_E_TYPEMISMATCH)
5463 typemismatch = TRUE;
5467 if (typemismatch)
5469 TRACE("type mismatch %s\n", debugstr_w(szName));
5470 return TYPE_E_TYPEMISMATCH;
5472 else
5474 TRACE("name not found %s\n", debugstr_w(szName));
5475 return S_OK;
5479 static HRESULT WINAPI ITypeLibComp_fnBindType(
5480 ITypeComp * iface,
5481 OLECHAR * szName,
5482 ULONG lHash,
5483 ITypeInfo ** ppTInfo,
5484 ITypeComp ** ppTComp)
5486 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5487 ITypeInfoImpl *info;
5489 TRACE("%p, %s, %#lx, %p, %p.\n", iface, debugstr_w(szName), lHash, ppTInfo, ppTComp);
5491 if(!szName || !ppTInfo || !ppTComp)
5492 return E_INVALIDARG;
5494 info = TLB_get_typeinfo_by_name(This, szName);
5495 if(!info){
5496 *ppTInfo = NULL;
5497 *ppTComp = NULL;
5498 return S_OK;
5501 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5502 ITypeInfo_AddRef(*ppTInfo);
5503 *ppTComp = &info->ITypeComp_iface;
5504 ITypeComp_AddRef(*ppTComp);
5506 return S_OK;
5509 static const ITypeCompVtbl tlbtcvt =
5512 ITypeLibComp_fnQueryInterface,
5513 ITypeLibComp_fnAddRef,
5514 ITypeLibComp_fnRelease,
5516 ITypeLibComp_fnBind,
5517 ITypeLibComp_fnBindType
5520 /*================== ITypeInfo(2) Methods ===================================*/
5521 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5523 ITypeInfoImpl *pTypeInfoImpl;
5525 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5526 if (pTypeInfoImpl)
5528 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5529 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5530 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5531 pTypeInfoImpl->ref = 0;
5532 pTypeInfoImpl->hreftype = -1;
5533 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5534 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5535 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5536 list_init(pTypeInfoImpl->pcustdata_list);
5538 TRACE("(%p)\n", pTypeInfoImpl);
5539 return pTypeInfoImpl;
5542 /* ITypeInfo::QueryInterface
5544 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5545 ITypeInfo2 *iface,
5546 REFIID riid,
5547 VOID **ppvObject)
5549 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5551 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5553 *ppvObject=NULL;
5554 if(IsEqualIID(riid, &IID_IUnknown) ||
5555 IsEqualIID(riid,&IID_ITypeInfo)||
5556 IsEqualIID(riid,&IID_ITypeInfo2))
5557 *ppvObject = &This->ITypeInfo2_iface;
5558 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5559 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5560 *ppvObject = &This->ICreateTypeInfo2_iface;
5561 else if(IsEqualIID(riid, &IID_ITypeComp))
5562 *ppvObject = &This->ITypeComp_iface;
5564 if(*ppvObject){
5565 IUnknown_AddRef((IUnknown*)*ppvObject);
5566 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5567 return S_OK;
5569 TRACE("-- Interface: E_NOINTERFACE\n");
5570 return E_NOINTERFACE;
5573 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5575 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5576 ULONG ref = InterlockedIncrement(&This->ref);
5578 TRACE("%p, refcount %lu.\n", iface, ref);
5580 if (ref == 1 /* incremented from 0 */)
5581 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5583 return ref;
5586 static void typeinfo_release_funcdesc(TLBFuncDesc *func)
5588 unsigned int i;
5590 for (i = 0; i < func->funcdesc.cParams; ++i)
5592 ELEMDESC *elemdesc = &func->funcdesc.lprgelemdescParam[i];
5593 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5594 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5595 TLB_FreeCustData(&func->pParamDesc[i].custdata_list);
5597 heap_free(func->funcdesc.lprgelemdescParam);
5598 heap_free(func->pParamDesc);
5599 TLB_FreeCustData(&func->custdata_list);
5602 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5604 UINT i;
5606 TRACE("destroying ITypeInfo(%p)\n",This);
5608 for (i = 0; i < This->typeattr.cFuncs; ++i)
5610 typeinfo_release_funcdesc(&This->funcdescs[i]);
5612 heap_free(This->funcdescs);
5614 for(i = 0; i < This->typeattr.cVars; ++i)
5616 TLBVarDesc *pVInfo = &This->vardescs[i];
5617 if (pVInfo->vardesc_create) {
5618 TLB_FreeVarDesc(pVInfo->vardesc_create);
5619 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5620 VariantClear(pVInfo->vardesc.u.lpvarValue);
5621 heap_free(pVInfo->vardesc.u.lpvarValue);
5623 TLB_FreeCustData(&pVInfo->custdata_list);
5625 heap_free(This->vardescs);
5627 if(This->impltypes){
5628 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5629 TLBImplType *pImpl = &This->impltypes[i];
5630 TLB_FreeCustData(&pImpl->custdata_list);
5632 heap_free(This->impltypes);
5635 TLB_FreeCustData(&This->custdata_list);
5637 heap_free(This);
5640 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5642 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5643 ULONG ref = InterlockedDecrement(&This->ref);
5645 TRACE("%p, refcount %lu.\n", iface, ref);
5647 if (!ref)
5649 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5650 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5651 if (not_attached_to_typelib)
5652 heap_free(This);
5653 /* otherwise This will be freed when typelib is freed */
5656 return ref;
5659 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5660 LPTYPEATTR *ppTypeAttr)
5662 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5663 SIZE_T size;
5665 TRACE("(%p)\n",This);
5667 size = sizeof(**ppTypeAttr);
5668 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5669 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5671 *ppTypeAttr = heap_alloc(size);
5672 if (!*ppTypeAttr)
5673 return E_OUTOFMEMORY;
5675 **ppTypeAttr = This->typeattr;
5676 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5678 if (This->tdescAlias)
5679 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5681 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5682 /* This should include all the inherited funcs */
5683 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5684 /* This is always the size of IDispatch's vtbl */
5685 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5686 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5688 return S_OK;
5691 /* ITypeInfo::GetTypeComp
5693 * Retrieves the ITypeComp interface for the type description, which enables a
5694 * client compiler to bind to the type description's members.
5697 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5698 ITypeComp * *ppTComp)
5700 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5702 TRACE("(%p)->(%p)\n", This, ppTComp);
5704 *ppTComp = &This->ITypeComp_iface;
5705 ITypeComp_AddRef(*ppTComp);
5706 return S_OK;
5709 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5711 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5712 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5713 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5714 return size;
5717 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5719 *dest = *src;
5720 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5721 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5723 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5724 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5725 *buffer += sizeof(PARAMDESCEX);
5726 *pparamdescex_dest = *pparamdescex_src;
5727 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5728 VariantInit(&pparamdescex_dest->varDefaultValue);
5729 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5730 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5732 else
5733 dest->u.paramdesc.pparamdescex = NULL;
5734 return S_OK;
5737 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5739 if (V_VT(var) == VT_INT)
5740 return VariantChangeType(var, var, 0, VT_I4);
5741 else if (V_VT(var) == VT_UINT)
5742 return VariantChangeType(var, var, 0, VT_UI4);
5744 return S_OK;
5747 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5749 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5750 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5753 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5755 FUNCDESC *dest;
5756 char *buffer;
5757 SIZE_T size = sizeof(*src);
5758 SHORT i;
5759 HRESULT hr;
5761 size += sizeof(*src->lprgscode) * src->cScodes;
5762 size += TLB_SizeElemDesc(&src->elemdescFunc);
5763 for (i = 0; i < src->cParams; i++)
5765 size += sizeof(ELEMDESC);
5766 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5769 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5770 if (!dest) return E_OUTOFMEMORY;
5772 *dest = *src;
5773 if (dispinterface) /* overwrite funckind */
5774 dest->funckind = FUNC_DISPATCH;
5775 buffer = (char *)(dest + 1);
5777 dest->oVft = dest->oVft & 0xFFFC;
5779 if (dest->cScodes) {
5780 dest->lprgscode = (SCODE *)buffer;
5781 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5782 buffer += sizeof(*src->lprgscode) * src->cScodes;
5783 } else
5784 dest->lprgscode = NULL;
5786 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5787 if (FAILED(hr))
5789 SysFreeString((BSTR)dest);
5790 return hr;
5793 if (dest->cParams) {
5794 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5795 buffer += sizeof(ELEMDESC) * src->cParams;
5796 for (i = 0; i < src->cParams; i++)
5798 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5799 if (FAILED(hr))
5800 break;
5802 if (FAILED(hr))
5804 /* undo the above actions */
5805 for (i = i - 1; i >= 0; i--)
5806 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5807 TLB_FreeElemDesc(&dest->elemdescFunc);
5808 SysFreeString((BSTR)dest);
5809 return hr;
5811 } else
5812 dest->lprgelemdescParam = NULL;
5814 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5815 * This accounts for several arguments that are separate in the signature of
5816 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5817 if (dispinterface && (src->funckind != FUNC_DISPATCH))
5819 /* functions that have a [retval] parameter return this value into pVarResult.
5820 * [retval] is always the last parameter (if present) */
5821 if (dest->cParams &&
5822 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5824 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5825 if (elemdesc->tdesc.vt != VT_PTR)
5827 ERR("elemdesc should have started with VT_PTR instead of:\n");
5828 if (ERR_ON(ole))
5829 dump_ELEMDESC(elemdesc);
5830 return E_UNEXPECTED;
5833 /* the type pointed to by this [retval] becomes elemdescFunc,
5834 * i.e. the function signature's return type.
5835 * We are using a flat buffer so there is no danger of leaking memory */
5836 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5838 /* remove the last parameter */
5839 dest->cParams--;
5841 else if (dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5842 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5843 * not pVarResult. So the function signature should show no return value. */
5844 dest->elemdescFunc.tdesc.vt = VT_VOID;
5846 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5847 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5848 if (dest->cParams && (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
5849 dest->cParams--;
5852 *dest_ptr = dest;
5853 return S_OK;
5856 static void TLB_FreeVarDesc(VARDESC *var_desc)
5858 TLB_FreeElemDesc(&var_desc->elemdescVar);
5859 if (var_desc->varkind == VAR_CONST)
5860 VariantClear(var_desc->u.lpvarValue);
5861 SysFreeString((BSTR)var_desc);
5864 /* internal function to make the inherited interfaces' methods appear
5865 * part of the interface */
5866 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5867 UINT index, const TLBFuncDesc **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5869 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5870 HRESULT hr;
5871 UINT implemented_funcs = 0;
5873 if (funcs)
5874 *funcs = 0;
5875 else
5876 *hrefoffset = DISPATCH_HREF_OFFSET;
5878 if(This->impltypes)
5880 ITypeInfo *pSubTypeInfo;
5881 UINT sub_funcs;
5883 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5884 if (FAILED(hr))
5885 return hr;
5887 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5888 index,
5889 ppFuncDesc,
5890 &sub_funcs, hrefoffset);
5891 implemented_funcs += sub_funcs;
5892 ITypeInfo_Release(pSubTypeInfo);
5893 if (SUCCEEDED(hr))
5894 return hr;
5895 *hrefoffset += DISPATCH_HREF_OFFSET;
5898 if (funcs)
5899 *funcs = implemented_funcs + This->typeattr.cFuncs;
5900 else
5901 *hrefoffset = 0;
5903 if (index < implemented_funcs)
5904 return E_INVALIDARG;
5905 index -= implemented_funcs;
5907 if (index >= This->typeattr.cFuncs)
5908 return TYPE_E_ELEMENTNOTFOUND;
5910 *ppFuncDesc = &This->funcdescs[index];
5911 return S_OK;
5914 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5916 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5918 if (This->typeattr.typekind == TKIND_DISPATCH)
5919 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5921 if (index >= This->typeattr.cFuncs)
5922 return TYPE_E_ELEMENTNOTFOUND;
5924 *func_desc = &This->funcdescs[index];
5925 return S_OK;
5928 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5930 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5931 while (TRUE)
5933 switch (pTypeDesc->vt)
5935 case VT_USERDEFINED:
5936 pTypeDesc->u.hreftype += hrefoffset;
5937 return;
5938 case VT_PTR:
5939 case VT_SAFEARRAY:
5940 pTypeDesc = pTypeDesc->u.lptdesc;
5941 break;
5942 case VT_CARRAY:
5943 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5944 break;
5945 default:
5946 return;
5951 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5953 SHORT i;
5954 for (i = 0; i < pFuncDesc->cParams; i++)
5955 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5956 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5959 /* ITypeInfo::GetFuncDesc
5961 * Retrieves the FUNCDESC structure that contains information about a
5962 * specified function.
5965 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5966 LPFUNCDESC *ppFuncDesc)
5968 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5969 const TLBFuncDesc *internal_funcdesc;
5970 HRESULT hr;
5971 UINT hrefoffset = 0;
5973 TRACE("(%p) index %d\n", This, index);
5975 if (!ppFuncDesc)
5976 return E_INVALIDARG;
5978 if (This->needs_layout)
5979 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5981 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5982 &internal_funcdesc, &hrefoffset);
5983 if (FAILED(hr))
5985 WARN("description for function %d not found\n", index);
5986 return hr;
5989 hr = TLB_AllocAndInitFuncDesc(
5990 &internal_funcdesc->funcdesc,
5991 ppFuncDesc,
5992 This->typeattr.typekind == TKIND_DISPATCH);
5994 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
5995 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5997 TRACE("-- %#lx.\n", hr);
5998 return hr;
6001 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6003 VARDESC *dest;
6004 char *buffer;
6005 SIZE_T size = sizeof(*src);
6006 HRESULT hr;
6008 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6009 if (src->varkind == VAR_CONST)
6010 size += sizeof(VARIANT);
6011 size += TLB_SizeElemDesc(&src->elemdescVar);
6013 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6014 if (!dest) return E_OUTOFMEMORY;
6016 *dest = *src;
6017 buffer = (char *)(dest + 1);
6018 if (src->lpstrSchema)
6020 int len;
6021 dest->lpstrSchema = (LPOLESTR)buffer;
6022 len = lstrlenW(src->lpstrSchema);
6023 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6024 buffer += (len + 1) * sizeof(WCHAR);
6027 if (src->varkind == VAR_CONST)
6029 HRESULT hr;
6031 dest->u.lpvarValue = (VARIANT *)buffer;
6032 *dest->u.lpvarValue = *src->u.lpvarValue;
6033 buffer += sizeof(VARIANT);
6034 VariantInit(dest->u.lpvarValue);
6035 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6036 if (FAILED(hr))
6038 SysFreeString((BSTR)dest);
6039 return hr;
6042 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6043 if (FAILED(hr))
6045 if (src->varkind == VAR_CONST)
6046 VariantClear(dest->u.lpvarValue);
6047 SysFreeString((BSTR)dest);
6048 return hr;
6050 *dest_ptr = dest;
6051 return S_OK;
6054 /* ITypeInfo::GetVarDesc
6056 * Retrieves a VARDESC structure that describes the specified variable.
6059 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6060 LPVARDESC *ppVarDesc)
6062 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6063 const TLBVarDesc *pVDesc = &This->vardescs[index];
6065 TRACE("(%p) index %d\n", This, index);
6067 if(index >= This->typeattr.cVars)
6068 return TYPE_E_ELEMENTNOTFOUND;
6070 if (This->needs_layout)
6071 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6073 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6076 /* internal function to make the inherited interfaces' methods appear
6077 * part of the interface, remembering if the top-level was dispinterface */
6078 static HRESULT typeinfo_getnames( ITypeInfo *iface, MEMBERID memid, BSTR *names,
6079 UINT max_names, UINT *num_names, BOOL dispinterface)
6081 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6082 const TLBFuncDesc *func_desc;
6083 const TLBVarDesc *var_desc;
6084 int i;
6086 *num_names = 0;
6088 func_desc = TLB_get_funcdesc_by_memberid(This, memid);
6089 if (func_desc)
6091 UINT params = func_desc->funcdesc.cParams;
6092 if (!max_names || !func_desc->Name)
6093 return S_OK;
6095 *names = SysAllocString(TLB_get_bstr(func_desc->Name));
6096 ++(*num_names);
6098 if (dispinterface && (func_desc->funcdesc.funckind != FUNC_DISPATCH))
6100 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6101 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
6102 --params; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6103 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
6104 --params; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6107 for (i = 0; i < params; i++)
6109 if (*num_names >= max_names || !func_desc->pParamDesc[i].Name)
6110 return S_OK;
6111 names[*num_names] = SysAllocString(TLB_get_bstr(func_desc->pParamDesc[i].Name));
6112 ++(*num_names);
6114 return S_OK;
6117 var_desc = TLB_get_vardesc_by_memberid(This, memid);
6118 if (var_desc)
6120 *names = SysAllocString(TLB_get_bstr(var_desc->Name));
6121 *num_names = 1;
6123 else
6125 if (This->impltypes &&
6126 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH))
6128 /* recursive search */
6129 ITypeInfo *parent;
6130 HRESULT result;
6131 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &parent);
6132 if (SUCCEEDED(result))
6134 result = typeinfo_getnames(parent, memid, names, max_names, num_names, dispinterface);
6135 ITypeInfo_Release(parent);
6136 return result;
6138 WARN("Could not search inherited interface!\n");
6140 else
6142 WARN("no names found\n");
6144 *num_names = 0;
6145 return TYPE_E_ELEMENTNOTFOUND;
6147 return S_OK;
6150 /* ITypeInfo_GetNames
6152 * Retrieves the variable with the specified member ID (or the name of the
6153 * property or method and its parameters) that correspond to the specified
6154 * function ID.
6156 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6157 BSTR *names, UINT max_names, UINT *num_names)
6159 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6161 TRACE("%p, %#lx, %p, %d, %p\n", iface, memid, names, max_names, num_names);
6163 if (!names) return E_INVALIDARG;
6165 return typeinfo_getnames((ITypeInfo *)iface, memid, names, max_names, num_names,
6166 This->typeattr.typekind == TKIND_DISPATCH);
6169 /* ITypeInfo::GetRefTypeOfImplType
6171 * If a type description describes a COM class, it retrieves the type
6172 * description of the implemented interface types. For an interface,
6173 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6174 * if any exist.
6177 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6178 ITypeInfo2 *iface,
6179 UINT index,
6180 HREFTYPE *pRefType)
6182 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6183 HRESULT hr = S_OK;
6185 TRACE("(%p) index %d\n", This, index);
6186 if (TRACE_ON(ole)) dump_TypeInfo(This);
6188 if(index==(UINT)-1)
6190 /* only valid on dual interfaces;
6191 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6194 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6196 *pRefType = -2;
6198 else
6200 hr = TYPE_E_ELEMENTNOTFOUND;
6203 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6205 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6206 *pRefType = This->pTypeLib->dispatch_href;
6208 else
6210 if(index >= This->typeattr.cImplTypes)
6211 hr = TYPE_E_ELEMENTNOTFOUND;
6212 else{
6213 *pRefType = This->impltypes[index].hRef;
6214 if (This->typeattr.typekind == TKIND_INTERFACE)
6215 *pRefType |= 0x2;
6219 if(TRACE_ON(ole))
6221 if(SUCCEEDED(hr))
6222 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType );
6223 else
6224 TRACE("FAILURE -- hresult %#lx.\n", hr);
6227 return hr;
6230 /* ITypeInfo::GetImplTypeFlags
6232 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6233 * or base interface in a type description.
6235 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6236 UINT index, INT *pImplTypeFlags)
6238 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6240 TRACE("(%p) index %d\n", This, index);
6242 if(!pImplTypeFlags)
6243 return E_INVALIDARG;
6245 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6246 *pImplTypeFlags = 0;
6247 return S_OK;
6250 if(index >= This->typeattr.cImplTypes)
6251 return TYPE_E_ELEMENTNOTFOUND;
6253 *pImplTypeFlags = This->impltypes[index].implflags;
6255 return S_OK;
6258 /* GetIDsOfNames
6259 * Maps between member names and member IDs, and parameter names and
6260 * parameter IDs.
6262 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6263 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6265 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6266 const TLBVarDesc *pVDesc;
6267 HRESULT ret=S_OK;
6268 UINT i, fdc;
6270 TRACE("%p, %s, %d.\n", iface, debugstr_w(*rgszNames), cNames);
6272 /* init out parameters in case of failure */
6273 for (i = 0; i < cNames; i++)
6274 pMemId[i] = MEMBERID_NIL;
6276 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6277 int j;
6278 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6279 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6280 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6281 for(i=1; i < cNames; i++){
6282 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6283 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6284 break;
6285 if( j<pFDesc->funcdesc.cParams)
6286 pMemId[i]=j;
6287 else
6288 ret=DISP_E_UNKNOWNNAME;
6290 TRACE("-- %#lx.\n", ret);
6291 return ret;
6294 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6295 if(pVDesc){
6296 if(cNames)
6297 *pMemId = pVDesc->vardesc.memid;
6298 return ret;
6300 /* not found, see if it can be found in an inherited interface */
6301 if(This->impltypes) {
6302 /* recursive search */
6303 ITypeInfo *pTInfo;
6304 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6305 if(SUCCEEDED(ret)){
6306 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6307 ITypeInfo_Release(pTInfo);
6308 return ret;
6310 WARN("Could not search inherited interface!\n");
6311 } else
6312 WARN("no names found\n");
6313 return DISP_E_UNKNOWNNAME;
6317 #ifdef __i386__
6319 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6320 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6321 __ASM_GLOBAL_FUNC( call_method,
6322 "pushl %ebp\n\t"
6323 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6324 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6325 "movl %esp,%ebp\n\t"
6326 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6327 "pushl %esi\n\t"
6328 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6329 "pushl %edi\n\t"
6330 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6331 "movl 12(%ebp),%edx\n\t"
6332 "movl %esp,%edi\n\t"
6333 "shll $2,%edx\n\t"
6334 "jz 1f\n\t"
6335 "subl %edx,%edi\n\t"
6336 "andl $~15,%edi\n\t"
6337 "movl %edi,%esp\n\t"
6338 "movl 12(%ebp),%ecx\n\t"
6339 "movl 16(%ebp),%esi\n\t"
6340 "cld\n\t"
6341 "rep; movsl\n"
6342 "1:\tcall *8(%ebp)\n\t"
6343 "subl %esp,%edi\n\t"
6344 "movl 20(%ebp),%ecx\n\t"
6345 "movl %edi,(%ecx)\n\t"
6346 "leal -8(%ebp),%esp\n\t"
6347 "popl %edi\n\t"
6348 __ASM_CFI(".cfi_same_value %edi\n\t")
6349 "popl %esi\n\t"
6350 __ASM_CFI(".cfi_same_value %esi\n\t")
6351 "popl %ebp\n\t"
6352 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6353 __ASM_CFI(".cfi_same_value %ebp\n\t")
6354 "ret" )
6355 __ASM_GLOBAL_FUNC( call_double_method,
6356 "jmp " __ASM_NAME("call_method") )
6358 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6359 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6361 int argspos = 0, stack_offset;
6362 void *func;
6363 UINT i;
6364 DWORD *args;
6366 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6367 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6368 pvargResult, V_VT(pvargResult));
6370 if (cc != CC_STDCALL && cc != CC_CDECL)
6372 FIXME("unsupported calling convention %d\n",cc);
6373 return E_INVALIDARG;
6376 /* maximum size for an argument is sizeof(VARIANT) */
6377 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6379 if (pvInstance)
6381 const FARPROC *vtable = *(FARPROC **)pvInstance;
6382 func = vtable[oVft/sizeof(void *)];
6383 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6385 else func = (void *)oVft;
6387 switch (vtReturn)
6389 case VT_DECIMAL:
6390 case VT_VARIANT:
6391 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6392 break;
6393 case VT_HRESULT:
6394 WARN("invalid return type %u\n", vtReturn);
6395 heap_free( args );
6396 return E_INVALIDARG;
6397 default:
6398 break;
6401 for (i = 0; i < cActuals; i++)
6403 VARIANT *arg = prgpvarg[i];
6405 switch (prgvt[i])
6407 case VT_EMPTY:
6408 break;
6409 case VT_I8:
6410 case VT_UI8:
6411 case VT_R8:
6412 case VT_DATE:
6413 case VT_CY:
6414 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6415 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6416 break;
6417 case VT_DECIMAL:
6418 case VT_VARIANT:
6419 memcpy( &args[argspos], arg, sizeof(*arg) );
6420 argspos += sizeof(*arg) / sizeof(DWORD);
6421 break;
6422 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6423 args[argspos++] = V_BOOL(arg);
6424 break;
6425 default:
6426 args[argspos++] = V_UI4(arg);
6427 break;
6429 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6432 switch (vtReturn)
6434 case VT_EMPTY:
6435 case VT_DECIMAL:
6436 case VT_VARIANT:
6437 call_method( func, argspos, args, &stack_offset );
6438 break;
6439 case VT_R4:
6440 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6441 break;
6442 case VT_R8:
6443 case VT_DATE:
6444 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6445 break;
6446 case VT_I8:
6447 case VT_UI8:
6448 case VT_CY:
6449 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6450 break;
6451 default:
6452 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6453 break;
6455 heap_free( args );
6456 if (stack_offset && cc == CC_STDCALL)
6458 WARN( "stack pointer off by %d\n", stack_offset );
6459 return DISP_E_BADCALLEE;
6461 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6462 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6463 return S_OK;
6466 #elif defined(__x86_64__)
6468 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6469 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6470 __ASM_GLOBAL_FUNC( call_method,
6471 "pushq %rbp\n\t"
6472 __ASM_SEH(".seh_pushreg %rbp\n\t")
6473 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6474 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6475 "movq %rsp,%rbp\n\t"
6476 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6477 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6478 "pushq %rsi\n\t"
6479 __ASM_SEH(".seh_pushreg %rsi\n\t")
6480 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6481 "pushq %rdi\n\t"
6482 __ASM_SEH(".seh_pushreg %rdi\n\t")
6483 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6484 __ASM_SEH(".seh_endprologue\n\t")
6485 "movq %rcx,%rax\n\t"
6486 "movq $4,%rcx\n\t"
6487 "cmp %rcx,%rdx\n\t"
6488 "cmovgq %rdx,%rcx\n\t"
6489 "leaq 0(,%rcx,8),%rdx\n\t"
6490 "subq %rdx,%rsp\n\t"
6491 "andq $~15,%rsp\n\t"
6492 "movq %rsp,%rdi\n\t"
6493 "movq %r8,%rsi\n\t"
6494 "rep; movsq\n\t"
6495 "movq 0(%rsp),%rcx\n\t"
6496 "movq 8(%rsp),%rdx\n\t"
6497 "movq 16(%rsp),%r8\n\t"
6498 "movq 24(%rsp),%r9\n\t"
6499 "movq 0(%rsp),%xmm0\n\t"
6500 "movq 8(%rsp),%xmm1\n\t"
6501 "movq 16(%rsp),%xmm2\n\t"
6502 "movq 24(%rsp),%xmm3\n\t"
6503 "callq *%rax\n\t"
6504 "leaq -16(%rbp),%rsp\n\t"
6505 "popq %rdi\n\t"
6506 __ASM_CFI(".cfi_same_value %rdi\n\t")
6507 "popq %rsi\n\t"
6508 __ASM_CFI(".cfi_same_value %rsi\n\t")
6509 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6510 "popq %rbp\n\t"
6511 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6512 __ASM_CFI(".cfi_same_value %rbp\n\t")
6513 "ret")
6514 __ASM_GLOBAL_FUNC( call_double_method,
6515 "jmp " __ASM_NAME("call_method") )
6517 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6518 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6520 int argspos = 0;
6521 UINT i;
6522 DWORD_PTR *args;
6523 void *func;
6525 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6526 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6527 pvargResult, V_VT(pvargResult));
6529 if (cc != CC_STDCALL && cc != CC_CDECL)
6531 FIXME("unsupported calling convention %d\n",cc);
6532 return E_INVALIDARG;
6535 /* maximum size for an argument is sizeof(DWORD_PTR) */
6536 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6538 if (pvInstance)
6540 const FARPROC *vtable = *(FARPROC **)pvInstance;
6541 func = vtable[oVft/sizeof(void *)];
6542 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6544 else func = (void *)oVft;
6546 switch (vtReturn)
6548 case VT_DECIMAL:
6549 case VT_VARIANT:
6550 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6551 break;
6552 case VT_HRESULT:
6553 WARN("invalid return type %u\n", vtReturn);
6554 heap_free( args );
6555 return E_INVALIDARG;
6556 default:
6557 break;
6560 for (i = 0; i < cActuals; i++)
6562 VARIANT *arg = prgpvarg[i];
6564 switch (prgvt[i])
6566 case VT_DECIMAL:
6567 case VT_VARIANT:
6568 args[argspos++] = (ULONG_PTR)arg;
6569 break;
6570 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6571 args[argspos++] = V_BOOL(arg);
6572 break;
6573 default:
6574 args[argspos++] = V_UI8(arg);
6575 break;
6577 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6580 switch (vtReturn)
6582 case VT_R4:
6583 V_R4(pvargResult) = call_double_method( func, argspos, args );
6584 break;
6585 case VT_R8:
6586 case VT_DATE:
6587 V_R8(pvargResult) = call_double_method( func, argspos, args );
6588 break;
6589 case VT_DECIMAL:
6590 case VT_VARIANT:
6591 call_method( func, argspos, args );
6592 break;
6593 default:
6594 V_UI8(pvargResult) = call_method( func, argspos, args );
6595 break;
6597 heap_free( args );
6598 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6599 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6600 return S_OK;
6603 #elif defined(__arm__)
6605 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6606 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6607 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6608 __ASM_GLOBAL_FUNC( call_method,
6609 /* r0 = *func
6610 * r1 = nb_stk_args
6611 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6612 * 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)
6615 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6616 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6618 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6619 "beq 1f\n\t" /* Skip allocation if no stack args */
6620 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6621 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6622 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6623 "subs r1, r1, #4\n\t" /* Decrement count */
6624 "bgt 2b\n\t" /* Loop till done */
6626 "1:\n\t"
6627 #ifndef __SOFTFP__
6628 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6629 #endif
6630 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6631 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6633 "blx ip\n\t" /* Call the target function */
6635 "mov sp, fp\n\t" /* Clean the stack using fp */
6636 "pop {fp, pc}\n\t" /* Restore fp and return */
6638 __ASM_GLOBAL_FUNC( call_float_method,
6639 "b " __ASM_NAME("call_method") )
6640 __ASM_GLOBAL_FUNC( call_double_method,
6641 "b " __ASM_NAME("call_method") )
6643 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6644 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6646 int argspos;
6647 void *func;
6648 UINT i;
6649 DWORD *args;
6650 struct {
6651 #ifndef __SOFTFP__
6652 union {
6653 float s[16];
6654 double d[8];
6655 } sd;
6656 #endif
6657 DWORD r[4];
6658 } regs;
6659 int rcount; /* 32-bit register index count */
6660 #ifndef __SOFTFP__
6661 int scount = 0; /* single-precision float register index count */
6662 int dcount = 0; /* double-precision float register index count */
6663 #endif
6665 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6666 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6668 if (cc != CC_STDCALL && cc != CC_CDECL)
6670 FIXME("unsupported calling convention %d\n",cc);
6671 return E_INVALIDARG;
6674 argspos = 0;
6675 rcount = 0;
6677 if (pvInstance)
6679 const FARPROC *vtable = *(FARPROC **)pvInstance;
6680 func = vtable[oVft/sizeof(void *)];
6681 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6683 else func = (void *)oVft;
6685 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6686 /* first as it will need to be in the 'r' registers: */
6687 switch (vtReturn)
6689 case VT_DECIMAL:
6690 case VT_VARIANT:
6691 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6692 break;
6693 case VT_HRESULT:
6694 WARN("invalid return type %u\n", vtReturn);
6695 return E_INVALIDARG;
6696 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6697 break;
6700 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6701 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6703 for (i = 0; i < cActuals; i++)
6705 VARIANT *arg = prgpvarg[i];
6706 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6707 int ntemp; /* Used for counting words split between registers and stack */
6709 switch (prgvt[i])
6711 case VT_EMPTY:
6712 break;
6713 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6714 case VT_DATE:
6715 #ifndef __SOFTFP__
6716 dcount = max( (scount + 1) / 2, dcount );
6717 if (dcount < 8)
6719 regs.sd.d[dcount++] = V_R8(arg);
6721 else
6723 argspos += (argspos % 2); /* align argspos to 8-bytes */
6724 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6725 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6727 break;
6728 #endif
6729 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6730 case VT_UI8:
6731 case VT_CY:
6732 if (rcount < 3)
6734 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6735 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6736 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6738 else
6740 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6741 argspos += (argspos % 2); /* align argspos to 8-bytes */
6742 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6743 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6745 break;
6746 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6747 case VT_VARIANT:
6748 /* 8-byte align 'r' and/or stack: */
6749 if (rcount < 3)
6750 rcount += (rcount % 2);
6751 else
6753 rcount = 4;
6754 argspos += (argspos % 2);
6756 ntemp = sizeof(*arg) / sizeof(DWORD);
6757 while (ntemp > 0)
6759 if (rcount < 4)
6760 regs.r[rcount++] = *pdwarg++;
6761 else
6762 args[argspos++] = *pdwarg++;
6763 --ntemp;
6765 break;
6766 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6767 if (rcount < 4)
6768 regs.r[rcount++] = V_BOOL(arg);
6769 else
6770 args[argspos++] = V_BOOL(arg);
6771 break;
6772 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6773 #ifndef __SOFTFP__
6774 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6775 if (scount < 16)
6776 regs.sd.s[scount++] = V_R4(arg);
6777 else
6778 args[argspos++] = V_UI4(arg);
6779 break;
6780 #endif
6781 default:
6782 if (rcount < 4)
6783 regs.r[rcount++] = V_UI4(arg);
6784 else
6785 args[argspos++] = V_UI4(arg);
6786 break;
6788 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6791 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6793 switch (vtReturn)
6795 case VT_EMPTY: /* EMPTY = no return value */
6796 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6797 case VT_VARIANT:
6798 call_method( func, argspos, args, (DWORD*)&regs );
6799 break;
6800 case VT_R4:
6801 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6802 break;
6803 case VT_R8:
6804 case VT_DATE:
6805 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6806 break;
6807 case VT_I8:
6808 case VT_UI8:
6809 case VT_CY:
6810 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6811 break;
6812 default:
6813 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6814 break;
6816 heap_free( args );
6817 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6818 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6819 return S_OK;
6822 #elif defined(__aarch64__)
6824 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6825 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6826 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6827 __ASM_GLOBAL_FUNC( call_method,
6828 "stp x29, x30, [sp, #-16]!\n\t"
6829 "mov x29, sp\n\t"
6830 "sub sp, sp, x1, lsl #3\n\t"
6831 "cbz x1, 2f\n"
6832 "1:\tsub x1, x1, #1\n\t"
6833 "ldr x4, [x2, x1, lsl #3]\n\t"
6834 "str x4, [sp, x1, lsl #3]\n\t"
6835 "cbnz x1, 1b\n"
6836 "2:\tmov x16, x0\n\t"
6837 "mov x9, x3\n\t"
6838 "ldp d0, d1, [x9]\n\t"
6839 "ldp d2, d3, [x9, #0x10]\n\t"
6840 "ldp d4, d5, [x9, #0x20]\n\t"
6841 "ldp d6, d7, [x9, #0x30]\n\t"
6842 "ldp x0, x1, [x9, #0x40]\n\t"
6843 "ldp x2, x3, [x9, #0x50]\n\t"
6844 "ldp x4, x5, [x9, #0x60]\n\t"
6845 "ldp x6, x7, [x9, #0x70]\n\t"
6846 "ldr x8, [x9, #0x80]\n\t"
6847 "blr x16\n\t"
6848 "mov sp, x29\n\t"
6849 "ldp x29, x30, [sp], #16\n\t"
6850 "ret" )
6851 __ASM_GLOBAL_FUNC( call_float_method,
6852 "b " __ASM_NAME("call_method") )
6853 __ASM_GLOBAL_FUNC( call_double_method,
6854 "b " __ASM_NAME("call_method") )
6856 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6857 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6859 int argspos;
6860 void *func;
6861 UINT i;
6862 DWORD_PTR *args;
6863 struct
6865 union
6867 float f;
6868 double d;
6869 } fp[8];
6870 DWORD_PTR x[9];
6871 } regs;
6872 int rcount; /* 64-bit register index count */
6873 int fpcount = 0; /* float register index count */
6875 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6876 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6878 if (cc != CC_STDCALL && cc != CC_CDECL)
6880 FIXME("unsupported calling convention %d\n",cc);
6881 return E_INVALIDARG;
6884 argspos = 0;
6885 rcount = 0;
6887 if (instance)
6889 const FARPROC *vtable = *(FARPROC **)instance;
6890 func = vtable[offset/sizeof(void *)];
6891 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6893 else func = (void *)offset;
6895 /* maximum size for an argument is 16 */
6896 args = heap_alloc( 16 * count );
6898 for (i = 0; i < count; i++)
6900 VARIANT *arg = vargs[i];
6902 switch (types[i])
6904 case VT_R4:
6905 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6906 else *(float *)&args[argspos++] = V_R4(arg);
6907 break;
6908 case VT_R8:
6909 case VT_DATE:
6910 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6911 else *(double *)&args[argspos++] = V_R8(arg);
6912 break;
6913 case VT_DECIMAL:
6914 if (rcount < 7)
6916 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6917 rcount += 2;
6919 else
6921 memcpy( &args[argspos], arg, sizeof(*arg) );
6922 argspos += 2;
6924 break;
6925 case VT_VARIANT:
6926 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6927 else args[argspos++] = (DWORD_PTR)arg;
6928 break;
6929 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6930 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6931 else args[argspos++] = V_BOOL(arg);
6932 break;
6933 default:
6934 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6935 else args[argspos++] = V_UI8(arg);
6936 break;
6938 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6941 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6943 switch (ret_type)
6945 case VT_HRESULT:
6946 heap_free( args );
6947 return E_INVALIDARG;
6948 case VT_DECIMAL:
6949 case VT_VARIANT:
6950 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6951 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6952 break;
6953 case VT_R4:
6954 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6955 break;
6956 case VT_R8:
6957 case VT_DATE:
6958 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6959 break;
6960 default:
6961 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6962 break;
6964 heap_free( args );
6965 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6966 TRACE("retval: %s\n", debugstr_variant(result));
6967 return S_OK;
6970 #else /* __aarch64__ */
6972 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6973 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6975 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6976 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6977 return E_NOTIMPL;
6980 #endif
6982 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6984 HRESULT hr = S_OK;
6985 ITypeInfo *tinfo2 = NULL;
6986 TYPEATTR *tattr = NULL;
6988 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6989 if (hr)
6991 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc->u.hreftype, hr);
6992 return hr;
6994 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6995 if (hr)
6997 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr);
6998 ITypeInfo_Release(tinfo2);
6999 return hr;
7002 switch (tattr->typekind)
7004 case TKIND_ENUM:
7005 *vt |= VT_I4;
7006 break;
7008 case TKIND_ALIAS:
7009 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7010 break;
7012 case TKIND_INTERFACE:
7013 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7014 *vt |= VT_DISPATCH;
7015 else
7016 *vt |= VT_UNKNOWN;
7017 break;
7019 case TKIND_DISPATCH:
7020 *vt |= VT_DISPATCH;
7021 break;
7023 case TKIND_COCLASS:
7024 *vt |= VT_DISPATCH;
7025 break;
7027 case TKIND_RECORD:
7028 FIXME("TKIND_RECORD unhandled.\n");
7029 hr = E_NOTIMPL;
7030 break;
7032 case TKIND_UNION:
7033 FIXME("TKIND_UNION unhandled.\n");
7034 hr = E_NOTIMPL;
7035 break;
7037 default:
7038 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7039 hr = E_NOTIMPL;
7040 break;
7042 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7043 ITypeInfo_Release(tinfo2);
7044 return hr;
7047 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7049 HRESULT hr = S_OK;
7051 /* enforce only one level of pointer indirection */
7052 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7054 tdesc = tdesc->u.lptdesc;
7056 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7057 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7058 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7059 if ((tdesc->vt == VT_USERDEFINED) ||
7060 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
7062 VARTYPE vt_userdefined = 0;
7063 const TYPEDESC *tdesc_userdefined = tdesc;
7064 if (tdesc->vt == VT_PTR)
7066 vt_userdefined = VT_BYREF;
7067 tdesc_userdefined = tdesc->u.lptdesc;
7069 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7070 if ((hr == S_OK) &&
7071 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7072 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7074 *vt |= vt_userdefined;
7075 return S_OK;
7078 *vt = VT_BYREF;
7081 switch (tdesc->vt)
7083 case VT_HRESULT:
7084 *vt |= VT_ERROR;
7085 break;
7086 case VT_USERDEFINED:
7087 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7088 break;
7089 case VT_VOID:
7090 case VT_CARRAY:
7091 case VT_PTR:
7092 case VT_LPSTR:
7093 case VT_LPWSTR:
7094 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7095 hr = DISP_E_BADVARTYPE;
7096 break;
7097 case VT_SAFEARRAY:
7098 *vt |= VT_ARRAY;
7099 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
7100 break;
7101 case VT_INT:
7102 *vt |= VT_I4;
7103 break;
7104 case VT_UINT:
7105 *vt |= VT_UI4;
7106 break;
7107 default:
7108 *vt |= tdesc->vt;
7109 break;
7111 return hr;
7114 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7116 ITypeInfo *tinfo2;
7117 TYPEATTR *tattr;
7118 HRESULT hres;
7119 int flags, i;
7121 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7122 if(FAILED(hres))
7123 return hres;
7125 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7126 if(FAILED(hres)) {
7127 ITypeInfo_Release(tinfo2);
7128 return hres;
7131 switch(tattr->typekind) {
7132 case TKIND_ALIAS:
7133 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
7134 break;
7136 case TKIND_INTERFACE:
7137 case TKIND_DISPATCH:
7138 *guid = tattr->guid;
7139 break;
7141 case TKIND_COCLASS:
7142 for (i = 0; i < tattr->cImplTypes; i++)
7144 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7145 if (flags & IMPLTYPEFLAG_FDEFAULT)
7146 break;
7149 if (i == tattr->cImplTypes)
7150 i = 0;
7152 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7153 if (SUCCEEDED(hres))
7154 hres = get_iface_guid(tinfo2, href, guid);
7155 break;
7157 default:
7158 ERR("Unexpected typekind %d\n", tattr->typekind);
7159 hres = E_UNEXPECTED;
7162 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7163 ITypeInfo_Release(tinfo2);
7164 return hres;
7167 static inline BOOL func_restricted( const FUNCDESC *desc )
7169 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7172 #define INVBUF_ELEMENT_SIZE \
7173 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7174 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7175 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7176 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7177 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7178 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7179 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7180 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7182 static HRESULT WINAPI ITypeInfo_fnInvoke(
7183 ITypeInfo2 *iface,
7184 VOID *pIUnk,
7185 MEMBERID memid,
7186 UINT16 wFlags,
7187 DISPPARAMS *pDispParams,
7188 VARIANT *pVarResult,
7189 EXCEPINFO *pExcepInfo,
7190 UINT *pArgErr)
7192 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7193 int i, j;
7194 unsigned int var_index;
7195 TYPEKIND type_kind;
7196 HRESULT hres;
7197 const TLBFuncDesc *pFuncInfo;
7198 UINT fdc;
7200 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface, pIUnk, memid, wFlags, pDispParams,
7201 pVarResult, pExcepInfo, pArgErr);
7203 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7204 return DISP_E_MEMBERNOTFOUND;
7206 if (!pDispParams)
7208 ERR("NULL pDispParams not allowed\n");
7209 return E_INVALIDARG;
7212 dump_DispParms(pDispParams);
7214 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7216 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7217 pDispParams->cNamedArgs, pDispParams->cArgs);
7218 return E_INVALIDARG;
7221 /* we do this instead of using GetFuncDesc since it will return a fake
7222 * FUNCDESC for dispinterfaces and we want the real function description */
7223 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7224 pFuncInfo = &This->funcdescs[fdc];
7225 if ((memid == pFuncInfo->funcdesc.memid) &&
7226 (wFlags & pFuncInfo->funcdesc.invkind) &&
7227 !func_restricted( &pFuncInfo->funcdesc ))
7228 break;
7231 if (fdc < This->typeattr.cFuncs) {
7232 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7234 if (TRACE_ON(ole))
7236 TRACE("invoking:\n");
7237 dump_TLBFuncDescOne(pFuncInfo);
7240 switch (func_desc->funckind) {
7241 case FUNC_PUREVIRTUAL:
7242 case FUNC_VIRTUAL: {
7243 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7244 VARIANT varresult;
7245 VARIANT retval = {{{0}}}; /* pointer for storing byref retvals in */
7246 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7247 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7248 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7249 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7250 UINT cNamedArgs = pDispParams->cNamedArgs;
7251 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7252 UINT vargs_converted=0;
7253 SAFEARRAY *a;
7255 hres = S_OK;
7257 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7259 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7261 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7262 hres = DISP_E_PARAMNOTFOUND;
7263 goto func_fail;
7267 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7269 ERR("functions with the vararg attribute do not support named arguments\n");
7270 hres = DISP_E_NONAMEDARGS;
7271 goto func_fail;
7274 for (i = 0; i < func_desc->cParams; i++)
7276 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7277 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7278 if (FAILED(hres))
7279 goto func_fail;
7282 TRACE("changing args\n");
7283 for (i = 0; i < func_desc->cParams; i++)
7285 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7286 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7287 VARIANTARG *src_arg;
7289 if (wParamFlags & PARAMFLAG_FLCID)
7291 prgpvarg[i] = &rgvarg[i];
7292 V_VT(prgpvarg[i]) = VT_I4;
7293 V_I4(prgpvarg[i]) = This->pTypeLib->lcid;
7294 continue;
7297 src_arg = NULL;
7299 for (j = 0; j < cNamedArgs; j++)
7301 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7303 src_arg = &pDispParams->rgvarg[j];
7304 break;
7308 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7310 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7311 vargs_converted++;
7314 if (wParamFlags & PARAMFLAG_FRETVAL)
7316 /* under most conditions the caller is not allowed to
7317 * pass in a dispparam arg in the index of what would be
7318 * the retval parameter. however, there is an exception
7319 * where the extra parameter is used in an extra
7320 * IDispatch::Invoke below */
7321 if ((i < pDispParams->cArgs) &&
7322 ((func_desc->cParams != 1) || !pVarResult ||
7323 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7325 hres = DISP_E_BADPARAMCOUNT;
7326 break;
7329 /* note: this check is placed so that if the caller passes
7330 * in a VARIANTARG for the retval we just ignore it, like
7331 * native does */
7332 if (i == func_desc->cParams - 1)
7334 prgpvarg[i] = &rgvarg[i];
7335 V_BYREF(prgpvarg[i]) = &retval;
7336 V_VT(prgpvarg[i]) = rgvt[i];
7338 else
7340 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7341 hres = E_UNEXPECTED;
7342 break;
7345 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7346 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7348 TRACE("%s\n", debugstr_variant(src_arg));
7350 if(rgvt[i]!=V_VT(src_arg))
7352 if (rgvt[i] == VT_VARIANT)
7353 hres = VariantCopy(&rgvarg[i], src_arg);
7354 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7356 if (rgvt[i] == V_VT(src_arg))
7357 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7358 else
7360 if (wParamFlags & PARAMFLAG_FIN)
7361 hres = VariantCopy(&missing_arg[i], src_arg);
7362 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7364 V_VT(&rgvarg[i]) = rgvt[i];
7366 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7368 SAFEARRAYBOUND bound;
7369 VARIANT *v;
7371 bound.lLbound = 0;
7372 bound.cElements = pDispParams->cArgs-i;
7373 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7375 ERR("SafeArrayCreate failed\n");
7376 break;
7378 hres = SafeArrayAccessData(a, (LPVOID)&v);
7379 if (hres != S_OK)
7381 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7382 SafeArrayDestroy(a);
7383 break;
7385 for (j = 0; j < bound.cElements; j++)
7386 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7387 hres = SafeArrayUnaccessData(a);
7388 if (hres != S_OK)
7390 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7391 SafeArrayDestroy(a);
7392 break;
7394 if (rgvt[i] & VT_BYREF)
7395 V_BYREF(&rgvarg[i]) = &a;
7396 else
7397 V_ARRAY(&rgvarg[i]) = a;
7398 V_VT(&rgvarg[i]) = rgvt[i];
7400 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7402 if (wParamFlags & PARAMFLAG_FIN)
7403 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7404 else
7405 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7406 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7407 V_VT(&rgvarg[i]) = rgvt[i];
7409 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7411 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7412 V_VT(&rgvarg[i]) = rgvt[i];
7414 else
7416 /* FIXME: this doesn't work for VT_BYREF arguments if
7417 * they are not the same type as in the paramdesc */
7418 V_VT(&rgvarg[i]) = V_VT(src_arg);
7419 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7420 V_VT(&rgvarg[i]) = rgvt[i];
7423 if (FAILED(hres))
7425 ERR("failed to convert param %d to %s from %s\n", i,
7426 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7427 break;
7429 prgpvarg[i] = &rgvarg[i];
7431 else
7433 prgpvarg[i] = src_arg;
7436 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7437 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7438 && V_UNKNOWN(prgpvarg[i])) {
7439 IUnknown *userdefined_iface;
7440 GUID guid;
7442 if (tdesc->vt == VT_PTR)
7443 tdesc = tdesc->u.lptdesc;
7445 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7446 if(FAILED(hres))
7447 break;
7449 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7450 if(FAILED(hres)) {
7451 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7452 break;
7455 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7456 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7459 else if (wParamFlags & PARAMFLAG_FOPT)
7461 VARIANTARG *arg;
7462 arg = prgpvarg[i] = &rgvarg[i];
7463 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7465 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7466 if (FAILED(hres))
7467 break;
7469 else
7471 /* if the function wants a pointer to a variant then
7472 * set that up, otherwise just pass the VT_ERROR in
7473 * the argument by value */
7474 if (rgvt[i] & VT_BYREF)
7476 V_VT(&missing_arg[i]) = VT_ERROR;
7477 V_ERROR(&missing_arg[i]) = DISP_E_PARAMNOTFOUND;
7479 V_VT(arg) = VT_VARIANT | VT_BYREF;
7480 V_VARIANTREF(arg) = &missing_arg[i];
7482 else
7484 V_VT(arg) = VT_ERROR;
7485 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
7489 else
7491 hres = DISP_E_BADPARAMCOUNT;
7492 break;
7495 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7497 /* VT_VOID is a special case for return types, so it is not
7498 * handled in the general function */
7499 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7500 V_VT(&varresult) = VT_EMPTY;
7501 else
7503 V_VT(&varresult) = 0;
7504 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7505 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7508 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7509 V_VT(&varresult), func_desc->cParams, rgvt,
7510 prgpvarg, &varresult);
7512 vargs_converted = 0;
7514 for (i = 0; i < func_desc->cParams; i++)
7516 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7518 if (wParamFlags & PARAMFLAG_FLCID)
7519 continue;
7520 else if (wParamFlags & PARAMFLAG_FRETVAL)
7522 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7524 if (pVarResult)
7526 VariantInit(pVarResult);
7527 /* deref return value */
7528 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7531 VARIANT_ClearInd(prgpvarg[i]);
7533 else if (vargs_converted < pDispParams->cArgs)
7535 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7536 if (wParamFlags & PARAMFLAG_FOUT)
7538 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7540 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7542 if (FAILED(hres))
7544 ERR("failed to convert param %d to vt %d\n", i,
7545 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7546 break;
7550 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7551 func_desc->cParamsOpt < 0 &&
7552 i == func_desc->cParams-1)
7554 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7555 LONG ubound;
7556 VARIANT *v;
7557 hres = SafeArrayGetUBound(a, 1, &ubound);
7558 if (hres != S_OK)
7560 ERR("SafeArrayGetUBound failed with %#lx.\n", hres);
7561 break;
7563 hres = SafeArrayAccessData(a, (LPVOID)&v);
7564 if (hres != S_OK)
7566 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7567 break;
7569 for (j = 0; j <= ubound; j++)
7570 VariantClear(&v[j]);
7571 hres = SafeArrayUnaccessData(a);
7572 if (hres != S_OK)
7574 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7575 break;
7578 VariantClear(&rgvarg[i]);
7579 vargs_converted++;
7581 else if (wParamFlags & PARAMFLAG_FOPT)
7583 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7584 VariantClear(&rgvarg[i]);
7587 VariantClear(&missing_arg[i]);
7590 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7592 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult));
7593 hres = DISP_E_EXCEPTION;
7594 if (pExcepInfo)
7596 IErrorInfo *pErrorInfo;
7597 pExcepInfo->scode = V_ERROR(&varresult);
7598 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7600 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7601 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7602 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7603 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7605 IErrorInfo_Release(pErrorInfo);
7609 if (V_VT(&varresult) != VT_ERROR)
7611 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7613 if (pVarResult)
7615 VariantClear(pVarResult);
7616 *pVarResult = varresult;
7618 else
7619 VariantClear(&varresult);
7622 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7623 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7624 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7625 (pDispParams->cArgs != 0))
7627 if (V_VT(pVarResult) == VT_DISPATCH)
7629 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7630 /* Note: not VariantClear; we still need the dispatch
7631 * pointer to be valid */
7632 VariantInit(pVarResult);
7633 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7634 GetSystemDefaultLCID(), wFlags,
7635 pDispParams, pVarResult, pExcepInfo, pArgErr);
7636 IDispatch_Release(pDispatch);
7638 else
7640 VariantClear(pVarResult);
7641 hres = DISP_E_NOTACOLLECTION;
7645 func_fail:
7646 heap_free(buffer);
7647 break;
7649 case FUNC_DISPATCH: {
7650 IDispatch *disp;
7652 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7653 if (SUCCEEDED(hres)) {
7654 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7655 hres = IDispatch_Invoke(
7656 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7657 pVarResult,pExcepInfo,pArgErr
7659 if (FAILED(hres))
7660 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres);
7661 IDispatch_Release(disp);
7662 } else
7663 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7664 break;
7666 default:
7667 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7668 hres = E_FAIL;
7669 break;
7672 TRACE("-- %#lx\n", hres);
7673 return hres;
7675 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7676 VARDESC *var_desc;
7678 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7679 if(FAILED(hres)) return hres;
7681 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7682 dump_VARDESC(var_desc);
7683 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7684 return E_NOTIMPL;
7687 /* not found, look for it in inherited interfaces */
7688 ITypeInfo2_GetTypeKind(iface, &type_kind);
7689 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7690 if(This->impltypes) {
7691 /* recursive search */
7692 ITypeInfo *pTInfo;
7693 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7694 if(SUCCEEDED(hres)){
7695 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7696 ITypeInfo_Release(pTInfo);
7697 return hres;
7699 WARN("Could not search inherited interface!\n");
7702 WARN("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
7703 return DISP_E_MEMBERNOTFOUND;
7706 /* ITypeInfo::GetDocumentation
7708 * Retrieves the documentation string, the complete Help file name and path,
7709 * and the context ID for the Help topic for a specified type description.
7711 * (Can be tested by the Visual Basic Editor in Word for instance.)
7713 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7714 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7715 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7717 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7718 const TLBFuncDesc *pFDesc;
7719 const TLBVarDesc *pVDesc;
7720 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7721 iface, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7722 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7723 if(pBstrName)
7724 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7725 if(pBstrDocString)
7726 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7727 if(pdwHelpContext)
7728 *pdwHelpContext=This->dwHelpContext;
7729 if(pBstrHelpFile)
7730 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7731 return S_OK;
7732 }else {/* for a member */
7733 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7734 if(pFDesc){
7735 if(pBstrName)
7736 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7737 if(pBstrDocString)
7738 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7739 if(pdwHelpContext)
7740 *pdwHelpContext=pFDesc->helpcontext;
7741 if(pBstrHelpFile)
7742 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7743 return S_OK;
7745 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7746 if(pVDesc){
7747 if(pBstrName)
7748 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7749 if(pBstrDocString)
7750 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7751 if(pdwHelpContext)
7752 *pdwHelpContext=pVDesc->HelpContext;
7753 if(pBstrHelpFile)
7754 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7755 return S_OK;
7759 if(This->impltypes &&
7760 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7761 /* recursive search */
7762 ITypeInfo *pTInfo;
7763 HRESULT result;
7764 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7765 if(SUCCEEDED(result)) {
7766 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7767 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7768 ITypeInfo_Release(pTInfo);
7769 return result;
7771 WARN("Could not search inherited interface!\n");
7774 WARN("member %ld not found\n", memid);
7775 return TYPE_E_ELEMENTNOTFOUND;
7778 /* ITypeInfo::GetDllEntry
7780 * Retrieves a description or specification of an entry point for a function
7781 * in a DLL.
7783 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7784 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7785 WORD *pwOrdinal)
7787 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7788 const TLBFuncDesc *pFDesc;
7790 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7792 if (pBstrDllName) *pBstrDllName = NULL;
7793 if (pBstrName) *pBstrName = NULL;
7794 if (pwOrdinal) *pwOrdinal = 0;
7796 if (This->typeattr.typekind != TKIND_MODULE)
7797 return TYPE_E_BADMODULEKIND;
7799 pFDesc = TLB_get_funcdesc_by_memberid_invkind(This, memid, invKind);
7800 if (!pFDesc) return TYPE_E_ELEMENTNOTFOUND;
7802 dump_TypeInfo(This);
7803 if (TRACE_ON(ole)) dump_TLBFuncDescOne(pFDesc);
7805 if (pBstrDllName) *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7807 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1))
7809 if (pBstrName) *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7810 if (pwOrdinal) *pwOrdinal = -1;
7812 else
7814 if (pBstrName) *pBstrName = NULL;
7815 if (pwOrdinal) *pwOrdinal = LOWORD(pFDesc->Entry);
7817 return S_OK;
7820 /* internal function to make the inherited interfaces' methods appear
7821 * part of the interface */
7822 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7823 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7825 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7826 HRESULT hr;
7828 TRACE("%p, %#lx.\n", iface, *hRefType);
7830 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7832 ITypeInfo *pSubTypeInfo;
7834 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7835 if (FAILED(hr))
7836 return hr;
7838 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7839 hRefType, ppTInfo);
7840 ITypeInfo_Release(pSubTypeInfo);
7841 if (SUCCEEDED(hr))
7842 return hr;
7844 *hRefType -= DISPATCH_HREF_OFFSET;
7846 if (!(*hRefType & DISPATCH_HREF_MASK))
7847 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7848 else
7849 return E_FAIL;
7852 /* ITypeInfo::GetRefTypeInfo
7854 * If a type description references other type descriptions, it retrieves
7855 * the referenced type descriptions.
7857 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7858 ITypeInfo2 *iface,
7859 HREFTYPE hRefType,
7860 ITypeInfo **ppTInfo)
7862 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7863 ITypeInfo *type_info = NULL;
7864 HRESULT result = E_FAIL;
7865 TLBRefType *ref_type;
7866 UINT i;
7868 if(!ppTInfo)
7869 return E_INVALIDARG;
7871 if ((INT)hRefType < 0) {
7872 ITypeInfoImpl *pTypeInfoImpl;
7874 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7875 !(This->typeattr.typekind == TKIND_INTERFACE ||
7876 This->typeattr.typekind == TKIND_DISPATCH))
7877 return TYPE_E_ELEMENTNOTFOUND;
7879 /* when we meet a DUAL typeinfo, we must create the alternate
7880 * version of it.
7882 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7884 *pTypeInfoImpl = *This;
7885 pTypeInfoImpl->ref = 0;
7886 list_init(&pTypeInfoImpl->custdata_list);
7888 if (This->typeattr.typekind == TKIND_INTERFACE)
7889 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7890 else
7891 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7893 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7894 /* the AddRef implicitly adds a reference to the parent typelib, which
7895 * stops the copied data from being destroyed until the new typeinfo's
7896 * refcount goes to zero, but we need to signal to the new instance to
7897 * not free its data structures when it is destroyed */
7898 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7899 ITypeInfo_AddRef(*ppTInfo);
7901 TRACE("got dual interface %p\n", *ppTInfo);
7902 return S_OK;
7905 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7906 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7908 if(!(hRefType & 0x1))
7910 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7912 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7914 result = S_OK;
7915 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7916 ITypeInfo_AddRef(type_info);
7917 break;
7922 if (!type_info)
7924 ITypeLib *pTLib = NULL;
7926 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7928 if(ref_type->reference == (hRefType & (~0x3)))
7929 break;
7931 if(&ref_type->entry == &This->pTypeLib->ref_list)
7933 FIXME("Can't find pRefType for ref %lx\n", hRefType);
7934 return E_FAIL;
7937 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7938 UINT Index;
7939 TRACE("internal reference\n");
7940 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7941 } else {
7942 if(ref_type->pImpTLInfo->pImpTypeLib) {
7943 TRACE("typeinfo in imported typelib that is already loaded\n");
7944 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7945 ITypeLib_AddRef(pTLib);
7946 result = S_OK;
7947 } else {
7948 /* Search in cached typelibs */
7949 ITypeLibImpl *entry;
7951 EnterCriticalSection(&cache_section);
7952 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
7954 if (entry->guid
7955 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
7956 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
7957 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
7958 && entry->set_lcid == ref_type->pImpTLInfo->lcid
7959 && entry->syskind == This->pTypeLib->syskind)
7961 TRACE("got cached %p\n", entry);
7962 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
7963 ITypeLib_AddRef(pTLib);
7964 result = S_OK;
7965 break;
7968 LeaveCriticalSection(&cache_section);
7970 if (!pTLib)
7972 BSTR libnam;
7974 /* Search on disk */
7975 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7976 ref_type->pImpTLInfo->wVersionMajor,
7977 ref_type->pImpTLInfo->wVersionMinor,
7978 This->pTypeLib->syskind,
7979 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7980 if (FAILED(result))
7981 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7983 result = LoadTypeLib(libnam, &pTLib);
7984 SysFreeString(libnam);
7987 if(SUCCEEDED(result)) {
7988 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7989 ITypeLib_AddRef(pTLib);
7993 if(SUCCEEDED(result)) {
7994 if(ref_type->index == TLB_REF_USE_GUID)
7995 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
7996 else
7997 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
7999 if (pTLib != NULL)
8000 ITypeLib_Release(pTLib);
8001 if (FAILED(result))
8003 WARN("(%p) failed hreftype %#lx.\n", iface, hRefType);
8004 return result;
8008 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
8009 ITypeInfo_Release(type_info);
8010 else *ppTInfo = type_info;
8012 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface, hRefType,
8013 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8014 return result;
8017 /* ITypeInfo::AddressOfMember
8019 * Retrieves the addresses of static functions or variables, such as those
8020 * defined in a DLL.
8022 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8023 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8025 HRESULT hr;
8026 BSTR dll, entry;
8027 WORD ordinal;
8028 HMODULE module;
8030 TRACE("%p, %lx, %#x, %p.\n", iface, memid, invKind, ppv);
8032 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8033 if (FAILED(hr))
8034 return hr;
8036 module = LoadLibraryW(dll);
8037 if (!module)
8039 ERR("couldn't load %s\n", debugstr_w(dll));
8040 SysFreeString(dll);
8041 SysFreeString(entry);
8042 return STG_E_FILENOTFOUND;
8044 /* FIXME: store library somewhere where we can free it */
8046 if (entry)
8048 LPSTR entryA;
8049 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8050 entryA = heap_alloc(len);
8051 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8053 *ppv = GetProcAddress(module, entryA);
8054 if (!*ppv)
8055 ERR("function not found %s\n", debugstr_a(entryA));
8057 heap_free(entryA);
8059 else
8061 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8062 if (!*ppv)
8063 ERR("function not found %d\n", ordinal);
8066 SysFreeString(dll);
8067 SysFreeString(entry);
8069 if (!*ppv)
8070 return TYPE_E_DLLFUNCTIONNOTFOUND;
8072 return S_OK;
8075 /* ITypeInfo::CreateInstance
8077 * Creates a new instance of a type that describes a component object class
8078 * (coclass).
8080 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8081 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8083 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8084 HRESULT hr;
8085 TYPEATTR *pTA;
8087 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8089 *ppvObj = NULL;
8091 if(pOuterUnk)
8093 WARN("Not able to aggregate\n");
8094 return CLASS_E_NOAGGREGATION;
8097 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8098 if(FAILED(hr)) return hr;
8100 if(pTA->typekind != TKIND_COCLASS)
8102 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8103 hr = E_INVALIDARG;
8104 goto end;
8107 hr = S_FALSE;
8108 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8110 IUnknown *pUnk;
8111 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8112 TRACE("GetActiveObject rets %#lx.\n", hr);
8113 if(hr == S_OK)
8115 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8116 IUnknown_Release(pUnk);
8120 if(hr != S_OK)
8121 hr = CoCreateInstance(&pTA->guid, NULL,
8122 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8123 riid, ppvObj);
8125 end:
8126 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8127 return hr;
8130 /* ITypeInfo::GetMops
8132 * Retrieves marshalling information.
8134 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, BSTR *pBstrMops)
8136 FIXME("%p, %ld stub!\n", iface, memid);
8137 *pBstrMops = NULL;
8138 return S_OK;
8141 /* ITypeInfo::GetContainingTypeLib
8143 * Retrieves the containing type library and the index of the type description
8144 * within that type library.
8146 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8147 ITypeLib * *ppTLib, UINT *pIndex)
8149 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8151 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8152 if (pIndex) {
8153 *pIndex=This->index;
8154 TRACE("returning pIndex=%d\n", *pIndex);
8157 if (ppTLib) {
8158 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8159 ITypeLib_AddRef(*ppTLib);
8160 TRACE("returning ppTLib=%p\n", *ppTLib);
8163 return S_OK;
8166 /* ITypeInfo::ReleaseTypeAttr
8168 * Releases a TYPEATTR previously returned by Get
8171 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8172 TYPEATTR* pTypeAttr)
8174 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8175 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8176 heap_free(pTypeAttr);
8179 /* ITypeInfo::ReleaseFuncDesc
8181 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8183 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8184 ITypeInfo2 *iface,
8185 FUNCDESC *pFuncDesc)
8187 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8188 SHORT i;
8190 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8192 for (i = 0; i < pFuncDesc->cParams; i++)
8193 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8194 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8196 SysFreeString((BSTR)pFuncDesc);
8199 /* ITypeInfo::ReleaseVarDesc
8201 * Releases a VARDESC previously returned by GetVarDesc.
8203 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8204 VARDESC *pVarDesc)
8206 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8207 TRACE("(%p)->(%p)\n", This, pVarDesc);
8209 TLB_FreeVarDesc(pVarDesc);
8212 /* ITypeInfo2::GetTypeKind
8214 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8217 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8218 TYPEKIND *pTypeKind)
8220 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8221 *pTypeKind = This->typeattr.typekind;
8222 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8223 return S_OK;
8226 /* ITypeInfo2::GetTypeFlags
8228 * Returns the type flags without any allocations. This returns a DWORD type
8229 * flag, which expands the type flags without growing the TYPEATTR (type
8230 * attribute).
8233 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8235 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8236 TRACE("%p, %p.\n", iface, pTypeFlags);
8237 *pTypeFlags=This->typeattr.wTypeFlags;
8238 return S_OK;
8241 /* ITypeInfo2::GetFuncIndexOfMemId
8242 * Binds to a specific member based on a known DISPID, where the member name
8243 * is not known (for example, when binding to a default member).
8246 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8247 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8249 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8250 UINT fdc;
8251 HRESULT result;
8253 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8254 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8255 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8256 break;
8258 if(fdc < This->typeattr.cFuncs) {
8259 *pFuncIndex = fdc;
8260 result = S_OK;
8261 } else
8262 result = TYPE_E_ELEMENTNOTFOUND;
8264 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface, memid, invKind, result);
8265 return result;
8268 /* TypeInfo2::GetVarIndexOfMemId
8270 * Binds to a specific member based on a known DISPID, where the member name
8271 * is not known (for example, when binding to a default member).
8274 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8275 MEMBERID memid, UINT *pVarIndex)
8277 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8278 TLBVarDesc *pVarInfo;
8280 TRACE("%p, %ld, %p.\n", iface, memid, pVarIndex);
8282 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8283 if(!pVarInfo)
8284 return TYPE_E_ELEMENTNOTFOUND;
8286 *pVarIndex = (pVarInfo - This->vardescs);
8288 return S_OK;
8291 /* ITypeInfo2::GetCustData
8293 * Gets the custom data
8295 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8296 ITypeInfo2 * iface,
8297 REFGUID guid,
8298 VARIANT *pVarVal)
8300 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8301 TLBCustData *pCData;
8303 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8305 if(!guid || !pVarVal)
8306 return E_INVALIDARG;
8308 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8310 VariantInit( pVarVal);
8311 if (pCData)
8312 VariantCopy( pVarVal, &pCData->data);
8313 else
8314 VariantClear( pVarVal );
8315 return S_OK;
8318 /* ITypeInfo2::GetFuncCustData
8320 * Gets the custom data
8322 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8323 ITypeInfo2 * iface,
8324 UINT index,
8325 REFGUID guid,
8326 VARIANT *pVarVal)
8328 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8329 const TLBFuncDesc *desc;
8330 TLBCustData *data;
8331 UINT hrefoffset;
8332 HRESULT hr;
8334 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8336 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8337 if (FAILED(hr))
8339 WARN("description for function %d not found\n", index);
8340 return hr;
8343 VariantInit(pVarVal);
8344 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8345 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8348 /* ITypeInfo2::GetParamCustData
8350 * Gets the custom data
8352 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8353 ITypeInfo2 * iface,
8354 UINT indexFunc,
8355 UINT indexParam,
8356 REFGUID guid,
8357 VARIANT *pVarVal)
8359 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8360 const TLBFuncDesc *pFDesc;
8361 TLBCustData *pCData;
8362 UINT hrefoffset;
8363 HRESULT hr;
8365 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8366 debugstr_guid(guid), pVarVal);
8368 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8369 if (FAILED(hr))
8370 return hr;
8372 if(indexParam >= pFDesc->funcdesc.cParams)
8373 return TYPE_E_ELEMENTNOTFOUND;
8375 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8376 if(!pCData)
8377 return TYPE_E_ELEMENTNOTFOUND;
8379 VariantInit(pVarVal);
8380 VariantCopy(pVarVal, &pCData->data);
8382 return S_OK;
8385 /* ITypeInfo2::GetVarCustData
8387 * Gets the custom data
8389 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8390 ITypeInfo2 * iface,
8391 UINT index,
8392 REFGUID guid,
8393 VARIANT *pVarVal)
8395 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8396 TLBCustData *pCData;
8397 TLBVarDesc *pVDesc = &This->vardescs[index];
8399 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8401 if(index >= This->typeattr.cVars)
8402 return TYPE_E_ELEMENTNOTFOUND;
8404 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8405 if(!pCData)
8406 return TYPE_E_ELEMENTNOTFOUND;
8408 VariantInit(pVarVal);
8409 VariantCopy(pVarVal, &pCData->data);
8411 return S_OK;
8414 /* ITypeInfo2::GetImplCustData
8416 * Gets the custom data
8418 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8419 ITypeInfo2 * iface,
8420 UINT index,
8421 REFGUID guid,
8422 VARIANT *pVarVal)
8424 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8425 TLBCustData *pCData;
8426 TLBImplType *pRDesc = &This->impltypes[index];
8428 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8430 if(index >= This->typeattr.cImplTypes)
8431 return TYPE_E_ELEMENTNOTFOUND;
8433 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8434 if(!pCData)
8435 return TYPE_E_ELEMENTNOTFOUND;
8437 VariantInit(pVarVal);
8438 VariantCopy(pVarVal, &pCData->data);
8440 return S_OK;
8443 /* ITypeInfo2::GetDocumentation2
8445 * Retrieves the documentation string, the complete Help file name and path,
8446 * the localization context to use, and the context ID for the library Help
8447 * topic in the Help file.
8450 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8451 ITypeInfo2 * iface,
8452 MEMBERID memid,
8453 LCID lcid,
8454 BSTR *pbstrHelpString,
8455 DWORD *pdwHelpStringContext,
8456 BSTR *pbstrHelpStringDll)
8458 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8459 const TLBFuncDesc *pFDesc;
8460 const TLBVarDesc *pVDesc;
8461 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8462 iface, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8463 pbstrHelpStringDll );
8464 /* the help string should be obtained from the helpstringdll,
8465 * using the _DLLGetDocumentation function, based on the supplied
8466 * lcid. Nice to do sometime...
8468 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8469 if(pbstrHelpString)
8470 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8471 if(pdwHelpStringContext)
8472 *pdwHelpStringContext=This->dwHelpStringContext;
8473 if(pbstrHelpStringDll)
8474 *pbstrHelpStringDll=
8475 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8476 return S_OK;
8477 }else {/* for a member */
8478 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8479 if(pFDesc){
8480 if(pbstrHelpString)
8481 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8482 if(pdwHelpStringContext)
8483 *pdwHelpStringContext=pFDesc->HelpStringContext;
8484 if(pbstrHelpStringDll)
8485 *pbstrHelpStringDll=
8486 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8487 return S_OK;
8489 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8490 if(pVDesc){
8491 if(pbstrHelpString)
8492 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8493 if(pdwHelpStringContext)
8494 *pdwHelpStringContext=pVDesc->HelpStringContext;
8495 if(pbstrHelpStringDll)
8496 *pbstrHelpStringDll=
8497 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8498 return S_OK;
8501 return TYPE_E_ELEMENTNOTFOUND;
8504 /* ITypeInfo2::GetAllCustData
8506 * Gets all custom data items for the Type info.
8509 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8510 ITypeInfo2 * iface,
8511 CUSTDATA *pCustData)
8513 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8515 TRACE("%p %p\n", This, pCustData);
8517 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8520 /* ITypeInfo2::GetAllFuncCustData
8522 * Gets all custom data items for the specified Function
8525 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8526 ITypeInfo2 * iface,
8527 UINT index,
8528 CUSTDATA *pCustData)
8530 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8531 const TLBFuncDesc *pFDesc;
8532 UINT hrefoffset;
8533 HRESULT hr;
8535 TRACE("%p %u %p\n", This, index, pCustData);
8537 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8538 if (FAILED(hr))
8539 return hr;
8541 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8544 /* ITypeInfo2::GetAllParamCustData
8546 * Gets all custom data items for the Functions
8549 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8550 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8552 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8553 const TLBFuncDesc *pFDesc;
8554 UINT hrefoffset;
8555 HRESULT hr;
8557 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8559 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8560 if (FAILED(hr))
8561 return hr;
8563 if(indexParam >= pFDesc->funcdesc.cParams)
8564 return TYPE_E_ELEMENTNOTFOUND;
8566 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8569 /* ITypeInfo2::GetAllVarCustData
8571 * Gets all custom data items for the specified Variable
8574 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8575 UINT index, CUSTDATA *pCustData)
8577 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8578 TLBVarDesc * pVDesc = &This->vardescs[index];
8580 TRACE("%p %u %p\n", This, index, pCustData);
8582 if(index >= This->typeattr.cVars)
8583 return TYPE_E_ELEMENTNOTFOUND;
8585 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8588 /* ITypeInfo2::GetAllImplCustData
8590 * Gets all custom data items for the specified implementation type
8593 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8594 ITypeInfo2 * iface,
8595 UINT index,
8596 CUSTDATA *pCustData)
8598 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8599 TLBImplType *pRDesc = &This->impltypes[index];
8601 TRACE("%p %u %p\n", This, index, pCustData);
8603 if(index >= This->typeattr.cImplTypes)
8604 return TYPE_E_ELEMENTNOTFOUND;
8606 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8609 static const ITypeInfo2Vtbl tinfvt =
8612 ITypeInfo_fnQueryInterface,
8613 ITypeInfo_fnAddRef,
8614 ITypeInfo_fnRelease,
8616 ITypeInfo_fnGetTypeAttr,
8617 ITypeInfo_fnGetTypeComp,
8618 ITypeInfo_fnGetFuncDesc,
8619 ITypeInfo_fnGetVarDesc,
8620 ITypeInfo_fnGetNames,
8621 ITypeInfo_fnGetRefTypeOfImplType,
8622 ITypeInfo_fnGetImplTypeFlags,
8623 ITypeInfo_fnGetIDsOfNames,
8624 ITypeInfo_fnInvoke,
8625 ITypeInfo_fnGetDocumentation,
8626 ITypeInfo_fnGetDllEntry,
8627 ITypeInfo_fnGetRefTypeInfo,
8628 ITypeInfo_fnAddressOfMember,
8629 ITypeInfo_fnCreateInstance,
8630 ITypeInfo_fnGetMops,
8631 ITypeInfo_fnGetContainingTypeLib,
8632 ITypeInfo_fnReleaseTypeAttr,
8633 ITypeInfo_fnReleaseFuncDesc,
8634 ITypeInfo_fnReleaseVarDesc,
8636 ITypeInfo2_fnGetTypeKind,
8637 ITypeInfo2_fnGetTypeFlags,
8638 ITypeInfo2_fnGetFuncIndexOfMemId,
8639 ITypeInfo2_fnGetVarIndexOfMemId,
8640 ITypeInfo2_fnGetCustData,
8641 ITypeInfo2_fnGetFuncCustData,
8642 ITypeInfo2_fnGetParamCustData,
8643 ITypeInfo2_fnGetVarCustData,
8644 ITypeInfo2_fnGetImplTypeCustData,
8645 ITypeInfo2_fnGetDocumentation2,
8646 ITypeInfo2_fnGetAllCustData,
8647 ITypeInfo2_fnGetAllFuncCustData,
8648 ITypeInfo2_fnGetAllParamCustData,
8649 ITypeInfo2_fnGetAllVarCustData,
8650 ITypeInfo2_fnGetAllImplTypeCustData,
8653 /******************************************************************************
8654 * CreateDispTypeInfo [OLEAUT32.31]
8656 * Build type information for an object so it can be called through an
8657 * IDispatch interface.
8659 * RETURNS
8660 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8661 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8663 * NOTES
8664 * This call allows an objects methods to be accessed through IDispatch, by
8665 * building an ITypeInfo object that IDispatch can use to call through.
8667 HRESULT WINAPI CreateDispTypeInfo(
8668 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8669 LCID lcid, /* [I] Locale Id */
8670 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8672 ITypeInfoImpl *pTIClass, *pTIIface;
8673 ITypeLibImpl *pTypeLibImpl;
8674 unsigned int param, func;
8675 TLBFuncDesc *pFuncDesc;
8676 TLBRefType *ref;
8678 TRACE("\n");
8679 pTypeLibImpl = TypeLibImpl_Constructor();
8680 if (!pTypeLibImpl) return E_FAIL;
8682 pTypeLibImpl->TypeInfoCount = 2;
8683 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8685 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8686 pTIIface->pTypeLib = pTypeLibImpl;
8687 pTIIface->index = 0;
8688 pTIIface->Name = NULL;
8689 pTIIface->dwHelpContext = -1;
8690 pTIIface->guid = NULL;
8691 pTIIface->typeattr.lcid = lcid;
8692 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8693 pTIIface->typeattr.wMajorVerNum = 0;
8694 pTIIface->typeattr.wMinorVerNum = 0;
8695 pTIIface->typeattr.cbAlignment = 2;
8696 pTIIface->typeattr.cbSizeInstance = -1;
8697 pTIIface->typeattr.cbSizeVft = -1;
8698 pTIIface->typeattr.cFuncs = 0;
8699 pTIIface->typeattr.cImplTypes = 0;
8700 pTIIface->typeattr.cVars = 0;
8701 pTIIface->typeattr.wTypeFlags = 0;
8702 pTIIface->hreftype = 0;
8704 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8705 pFuncDesc = pTIIface->funcdescs;
8706 for(func = 0; func < pidata->cMembers; func++) {
8707 METHODDATA *md = pidata->pmethdata + func;
8708 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8709 pFuncDesc->funcdesc.memid = md->dispid;
8710 pFuncDesc->funcdesc.lprgscode = NULL;
8711 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8712 pFuncDesc->funcdesc.invkind = md->wFlags;
8713 pFuncDesc->funcdesc.callconv = md->cc;
8714 pFuncDesc->funcdesc.cParams = md->cArgs;
8715 pFuncDesc->funcdesc.cParamsOpt = 0;
8716 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8717 pFuncDesc->funcdesc.cScodes = 0;
8718 pFuncDesc->funcdesc.wFuncFlags = 0;
8719 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8720 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8721 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8722 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8723 md->cArgs * sizeof(ELEMDESC));
8724 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8725 for(param = 0; param < md->cArgs; param++) {
8726 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8727 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8729 pFuncDesc->helpcontext = 0;
8730 pFuncDesc->HelpStringContext = 0;
8731 pFuncDesc->HelpString = NULL;
8732 pFuncDesc->Entry = NULL;
8733 list_init(&pFuncDesc->custdata_list);
8734 pTIIface->typeattr.cFuncs++;
8735 ++pFuncDesc;
8738 dump_TypeInfo(pTIIface);
8740 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8741 pTIClass->pTypeLib = pTypeLibImpl;
8742 pTIClass->index = 1;
8743 pTIClass->Name = NULL;
8744 pTIClass->dwHelpContext = -1;
8745 pTIClass->guid = NULL;
8746 pTIClass->typeattr.lcid = lcid;
8747 pTIClass->typeattr.typekind = TKIND_COCLASS;
8748 pTIClass->typeattr.wMajorVerNum = 0;
8749 pTIClass->typeattr.wMinorVerNum = 0;
8750 pTIClass->typeattr.cbAlignment = 2;
8751 pTIClass->typeattr.cbSizeInstance = -1;
8752 pTIClass->typeattr.cbSizeVft = -1;
8753 pTIClass->typeattr.cFuncs = 0;
8754 pTIClass->typeattr.cImplTypes = 1;
8755 pTIClass->typeattr.cVars = 0;
8756 pTIClass->typeattr.wTypeFlags = 0;
8757 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8759 pTIClass->impltypes = TLBImplType_Alloc(1);
8761 ref = heap_alloc_zero(sizeof(*ref));
8762 ref->pImpTLInfo = TLB_REF_INTERNAL;
8763 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8765 dump_TypeInfo(pTIClass);
8767 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8769 ITypeInfo_AddRef(*pptinfo);
8770 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8772 return S_OK;
8776 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8778 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8780 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8783 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8785 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8787 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8790 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8792 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8794 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8797 static HRESULT WINAPI ITypeComp_fnBind(
8798 ITypeComp * iface,
8799 OLECHAR * szName,
8800 ULONG lHash,
8801 WORD wFlags,
8802 ITypeInfo ** ppTInfo,
8803 DESCKIND * pDescKind,
8804 BINDPTR * pBindPtr)
8806 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8807 const TLBFuncDesc *pFDesc;
8808 const TLBVarDesc *pVDesc;
8809 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8810 UINT fdc;
8812 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8814 *pDescKind = DESCKIND_NONE;
8815 pBindPtr->lpfuncdesc = NULL;
8816 *ppTInfo = NULL;
8818 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8819 pFDesc = &This->funcdescs[fdc];
8820 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8821 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8822 break;
8823 else
8824 /* name found, but wrong flags */
8825 hr = TYPE_E_TYPEMISMATCH;
8829 if (fdc < This->typeattr.cFuncs)
8831 HRESULT hr = TLB_AllocAndInitFuncDesc(
8832 &pFDesc->funcdesc,
8833 &pBindPtr->lpfuncdesc,
8834 This->typeattr.typekind == TKIND_DISPATCH);
8835 if (FAILED(hr))
8836 return hr;
8837 *pDescKind = DESCKIND_FUNCDESC;
8838 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8839 ITypeInfo_AddRef(*ppTInfo);
8840 return S_OK;
8841 } else {
8842 pVDesc = TLB_get_vardesc_by_name(This, szName);
8843 if(pVDesc){
8844 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8845 if (FAILED(hr))
8846 return hr;
8847 *pDescKind = DESCKIND_VARDESC;
8848 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8849 ITypeInfo_AddRef(*ppTInfo);
8850 return S_OK;
8854 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8855 /* recursive search */
8856 ITypeInfo *pTInfo;
8857 ITypeComp *pTComp;
8858 HRESULT hr;
8859 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8860 if (SUCCEEDED(hr))
8862 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8863 ITypeInfo_Release(pTInfo);
8865 if (SUCCEEDED(hr))
8867 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8868 ITypeComp_Release(pTComp);
8869 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8870 This->typeattr.typekind == TKIND_DISPATCH)
8872 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8873 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8874 SysFreeString((BSTR)tmp);
8876 return hr;
8878 WARN("Could not search inherited interface!\n");
8880 if (hr == DISP_E_MEMBERNOTFOUND)
8881 hr = S_OK;
8882 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8883 return hr;
8886 static HRESULT WINAPI ITypeComp_fnBindType(
8887 ITypeComp * iface,
8888 OLECHAR * szName,
8889 ULONG lHash,
8890 ITypeInfo ** ppTInfo,
8891 ITypeComp ** ppTComp)
8893 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8895 /* strange behaviour (does nothing) but like the
8896 * original */
8898 if (!ppTInfo || !ppTComp)
8899 return E_POINTER;
8901 *ppTInfo = NULL;
8902 *ppTComp = NULL;
8904 return S_OK;
8907 static const ITypeCompVtbl tcompvt =
8910 ITypeComp_fnQueryInterface,
8911 ITypeComp_fnAddRef,
8912 ITypeComp_fnRelease,
8914 ITypeComp_fnBind,
8915 ITypeComp_fnBindType
8918 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8919 ICreateTypeLib2** ppctlib)
8921 ITypeLibImpl *This;
8922 HRESULT hres;
8924 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8926 if (!szFile) return E_INVALIDARG;
8928 This = TypeLibImpl_Constructor();
8929 if (!This)
8930 return E_OUTOFMEMORY;
8932 This->lcid = GetSystemDefaultLCID();
8933 This->syskind = syskind;
8934 This->ptr_size = get_ptr_size(syskind);
8936 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8937 if (!This->path) {
8938 ITypeLib2_Release(&This->ITypeLib2_iface);
8939 return E_OUTOFMEMORY;
8941 lstrcpyW(This->path, szFile);
8943 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8944 ITypeLib2_Release(&This->ITypeLib2_iface);
8945 return hres;
8948 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8949 REFIID riid, void **object)
8951 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8953 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8956 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8958 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8960 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8963 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8965 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8967 return ITypeLib2_Release(&This->ITypeLib2_iface);
8970 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8971 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8973 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8974 ITypeInfoImpl *info;
8975 HRESULT hres;
8977 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8979 if (!ctinfo || !name)
8980 return E_INVALIDARG;
8982 info = TLB_get_typeinfo_by_name(This, name);
8983 if (info)
8984 return TYPE_E_NAMECONFLICT;
8986 if (This->typeinfos)
8987 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8988 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8989 else
8990 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8992 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8994 info->pTypeLib = This;
8995 info->Name = TLB_append_str(&This->name_list, name);
8996 info->index = This->TypeInfoCount;
8997 info->typeattr.typekind = kind;
8998 info->typeattr.cbAlignment = 4;
9000 switch (info->typeattr.typekind) {
9001 case TKIND_ENUM:
9002 case TKIND_INTERFACE:
9003 case TKIND_DISPATCH:
9004 case TKIND_COCLASS:
9005 info->typeattr.cbSizeInstance = This->ptr_size;
9006 break;
9007 case TKIND_RECORD:
9008 case TKIND_UNION:
9009 info->typeattr.cbSizeInstance = 0;
9010 break;
9011 case TKIND_MODULE:
9012 info->typeattr.cbSizeInstance = 2;
9013 break;
9014 case TKIND_ALIAS:
9015 info->typeattr.cbSizeInstance = -0x75;
9016 break;
9017 default:
9018 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9019 info->typeattr.cbSizeInstance = 0xdeadbeef;
9020 break;
9023 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9024 &IID_ICreateTypeInfo, (void **)ctinfo);
9025 if (FAILED(hres)) {
9026 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9027 return hres;
9030 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9032 ++This->TypeInfoCount;
9034 return S_OK;
9037 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9038 LPOLESTR name)
9040 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9042 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9044 if (!name)
9045 return E_INVALIDARG;
9047 This->Name = TLB_append_str(&This->name_list, name);
9049 return S_OK;
9052 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9053 WORD majorVerNum, WORD minorVerNum)
9055 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9057 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9059 This->ver_major = majorVerNum;
9060 This->ver_minor = minorVerNum;
9062 return S_OK;
9065 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9066 REFGUID guid)
9068 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9070 TRACE("%p %s\n", This, debugstr_guid(guid));
9072 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9074 return S_OK;
9077 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9078 LPOLESTR doc)
9080 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9082 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9084 if (!doc)
9085 return E_INVALIDARG;
9087 This->DocString = TLB_append_str(&This->string_list, doc);
9089 return S_OK;
9092 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9093 LPOLESTR helpFileName)
9095 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9097 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9099 if (!helpFileName)
9100 return E_INVALIDARG;
9102 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9104 return S_OK;
9107 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9108 DWORD helpContext)
9110 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9112 TRACE("%p, %ld.\n", iface, helpContext);
9114 This->dwHelpContext = helpContext;
9116 return S_OK;
9119 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9120 LCID lcid)
9122 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9124 TRACE("%p, %#lx.\n", iface, lcid);
9126 This->set_lcid = lcid;
9128 return S_OK;
9131 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9132 UINT libFlags)
9134 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9136 TRACE("%p %x\n", This, libFlags);
9138 This->libflags = libFlags;
9140 return S_OK;
9143 typedef struct tagWMSFT_SegContents {
9144 DWORD len;
9145 void *data;
9146 } WMSFT_SegContents;
9148 typedef struct tagWMSFT_TLBFile {
9149 MSFT_Header header;
9150 WMSFT_SegContents typeinfo_seg;
9151 WMSFT_SegContents impfile_seg;
9152 WMSFT_SegContents impinfo_seg;
9153 WMSFT_SegContents ref_seg;
9154 WMSFT_SegContents guidhash_seg;
9155 WMSFT_SegContents guid_seg;
9156 WMSFT_SegContents namehash_seg;
9157 WMSFT_SegContents name_seg;
9158 WMSFT_SegContents string_seg;
9159 WMSFT_SegContents typdesc_seg;
9160 WMSFT_SegContents arraydesc_seg;
9161 WMSFT_SegContents custdata_seg;
9162 WMSFT_SegContents cdguids_seg;
9163 MSFT_SegDir segdir;
9164 WMSFT_SegContents aux_seg;
9165 } WMSFT_TLBFile;
9167 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9168 WMSFT_TLBFile *file)
9170 TLBString *str;
9171 UINT last_offs;
9172 char *data;
9174 file->string_seg.len = 0;
9175 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9176 int size;
9178 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9179 if (size == 0)
9180 return E_UNEXPECTED;
9182 size += sizeof(INT16);
9183 if (size % 4)
9184 size = (size + 4) & ~0x3;
9185 if (size < 8)
9186 size = 8;
9188 file->string_seg.len += size;
9190 /* temporarily use str->offset to store the length of the aligned,
9191 * converted string */
9192 str->offset = size;
9195 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9197 last_offs = 0;
9198 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9199 int size;
9201 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9202 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9203 if (size == 0) {
9204 heap_free(file->string_seg.data);
9205 return E_UNEXPECTED;
9208 *((INT16*)data) = size;
9210 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9212 size = str->offset;
9213 data += size;
9214 str->offset = last_offs;
9215 last_offs += size;
9218 return S_OK;
9221 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9222 WMSFT_TLBFile *file)
9224 TLBString *str;
9225 UINT last_offs;
9226 char *data;
9227 MSFT_NameIntro *last_intro = NULL;
9229 file->header.nametablecount = 0;
9230 file->header.nametablechars = 0;
9232 file->name_seg.len = 0;
9233 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9234 int size;
9236 size = lstrlenW(str->str);
9237 file->header.nametablechars += size;
9238 file->header.nametablecount++;
9240 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9241 if (size == 0)
9242 return E_UNEXPECTED;
9244 size += sizeof(MSFT_NameIntro);
9245 if (size % 4)
9246 size = (size + 4) & ~0x3;
9247 if (size < 8)
9248 size = 8;
9250 file->name_seg.len += size;
9252 /* temporarily use str->offset to store the length of the aligned,
9253 * converted string */
9254 str->offset = size;
9257 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9258 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9260 last_offs = 0;
9261 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9262 int size, hash;
9263 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9265 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9266 data + sizeof(MSFT_NameIntro),
9267 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9268 if (size == 0) {
9269 heap_free(file->name_seg.data);
9270 return E_UNEXPECTED;
9272 data[sizeof(MSFT_NameIntro) + size] = '\0';
9274 intro->hreftype = -1; /* TODO? */
9275 intro->namelen = size & 0xFF;
9276 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9277 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9278 intro->namelen |= hash << 16;
9279 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9280 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9282 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9283 str->offset - size - sizeof(MSFT_NameIntro));
9285 /* update str->offset to actual value to use in other
9286 * compilation functions that require positions within
9287 * the string table */
9288 last_intro = intro;
9289 size = str->offset;
9290 data += size;
9291 str->offset = last_offs;
9292 last_offs += size;
9295 if(last_intro)
9296 last_intro->hreftype = 0; /* last one is 0? */
9298 return S_OK;
9301 static inline int hash_guid(GUID *guid)
9303 int i, hash = 0;
9305 for (i = 0; i < 8; i ++)
9306 hash ^= ((const short *)guid)[i];
9308 return hash & 0x1f;
9311 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9313 TLBGuid *guid;
9314 MSFT_GuidEntry *entry;
9315 DWORD offs;
9316 int hash_key, *guidhashtab;
9318 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9319 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9321 entry = file->guid_seg.data;
9322 offs = 0;
9323 guidhashtab = file->guidhash_seg.data;
9324 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9325 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9326 entry->hreftype = guid->hreftype;
9328 hash_key = hash_guid(&guid->guid);
9329 entry->next_hash = guidhashtab[hash_key];
9330 guidhashtab[hash_key] = offs;
9332 guid->offset = offs;
9333 offs += sizeof(MSFT_GuidEntry);
9334 ++entry;
9337 return S_OK;
9340 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9342 VARIANT v = *value;
9343 VARTYPE arg_type = V_VT(value);
9344 int mask = 0;
9345 HRESULT hres;
9346 DWORD ret = file->custdata_seg.len;
9348 if(arg_type == VT_INT)
9349 arg_type = VT_I4;
9350 if(arg_type == VT_UINT)
9351 arg_type = VT_UI4;
9353 v = *value;
9354 if(V_VT(value) != arg_type) {
9355 hres = VariantChangeType(&v, value, 0, arg_type);
9356 if(FAILED(hres)){
9357 ERR("VariantChangeType failed: %#lx.\n", hres);
9358 return -1;
9362 /* Check if default value can be stored in-place */
9363 switch(arg_type){
9364 case VT_I4:
9365 case VT_UI4:
9366 mask = 0x3ffffff;
9367 if(V_UI4(&v) > 0x3ffffff)
9368 break;
9369 /* fall through */
9370 case VT_I1:
9371 case VT_UI1:
9372 case VT_BOOL:
9373 if(!mask)
9374 mask = 0xff;
9375 /* fall through */
9376 case VT_I2:
9377 case VT_UI2:
9378 if(!mask)
9379 mask = 0xffff;
9380 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9383 /* have to allocate space in custdata_seg */
9384 switch(arg_type) {
9385 case VT_I4:
9386 case VT_R4:
9387 case VT_UI4:
9388 case VT_INT:
9389 case VT_UINT:
9390 case VT_HRESULT:
9391 case VT_PTR: {
9392 /* Construct the data to be allocated */
9393 int *data;
9395 if(file->custdata_seg.data){
9396 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9397 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9398 file->custdata_seg.len += sizeof(int) * 2;
9399 }else{
9400 file->custdata_seg.len = sizeof(int) * 2;
9401 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9404 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9405 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9407 /* TODO: Check if the encoded data is already present in custdata_seg */
9409 return ret;
9412 case VT_BSTR: {
9413 int mb_len = WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), NULL, 0, NULL, NULL );
9414 int i, len = (6 + mb_len + 3) & ~0x3;
9415 char *data;
9417 if(file->custdata_seg.data){
9418 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9419 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9420 file->custdata_seg.len += len;
9421 }else{
9422 file->custdata_seg.len = len;
9423 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9426 *((unsigned short *)data) = V_VT(value);
9427 *((unsigned int *)(data+2)) = mb_len;
9428 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], mb_len, NULL, NULL);
9429 for (i = 6 + mb_len; i < len; i++)
9430 data[i] = 0x57;
9432 /* TODO: Check if the encoded data is already present in custdata_seg */
9434 return ret;
9436 default:
9437 FIXME("Argument type not yet handled\n");
9438 return -1;
9442 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9444 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9446 DWORD offs = file->arraydesc_seg.len;
9447 DWORD *encoded;
9448 USHORT i;
9450 /* TODO: we should check for duplicates, but that's harder because each
9451 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9452 * at the library-level) */
9454 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9455 if(!file->arraydesc_seg.data)
9456 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9457 else
9458 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9459 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9461 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9462 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9463 for(i = 0; i < desc->cDims; ++i){
9464 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9465 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9468 return offs;
9471 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9473 DWORD junk;
9474 INT16 junk2;
9475 DWORD offs = 0;
9476 DWORD encoded[2];
9477 VARTYPE vt, subtype;
9478 char *data;
9480 if(!desc)
9481 return -1;
9483 if(!out_mix)
9484 out_mix = &junk;
9485 if(!out_size)
9486 out_size = &junk2;
9488 vt = desc->vt & VT_TYPEMASK;
9490 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9491 DWORD mix;
9492 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9493 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9494 *out_mix = 0x7FFF;
9495 *out_size += 2 * sizeof(DWORD);
9496 }else if(vt == VT_CARRAY){
9497 encoded[0] = desc->vt | (0x7FFE << 16);
9498 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9499 *out_mix = 0x7FFE;
9500 }else if(vt == VT_USERDEFINED){
9501 encoded[0] = desc->vt | (0x7FFF << 16);
9502 encoded[1] = desc->u.hreftype;
9503 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9504 }else{
9505 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9507 switch(vt){
9508 case VT_INT:
9509 subtype = VT_I4;
9510 break;
9511 case VT_UINT:
9512 subtype = VT_UI4;
9513 break;
9514 case VT_VOID:
9515 subtype = VT_EMPTY;
9516 break;
9517 default:
9518 subtype = vt;
9519 break;
9522 *out_mix = subtype;
9523 return 0x80000000 | (subtype << 16) | desc->vt;
9526 data = file->typdesc_seg.data;
9527 while(offs < file->typdesc_seg.len){
9528 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9529 return offs;
9530 offs += sizeof(encoded);
9533 file->typdesc_seg.len += sizeof(encoded);
9534 if(!file->typdesc_seg.data)
9535 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9536 else
9537 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9539 memcpy(&data[offs], encoded, sizeof(encoded));
9541 return offs;
9544 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9546 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9547 DWORD ret = cdguids_seg->len, offs;
9548 MSFT_CDGuid *cdguid;
9549 TLBCustData *cd;
9551 if(list_empty(custdata_list))
9552 return -1;
9554 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9555 if(!cdguids_seg->data){
9556 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9557 }else {
9558 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9559 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9562 offs = ret + sizeof(MSFT_CDGuid);
9563 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9564 cdguid->GuidOffset = cd->guid->offset;
9565 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9566 cdguid->next = offs;
9567 offs += sizeof(MSFT_CDGuid);
9568 ++cdguid;
9571 --cdguid;
9572 cdguid->next = -1;
9574 return ret;
9577 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9578 WMSFT_TLBFile *file)
9580 WMSFT_SegContents *aux_seg = &file->aux_seg;
9581 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9582 MSFT_VarRecord *varrecord;
9583 MSFT_FuncRecord *funcrecord;
9584 MEMBERID *memid;
9585 DWORD *name, *offsets, offs;
9587 for(i = 0; i < info->typeattr.cFuncs; ++i){
9588 TLBFuncDesc *desc = &info->funcdescs[i];
9590 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9592 /* optional fields */
9593 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9594 if(!list_empty(&desc->custdata_list))
9595 recorded_size += 7 * sizeof(INT);
9596 else if(desc->HelpStringContext != 0)
9597 recorded_size += 6 * sizeof(INT);
9598 /* res9? resA? */
9599 else if(desc->Entry)
9600 recorded_size += 3 * sizeof(INT);
9601 else if(desc->HelpString)
9602 recorded_size += 2 * sizeof(INT);
9603 else if(desc->helpcontext)
9604 recorded_size += sizeof(INT);
9606 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9608 for(j = 0; j < desc->funcdesc.cParams; ++j){
9609 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9610 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9611 break;
9615 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9618 for(i = 0; i < info->typeattr.cVars; ++i){
9619 TLBVarDesc *desc = &info->vardescs[i];
9621 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9623 /* optional fields */
9624 if(desc->HelpStringContext != 0)
9625 recorded_size += 5 * sizeof(INT);
9626 else if(!list_empty(&desc->custdata_list))
9627 recorded_size += 4 * sizeof(INT);
9628 /* res9? */
9629 else if(desc->HelpString)
9630 recorded_size += 2 * sizeof(INT);
9631 else if(desc->HelpContext != 0)
9632 recorded_size += sizeof(INT);
9634 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9637 if(!recorded_size && !extra_size)
9638 return ret;
9640 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9642 aux_seg->len += recorded_size + extra_size;
9644 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9646 if(aux_seg->data)
9647 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9648 else
9649 aux_seg->data = heap_alloc(aux_seg->len);
9651 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9653 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9654 offs = 0;
9656 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9657 for(i = 0; i < info->typeattr.cFuncs; ++i){
9658 TLBFuncDesc *desc = &info->funcdescs[i];
9659 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9661 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9662 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9663 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9664 funcrecord->VtableOffset = desc->funcdesc.oVft;
9666 /* FKCCIC:
9667 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9668 * ^^^funckind
9669 * ^^^ ^invkind
9670 * ^has_cust_data
9671 * ^^^^callconv
9672 * ^has_param_defaults
9673 * ^oEntry_is_intresource
9675 funcrecord->FKCCIC =
9676 desc->funcdesc.funckind |
9677 (desc->funcdesc.invkind << 3) |
9678 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9679 (desc->funcdesc.callconv << 8);
9681 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9682 funcrecord->FKCCIC |= 0x2000;
9684 for(j = 0; j < desc->funcdesc.cParams; ++j){
9685 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9686 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9687 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9690 if(paramdefault_size > 0)
9691 funcrecord->FKCCIC |= 0x1000;
9693 funcrecord->nrargs = desc->funcdesc.cParams;
9694 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9696 /* optional fields */
9697 /* res9? resA? */
9698 if(!list_empty(&desc->custdata_list)){
9699 size += 7 * sizeof(INT);
9700 funcrecord->HelpContext = desc->helpcontext;
9701 if(desc->HelpString)
9702 funcrecord->oHelpString = desc->HelpString->offset;
9703 else
9704 funcrecord->oHelpString = -1;
9705 if(!desc->Entry)
9706 funcrecord->oEntry = -1;
9707 else if(IS_INTRESOURCE(desc->Entry))
9708 funcrecord->oEntry = LOWORD(desc->Entry);
9709 else
9710 funcrecord->oEntry = desc->Entry->offset;
9711 funcrecord->res9 = -1;
9712 funcrecord->resA = -1;
9713 funcrecord->HelpStringContext = desc->HelpStringContext;
9714 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9715 }else if(desc->HelpStringContext != 0){
9716 size += 6 * sizeof(INT);
9717 funcrecord->HelpContext = desc->helpcontext;
9718 if(desc->HelpString)
9719 funcrecord->oHelpString = desc->HelpString->offset;
9720 else
9721 funcrecord->oHelpString = -1;
9722 if(!desc->Entry)
9723 funcrecord->oEntry = -1;
9724 else if(IS_INTRESOURCE(desc->Entry))
9725 funcrecord->oEntry = LOWORD(desc->Entry);
9726 else
9727 funcrecord->oEntry = desc->Entry->offset;
9728 funcrecord->res9 = -1;
9729 funcrecord->resA = -1;
9730 funcrecord->HelpStringContext = desc->HelpStringContext;
9731 }else if(desc->Entry){
9732 size += 3 * sizeof(INT);
9733 funcrecord->HelpContext = desc->helpcontext;
9734 if(desc->HelpString)
9735 funcrecord->oHelpString = desc->HelpString->offset;
9736 else
9737 funcrecord->oHelpString = -1;
9738 if(!desc->Entry)
9739 funcrecord->oEntry = -1;
9740 else if(IS_INTRESOURCE(desc->Entry))
9741 funcrecord->oEntry = LOWORD(desc->Entry);
9742 else
9743 funcrecord->oEntry = desc->Entry->offset;
9744 }else if(desc->HelpString){
9745 size += 2 * sizeof(INT);
9746 funcrecord->HelpContext = desc->helpcontext;
9747 funcrecord->oHelpString = desc->HelpString->offset;
9748 }else if(desc->helpcontext){
9749 size += sizeof(INT);
9750 funcrecord->HelpContext = desc->helpcontext;
9753 paramdefault = (DWORD*)((char *)funcrecord + size);
9754 size += paramdefault_size;
9756 for(j = 0; j < desc->funcdesc.cParams; ++j){
9757 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9759 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9760 if(desc->pParamDesc[j].Name)
9761 info->oName = desc->pParamDesc[j].Name->offset;
9762 else
9763 info->oName = -1;
9764 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9766 if(paramdefault_size){
9767 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9768 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9769 else if(paramdefault_size)
9770 *paramdefault = -1;
9771 ++paramdefault;
9774 size += sizeof(MSFT_ParameterInfo);
9777 funcrecord->Info = size | (i << 16); /* is it just the index? */
9779 *offsets = offs;
9780 offs += size;
9781 ++offsets;
9783 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9786 varrecord = (MSFT_VarRecord*)funcrecord;
9787 for(i = 0; i < info->typeattr.cVars; ++i){
9788 TLBVarDesc *desc = &info->vardescs[i];
9789 DWORD size = 5 * sizeof(INT);
9791 varrecord->vardescsize = sizeof(desc->vardesc);
9792 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9793 varrecord->Flags = desc->vardesc.wVarFlags;
9794 varrecord->VarKind = desc->vardesc.varkind;
9796 if(desc->vardesc.varkind == VAR_CONST){
9797 varrecord->vardescsize += sizeof(VARIANT);
9798 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9799 }else
9800 varrecord->OffsValue = desc->vardesc.u.oInst;
9802 /* res9? */
9803 if(desc->HelpStringContext != 0){
9804 size += 5 * sizeof(INT);
9805 varrecord->HelpContext = desc->HelpContext;
9806 if(desc->HelpString)
9807 varrecord->HelpString = desc->HelpString->offset;
9808 else
9809 varrecord->HelpString = -1;
9810 varrecord->res9 = -1;
9811 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9812 varrecord->HelpStringContext = desc->HelpStringContext;
9813 }else if(!list_empty(&desc->custdata_list)){
9814 size += 4 * sizeof(INT);
9815 varrecord->HelpContext = desc->HelpContext;
9816 if(desc->HelpString)
9817 varrecord->HelpString = desc->HelpString->offset;
9818 else
9819 varrecord->HelpString = -1;
9820 varrecord->res9 = -1;
9821 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9822 }else if(desc->HelpString){
9823 size += 2 * sizeof(INT);
9824 varrecord->HelpContext = desc->HelpContext;
9825 if(desc->HelpString)
9826 varrecord->HelpString = desc->HelpString->offset;
9827 else
9828 varrecord->HelpString = -1;
9829 }else if(desc->HelpContext != 0){
9830 size += sizeof(INT);
9831 varrecord->HelpContext = desc->HelpContext;
9834 varrecord->Info = size | (i << 16);
9836 *offsets = offs;
9837 offs += size;
9838 ++offsets;
9840 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9843 memid = (MEMBERID*)varrecord;
9844 for(i = 0; i < info->typeattr.cFuncs; ++i){
9845 TLBFuncDesc *desc = &info->funcdescs[i];
9846 *memid = desc->funcdesc.memid;
9847 ++memid;
9849 for(i = 0; i < info->typeattr.cVars; ++i){
9850 TLBVarDesc *desc = &info->vardescs[i];
9851 *memid = desc->vardesc.memid;
9852 ++memid;
9855 name = (DWORD*)memid;
9856 for(i = 0; i < info->typeattr.cFuncs; ++i){
9857 TLBFuncDesc *desc = &info->funcdescs[i];
9858 if(desc->Name)
9859 *name = desc->Name->offset;
9860 else
9861 *name = -1;
9862 ++name;
9864 for(i = 0; i < info->typeattr.cVars; ++i){
9865 TLBVarDesc *desc = &info->vardescs[i];
9866 if(desc->Name)
9867 *name = desc->Name->offset;
9868 else
9869 *name = -1;
9870 ++name;
9873 return ret;
9876 typedef struct tagWMSFT_RefChunk {
9877 DWORD href;
9878 DWORD res04;
9879 DWORD res08;
9880 DWORD next;
9881 } WMSFT_RefChunk;
9883 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9885 DWORD offs = file->ref_seg.len, i;
9886 WMSFT_RefChunk *chunk;
9888 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9889 if(!file->ref_seg.data)
9890 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9891 else
9892 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9894 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9896 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9897 chunk->href = info->impltypes[i].hRef;
9898 chunk->res04 = info->impltypes[i].implflags;
9899 chunk->res08 = -1;
9900 if(i < info->typeattr.cImplTypes - 1)
9901 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9902 else
9903 chunk->next = -1;
9904 ++chunk;
9907 return offs;
9910 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9912 DWORD size;
9914 size = sizeof(MSFT_TypeInfoBase);
9916 if(data){
9917 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9918 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9919 base->typekind = TKIND_DISPATCH;
9920 else
9921 base->typekind = info->typeattr.typekind;
9922 base->typekind |= index << 16; /* TODO: There are some other flags here */
9923 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9924 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9925 base->res2 = 0;
9926 base->res3 = 0;
9927 base->res4 = 3;
9928 base->res5 = 0;
9929 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9930 base->res7 = 0;
9931 base->res8 = 0;
9932 base->res9 = 0;
9933 base->resA = 0;
9934 if(info->guid)
9935 base->posguid = info->guid->offset;
9936 else
9937 base->posguid = -1;
9938 base->flags = info->typeattr.wTypeFlags;
9939 if(info->Name) {
9940 base->NameOffset = info->Name->offset;
9942 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9943 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9944 }else {
9945 base->NameOffset = -1;
9947 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9948 if(info->DocString)
9949 base->docstringoffs = info->DocString->offset;
9950 else
9951 base->docstringoffs = -1;
9952 base->helpstringcontext = info->dwHelpStringContext;
9953 base->helpcontext = info->dwHelpContext;
9954 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9955 base->cImplTypes = info->typeattr.cImplTypes;
9956 base->cbSizeVft = info->typeattr.cbSizeVft;
9957 base->size = info->typeattr.cbSizeInstance;
9958 if(info->typeattr.typekind == TKIND_COCLASS){
9959 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9960 }else if(info->typeattr.typekind == TKIND_ALIAS){
9961 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9962 }else if(info->typeattr.typekind == TKIND_MODULE){
9963 if(info->DllName)
9964 base->datatype1 = info->DllName->offset;
9965 else
9966 base->datatype1 = -1;
9967 }else{
9968 if(info->typeattr.cImplTypes > 0)
9969 base->datatype1 = info->impltypes[0].hRef;
9970 else
9971 base->datatype1 = -1;
9973 base->datatype2 = index; /* FIXME: i think there's more here */
9974 base->res18 = 0;
9975 base->res19 = -1;
9978 return size;
9981 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9983 UINT i;
9985 file->typeinfo_seg.len = 0;
9986 for(i = 0; i < This->TypeInfoCount; ++i){
9987 ITypeInfoImpl *info = This->typeinfos[i];
9988 *junk = file->typeinfo_seg.len;
9989 ++junk;
9990 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9993 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9994 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9996 file->aux_seg.len = 0;
9997 file->aux_seg.data = NULL;
9999 file->typeinfo_seg.len = 0;
10000 for(i = 0; i < This->TypeInfoCount; ++i){
10001 ITypeInfoImpl *info = This->typeinfos[i];
10002 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
10003 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
10007 typedef struct tagWMSFT_ImpFile {
10008 INT guid_offs;
10009 LCID lcid;
10010 DWORD version;
10011 } WMSFT_ImpFile;
10013 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
10015 TLBImpLib *implib;
10016 WMSFT_ImpFile *impfile;
10017 char *data;
10018 DWORD last_offs = 0;
10020 file->impfile_seg.len = 0;
10021 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10022 int size = 0;
10024 if(implib->name){
10025 WCHAR *path = wcsrchr(implib->name, '\\');
10026 if(path)
10027 ++path;
10028 else
10029 path = implib->name;
10030 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10031 if (size == 0)
10032 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10035 size += sizeof(INT16);
10036 if (size % 4)
10037 size = (size + 4) & ~0x3;
10038 if (size < 8)
10039 size = 8;
10041 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10044 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
10046 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10047 int strlen = 0, size;
10049 impfile = (WMSFT_ImpFile*)data;
10050 impfile->guid_offs = implib->guid->offset;
10051 impfile->lcid = implib->lcid;
10052 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10054 data += sizeof(WMSFT_ImpFile);
10056 if(implib->name){
10057 WCHAR *path= wcsrchr(implib->name, '\\');
10058 if(path)
10059 ++path;
10060 else
10061 path = implib->name;
10062 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10063 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10064 if (strlen == 0)
10065 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10068 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10070 size = strlen + sizeof(INT16);
10071 if (size % 4)
10072 size = (size + 4) & ~0x3;
10073 if (size < 8)
10074 size = 8;
10075 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10077 data += size;
10078 implib->offset = last_offs;
10079 last_offs += size + sizeof(WMSFT_ImpFile);
10083 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10085 MSFT_ImpInfo *info;
10086 TLBRefType *ref_type;
10087 UINT i = 0;
10089 WMSFT_compile_impfile(This, file);
10091 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10092 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10094 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10095 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10096 if(ref_type->index == TLB_REF_USE_GUID){
10097 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10098 info->oGuid = ref_type->guid->offset;
10099 }else
10100 info->oGuid = ref_type->index;
10101 info->oImpFile = ref_type->pImpTLInfo->offset;
10102 ++i;
10103 ++info;
10107 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10109 file->guidhash_seg.len = 0x80;
10110 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10111 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10114 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10116 file->namehash_seg.len = 0x200;
10117 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10118 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10121 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10123 if(contents && contents->len){
10124 segdir->offset = *running_offset;
10125 segdir->length = contents->len;
10126 *running_offset += segdir->length;
10127 }else{
10128 segdir->offset = -1;
10129 segdir->length = 0;
10132 /* TODO: do these ever change? */
10133 segdir->res08 = -1;
10134 segdir->res0c = 0xf;
10137 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10139 DWORD written;
10140 if(segment)
10141 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10144 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10145 DWORD file_len)
10147 DWORD i;
10148 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10150 for(i = 0; i < This->TypeInfoCount; ++i){
10151 base->memoffset += file_len;
10152 ++base;
10155 return S_OK;
10158 static void WMSFT_free_file(WMSFT_TLBFile *file)
10160 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10161 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10162 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10163 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10164 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10165 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10166 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10167 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10168 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10169 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10170 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10171 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10172 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10173 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10176 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10178 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10179 WMSFT_TLBFile file;
10180 DWORD written, junk_size, junk_offs, running_offset;
10181 BOOL br;
10182 HANDLE outfile;
10183 HRESULT hres;
10184 DWORD *junk;
10185 UINT i;
10187 TRACE("%p\n", This);
10189 for(i = 0; i < This->TypeInfoCount; ++i)
10190 if(This->typeinfos[i]->needs_layout)
10191 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10193 memset(&file, 0, sizeof(file));
10195 file.header.magic1 = 0x5446534D;
10196 file.header.magic2 = 0x00010002;
10197 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10198 file.header.lcid2 = This->set_lcid;
10199 file.header.varflags = 0x40 | This->syskind;
10200 if (This->HelpFile)
10201 file.header.varflags |= 0x10;
10202 if (This->HelpStringDll)
10203 file.header.varflags |= HELPDLLFLAG;
10204 file.header.version = (This->ver_minor << 16) | This->ver_major;
10205 file.header.flags = This->libflags;
10206 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10207 file.header.helpcontext = This->dwHelpContext;
10208 file.header.res44 = 0x20;
10209 file.header.res48 = 0x80;
10210 file.header.dispatchpos = This->dispatch_href;
10212 WMSFT_compile_namehash(This, &file);
10213 /* do name and string compilation to get offsets for other compilations */
10214 hres = WMSFT_compile_names(This, &file);
10215 if (FAILED(hres)){
10216 WMSFT_free_file(&file);
10217 return hres;
10220 hres = WMSFT_compile_strings(This, &file);
10221 if (FAILED(hres)){
10222 WMSFT_free_file(&file);
10223 return hres;
10226 WMSFT_compile_guidhash(This, &file);
10227 hres = WMSFT_compile_guids(This, &file);
10228 if (FAILED(hres)){
10229 WMSFT_free_file(&file);
10230 return hres;
10233 if(This->HelpFile)
10234 file.header.helpfile = This->HelpFile->offset;
10235 else
10236 file.header.helpfile = -1;
10238 if(This->DocString)
10239 file.header.helpstring = This->DocString->offset;
10240 else
10241 file.header.helpstring = -1;
10243 /* do some more segment compilation */
10244 file.header.nimpinfos = list_count(&This->ref_list);
10245 file.header.nrtypeinfos = This->TypeInfoCount;
10247 if(This->Name)
10248 file.header.NameOffset = This->Name->offset;
10249 else
10250 file.header.NameOffset = -1;
10252 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10254 if(This->guid)
10255 file.header.posguid = This->guid->offset;
10256 else
10257 file.header.posguid = -1;
10259 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10260 if(file.header.varflags & HELPDLLFLAG)
10261 junk_size += sizeof(DWORD);
10262 if(junk_size){
10263 junk = heap_alloc_zero(junk_size);
10264 if(file.header.varflags & HELPDLLFLAG){
10265 *junk = This->HelpStringDll->offset;
10266 junk_offs = 1;
10267 }else
10268 junk_offs = 0;
10269 }else{
10270 junk = NULL;
10271 junk_offs = 0;
10274 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10275 WMSFT_compile_impinfo(This, &file);
10277 running_offset = 0;
10279 TRACE("header at: 0x%lx\n", running_offset);
10280 running_offset += sizeof(file.header);
10282 TRACE("junk at: 0x%lx\n", running_offset);
10283 running_offset += junk_size;
10285 TRACE("segdir at: 0x%lx\n", running_offset);
10286 running_offset += sizeof(file.segdir);
10288 TRACE("typeinfo at: 0x%lx\n", running_offset);
10289 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10291 TRACE("guidhashtab at: 0x%lx\n", running_offset);
10292 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10294 TRACE("guidtab at: 0x%lx\n", running_offset);
10295 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10297 TRACE("reftab at: 0x%lx\n", running_offset);
10298 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10300 TRACE("impinfo at: 0x%lx\n", running_offset);
10301 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10303 TRACE("impfiles at: 0x%lx\n", running_offset);
10304 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10306 TRACE("namehashtab at: 0x%lx\n", running_offset);
10307 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10309 TRACE("nametab at: 0x%lx\n", running_offset);
10310 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10312 TRACE("stringtab at: 0x%lx\n", running_offset);
10313 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10315 TRACE("typdesc at: 0x%lx\n", running_offset);
10316 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10318 TRACE("arraydescriptions at: 0x%lx\n", running_offset);
10319 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10321 TRACE("custdata at: 0x%lx\n", running_offset);
10322 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10324 TRACE("cdguids at: 0x%lx\n", running_offset);
10325 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10327 TRACE("res0e at: 0x%lx\n", running_offset);
10328 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10330 TRACE("res0f at: 0x%lx\n", running_offset);
10331 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10333 TRACE("aux_seg at: 0x%lx\n", running_offset);
10335 WMSFT_fixup_typeinfos(This, &file, running_offset);
10337 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10338 FILE_ATTRIBUTE_NORMAL, 0);
10339 if (outfile == INVALID_HANDLE_VALUE){
10340 WMSFT_free_file(&file);
10341 heap_free(junk);
10342 return TYPE_E_IOERROR;
10345 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10346 if (!br) {
10347 WMSFT_free_file(&file);
10348 CloseHandle(outfile);
10349 heap_free(junk);
10350 return TYPE_E_IOERROR;
10353 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10354 heap_free(junk);
10355 if (!br) {
10356 WMSFT_free_file(&file);
10357 CloseHandle(outfile);
10358 return TYPE_E_IOERROR;
10361 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10362 if (!br) {
10363 WMSFT_free_file(&file);
10364 CloseHandle(outfile);
10365 return TYPE_E_IOERROR;
10368 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10369 WMSFT_write_segment(outfile, &file.guidhash_seg);
10370 WMSFT_write_segment(outfile, &file.guid_seg);
10371 WMSFT_write_segment(outfile, &file.ref_seg);
10372 WMSFT_write_segment(outfile, &file.impinfo_seg);
10373 WMSFT_write_segment(outfile, &file.impfile_seg);
10374 WMSFT_write_segment(outfile, &file.namehash_seg);
10375 WMSFT_write_segment(outfile, &file.name_seg);
10376 WMSFT_write_segment(outfile, &file.string_seg);
10377 WMSFT_write_segment(outfile, &file.typdesc_seg);
10378 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10379 WMSFT_write_segment(outfile, &file.custdata_seg);
10380 WMSFT_write_segment(outfile, &file.cdguids_seg);
10381 WMSFT_write_segment(outfile, &file.aux_seg);
10383 WMSFT_free_file(&file);
10385 CloseHandle(outfile);
10387 return S_OK;
10390 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10391 LPOLESTR name)
10393 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10394 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10395 return E_NOTIMPL;
10398 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10399 REFGUID guid, VARIANT *varVal)
10401 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10402 TLBGuid *tlbguid;
10404 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10406 if (!guid || !varVal)
10407 return E_INVALIDARG;
10409 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10411 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10414 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10415 ULONG helpStringContext)
10417 FIXME("%p, %lu - stub\n", iface, helpStringContext);
10418 return E_NOTIMPL;
10421 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10422 LPOLESTR filename)
10424 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10425 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10427 if (!filename)
10428 return E_INVALIDARG;
10430 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10432 return S_OK;
10435 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10436 ICreateTypeLib2_fnQueryInterface,
10437 ICreateTypeLib2_fnAddRef,
10438 ICreateTypeLib2_fnRelease,
10439 ICreateTypeLib2_fnCreateTypeInfo,
10440 ICreateTypeLib2_fnSetName,
10441 ICreateTypeLib2_fnSetVersion,
10442 ICreateTypeLib2_fnSetGuid,
10443 ICreateTypeLib2_fnSetDocString,
10444 ICreateTypeLib2_fnSetHelpFileName,
10445 ICreateTypeLib2_fnSetHelpContext,
10446 ICreateTypeLib2_fnSetLcid,
10447 ICreateTypeLib2_fnSetLibFlags,
10448 ICreateTypeLib2_fnSaveAllChanges,
10449 ICreateTypeLib2_fnDeleteTypeInfo,
10450 ICreateTypeLib2_fnSetCustData,
10451 ICreateTypeLib2_fnSetHelpStringContext,
10452 ICreateTypeLib2_fnSetHelpStringDll
10455 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10456 REFIID riid, void **object)
10458 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10460 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10463 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10465 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10467 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10470 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10472 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10474 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10477 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10478 REFGUID guid)
10480 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10482 TRACE("%p %s\n", This, debugstr_guid(guid));
10484 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10486 return S_OK;
10489 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10490 UINT typeFlags)
10492 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10493 WORD old_flags;
10494 HRESULT hres;
10496 TRACE("%p %x\n", This, typeFlags);
10498 if (typeFlags & TYPEFLAG_FDUAL) {
10499 ITypeLib *stdole;
10500 ITypeInfo *dispatch;
10501 HREFTYPE hreftype;
10502 HRESULT hres;
10504 hres = LoadTypeLib(L"stdole2.tlb", &stdole);
10505 if(FAILED(hres))
10506 return hres;
10508 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10509 ITypeLib_Release(stdole);
10510 if(FAILED(hres))
10511 return hres;
10513 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10514 ITypeInfo_Release(dispatch);
10515 if(FAILED(hres))
10516 return hres;
10519 old_flags = This->typeattr.wTypeFlags;
10520 This->typeattr.wTypeFlags = typeFlags;
10522 hres = ICreateTypeInfo2_LayOut(iface);
10523 if (FAILED(hres)) {
10524 This->typeattr.wTypeFlags = old_flags;
10525 return hres;
10528 return S_OK;
10531 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10532 LPOLESTR doc)
10534 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10536 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10538 if (!doc)
10539 return E_INVALIDARG;
10541 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10543 return S_OK;
10546 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10547 DWORD helpContext)
10549 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10551 TRACE("%p, %ld.\n", iface, helpContext);
10553 This->dwHelpContext = helpContext;
10555 return S_OK;
10558 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10559 WORD majorVerNum, WORD minorVerNum)
10561 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10563 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10565 This->typeattr.wMajorVerNum = majorVerNum;
10566 This->typeattr.wMinorVerNum = minorVerNum;
10568 return S_OK;
10571 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10572 ITypeInfo *typeInfo, HREFTYPE *refType)
10574 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10575 UINT index;
10576 ITypeLib *container;
10577 TLBRefType *ref_type;
10578 TLBImpLib *implib;
10579 TYPEATTR *typeattr;
10580 TLIBATTR *libattr;
10581 HRESULT hres;
10583 TRACE("%p %p %p\n", This, typeInfo, refType);
10585 if (!typeInfo || !refType)
10586 return E_INVALIDARG;
10588 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10589 if (FAILED(hres))
10590 return hres;
10592 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10593 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10595 ITypeLib_Release(container);
10597 *refType = target->hreftype;
10599 return S_OK;
10602 hres = ITypeLib_GetLibAttr(container, &libattr);
10603 if (FAILED(hres)) {
10604 ITypeLib_Release(container);
10605 return hres;
10608 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10609 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10610 implib->lcid == libattr->lcid &&
10611 implib->wVersionMajor == libattr->wMajorVerNum &&
10612 implib->wVersionMinor == libattr->wMinorVerNum)
10613 break;
10616 if(&implib->entry == &This->pTypeLib->implib_list){
10617 implib = heap_alloc_zero(sizeof(TLBImpLib));
10619 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10620 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10621 implib->name = SysAllocString(our_container->path);
10622 }else{
10623 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10624 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10625 if(FAILED(hres)){
10626 implib->name = NULL;
10627 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres);
10631 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10632 implib->lcid = libattr->lcid;
10633 implib->wVersionMajor = libattr->wMajorVerNum;
10634 implib->wVersionMinor = libattr->wMinorVerNum;
10636 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10639 ITypeLib_ReleaseTLibAttr(container, libattr);
10640 ITypeLib_Release(container);
10642 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10643 if (FAILED(hres))
10644 return hres;
10646 index = 0;
10647 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10648 if(ref_type->index == TLB_REF_USE_GUID &&
10649 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10650 ref_type->tkind == typeattr->typekind)
10651 break;
10652 ++index;
10655 if(&ref_type->entry == &This->pTypeLib->ref_list){
10656 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10658 ref_type->tkind = typeattr->typekind;
10659 ref_type->pImpTLInfo = implib;
10660 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10662 ref_type->index = TLB_REF_USE_GUID;
10664 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10666 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10669 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10671 *refType = ref_type->reference | 0x1;
10673 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10674 This->pTypeLib->dispatch_href = *refType;
10676 return S_OK;
10679 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10680 UINT index, FUNCDESC *funcDesc)
10682 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10683 TLBFuncDesc tmp_func_desc, *func_desc;
10684 int buf_size, i;
10685 char *buffer;
10686 HRESULT hres;
10688 TRACE("%p %u %p\n", This, index, funcDesc);
10690 if (!funcDesc || funcDesc->oVft & 3)
10691 return E_INVALIDARG;
10693 switch (This->typeattr.typekind) {
10694 case TKIND_MODULE:
10695 if (funcDesc->funckind != FUNC_STATIC)
10696 return TYPE_E_BADMODULEKIND;
10697 break;
10698 case TKIND_DISPATCH:
10699 if (funcDesc->funckind != FUNC_DISPATCH)
10700 return TYPE_E_BADMODULEKIND;
10701 break;
10702 default:
10703 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10704 return TYPE_E_BADMODULEKIND;
10707 if (index > This->typeattr.cFuncs)
10708 return TYPE_E_ELEMENTNOTFOUND;
10710 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10711 !funcDesc->cParams)
10712 return TYPE_E_INCONSISTENTPROPFUNCS;
10714 #ifdef _WIN64
10715 if(This->pTypeLib->syskind == SYS_WIN64 &&
10716 funcDesc->oVft % 8 != 0)
10717 return E_INVALIDARG;
10718 #endif
10720 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10721 TLBFuncDesc_Constructor(&tmp_func_desc);
10723 tmp_func_desc.funcdesc = *funcDesc;
10725 if (tmp_func_desc.funcdesc.oVft != 0)
10726 tmp_func_desc.funcdesc.oVft |= 1;
10728 if (funcDesc->cScodes && funcDesc->lprgscode) {
10729 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10730 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10731 } else {
10732 tmp_func_desc.funcdesc.lprgscode = NULL;
10733 tmp_func_desc.funcdesc.cScodes = 0;
10736 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10737 for (i = 0; i < funcDesc->cParams; ++i) {
10738 buf_size += sizeof(ELEMDESC);
10739 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10741 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10742 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10744 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10745 if (FAILED(hres)) {
10746 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10747 heap_free(tmp_func_desc.funcdesc.lprgscode);
10748 return hres;
10751 for (i = 0; i < funcDesc->cParams; ++i) {
10752 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10753 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10754 if (FAILED(hres)) {
10755 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10756 heap_free(tmp_func_desc.funcdesc.lprgscode);
10757 return hres;
10759 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10760 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10761 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10762 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10763 if (FAILED(hres)) {
10764 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10765 heap_free(tmp_func_desc.funcdesc.lprgscode);
10766 return hres;
10771 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10773 if (This->funcdescs) {
10774 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10775 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10777 if (index < This->typeattr.cFuncs) {
10778 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10779 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10780 func_desc = This->funcdescs + index;
10781 } else
10782 func_desc = This->funcdescs + This->typeattr.cFuncs;
10784 /* move custdata lists to the new memory location */
10785 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10786 if(index != i)
10787 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10789 } else
10790 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10792 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10793 list_init(&func_desc->custdata_list);
10795 ++This->typeattr.cFuncs;
10797 This->needs_layout = TRUE;
10799 return S_OK;
10802 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10803 UINT index, HREFTYPE refType)
10805 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10806 TLBImplType *impl_type;
10807 HRESULT hres;
10809 TRACE("%p, %u, %ld.\n", iface, index, refType);
10811 switch(This->typeattr.typekind){
10812 case TKIND_COCLASS: {
10813 if (index == -1) {
10814 FIXME("Unhandled index: -1\n");
10815 return E_NOTIMPL;
10818 if(index != This->typeattr.cImplTypes)
10819 return TYPE_E_ELEMENTNOTFOUND;
10821 break;
10823 case TKIND_INTERFACE:
10824 case TKIND_DISPATCH:
10825 if (index != 0 || This->typeattr.cImplTypes)
10826 return TYPE_E_ELEMENTNOTFOUND;
10827 break;
10828 default:
10829 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10830 return E_NOTIMPL;
10833 if (This->impltypes){
10834 UINT i;
10836 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10837 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10839 if (index < This->typeattr.cImplTypes) {
10840 memmove(This->impltypes + index + 1, This->impltypes + index,
10841 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10842 impl_type = This->impltypes + index;
10843 } else
10844 impl_type = This->impltypes + This->typeattr.cImplTypes;
10846 /* move custdata lists to the new memory location */
10847 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10848 if(index != i)
10849 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10851 } else
10852 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10854 memset(impl_type, 0, sizeof(TLBImplType));
10855 TLBImplType_Constructor(impl_type);
10856 impl_type->hRef = refType;
10858 ++This->typeattr.cImplTypes;
10860 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10861 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10863 hres = ICreateTypeInfo2_LayOut(iface);
10864 if (FAILED(hres))
10865 return hres;
10867 return S_OK;
10870 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10871 UINT index, INT implTypeFlags)
10873 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10874 TLBImplType *impl_type = &This->impltypes[index];
10876 TRACE("%p %u %x\n", This, index, implTypeFlags);
10878 if (This->typeattr.typekind != TKIND_COCLASS)
10879 return TYPE_E_BADMODULEKIND;
10881 if (index >= This->typeattr.cImplTypes)
10882 return TYPE_E_ELEMENTNOTFOUND;
10884 impl_type->implflags = implTypeFlags;
10886 return S_OK;
10889 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10890 WORD alignment)
10892 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10894 TRACE("%p %d\n", This, alignment);
10896 This->typeattr.cbAlignment = alignment;
10898 return S_OK;
10901 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10902 LPOLESTR schema)
10904 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10906 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10908 if (!schema)
10909 return E_INVALIDARG;
10911 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10913 This->typeattr.lpstrSchema = This->Schema->str;
10915 return S_OK;
10918 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10919 UINT index, VARDESC *varDesc)
10921 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10922 TLBVarDesc *var_desc;
10923 HRESULT hr;
10925 TRACE("%p %u %p\n", This, index, varDesc);
10927 if (This->vardescs){
10928 UINT i;
10930 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10931 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10933 if (index < This->typeattr.cVars) {
10934 memmove(This->vardescs + index + 1, This->vardescs + index,
10935 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10936 var_desc = This->vardescs + index;
10937 } else
10938 var_desc = This->vardescs + This->typeattr.cVars;
10940 /* move custdata lists to the new memory location */
10941 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10942 if(index != i)
10943 TLB_relink_custdata(&This->vardescs[i].custdata_list);
10945 } else
10946 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10948 TLBVarDesc_Constructor(var_desc);
10949 hr = TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10950 if (FAILED(hr))
10951 return hr;
10952 var_desc->vardesc = *var_desc->vardesc_create;
10954 ++This->typeattr.cVars;
10956 This->needs_layout = TRUE;
10958 return S_OK;
10961 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10962 UINT index, LPOLESTR *names, UINT numNames)
10964 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10965 TLBFuncDesc *func_desc = &This->funcdescs[index];
10966 int i;
10968 TRACE("%p %u %p %u\n", This, index, names, numNames);
10970 if (!names)
10971 return E_INVALIDARG;
10973 if (index >= This->typeattr.cFuncs || numNames == 0)
10974 return TYPE_E_ELEMENTNOTFOUND;
10976 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10977 if(numNames > func_desc->funcdesc.cParams)
10978 return TYPE_E_ELEMENTNOTFOUND;
10979 } else
10980 if(numNames > func_desc->funcdesc.cParams + 1)
10981 return TYPE_E_ELEMENTNOTFOUND;
10983 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10984 TLBFuncDesc *iter = &This->funcdescs[i];
10985 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
10986 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10987 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10988 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10989 continue;
10990 return TYPE_E_AMBIGUOUSNAME;
10994 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10996 for (i = 1; i < numNames; ++i) {
10997 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10998 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
11001 return S_OK;
11004 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
11005 UINT index, LPOLESTR name)
11007 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11009 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
11011 if(!name)
11012 return E_INVALIDARG;
11014 if(index >= This->typeattr.cVars)
11015 return TYPE_E_ELEMENTNOTFOUND;
11017 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
11018 return S_OK;
11021 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
11022 TYPEDESC *tdescAlias)
11024 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11025 HRESULT hr;
11027 TRACE("%p %p\n", This, tdescAlias);
11029 if(!tdescAlias)
11030 return E_INVALIDARG;
11032 if(This->typeattr.typekind != TKIND_ALIAS)
11033 return TYPE_E_BADMODULEKIND;
11035 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11036 if(FAILED(hr))
11037 return hr;
11039 heap_free(This->tdescAlias);
11040 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11041 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11043 return S_OK;
11046 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11047 UINT index, LPOLESTR dllName, LPOLESTR procName)
11049 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11050 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11051 return E_NOTIMPL;
11054 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11055 UINT index, LPOLESTR docString)
11057 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11058 TLBFuncDesc *func_desc = &This->funcdescs[index];
11060 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11062 if(!docString)
11063 return E_INVALIDARG;
11065 if(index >= This->typeattr.cFuncs)
11066 return TYPE_E_ELEMENTNOTFOUND;
11068 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11070 return S_OK;
11073 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11074 UINT index, LPOLESTR docString)
11076 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11077 TLBVarDesc *var_desc = &This->vardescs[index];
11079 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11081 if(!docString)
11082 return E_INVALIDARG;
11084 if(index >= This->typeattr.cVars)
11085 return TYPE_E_ELEMENTNOTFOUND;
11087 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11089 return S_OK;
11092 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11093 UINT index, DWORD helpContext)
11095 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11096 TLBFuncDesc *func_desc = &This->funcdescs[index];
11098 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
11100 if(index >= This->typeattr.cFuncs)
11101 return TYPE_E_ELEMENTNOTFOUND;
11103 func_desc->helpcontext = helpContext;
11105 return S_OK;
11108 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11109 UINT index, DWORD helpContext)
11111 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11112 TLBVarDesc *var_desc = &This->vardescs[index];
11114 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
11116 if(index >= This->typeattr.cVars)
11117 return TYPE_E_ELEMENTNOTFOUND;
11119 var_desc->HelpContext = helpContext;
11121 return S_OK;
11124 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11125 UINT index, BSTR bstrMops)
11127 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11128 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11129 return E_NOTIMPL;
11132 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11133 IDLDESC *idlDesc)
11135 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11137 TRACE("%p %p\n", This, idlDesc);
11139 if (!idlDesc)
11140 return E_INVALIDARG;
11142 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11143 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11145 return S_OK;
11148 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11150 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11151 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11152 TLBFuncDesc *func_desc;
11153 UINT user_vft = 0, i, depth = 0;
11154 HRESULT hres = S_OK;
11156 TRACE("%p\n", This);
11158 This->needs_layout = FALSE;
11160 if (This->typeattr.typekind == TKIND_INTERFACE) {
11161 ITypeInfo *inh;
11162 TYPEATTR *attr;
11163 HREFTYPE inh_href;
11165 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11167 if (SUCCEEDED(hres)) {
11168 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11170 if (SUCCEEDED(hres)) {
11171 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11172 if (FAILED(hres)) {
11173 ITypeInfo_Release(inh);
11174 return hres;
11176 This->typeattr.cbSizeVft = attr->cbSizeVft;
11177 ITypeInfo_ReleaseTypeAttr(inh, attr);
11180 ++depth;
11181 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11182 if(SUCCEEDED(hres)){
11183 ITypeInfo *next;
11184 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11185 if(SUCCEEDED(hres)){
11186 ITypeInfo_Release(inh);
11187 inh = next;
11190 }while(SUCCEEDED(hres));
11191 hres = S_OK;
11193 ITypeInfo_Release(inh);
11194 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11195 This->typeattr.cbSizeVft = 0;
11196 hres = S_OK;
11197 } else
11198 return hres;
11199 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11200 This->typeattr.cbSizeVft = 0;
11201 hres = S_OK;
11202 } else
11203 return hres;
11204 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11205 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11206 else
11207 This->typeattr.cbSizeVft = 0;
11209 func_desc = This->funcdescs;
11210 i = 0;
11211 while (i < This->typeattr.cFuncs) {
11212 if (!(func_desc->funcdesc.oVft & 0x1))
11213 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11215 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11216 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11218 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11220 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11221 TLBFuncDesc *iter;
11222 UINT j = 0;
11223 BOOL reset = FALSE;
11225 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11227 iter = This->funcdescs;
11228 while (j < This->typeattr.cFuncs) {
11229 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11230 if (!reset) {
11231 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11232 reset = TRUE;
11233 } else
11234 ++func_desc->funcdesc.memid;
11235 iter = This->funcdescs;
11236 j = 0;
11237 } else {
11238 ++iter;
11239 ++j;
11244 ++func_desc;
11245 ++i;
11248 if (user_vft > This->typeattr.cbSizeVft)
11249 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11251 for(i = 0; i < This->typeattr.cVars; ++i){
11252 TLBVarDesc *var_desc = &This->vardescs[i];
11253 if(var_desc->vardesc.memid == MEMBERID_NIL){
11254 UINT j = 0;
11255 BOOL reset = FALSE;
11256 TLBVarDesc *iter;
11258 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11260 iter = This->vardescs;
11261 while (j < This->typeattr.cVars) {
11262 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11263 if (!reset) {
11264 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11265 reset = TRUE;
11266 } else
11267 ++var_desc->vardesc.memid;
11268 iter = This->vardescs;
11269 j = 0;
11270 } else {
11271 ++iter;
11272 ++j;
11278 return hres;
11281 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11282 UINT index)
11284 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11285 unsigned int i;
11287 TRACE("%p %u\n", This, index);
11289 if (index >= This->typeattr.cFuncs)
11290 return TYPE_E_ELEMENTNOTFOUND;
11292 typeinfo_release_funcdesc(&This->funcdescs[index]);
11294 --This->typeattr.cFuncs;
11295 if (index != This->typeattr.cFuncs)
11297 memmove(This->funcdescs + index, This->funcdescs + index + 1,
11298 sizeof(*This->funcdescs) * (This->typeattr.cFuncs - index));
11299 for (i = index; i < This->typeattr.cFuncs; ++i)
11300 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
11303 This->needs_layout = TRUE;
11305 return S_OK;
11308 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11309 MEMBERID memid, INVOKEKIND invKind)
11311 FIXME("%p, %#lx, %d - stub\n", iface, memid, invKind);
11312 return E_NOTIMPL;
11315 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11316 UINT index)
11318 FIXME("%p, %u - stub\n", iface, index);
11319 return E_NOTIMPL;
11322 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11323 MEMBERID memid)
11325 FIXME("%p, %#lx - stub\n", iface, memid);
11326 return E_NOTIMPL;
11329 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11330 UINT index)
11332 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11333 int i;
11335 TRACE("%p %u\n", This, index);
11337 if (index >= This->typeattr.cImplTypes)
11338 return TYPE_E_ELEMENTNOTFOUND;
11340 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11341 --This->typeattr.cImplTypes;
11343 if (index < This->typeattr.cImplTypes)
11345 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11346 sizeof(*This->impltypes));
11347 for (i = index; i < This->typeattr.cImplTypes; ++i)
11348 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11351 return S_OK;
11354 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11355 REFGUID guid, VARIANT *varVal)
11357 TLBGuid *tlbguid;
11359 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11361 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11363 if (!guid || !varVal)
11364 return E_INVALIDARG;
11366 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11368 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11371 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11372 UINT index, REFGUID guid, VARIANT *varVal)
11374 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11375 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11376 return E_NOTIMPL;
11379 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11380 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11382 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11383 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11384 return E_NOTIMPL;
11387 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11388 UINT index, REFGUID guid, VARIANT *varVal)
11390 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11391 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11392 return E_NOTIMPL;
11395 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11396 UINT index, REFGUID guid, VARIANT *varVal)
11398 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11399 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11400 return E_NOTIMPL;
11403 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11404 ULONG helpStringContext)
11406 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11408 TRACE("%p, %lu.\n", iface, helpStringContext);
11410 This->dwHelpStringContext = helpStringContext;
11412 return S_OK;
11415 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11416 UINT index, ULONG helpStringContext)
11418 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11419 return E_NOTIMPL;
11422 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11423 UINT index, ULONG helpStringContext)
11425 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11426 return E_NOTIMPL;
11429 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11431 FIXME("%p - stub\n", iface);
11432 return E_NOTIMPL;
11435 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11436 LPOLESTR name)
11438 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11440 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11442 if (!name)
11443 return E_INVALIDARG;
11445 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11447 return S_OK;
11450 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11451 ICreateTypeInfo2_fnQueryInterface,
11452 ICreateTypeInfo2_fnAddRef,
11453 ICreateTypeInfo2_fnRelease,
11454 ICreateTypeInfo2_fnSetGuid,
11455 ICreateTypeInfo2_fnSetTypeFlags,
11456 ICreateTypeInfo2_fnSetDocString,
11457 ICreateTypeInfo2_fnSetHelpContext,
11458 ICreateTypeInfo2_fnSetVersion,
11459 ICreateTypeInfo2_fnAddRefTypeInfo,
11460 ICreateTypeInfo2_fnAddFuncDesc,
11461 ICreateTypeInfo2_fnAddImplType,
11462 ICreateTypeInfo2_fnSetImplTypeFlags,
11463 ICreateTypeInfo2_fnSetAlignment,
11464 ICreateTypeInfo2_fnSetSchema,
11465 ICreateTypeInfo2_fnAddVarDesc,
11466 ICreateTypeInfo2_fnSetFuncAndParamNames,
11467 ICreateTypeInfo2_fnSetVarName,
11468 ICreateTypeInfo2_fnSetTypeDescAlias,
11469 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11470 ICreateTypeInfo2_fnSetFuncDocString,
11471 ICreateTypeInfo2_fnSetVarDocString,
11472 ICreateTypeInfo2_fnSetFuncHelpContext,
11473 ICreateTypeInfo2_fnSetVarHelpContext,
11474 ICreateTypeInfo2_fnSetMops,
11475 ICreateTypeInfo2_fnSetTypeIdldesc,
11476 ICreateTypeInfo2_fnLayOut,
11477 ICreateTypeInfo2_fnDeleteFuncDesc,
11478 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11479 ICreateTypeInfo2_fnDeleteVarDesc,
11480 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11481 ICreateTypeInfo2_fnDeleteImplType,
11482 ICreateTypeInfo2_fnSetCustData,
11483 ICreateTypeInfo2_fnSetFuncCustData,
11484 ICreateTypeInfo2_fnSetParamCustData,
11485 ICreateTypeInfo2_fnSetVarCustData,
11486 ICreateTypeInfo2_fnSetImplTypeCustData,
11487 ICreateTypeInfo2_fnSetHelpStringContext,
11488 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11489 ICreateTypeInfo2_fnSetVarHelpStringContext,
11490 ICreateTypeInfo2_fnInvalidate,
11491 ICreateTypeInfo2_fnSetName
11494 /******************************************************************************
11495 * ClearCustData (OLEAUT32.171)
11497 * Clear a custom data type's data.
11499 * PARAMS
11500 * lpCust [I] The custom data type instance
11502 * RETURNS
11503 * Nothing.
11505 void WINAPI ClearCustData(CUSTDATA *lpCust)
11507 if (lpCust && lpCust->cCustData)
11509 if (lpCust->prgCustData)
11511 DWORD i;
11513 for (i = 0; i < lpCust->cCustData; i++)
11514 VariantClear(&lpCust->prgCustData[i].varValue);
11516 CoTaskMemFree(lpCust->prgCustData);
11517 lpCust->prgCustData = NULL;
11519 lpCust->cCustData = 0;