winebus.sys: Add missing keyboard free_device callback.
[wine.git] / dlls / oleaut32 / typelib.c
blob4669b03d5fc68bba084055465d9a5826d5ffd4dc
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include <stdlib.h>
51 #include <string.h>
52 #include <stdarg.h>
53 #include <stdio.h>
54 #include <ctype.h>
56 #define COBJMACROS
57 #define NONAMELESSUNION
59 #include "winerror.h"
60 #include "windef.h"
61 #include "winbase.h"
62 #include "winnls.h"
63 #include "winreg.h"
64 #include "winuser.h"
65 #include "winternl.h"
66 #include "lzexpand.h"
68 #include "objbase.h"
69 #include "typelib.h"
70 #include "wine/debug.h"
71 #include "variant.h"
72 #include "wine/asm.h"
73 #include "wine/heap.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
101 static void TLB_FreeVarDesc(VARDESC*);
103 /****************************************************************************
104 * FromLExxx
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
109 #ifdef WORDS_BIGENDIAN
110 static WORD FromLEWord(WORD p_iVal)
112 return (((p_iVal & 0x00FF) << 8) |
113 ((p_iVal & 0xFF00) >> 8));
117 static DWORD FromLEDWord(DWORD p_iVal)
119 return (((p_iVal & 0x000000FF) << 24) |
120 ((p_iVal & 0x0000FF00) << 8) |
121 ((p_iVal & 0x00FF0000) >> 8) |
122 ((p_iVal & 0xFF000000) >> 24));
124 #else
125 #define FromLEWord(X) (X)
126 #define FromLEDWord(X) (X)
127 #endif
129 #define DISPATCH_HREF_OFFSET 0x01000000
130 #define DISPATCH_HREF_MASK 0xff000000
132 /****************************************************************************
133 * FromLExxx
135 * Fix byte order in any structure if necessary
137 #ifdef WORDS_BIGENDIAN
138 static void FromLEWords(void *p_Val, int p_iSize)
140 WORD *Val = p_Val;
142 p_iSize /= sizeof(WORD);
144 while (p_iSize) {
145 *Val = FromLEWord(*Val);
146 Val++;
147 p_iSize--;
152 static void FromLEDWords(void *p_Val, int p_iSize)
154 DWORD *Val = p_Val;
156 p_iSize /= sizeof(DWORD);
158 while (p_iSize) {
159 *Val = FromLEDWord(*Val);
160 Val++;
161 p_iSize--;
164 #else
165 #define FromLEWords(X,Y) /*nothing*/
166 #define FromLEDWords(X,Y) /*nothing*/
167 #endif
170 * Find a typelib key which matches a requested maj.min version.
172 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 lstrcpyW( buffer, L"Typelib\\" );
181 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 lstrcpyW( buffer, L"Typelib\\" );
242 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
243 swprintf( buffer + lstrlenW(buffer), 20, L"\\%x.%x", wMaj, wMin );
244 return buffer;
247 /* get the path of an interface key, in the form "Interface\\<guid>" */
248 /* buffer must be at least 50 characters long */
249 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
251 lstrcpyW( buffer, L"Interface\\" );
252 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
253 return buffer;
256 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
257 /* buffer must be at least 16 characters long */
258 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
260 swprintf( buffer, 16, L"%lx\\", lcid );
261 switch(syskind)
263 case SYS_WIN16: lstrcatW( buffer, L"win16" ); break;
264 case SYS_WIN32: lstrcatW( buffer, L"win32" ); break;
265 case SYS_WIN64: lstrcatW( buffer, L"win64" ); break;
266 default:
267 TRACE("Typelib is for unsupported syskind %i\n", syskind);
268 return NULL;
270 return buffer;
273 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
275 struct tlibredirect_data
277 ULONG size;
278 DWORD res;
279 ULONG name_len;
280 ULONG name_offset;
281 LANGID langid;
282 WORD flags;
283 ULONG help_len;
284 ULONG help_offset;
285 WORD major_version;
286 WORD minor_version;
289 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
290 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
291 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
293 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
294 LCID myLCID = lcid;
295 HKEY hkey;
296 WCHAR buffer[60];
297 WCHAR Path[MAX_PATH];
298 LONG res;
300 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
302 if (redir)
304 ACTCTX_SECTION_KEYED_DATA data;
306 data.cbSize = sizeof(data);
307 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
309 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
310 WCHAR *nameW;
311 DWORD len;
313 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
314 return TYPE_E_LIBNOTREGISTERED;
316 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
317 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
318 if (!len) return TYPE_E_LIBNOTREGISTERED;
320 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
321 *path = SysAllocString( Path );
322 return S_OK;
326 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
327 get_typelib_key( guid, wMaj, wMin, buffer );
329 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
330 if (res == ERROR_FILE_NOT_FOUND)
332 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
333 return TYPE_E_LIBNOTREGISTERED;
335 else if (res != ERROR_SUCCESS)
337 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
338 return TYPE_E_REGISTRYACCESS;
341 while (hr != S_OK)
343 LONG dwPathLen = sizeof(Path);
345 get_lcid_subkey( myLCID, syskind, buffer );
347 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
349 if (!lcid)
350 break;
351 else if (myLCID == lcid)
353 /* try with sub-langid */
354 myLCID = SUBLANGID(lcid);
356 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
358 /* try with system langid */
359 myLCID = 0;
361 else
363 break;
366 else
368 *path = SysAllocString( Path );
369 hr = S_OK;
372 RegCloseKey( hkey );
373 TRACE_(typelib)("-- 0x%08x\n", hr);
374 return hr;
377 /****************************************************************************
378 * QueryPathOfRegTypeLib [OLEAUT32.164]
380 * Gets the path to a registered type library.
382 * PARAMS
383 * guid [I] referenced guid
384 * wMaj [I] major version
385 * wMin [I] minor version
386 * lcid [I] locale id
387 * path [O] path of typelib
389 * RETURNS
390 * Success: S_OK.
391 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
392 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
393 * opened.
395 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
397 BOOL redir = TRUE;
398 #ifdef _WIN64
399 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
400 if(SUCCEEDED(hres))
401 return hres;
402 redir = FALSE;
403 #endif
404 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
407 /******************************************************************************
408 * CreateTypeLib [OLEAUT32.160] creates a typelib
410 * RETURNS
411 * Success: S_OK
412 * Failure: Status
414 HRESULT WINAPI CreateTypeLib(
415 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
417 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
418 return E_FAIL;
421 /******************************************************************************
422 * LoadTypeLib [OLEAUT32.161]
424 * Loads a type library
426 * PARAMS
427 * szFile [I] Name of file to load from.
428 * pptLib [O] Pointer that receives ITypeLib object on success.
430 * RETURNS
431 * Success: S_OK
432 * Failure: Status
434 * SEE
435 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
437 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
439 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
440 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
443 /******************************************************************************
444 * LoadTypeLibEx [OLEAUT32.183]
446 * Loads and optionally registers a type library
448 * RETURNS
449 * Success: S_OK
450 * Failure: Status
452 HRESULT WINAPI LoadTypeLibEx(
453 LPCOLESTR szFile, /* [in] Name of file to load from */
454 REGKIND regkind, /* [in] Specify kind of registration */
455 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
457 WCHAR szPath[MAX_PATH+1];
458 HRESULT res;
460 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
462 if (!szFile || !pptLib)
463 return E_INVALIDARG;
465 *pptLib = NULL;
467 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
469 if (SUCCEEDED(res))
470 switch(regkind)
472 case REGKIND_DEFAULT:
473 /* don't register typelibs supplied with full path. Experimentation confirms the following */
474 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
475 (szFile[0] && (szFile[1] == ':'))) break;
476 /* else fall-through */
478 case REGKIND_REGISTER:
479 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
481 ITypeLib_Release(*pptLib);
482 *pptLib = 0;
484 break;
485 case REGKIND_NONE:
486 break;
489 TRACE(" returns %08x\n",res);
490 return res;
493 /******************************************************************************
494 * LoadRegTypeLib [OLEAUT32.162]
496 * Loads a registered type library.
498 * PARAMS
499 * rguid [I] GUID of the registered type library.
500 * wVerMajor [I] major version.
501 * wVerMinor [I] minor version.
502 * lcid [I] locale ID.
503 * ppTLib [O] pointer that receives an ITypeLib object on success.
505 * RETURNS
506 * Success: S_OK.
507 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
508 * LoadTypeLib.
510 HRESULT WINAPI LoadRegTypeLib(
511 REFGUID rguid,
512 WORD wVerMajor,
513 WORD wVerMinor,
514 LCID lcid,
515 ITypeLib **ppTLib)
517 BSTR bstr=NULL;
518 HRESULT res;
520 *ppTLib = NULL;
522 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
524 if(SUCCEEDED(res))
526 res= LoadTypeLib(bstr, ppTLib);
527 SysFreeString(bstr);
529 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
531 TLIBATTR *attr;
533 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
534 if (res == S_OK)
536 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
537 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
539 if (mismatch)
541 ITypeLib_Release(*ppTLib);
542 *ppTLib = NULL;
543 res = TYPE_E_LIBNOTREGISTERED;
549 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
551 return res;
554 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
556 WCHAR keyName[60];
557 HKEY key, subKey;
559 get_interface_key( &tattr->guid, keyName );
560 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
561 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
563 const WCHAR *proxy_clsid;
565 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
566 proxy_clsid = L"{00020424-0000-0000-C000-000000000046}";
567 else
568 proxy_clsid = L"{00020420-0000-0000-C000-000000000046}";
570 if (name)
571 RegSetValueExW(key, NULL, 0, REG_SZ,
572 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR));
574 if (!RegCreateKeyExW(key, L"ProxyStubClsid", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
576 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
577 RegCloseKey(subKey);
580 if (!RegCreateKeyExW(key, L"ProxyStubClsid32", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
582 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
583 RegCloseKey(subKey);
586 if (RegCreateKeyExW(key, L"TypeLib", 0, NULL, 0,
587 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
589 WCHAR buffer[40];
591 StringFromGUID2(&libattr->guid, buffer, 40);
592 RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
594 swprintf(buffer, ARRAY_SIZE(buffer), L"%x.%x", libattr->wMajorVerNum, libattr->wMinorVerNum);
595 RegSetValueExW(subKey, L"Version", 0, REG_SZ, (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
596 RegCloseKey(subKey);
599 RegCloseKey(key);
603 /******************************************************************************
604 * RegisterTypeLib [OLEAUT32.163]
605 * Adds information about a type library to the System Registry
606 * NOTES
607 * Docs: ITypeLib FAR * ptlib
608 * Docs: OLECHAR FAR* szFullPath
609 * Docs: OLECHAR FAR* szHelpDir
611 * RETURNS
612 * Success: S_OK
613 * Failure: Status
615 HRESULT WINAPI RegisterTypeLib(ITypeLib *ptlib, const WCHAR *szFullPath, const WCHAR *szHelpDir)
617 HRESULT res;
618 TLIBATTR *attr;
619 WCHAR keyName[60];
620 WCHAR tmp[16];
621 HKEY key, subKey;
622 UINT types, tidx;
623 TYPEKIND kind;
624 DWORD disposition;
626 if (ptlib == NULL || szFullPath == NULL)
627 return E_INVALIDARG;
629 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
630 return E_FAIL;
632 #ifndef _WIN64
633 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
634 #endif
636 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
638 res = S_OK;
639 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
640 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
642 LPOLESTR doc;
644 /* Set the human-readable name of the typelib */
645 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
646 res = E_FAIL;
647 else if (doc)
649 if (RegSetValueExW(key, NULL, 0, REG_SZ,
650 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
651 res = E_FAIL;
653 SysFreeString(doc);
656 /* Make up the name of the typelib path subkey */
657 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
659 /* Create the typelib path subkey */
660 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
661 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
663 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
664 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
665 res = E_FAIL;
667 RegCloseKey(subKey);
669 else
670 res = E_FAIL;
672 /* Create the flags subkey */
673 if (res == S_OK && RegCreateKeyExW(key, L"FLAGS", 0, NULL, 0,
674 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
676 WCHAR buf[20];
678 /* FIXME: is %u correct? */
679 swprintf(buf, ARRAY_SIZE(buf), L"%u", attr->wLibFlags);
680 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
681 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
682 res = E_FAIL;
684 RegCloseKey(subKey);
686 else
687 res = E_FAIL;
689 /* create the helpdir subkey */
690 if (res == S_OK && RegCreateKeyExW(key, L"HELPDIR", 0, NULL, 0,
691 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
693 BSTR freeHelpDir = NULL;
694 WCHAR *file_name;
696 /* if we created a new key, and helpDir was null, set the helpdir
697 to the directory which contains the typelib. However,
698 if we just opened an existing key, we leave the helpdir alone */
699 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
700 szHelpDir = freeHelpDir = SysAllocString(szFullPath);
701 file_name = wcsrchr(szHelpDir, '\\');
702 if (file_name && file_name[1]) {
703 /* possible remove a numeric \index (resource-id) */
704 WCHAR *end_ptr = file_name + 1;
705 while ('0' <= *end_ptr && *end_ptr <= '9') end_ptr++;
706 if (!*end_ptr)
708 *file_name = 0;
709 file_name = wcsrchr(szHelpDir, '\\');
712 if (file_name)
713 *file_name = 0;
716 /* if we have an szHelpDir, set it! */
717 if (szHelpDir != NULL) {
718 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
719 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
720 res = E_FAIL;
724 SysFreeString(freeHelpDir);
725 RegCloseKey(subKey);
726 } else {
727 res = E_FAIL;
730 RegCloseKey(key);
732 else
733 res = E_FAIL;
735 /* register OLE Automation-compatible interfaces for this typelib */
736 types = ITypeLib_GetTypeInfoCount(ptlib);
737 for (tidx=0; tidx<types; tidx++) {
738 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
739 LPOLESTR name = NULL;
740 ITypeInfo *tinfo = NULL;
742 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
744 switch (kind) {
745 case TKIND_INTERFACE:
746 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
747 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
748 break;
750 case TKIND_DISPATCH:
751 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
752 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
753 break;
755 default:
756 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
757 break;
760 if (tinfo) {
761 TYPEATTR *tattr = NULL;
762 ITypeInfo_GetTypeAttr(tinfo, &tattr);
764 if (tattr) {
765 TRACE_(typelib)("guid=%s, flags=%04x (",
766 debugstr_guid(&tattr->guid),
767 tattr->wTypeFlags);
769 if (TRACE_ON(typelib)) {
770 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
771 XX(FAPPOBJECT);
772 XX(FCANCREATE);
773 XX(FLICENSED);
774 XX(FPREDECLID);
775 XX(FHIDDEN);
776 XX(FCONTROL);
777 XX(FDUAL);
778 XX(FNONEXTENSIBLE);
779 XX(FOLEAUTOMATION);
780 XX(FRESTRICTED);
781 XX(FAGGREGATABLE);
782 XX(FREPLACEABLE);
783 XX(FDISPATCHABLE);
784 XX(FREVERSEBIND);
785 XX(FPROXY);
786 #undef XX
787 MESSAGE("\n");
790 /* Register all dispinterfaces (which includes dual interfaces) and
791 oleautomation interfaces */
792 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
793 kind == TKIND_DISPATCH)
795 BOOL is_wow64;
796 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
798 /* register interface<->typelib coupling */
799 TLB_register_interface(attr, name, tattr, 0);
801 /* register TLBs into the opposite registry view, too */
802 if(opposite == KEY_WOW64_32KEY ||
803 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
804 TLB_register_interface(attr, name, tattr, opposite);
807 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
810 ITypeInfo_Release(tinfo);
813 SysFreeString(name);
817 ITypeLib_ReleaseTLibAttr(ptlib, attr);
819 return res;
822 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
824 WCHAR subKeyName[50];
825 HKEY subKey;
827 /* the path to the type */
828 get_interface_key( guid, subKeyName );
830 /* Delete its bits */
831 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
832 return;
834 RegDeleteKeyW(subKey, L"ProxyStubClsid");
835 RegDeleteKeyW(subKey, L"ProxyStubClsid32");
836 RegDeleteKeyW(subKey, L"TypeLib");
837 RegCloseKey(subKey);
838 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
841 /******************************************************************************
842 * UnRegisterTypeLib [OLEAUT32.186]
843 * Removes information about a type library from the System Registry
844 * NOTES
846 * RETURNS
847 * Success: S_OK
848 * Failure: Status
850 HRESULT WINAPI UnRegisterTypeLib(
851 REFGUID libid, /* [in] Guid of the library */
852 WORD wVerMajor, /* [in] major version */
853 WORD wVerMinor, /* [in] minor version */
854 LCID lcid, /* [in] locale id */
855 SYSKIND syskind)
857 BSTR tlibPath = NULL;
858 DWORD tmpLength;
859 WCHAR keyName[60];
860 WCHAR subKeyName[50];
861 int result = S_OK;
862 DWORD i = 0;
863 BOOL deleteOtherStuff;
864 HKEY key = NULL;
865 TYPEATTR* typeAttr = NULL;
866 TYPEKIND kind;
867 ITypeInfo* typeInfo = NULL;
868 ITypeLib* typeLib = NULL;
869 int numTypes;
871 TRACE("(IID: %s)\n",debugstr_guid(libid));
873 /* Create the path to the key */
874 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
876 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
878 TRACE("Unsupported syskind %i\n", syskind);
879 result = E_INVALIDARG;
880 goto end;
883 /* get the path to the typelib on disk */
884 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
885 result = E_INVALIDARG;
886 goto end;
889 /* Try and open the key to the type library. */
890 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
891 result = E_INVALIDARG;
892 goto end;
895 /* Try and load the type library */
896 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
897 result = TYPE_E_INVALIDSTATE;
898 goto end;
901 /* remove any types registered with this typelib */
902 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
903 for (i=0; i<numTypes; i++) {
904 /* get the kind of type */
905 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
906 goto enddeleteloop;
909 /* skip non-interfaces, and get type info for the type */
910 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
911 goto enddeleteloop;
913 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
914 goto enddeleteloop;
916 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
917 goto enddeleteloop;
920 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
921 kind == TKIND_DISPATCH)
923 BOOL is_wow64;
924 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
926 TLB_unregister_interface(&typeAttr->guid, 0);
928 /* unregister TLBs into the opposite registry view, too */
929 if(opposite == KEY_WOW64_32KEY ||
930 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
931 TLB_unregister_interface(&typeAttr->guid, opposite);
935 enddeleteloop:
936 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
937 typeAttr = NULL;
938 if (typeInfo) ITypeInfo_Release(typeInfo);
939 typeInfo = NULL;
942 /* Now, delete the type library path subkey */
943 get_lcid_subkey( lcid, syskind, subKeyName );
944 RegDeleteKeyW(key, subKeyName);
945 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
946 RegDeleteKeyW(key, subKeyName);
948 /* check if there is anything besides the FLAGS/HELPDIR keys.
949 If there is, we don't delete them */
950 tmpLength = ARRAY_SIZE(subKeyName);
951 deleteOtherStuff = TRUE;
952 i = 0;
953 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
954 tmpLength = ARRAY_SIZE(subKeyName);
956 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
957 if (!wcscmp(subKeyName, L"FLAGS")) continue;
958 if (!wcscmp(subKeyName, L"HELPDIR")) continue;
959 deleteOtherStuff = FALSE;
960 break;
963 /* only delete the other parts of the key if we're absolutely sure */
964 if (deleteOtherStuff) {
965 RegDeleteKeyW(key, L"FLAGS");
966 RegDeleteKeyW(key, L"HELPDIR");
967 RegCloseKey(key);
968 key = NULL;
970 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
971 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
972 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
975 end:
976 SysFreeString(tlibPath);
977 if (typeLib) ITypeLib_Release(typeLib);
978 if (key) RegCloseKey(key);
979 return result;
982 /******************************************************************************
983 * RegisterTypeLibForUser [OLEAUT32.442]
984 * Adds information about a type library to the user registry
985 * NOTES
986 * Docs: ITypeLib FAR * ptlib
987 * Docs: OLECHAR FAR* szFullPath
988 * Docs: OLECHAR FAR* szHelpDir
990 * RETURNS
991 * Success: S_OK
992 * Failure: Status
994 HRESULT WINAPI RegisterTypeLibForUser(
995 ITypeLib * ptlib, /* [in] Pointer to the library*/
996 OLECHAR * szFullPath, /* [in] full Path of the library*/
997 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
998 may be NULL*/
1000 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1001 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1002 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1005 /******************************************************************************
1006 * UnRegisterTypeLibForUser [OLEAUT32.443]
1007 * Removes information about a type library from the user registry
1009 * RETURNS
1010 * Success: S_OK
1011 * Failure: Status
1013 HRESULT WINAPI UnRegisterTypeLibForUser(
1014 REFGUID libid, /* [in] GUID of the library */
1015 WORD wVerMajor, /* [in] major version */
1016 WORD wVerMinor, /* [in] minor version */
1017 LCID lcid, /* [in] locale id */
1018 SYSKIND syskind)
1020 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1021 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1022 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1025 /*======================= ITypeLib implementation =======================*/
1027 typedef struct tagTLBGuid {
1028 GUID guid;
1029 INT hreftype;
1030 UINT offset;
1031 struct list entry;
1032 } TLBGuid;
1034 typedef struct tagTLBCustData
1036 TLBGuid *guid;
1037 VARIANT data;
1038 struct list entry;
1039 } TLBCustData;
1041 /* data structure for import typelibs */
1042 typedef struct tagTLBImpLib
1044 int offset; /* offset in the file (MSFT)
1045 offset in nametable (SLTG)
1046 just used to identify library while reading
1047 data from file */
1048 TLBGuid *guid; /* libid */
1049 BSTR name; /* name */
1051 LCID lcid; /* lcid of imported typelib */
1053 WORD wVersionMajor; /* major version number */
1054 WORD wVersionMinor; /* minor version number */
1056 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1057 NULL if not yet loaded */
1058 struct list entry;
1059 } TLBImpLib;
1061 typedef struct tagTLBString {
1062 BSTR str;
1063 UINT offset;
1064 struct list entry;
1065 } TLBString;
1067 /* internal ITypeLib data */
1068 typedef struct tagITypeLibImpl
1070 ITypeLib2 ITypeLib2_iface;
1071 ITypeComp ITypeComp_iface;
1072 ICreateTypeLib2 ICreateTypeLib2_iface;
1073 LONG ref;
1074 TLBGuid *guid;
1075 LCID lcid;
1076 SYSKIND syskind;
1077 int ptr_size;
1078 WORD ver_major;
1079 WORD ver_minor;
1080 WORD libflags;
1081 LCID set_lcid;
1083 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1084 * exported to the application as a UNICODE string.
1086 struct list string_list;
1087 struct list name_list;
1088 struct list guid_list;
1090 const TLBString *Name;
1091 const TLBString *DocString;
1092 const TLBString *HelpFile;
1093 const TLBString *HelpStringDll;
1094 DWORD dwHelpContext;
1095 int TypeInfoCount; /* nr of typeinfo's in librarry */
1096 struct tagITypeInfoImpl **typeinfos;
1097 struct list custdata_list;
1098 struct list implib_list;
1099 int ctTypeDesc; /* number of items in type desc array */
1100 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1101 library. Only used while reading MSFT
1102 typelibs */
1103 struct list ref_list; /* list of ref types in this typelib */
1104 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1107 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1108 struct list entry;
1109 WCHAR *path;
1110 INT index;
1111 } ITypeLibImpl;
1113 static const ITypeLib2Vtbl tlbvt;
1114 static const ITypeCompVtbl tlbtcvt;
1115 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1117 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1119 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1122 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1124 return impl_from_ITypeLib2((ITypeLib2*)iface);
1127 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1129 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1132 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1134 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1137 /* ITypeLib methods */
1138 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1139 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1141 /*======================= ITypeInfo implementation =======================*/
1143 /* data for referenced types */
1144 typedef struct tagTLBRefType
1146 INT index; /* Type index for internal ref or for external ref
1147 it the format is SLTG. -2 indicates to
1148 use guid */
1150 TYPEKIND tkind;
1151 TLBGuid *guid; /* guid of the referenced type */
1152 /* if index == TLB_REF_USE_GUID */
1154 HREFTYPE reference; /* The href of this ref */
1155 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1156 TLB_REF_INTERNAL for internal refs
1157 TLB_REF_NOT_FOUND for broken refs */
1159 struct list entry;
1160 } TLBRefType;
1162 #define TLB_REF_USE_GUID -2
1164 #define TLB_REF_INTERNAL (void*)-2
1165 #define TLB_REF_NOT_FOUND (void*)-1
1167 /* internal Parameter data */
1168 typedef struct tagTLBParDesc
1170 const TLBString *Name;
1171 struct list custdata_list;
1172 } TLBParDesc;
1174 /* internal Function data */
1175 typedef struct tagTLBFuncDesc
1177 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1178 const TLBString *Name; /* the name of this function */
1179 TLBParDesc *pParamDesc; /* array with param names and custom data */
1180 int helpcontext;
1181 int HelpStringContext;
1182 const TLBString *HelpString;
1183 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1184 struct list custdata_list;
1185 } TLBFuncDesc;
1187 /* internal Variable data */
1188 typedef struct tagTLBVarDesc
1190 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1191 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1192 const TLBString *Name; /* the name of this variable */
1193 int HelpContext;
1194 int HelpStringContext;
1195 const TLBString *HelpString;
1196 struct list custdata_list;
1197 } TLBVarDesc;
1199 /* internal implemented interface data */
1200 typedef struct tagTLBImplType
1202 HREFTYPE hRef; /* hRef of interface */
1203 int implflags; /* IMPLFLAG_*s */
1204 struct list custdata_list;
1205 } TLBImplType;
1207 /* internal TypeInfo data */
1208 typedef struct tagITypeInfoImpl
1210 ITypeInfo2 ITypeInfo2_iface;
1211 ITypeComp ITypeComp_iface;
1212 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1213 LONG ref;
1214 BOOL not_attached_to_typelib;
1215 BOOL needs_layout;
1217 TLBGuid *guid;
1218 TYPEATTR typeattr;
1219 TYPEDESC *tdescAlias;
1221 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1222 int index; /* index in this typelib; */
1223 HREFTYPE hreftype; /* hreftype for app object binding */
1224 /* type libs seem to store the doc strings in ascii
1225 * so why should we do it in unicode?
1227 const TLBString *Name;
1228 const TLBString *DocString;
1229 const TLBString *DllName;
1230 const TLBString *Schema;
1231 DWORD dwHelpContext;
1232 DWORD dwHelpStringContext;
1234 /* functions */
1235 TLBFuncDesc *funcdescs;
1237 /* variables */
1238 TLBVarDesc *vardescs;
1240 /* Implemented Interfaces */
1241 TLBImplType *impltypes;
1243 struct list *pcustdata_list;
1244 struct list custdata_list;
1245 } ITypeInfoImpl;
1247 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1249 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1252 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1254 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1257 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1259 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1262 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1264 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1267 static const ITypeInfo2Vtbl tinfvt;
1268 static const ITypeCompVtbl tcompvt;
1269 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1271 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1272 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1274 typedef struct tagTLBContext
1276 unsigned int oStart; /* start of TLB in file */
1277 unsigned int pos; /* current pos */
1278 unsigned int length; /* total length */
1279 void *mapping; /* memory mapping */
1280 MSFT_SegDir * pTblDir;
1281 ITypeLibImpl* pLibInfo;
1282 } TLBContext;
1285 static inline BSTR TLB_get_bstr(const TLBString *str)
1287 return str != NULL ? str->str : NULL;
1290 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1292 if(!str)
1293 return 1;
1294 return memcmp(left, str->str, len);
1297 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1299 return guid != NULL ? &guid->guid : NULL;
1302 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1304 return guid != NULL ? &guid->guid : &GUID_NULL;
1307 static int get_ptr_size(SYSKIND syskind)
1309 switch(syskind){
1310 case SYS_WIN64:
1311 return 8;
1312 case SYS_WIN32:
1313 case SYS_MAC:
1314 case SYS_WIN16:
1315 return 4;
1317 WARN("Unhandled syskind: 0x%x\n", syskind);
1318 return 4;
1322 debug
1324 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1325 if (pTD->vt & VT_RESERVED)
1326 szVarType += strlen(strcpy(szVarType, "reserved | "));
1327 if (pTD->vt & VT_BYREF)
1328 szVarType += strlen(strcpy(szVarType, "ref to "));
1329 if (pTD->vt & VT_ARRAY)
1330 szVarType += strlen(strcpy(szVarType, "array of "));
1331 if (pTD->vt & VT_VECTOR)
1332 szVarType += strlen(strcpy(szVarType, "vector of "));
1333 switch(pTD->vt & VT_TYPEMASK) {
1334 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1335 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1336 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1337 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1338 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1339 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1340 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1341 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1342 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1343 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1344 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1345 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1346 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1347 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1348 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1349 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1350 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1351 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1352 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1353 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1354 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1355 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 %08x\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=%x offset=%x\n", import->wVersionMajor,
1485 import->wVersionMinor, import->lcid, import->offset);
1488 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1490 TLBRefType *ref;
1492 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1494 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1495 if(ref->index == -1)
1496 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1497 else
1498 TRACE_(typelib)("type no: %d\n", ref->index);
1500 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1502 TRACE_(typelib)("in lib\n");
1503 dump_TLBImpLib(ref->pImpTLInfo);
1508 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1510 if(!impl)
1511 return;
1512 while (n) {
1513 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1514 impl->hRef, impl->implflags);
1515 ++impl;
1516 --n;
1520 static void dump_DispParms(const DISPPARAMS * pdp)
1522 unsigned int index;
1524 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1526 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1528 TRACE("named args:\n");
1529 for (index = 0; index < pdp->cNamedArgs; index++)
1530 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1533 if (pdp->cArgs && pdp->rgvarg)
1535 TRACE("args:\n");
1536 for (index = 0; index < pdp->cArgs; index++)
1537 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1541 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1543 TRACE("%p ref=%u\n", pty, pty->ref);
1544 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1545 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1546 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1547 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1548 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1549 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1550 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1551 if (TRACE_ON(ole))
1552 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1553 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1554 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1557 static void dump_VARDESC(const VARDESC *v)
1559 MESSAGE("memid %d\n",v->memid);
1560 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1561 MESSAGE("oInst %d\n",v->u.oInst);
1562 dump_ELEMDESC(&(v->elemdescVar));
1563 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1564 MESSAGE("varkind %d\n",v->varkind);
1567 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1569 /* VT_LPWSTR is largest type that, may appear in type description */
1570 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1571 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1572 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1573 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1574 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1575 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1576 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1577 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1580 static void TLB_abort(void)
1582 DebugBreak();
1585 /* returns the size required for a deep copy of a typedesc into a
1586 * flat buffer */
1587 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1589 SIZE_T size = 0;
1591 if (alloc_initial_space)
1592 size += sizeof(TYPEDESC);
1594 switch (tdesc->vt)
1596 case VT_PTR:
1597 case VT_SAFEARRAY:
1598 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1599 break;
1600 case VT_CARRAY:
1601 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1602 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1603 break;
1605 return size;
1608 /* deep copy a typedesc into a flat buffer */
1609 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1611 if (!dest)
1613 dest = buffer;
1614 buffer = (char *)buffer + sizeof(TYPEDESC);
1617 *dest = *src;
1619 switch (src->vt)
1621 case VT_PTR:
1622 case VT_SAFEARRAY:
1623 dest->u.lptdesc = buffer;
1624 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1625 break;
1626 case VT_CARRAY:
1627 dest->u.lpadesc = buffer;
1628 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1629 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1630 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1631 break;
1633 return buffer;
1636 /* free custom data allocated by MSFT_CustData */
1637 static inline void TLB_FreeCustData(struct list *custdata_list)
1639 TLBCustData *cd, *cdn;
1640 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1642 list_remove(&cd->entry);
1643 VariantClear(&cd->data);
1644 heap_free(cd);
1648 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1650 DWORD len;
1651 BSTR ret;
1653 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1654 ret = SysAllocStringLen(NULL, len - 1);
1655 if (!ret) return ret;
1656 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1657 return ret;
1660 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1662 int i;
1664 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1666 if (typeinfo->funcdescs[i].funcdesc.memid == memid)
1667 return &typeinfo->funcdescs[i];
1670 return NULL;
1673 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl *typeinfo, MEMBERID memid, INVOKEKIND invkind)
1675 int i;
1677 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1679 if (typeinfo->funcdescs[i].funcdesc.memid == memid && typeinfo->funcdescs[i].funcdesc.invkind == invkind)
1680 return &typeinfo->funcdescs[i];
1683 return NULL;
1686 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1688 int i;
1690 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1692 if (typeinfo->vardescs[i].vardesc.memid == memid)
1693 return &typeinfo->vardescs[i];
1696 return NULL;
1699 static inline TLBVarDesc *TLB_get_vardesc_by_name(ITypeInfoImpl *typeinfo, const OLECHAR *name)
1701 int i;
1703 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1705 if (!lstrcmpiW(TLB_get_bstr(typeinfo->vardescs[i].Name), name))
1706 return &typeinfo->vardescs[i];
1709 return NULL;
1712 static inline TLBCustData *TLB_get_custdata_by_guid(const struct list *custdata_list, REFGUID guid)
1714 TLBCustData *cust_data;
1715 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1716 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1717 return cust_data;
1718 return NULL;
1721 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeLibImpl *typelib, const OLECHAR *name)
1723 int i;
1725 for (i = 0; i < typelib->TypeInfoCount; ++i)
1727 if (!lstrcmpiW(TLB_get_bstr(typelib->typeinfos[i]->Name), name))
1728 return typelib->typeinfos[i];
1731 return NULL;
1734 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1736 list_init(&var_desc->custdata_list);
1739 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1741 TLBVarDesc *ret;
1743 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1744 if(!ret)
1745 return NULL;
1747 while(n){
1748 TLBVarDesc_Constructor(&ret[n-1]);
1749 --n;
1752 return ret;
1755 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1757 TLBParDesc *ret;
1759 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1760 if(!ret)
1761 return NULL;
1763 while(n){
1764 list_init(&ret[n-1].custdata_list);
1765 --n;
1768 return ret;
1771 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1773 list_init(&func_desc->custdata_list);
1776 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1778 TLBFuncDesc *ret;
1780 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1781 if(!ret)
1782 return NULL;
1784 while(n){
1785 TLBFuncDesc_Constructor(&ret[n-1]);
1786 --n;
1789 return ret;
1792 static void TLBImplType_Constructor(TLBImplType *impl)
1794 list_init(&impl->custdata_list);
1797 static TLBImplType *TLBImplType_Alloc(UINT n)
1799 TLBImplType *ret;
1801 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1802 if(!ret)
1803 return NULL;
1805 while(n){
1806 TLBImplType_Constructor(&ret[n-1]);
1807 --n;
1810 return ret;
1813 static TLBGuid *TLB_append_guid(struct list *guid_list,
1814 const GUID *new_guid, HREFTYPE hreftype)
1816 TLBGuid *guid;
1818 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1819 if (IsEqualGUID(&guid->guid, new_guid))
1820 return guid;
1823 guid = heap_alloc(sizeof(TLBGuid));
1824 if (!guid)
1825 return NULL;
1827 memcpy(&guid->guid, new_guid, sizeof(GUID));
1828 guid->hreftype = hreftype;
1830 list_add_tail(guid_list, &guid->entry);
1832 return guid;
1835 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1837 TLBCustData *cust_data;
1839 switch(V_VT(var)){
1840 case VT_I4:
1841 case VT_R4:
1842 case VT_UI4:
1843 case VT_INT:
1844 case VT_UINT:
1845 case VT_HRESULT:
1846 case VT_BSTR:
1847 break;
1848 default:
1849 return DISP_E_BADVARTYPE;
1852 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1854 if (!cust_data) {
1855 cust_data = heap_alloc(sizeof(TLBCustData));
1856 if (!cust_data)
1857 return E_OUTOFMEMORY;
1859 cust_data->guid = tlbguid;
1860 VariantInit(&cust_data->data);
1862 list_add_tail(custdata_list, &cust_data->entry);
1863 }else
1864 VariantClear(&cust_data->data);
1866 return VariantCopy(&cust_data->data, var);
1869 /* Used to update list pointers after list itself was moved. */
1870 static void TLB_relink_custdata(struct list *custdata_list)
1872 if (custdata_list->prev == custdata_list->next)
1873 list_init(custdata_list);
1874 else
1876 custdata_list->prev->next = custdata_list;
1877 custdata_list->next->prev = custdata_list;
1881 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1883 TLBString *str;
1885 if(!new_str)
1886 return NULL;
1888 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1889 if (wcscmp(str->str, new_str) == 0)
1890 return str;
1893 str = heap_alloc(sizeof(TLBString));
1894 if (!str)
1895 return NULL;
1897 str->str = SysAllocString(new_str);
1898 if (!str->str) {
1899 heap_free(str);
1900 return NULL;
1903 list_add_tail(string_list, &str->entry);
1905 return str;
1908 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1909 ULONG *size, WORD *align)
1911 ITypeInfo *other;
1912 TYPEATTR *attr;
1913 HRESULT hr;
1915 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1916 if(FAILED(hr))
1917 return hr;
1919 hr = ITypeInfo_GetTypeAttr(other, &attr);
1920 if(FAILED(hr)){
1921 ITypeInfo_Release(other);
1922 return hr;
1925 if(size)
1926 *size = attr->cbSizeInstance;
1927 if(align)
1928 *align = attr->cbAlignment;
1930 ITypeInfo_ReleaseTypeAttr(other, attr);
1931 ITypeInfo_Release(other);
1933 return S_OK;
1936 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1937 TYPEDESC *tdesc, ULONG *size, WORD *align)
1939 ULONG i, sub, ptr_size;
1940 HRESULT hr;
1942 ptr_size = get_ptr_size(sys);
1944 switch(tdesc->vt){
1945 case VT_VOID:
1946 *size = 0;
1947 break;
1948 case VT_I1:
1949 case VT_UI1:
1950 *size = 1;
1951 break;
1952 case VT_I2:
1953 case VT_BOOL:
1954 case VT_UI2:
1955 *size = 2;
1956 break;
1957 case VT_I4:
1958 case VT_R4:
1959 case VT_ERROR:
1960 case VT_UI4:
1961 case VT_INT:
1962 case VT_UINT:
1963 case VT_HRESULT:
1964 *size = 4;
1965 break;
1966 case VT_R8:
1967 case VT_I8:
1968 case VT_UI8:
1969 *size = 8;
1970 break;
1971 case VT_BSTR:
1972 case VT_DISPATCH:
1973 case VT_UNKNOWN:
1974 case VT_PTR:
1975 case VT_SAFEARRAY:
1976 case VT_LPSTR:
1977 case VT_LPWSTR:
1978 *size = ptr_size;
1979 break;
1980 case VT_DATE:
1981 *size = sizeof(DATE);
1982 break;
1983 case VT_VARIANT:
1984 *size = sizeof(VARIANT);
1985 #ifdef _WIN64
1986 if(sys == SYS_WIN32)
1987 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1988 #endif
1989 break;
1990 case VT_DECIMAL:
1991 *size = sizeof(DECIMAL);
1992 break;
1993 case VT_CY:
1994 *size = sizeof(CY);
1995 break;
1996 case VT_CARRAY:
1997 *size = 0;
1998 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
1999 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2000 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2001 if(FAILED(hr))
2002 return hr;
2003 *size *= sub;
2004 return S_OK;
2005 case VT_USERDEFINED:
2006 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2007 default:
2008 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2009 return E_FAIL;
2012 if(align){
2013 if(*size < 4)
2014 *align = *size;
2015 else
2016 *align = 4;
2019 return S_OK;
2022 /**********************************************************************
2024 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2027 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2029 if (where != DO_NOT_SEEK)
2031 where += pcx->oStart;
2032 if (where > pcx->length)
2034 /* FIXME */
2035 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2036 TLB_abort();
2038 pcx->pos = where;
2042 /* read function */
2043 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2045 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2046 pcx->pos, count, pcx->oStart, pcx->length, where);
2048 MSFT_Seek(pcx, where);
2049 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2050 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2051 pcx->pos += count;
2052 return count;
2055 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2056 LONG where )
2058 DWORD ret;
2060 ret = MSFT_Read(buffer, count, pcx, where);
2061 FromLEDWords(buffer, ret);
2063 return ret;
2066 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2067 LONG where )
2069 DWORD ret;
2071 ret = MSFT_Read(buffer, count, pcx, where);
2072 FromLEWords(buffer, ret);
2074 return ret;
2077 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2079 TLBGuid *guid;
2080 MSFT_GuidEntry entry;
2081 int offs = 0;
2083 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2084 while (1) {
2085 if (offs >= pcx->pTblDir->pGuidTab.length)
2086 return S_OK;
2088 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2090 guid = heap_alloc(sizeof(TLBGuid));
2092 guid->offset = offs;
2093 guid->guid = entry.guid;
2094 guid->hreftype = entry.hreftype;
2096 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2098 offs += sizeof(MSFT_GuidEntry);
2102 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2104 TLBGuid *ret;
2106 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2107 if(ret->offset == offset){
2108 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2109 return ret;
2113 return NULL;
2116 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2118 MSFT_NameIntro niName;
2120 if (offset < 0)
2122 ERR_(typelib)("bad offset %d\n", offset);
2123 return -1;
2126 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2127 pcx->pTblDir->pNametab.offset+offset);
2129 return niName.hreftype;
2132 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2134 char *string;
2135 MSFT_NameIntro intro;
2136 INT16 len_piece;
2137 int offs = 0, lengthInChars;
2139 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2140 while (1) {
2141 TLBString *tlbstr;
2143 if (offs >= pcx->pTblDir->pNametab.length)
2144 return S_OK;
2146 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2147 intro.namelen &= 0xFF;
2148 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2149 if(len_piece % 4)
2150 len_piece = (len_piece + 4) & ~0x3;
2151 if(len_piece < 8)
2152 len_piece = 8;
2154 string = heap_alloc(len_piece + 1);
2155 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2156 string[intro.namelen] = '\0';
2158 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2159 string, -1, NULL, 0);
2160 if (!lengthInChars) {
2161 heap_free(string);
2162 return E_UNEXPECTED;
2165 tlbstr = heap_alloc(sizeof(TLBString));
2167 tlbstr->offset = offs;
2168 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2169 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2171 heap_free(string);
2173 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2175 offs += len_piece;
2179 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2181 TLBString *tlbstr;
2183 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2184 if (tlbstr->offset == offset) {
2185 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2186 return tlbstr;
2190 return NULL;
2193 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2195 TLBString *tlbstr;
2197 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2198 if (tlbstr->offset == offset) {
2199 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2200 return tlbstr;
2204 return NULL;
2208 * read a value and fill a VARIANT structure
2210 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2212 int size;
2214 TRACE_(typelib)("\n");
2216 if(offset <0) { /* data are packed in here */
2217 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2218 V_I4(pVar) = offset & 0x3ffffff;
2219 return;
2221 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2222 pcx->pTblDir->pCustData.offset + offset );
2223 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2224 switch (V_VT(pVar)){
2225 case VT_EMPTY: /* FIXME: is this right? */
2226 case VT_NULL: /* FIXME: is this right? */
2227 case VT_I2 : /* this should not happen */
2228 case VT_I4 :
2229 case VT_R4 :
2230 case VT_ERROR :
2231 case VT_BOOL :
2232 case VT_I1 :
2233 case VT_UI1 :
2234 case VT_UI2 :
2235 case VT_UI4 :
2236 case VT_INT :
2237 case VT_UINT :
2238 case VT_VOID : /* FIXME: is this right? */
2239 case VT_HRESULT :
2240 size=4; break;
2241 case VT_R8 :
2242 case VT_CY :
2243 case VT_DATE :
2244 case VT_I8 :
2245 case VT_UI8 :
2246 case VT_DECIMAL : /* FIXME: is this right? */
2247 case VT_FILETIME :
2248 size=8;break;
2249 /* pointer types with known behaviour */
2250 case VT_BSTR :{
2251 char * ptr;
2252 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2253 if(size == -1){
2254 V_BSTR(pVar) = NULL;
2255 }else{
2256 ptr = heap_alloc_zero(size);
2257 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2258 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2259 /* FIXME: do we need a AtoW conversion here? */
2260 V_UNION(pVar, bstrVal[size])='\0';
2261 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2262 heap_free(ptr);
2265 size=-4; break;
2266 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2267 case VT_DISPATCH :
2268 case VT_VARIANT :
2269 case VT_UNKNOWN :
2270 case VT_PTR :
2271 case VT_SAFEARRAY :
2272 case VT_CARRAY :
2273 case VT_USERDEFINED :
2274 case VT_LPSTR :
2275 case VT_LPWSTR :
2276 case VT_BLOB :
2277 case VT_STREAM :
2278 case VT_STORAGE :
2279 case VT_STREAMED_OBJECT :
2280 case VT_STORED_OBJECT :
2281 case VT_BLOB_OBJECT :
2282 case VT_CF :
2283 case VT_CLSID :
2284 default:
2285 size=0;
2286 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2287 V_VT(pVar));
2290 if(size>0) /* (big|small) endian correct? */
2291 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2292 return;
2295 * create a linked list with custom data
2297 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2299 MSFT_CDGuid entry;
2300 TLBCustData* pNew;
2301 int count=0;
2303 TRACE_(typelib)("\n");
2305 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2307 while(offset >=0){
2308 count++;
2309 pNew=heap_alloc_zero(sizeof(TLBCustData));
2310 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2311 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2312 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2313 list_add_head(custdata_list, &pNew->entry);
2314 offset = entry.next;
2316 return count;
2319 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2321 if(type <0)
2322 pTd->vt=type & VT_TYPEMASK;
2323 else
2324 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2326 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2329 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2331 return (invkind == INVOKE_PROPERTYGET ||
2332 invkind == INVOKE_PROPERTYPUT ||
2333 invkind == INVOKE_PROPERTYPUTREF);
2336 static void
2337 MSFT_DoFuncs(TLBContext* pcx,
2338 ITypeInfoImpl* pTI,
2339 int cFuncs,
2340 int cVars,
2341 int offset,
2342 TLBFuncDesc** pptfd)
2345 * member information is stored in a data structure at offset
2346 * indicated by the memoffset field of the typeinfo structure
2347 * There are several distinctive parts.
2348 * The first part starts with a field that holds the total length
2349 * of this (first) part excluding this field. Then follow the records,
2350 * for each member there is one record.
2352 * The first entry is always the length of the record (including this
2353 * length word).
2354 * The rest of the record depends on the type of the member. If there is
2355 * a field indicating the member type (function, variable, interface, etc)
2356 * I have not found it yet. At this time we depend on the information
2357 * in the type info and the usual order how things are stored.
2359 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2360 * for each member;
2362 * Third is an equal sized array with file offsets to the name entry
2363 * of each member.
2365 * The fourth and last (?) part is an array with offsets to the records
2366 * in the first part of this file segment.
2369 int infolen, nameoffset, reclength, i;
2370 int recoffset = offset + sizeof(INT);
2372 char *recbuf = heap_alloc(0xffff);
2373 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2374 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2376 TRACE_(typelib)("\n");
2378 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2380 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2381 ptfd = *pptfd;
2382 for ( i = 0; i < cFuncs ; i++ )
2384 int optional;
2386 /* name, eventually add to a hash table */
2387 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2388 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2390 /* read the function information record */
2391 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2393 reclength &= 0xffff;
2395 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2397 /* size without argument data */
2398 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2399 if (pFuncRec->FKCCIC & 0x1000)
2400 optional -= pFuncRec->nrargs * sizeof(INT);
2402 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2403 ptfd->helpcontext = pFuncRec->HelpContext;
2405 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2406 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2408 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2410 if (pFuncRec->FKCCIC & 0x2000 )
2412 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2413 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2414 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2416 else
2417 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2419 else
2420 ptfd->Entry = (TLBString*)-1;
2422 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2423 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2425 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2426 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2428 /* fill the FuncDesc Structure */
2429 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2430 offset + infolen + ( i + 1) * sizeof(INT));
2432 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2433 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2434 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2435 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2436 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2437 if (ptfd->funcdesc.funckind == FUNC_DISPATCH)
2438 ptfd->funcdesc.oVft = 0;
2439 else
2440 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2441 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2443 /* nameoffset is sometimes -1 on the second half of a propget/propput
2444 * pair of functions */
2445 if ((nameoffset == -1) && (i > 0) &&
2446 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2447 TLB_is_propgetput(ptfd->funcdesc.invkind))
2448 ptfd->Name = ptfd_prev->Name;
2449 else
2450 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2452 MSFT_GetTdesc(pcx,
2453 pFuncRec->DataType,
2454 &ptfd->funcdesc.elemdescFunc.tdesc);
2456 /* do the parameters/arguments */
2457 if(pFuncRec->nrargs)
2459 int j = 0;
2460 MSFT_ParameterInfo paraminfo;
2462 ptfd->funcdesc.lprgelemdescParam =
2463 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2465 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2467 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2468 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2470 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2472 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2474 MSFT_GetTdesc(pcx,
2475 paraminfo.DataType,
2476 &elemdesc->tdesc);
2478 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2480 /* name */
2481 if (paraminfo.oName != -1)
2482 ptfd->pParamDesc[j].Name =
2483 MSFT_ReadName( pcx, paraminfo.oName );
2484 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2486 /* default value */
2487 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2488 (pFuncRec->FKCCIC & 0x1000) )
2490 INT* pInt = (INT *)((char *)pFuncRec +
2491 reclength -
2492 (pFuncRec->nrargs * 4) * sizeof(INT) );
2494 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2496 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2497 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2499 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2500 pInt[j], pcx);
2502 else
2503 elemdesc->u.paramdesc.pparamdescex = NULL;
2505 /* custom info */
2506 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2507 j*sizeof(pFuncRec->oArgCustData[0])) &&
2508 pFuncRec->FKCCIC & 0x80 )
2510 MSFT_CustData(pcx,
2511 pFuncRec->oArgCustData[j],
2512 &ptfd->pParamDesc[j].custdata_list);
2515 /* SEEK value = jump to offset,
2516 * from there jump to the end of record,
2517 * go back by (j-1) arguments
2519 MSFT_ReadLEDWords( &paraminfo ,
2520 sizeof(MSFT_ParameterInfo), pcx,
2521 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2522 * sizeof(MSFT_ParameterInfo)));
2526 /* scode is not used: archaic win16 stuff FIXME: right? */
2527 ptfd->funcdesc.cScodes = 0 ;
2528 ptfd->funcdesc.lprgscode = NULL ;
2530 ptfd_prev = ptfd;
2531 ++ptfd;
2532 recoffset += reclength;
2534 heap_free(recbuf);
2537 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2538 int cVars, int offset, TLBVarDesc ** pptvd)
2540 int infolen, nameoffset, reclength;
2541 char recbuf[256];
2542 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2543 TLBVarDesc *ptvd;
2544 int i;
2545 int recoffset;
2547 TRACE_(typelib)("\n");
2549 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2550 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2551 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2552 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2553 recoffset += offset+sizeof(INT);
2554 for(i=0;i<cVars;i++, ++ptvd){
2555 /* name, eventually add to a hash table */
2556 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2557 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2558 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2559 /* read the variable information record */
2560 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2561 reclength &= 0xff;
2562 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2564 /* optional data */
2565 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2566 ptvd->HelpContext = pVarRec->HelpContext;
2568 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2569 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2571 if (reclength > FIELD_OFFSET(MSFT_VarRecord, oCustData))
2572 MSFT_CustData(pcx, pVarRec->oCustData, &ptvd->custdata_list);
2574 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2575 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2577 /* fill the VarDesc Structure */
2578 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2579 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2580 ptvd->vardesc.varkind = pVarRec->VarKind;
2581 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2582 MSFT_GetTdesc(pcx, pVarRec->DataType,
2583 &ptvd->vardesc.elemdescVar.tdesc);
2584 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2585 if(pVarRec->VarKind == VAR_CONST ){
2586 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2587 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2588 pVarRec->OffsValue, pcx);
2589 } else
2590 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2591 recoffset += reclength;
2595 /* process Implemented Interfaces of a com class */
2596 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2597 int offset)
2599 int i;
2600 MSFT_RefRecord refrec;
2601 TLBImplType *pImpl;
2603 TRACE_(typelib)("\n");
2605 pTI->impltypes = TLBImplType_Alloc(count);
2606 pImpl = pTI->impltypes;
2607 for(i=0;i<count;i++){
2608 if(offset<0) break; /* paranoia */
2609 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2610 pImpl->hRef = refrec.reftype;
2611 pImpl->implflags=refrec.flags;
2612 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2613 offset=refrec.onext;
2614 ++pImpl;
2618 #ifdef _WIN64
2619 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2620 * and some structures, and fix the alignment */
2621 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2623 if(info->typeattr.typekind == TKIND_ALIAS){
2624 switch(info->tdescAlias->vt){
2625 case VT_BSTR:
2626 case VT_DISPATCH:
2627 case VT_UNKNOWN:
2628 case VT_PTR:
2629 case VT_SAFEARRAY:
2630 case VT_LPSTR:
2631 case VT_LPWSTR:
2632 info->typeattr.cbSizeInstance = sizeof(void*);
2633 info->typeattr.cbAlignment = sizeof(void*);
2634 break;
2635 case VT_CARRAY:
2636 case VT_USERDEFINED:
2637 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2638 break;
2639 case VT_VARIANT:
2640 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2641 info->typeattr.cbAlignment = 8;
2642 default:
2643 if(info->typeattr.cbSizeInstance < sizeof(void*))
2644 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2645 else
2646 info->typeattr.cbAlignment = sizeof(void*);
2647 break;
2649 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2650 info->typeattr.typekind == TKIND_DISPATCH ||
2651 info->typeattr.typekind == TKIND_COCLASS){
2652 info->typeattr.cbSizeInstance = sizeof(void*);
2653 info->typeattr.cbAlignment = sizeof(void*);
2656 #endif
2659 * process a typeinfo record
2661 static ITypeInfoImpl * MSFT_DoTypeInfo(
2662 TLBContext *pcx,
2663 int count,
2664 ITypeLibImpl * pLibInfo)
2666 MSFT_TypeInfoBase tiBase;
2667 ITypeInfoImpl *ptiRet;
2669 TRACE_(typelib)("count=%u\n", count);
2671 ptiRet = ITypeInfoImpl_Constructor();
2672 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2673 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2675 /* this is where we are coming from */
2676 ptiRet->pTypeLib = pLibInfo;
2677 ptiRet->index=count;
2679 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2680 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2681 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2682 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2683 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2684 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2685 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2686 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2687 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2688 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2689 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2690 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2691 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2692 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2693 TYPEDESC tmp;
2694 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2695 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2696 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2699 /* FIXME: */
2700 /* IDLDESC idldescType; *//* never saw this one != zero */
2702 /* name, eventually add to a hash table */
2703 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2704 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2705 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2706 /* help info */
2707 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2708 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2709 ptiRet->dwHelpContext=tiBase.helpcontext;
2711 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2712 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2714 /* note: InfoType's Help file and HelpStringDll come from the containing
2715 * library. Further HelpString and Docstring appear to be the same thing :(
2717 /* functions */
2718 if(ptiRet->typeattr.cFuncs >0 )
2719 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2720 ptiRet->typeattr.cVars,
2721 tiBase.memoffset, &ptiRet->funcdescs);
2722 /* variables */
2723 if(ptiRet->typeattr.cVars >0 )
2724 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2725 ptiRet->typeattr.cVars,
2726 tiBase.memoffset, &ptiRet->vardescs);
2727 if(ptiRet->typeattr.cImplTypes >0 ) {
2728 switch(ptiRet->typeattr.typekind)
2730 case TKIND_COCLASS:
2731 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2732 tiBase.datatype1);
2733 break;
2734 case TKIND_DISPATCH:
2735 /* This is not -1 when the interface is a non-base dual interface or
2736 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2737 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2738 not this interface.
2741 if (tiBase.datatype1 != -1)
2743 ptiRet->impltypes = TLBImplType_Alloc(1);
2744 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2746 break;
2747 default:
2748 ptiRet->impltypes = TLBImplType_Alloc(1);
2749 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2750 break;
2753 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2755 TRACE_(typelib)("%s guid: %s kind:%s\n",
2756 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2757 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2758 typekind_desc[ptiRet->typeattr.typekind]);
2759 if (TRACE_ON(typelib))
2760 dump_TypeInfo(ptiRet);
2762 return ptiRet;
2765 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2767 char *string;
2768 INT16 len_str, len_piece;
2769 int offs = 0, lengthInChars;
2771 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2772 while (1) {
2773 TLBString *tlbstr;
2775 if (offs >= pcx->pTblDir->pStringtab.length)
2776 return S_OK;
2778 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2779 len_piece = len_str + sizeof(INT16);
2780 if(len_piece % 4)
2781 len_piece = (len_piece + 4) & ~0x3;
2782 if(len_piece < 8)
2783 len_piece = 8;
2785 string = heap_alloc(len_piece + 1);
2786 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2787 string[len_str] = '\0';
2789 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2790 string, -1, NULL, 0);
2791 if (!lengthInChars) {
2792 heap_free(string);
2793 return E_UNEXPECTED;
2796 tlbstr = heap_alloc(sizeof(TLBString));
2798 tlbstr->offset = offs;
2799 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2800 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2802 heap_free(string);
2804 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2806 offs += len_piece;
2810 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2812 TLBRefType *ref;
2813 int offs = 0;
2815 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2816 while (offs < pcx->pTblDir->pImpInfo.length) {
2817 MSFT_ImpInfo impinfo;
2818 TLBImpLib *pImpLib;
2820 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2822 ref = heap_alloc_zero(sizeof(TLBRefType));
2823 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2825 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2826 if(pImpLib->offset==impinfo.oImpFile)
2827 break;
2829 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2830 ref->reference = offs;
2831 ref->pImpTLInfo = pImpLib;
2832 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2833 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2834 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2835 ref->index = TLB_REF_USE_GUID;
2836 } else
2837 ref->index = impinfo.oGuid;
2838 }else{
2839 ERR("Cannot find a reference\n");
2840 ref->reference = -1;
2841 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2844 offs += sizeof(impinfo);
2847 return S_OK;
2850 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2851 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2852 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2853 * tradeoff here.
2855 static struct list tlb_cache = LIST_INIT(tlb_cache);
2856 static CRITICAL_SECTION cache_section;
2857 static CRITICAL_SECTION_DEBUG cache_section_debug =
2859 0, 0, &cache_section,
2860 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2861 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2863 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2866 typedef struct TLB_PEFile
2868 IUnknown IUnknown_iface;
2869 LONG refs;
2870 HMODULE dll;
2871 HRSRC typelib_resource;
2872 HGLOBAL typelib_global;
2873 LPVOID typelib_base;
2874 } TLB_PEFile;
2876 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2878 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2881 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2883 if (IsEqualIID(riid, &IID_IUnknown))
2885 *ppv = iface;
2886 IUnknown_AddRef(iface);
2887 return S_OK;
2889 *ppv = NULL;
2890 return E_NOINTERFACE;
2893 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2895 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2896 return InterlockedIncrement(&This->refs);
2899 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2901 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2902 ULONG refs = InterlockedDecrement(&This->refs);
2903 if (!refs)
2905 if (This->typelib_global)
2906 FreeResource(This->typelib_global);
2907 if (This->dll)
2908 FreeLibrary(This->dll);
2909 heap_free(This);
2911 return refs;
2914 static const IUnknownVtbl TLB_PEFile_Vtable =
2916 TLB_PEFile_QueryInterface,
2917 TLB_PEFile_AddRef,
2918 TLB_PEFile_Release
2921 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2923 TLB_PEFile *This;
2924 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2926 This = heap_alloc(sizeof(TLB_PEFile));
2927 if (!This)
2928 return E_OUTOFMEMORY;
2930 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2931 This->refs = 1;
2932 This->dll = NULL;
2933 This->typelib_resource = NULL;
2934 This->typelib_global = NULL;
2935 This->typelib_base = NULL;
2937 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2938 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2940 if (This->dll)
2942 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), L"TYPELIB");
2943 if (This->typelib_resource)
2945 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2946 if (This->typelib_global)
2948 This->typelib_base = LockResource(This->typelib_global);
2950 if (This->typelib_base)
2952 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2953 *ppBase = This->typelib_base;
2954 *ppFile = &This->IUnknown_iface;
2955 return S_OK;
2960 TRACE("No TYPELIB resource found\n");
2961 hr = E_FAIL;
2964 TLB_PEFile_Release(&This->IUnknown_iface);
2965 return hr;
2968 typedef struct TLB_NEFile
2970 IUnknown IUnknown_iface;
2971 LONG refs;
2972 LPVOID typelib_base;
2973 } TLB_NEFile;
2975 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2977 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2980 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2982 if (IsEqualIID(riid, &IID_IUnknown))
2984 *ppv = iface;
2985 IUnknown_AddRef(iface);
2986 return S_OK;
2988 *ppv = NULL;
2989 return E_NOINTERFACE;
2992 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2994 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2995 return InterlockedIncrement(&This->refs);
2998 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3000 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3001 ULONG refs = InterlockedDecrement(&This->refs);
3002 if (!refs)
3004 heap_free(This->typelib_base);
3005 heap_free(This);
3007 return refs;
3010 static const IUnknownVtbl TLB_NEFile_Vtable =
3012 TLB_NEFile_QueryInterface,
3013 TLB_NEFile_AddRef,
3014 TLB_NEFile_Release
3017 /***********************************************************************
3018 * read_xx_header [internal]
3020 static int read_xx_header( HFILE lzfd )
3022 IMAGE_DOS_HEADER mzh;
3023 char magic[3];
3025 LZSeek( lzfd, 0, SEEK_SET );
3026 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3027 return 0;
3028 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3029 return 0;
3031 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3032 if ( 2 != LZRead( lzfd, magic, 2 ) )
3033 return 0;
3035 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3037 if ( magic[0] == 'N' && magic[1] == 'E' )
3038 return IMAGE_OS2_SIGNATURE;
3039 if ( magic[0] == 'P' && magic[1] == 'E' )
3040 return IMAGE_NT_SIGNATURE;
3042 magic[2] = '\0';
3043 WARN("Can't handle %s files.\n", magic );
3044 return 0;
3048 /***********************************************************************
3049 * find_ne_resource [internal]
3051 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3052 DWORD *resLen, DWORD *resOff )
3054 IMAGE_OS2_HEADER nehd;
3055 NE_TYPEINFO *typeInfo;
3056 NE_NAMEINFO *nameInfo;
3057 DWORD nehdoffset;
3058 LPBYTE resTab;
3059 DWORD resTabSize;
3060 int count;
3062 /* Read in NE header */
3063 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3064 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3066 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3067 if ( !resTabSize )
3069 TRACE("No resources in NE dll\n" );
3070 return FALSE;
3073 /* Read in resource table */
3074 resTab = heap_alloc( resTabSize );
3075 if ( !resTab ) return FALSE;
3077 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3078 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3080 heap_free( resTab );
3081 return FALSE;
3084 /* Find resource */
3085 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3087 if (!IS_INTRESOURCE(typeid)) /* named type */
3089 BYTE len = strlen( typeid );
3090 while (typeInfo->type_id)
3092 if (!(typeInfo->type_id & 0x8000))
3094 BYTE *p = resTab + typeInfo->type_id;
3095 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3097 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3098 typeInfo->count * sizeof(NE_NAMEINFO));
3101 else /* numeric type id */
3103 WORD id = LOWORD(typeid) | 0x8000;
3104 while (typeInfo->type_id)
3106 if (typeInfo->type_id == id) goto found_type;
3107 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3108 typeInfo->count * sizeof(NE_NAMEINFO));
3111 TRACE("No typeid entry found for %p\n", typeid );
3112 heap_free( resTab );
3113 return FALSE;
3115 found_type:
3116 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3118 if (!IS_INTRESOURCE(resid)) /* named resource */
3120 BYTE len = strlen( resid );
3121 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3123 BYTE *p = resTab + nameInfo->id;
3124 if (nameInfo->id & 0x8000) continue;
3125 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3128 else /* numeric resource id */
3130 WORD id = LOWORD(resid) | 0x8000;
3131 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3132 if (nameInfo->id == id) goto found_name;
3134 TRACE("No resid entry found for %p\n", typeid );
3135 heap_free( resTab );
3136 return FALSE;
3138 found_name:
3139 /* Return resource data */
3140 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3141 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3143 heap_free( resTab );
3144 return TRUE;
3147 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3149 HFILE lzfd = -1;
3150 OFSTRUCT ofs;
3151 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3152 TLB_NEFile *This;
3154 This = heap_alloc(sizeof(TLB_NEFile));
3155 if (!This) return E_OUTOFMEMORY;
3157 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3158 This->refs = 1;
3159 This->typelib_base = NULL;
3161 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3162 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3164 DWORD reslen, offset;
3165 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3167 This->typelib_base = heap_alloc(reslen);
3168 if( !This->typelib_base )
3169 hr = E_OUTOFMEMORY;
3170 else
3172 LZSeek( lzfd, offset, SEEK_SET );
3173 reslen = LZRead( lzfd, This->typelib_base, reslen );
3174 LZClose( lzfd );
3175 *ppBase = This->typelib_base;
3176 *pdwTLBLength = reslen;
3177 *ppFile = &This->IUnknown_iface;
3178 return S_OK;
3183 if( lzfd >= 0) LZClose( lzfd );
3184 TLB_NEFile_Release(&This->IUnknown_iface);
3185 return hr;
3188 typedef struct TLB_Mapping
3190 IUnknown IUnknown_iface;
3191 LONG refs;
3192 HANDLE file;
3193 HANDLE mapping;
3194 LPVOID typelib_base;
3195 } TLB_Mapping;
3197 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3199 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3202 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3204 if (IsEqualIID(riid, &IID_IUnknown))
3206 *ppv = iface;
3207 IUnknown_AddRef(iface);
3208 return S_OK;
3210 *ppv = NULL;
3211 return E_NOINTERFACE;
3214 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3216 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3217 return InterlockedIncrement(&This->refs);
3220 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3222 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3223 ULONG refs = InterlockedDecrement(&This->refs);
3224 if (!refs)
3226 if (This->typelib_base)
3227 UnmapViewOfFile(This->typelib_base);
3228 if (This->mapping)
3229 CloseHandle(This->mapping);
3230 if (This->file != INVALID_HANDLE_VALUE)
3231 CloseHandle(This->file);
3232 heap_free(This);
3234 return refs;
3237 static const IUnknownVtbl TLB_Mapping_Vtable =
3239 TLB_Mapping_QueryInterface,
3240 TLB_Mapping_AddRef,
3241 TLB_Mapping_Release
3244 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3246 TLB_Mapping *This;
3248 This = heap_alloc(sizeof(TLB_Mapping));
3249 if (!This)
3250 return E_OUTOFMEMORY;
3252 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3253 This->refs = 1;
3254 This->file = INVALID_HANDLE_VALUE;
3255 This->mapping = NULL;
3256 This->typelib_base = NULL;
3258 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3259 if (INVALID_HANDLE_VALUE != This->file)
3261 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3262 if (This->mapping)
3264 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3265 if(This->typelib_base)
3267 /* retrieve file size */
3268 *pdwTLBLength = GetFileSize(This->file, NULL);
3269 *ppBase = This->typelib_base;
3270 *ppFile = &This->IUnknown_iface;
3271 return S_OK;
3276 IUnknown_Release(&This->IUnknown_iface);
3277 return TYPE_E_CANTLOADLIBRARY;
3280 /****************************************************************************
3281 * TLB_ReadTypeLib
3283 * find the type of the typelib file and map the typelib resource into
3284 * the memory
3287 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3288 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3290 ITypeLibImpl *entry;
3291 HRESULT ret;
3292 INT index = 1;
3293 LPWSTR index_str, file = (LPWSTR)pszFileName;
3294 LPVOID pBase = NULL;
3295 DWORD dwTLBLength = 0;
3296 IUnknown *pFile = NULL;
3297 HANDLE h;
3299 *ppTypeLib = NULL;
3301 index_str = wcsrchr(pszFileName, '\\');
3302 if(index_str && *++index_str != '\0')
3304 LPWSTR end_ptr;
3305 LONG idx = wcstol(index_str, &end_ptr, 10);
3306 if(*end_ptr == '\0')
3308 int str_len = index_str - pszFileName - 1;
3309 index = idx;
3310 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3311 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3312 file[str_len] = 0;
3316 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3318 if(wcschr(file, '\\'))
3320 lstrcpyW(pszPath, file);
3322 else
3324 int len = GetSystemDirectoryW(pszPath, cchPath);
3325 pszPath[len] = '\\';
3326 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3330 if(file != pszFileName) heap_free(file);
3332 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3333 if(h != INVALID_HANDLE_VALUE){
3334 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3335 CloseHandle(h);
3338 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3340 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3341 EnterCriticalSection(&cache_section);
3342 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3344 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3346 TRACE("cache hit\n");
3347 *ppTypeLib = &entry->ITypeLib2_iface;
3348 ITypeLib2_AddRef(*ppTypeLib);
3349 LeaveCriticalSection(&cache_section);
3350 return S_OK;
3353 LeaveCriticalSection(&cache_section);
3355 /* now actually load and parse the typelib */
3357 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3358 if (ret == TYPE_E_CANTLOADLIBRARY)
3359 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3360 if (ret == TYPE_E_CANTLOADLIBRARY)
3361 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3362 if (SUCCEEDED(ret))
3364 if (dwTLBLength >= 4)
3366 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3367 if (dwSignature == MSFT_SIGNATURE)
3368 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3369 else if (dwSignature == SLTG_SIGNATURE)
3370 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3371 else
3373 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3374 ret = TYPE_E_CANTLOADLIBRARY;
3377 else
3378 ret = TYPE_E_CANTLOADLIBRARY;
3379 IUnknown_Release(pFile);
3382 if(*ppTypeLib) {
3383 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3385 TRACE("adding to cache\n");
3386 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3387 lstrcpyW(impl->path, pszPath);
3388 /* We should really canonicalise the path here. */
3389 impl->index = index;
3391 /* FIXME: check if it has added already in the meantime */
3392 EnterCriticalSection(&cache_section);
3393 list_add_head(&tlb_cache, &impl->entry);
3394 LeaveCriticalSection(&cache_section);
3395 ret = S_OK;
3397 else
3399 if(ret != E_FAIL)
3400 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3402 ret = TYPE_E_CANTLOADLIBRARY;
3406 return ret;
3409 /*================== ITypeLib(2) Methods ===================================*/
3411 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3413 ITypeLibImpl* pTypeLibImpl;
3415 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3416 if (!pTypeLibImpl) return NULL;
3418 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3419 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3420 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3421 pTypeLibImpl->ref = 1;
3423 list_init(&pTypeLibImpl->implib_list);
3424 list_init(&pTypeLibImpl->custdata_list);
3425 list_init(&pTypeLibImpl->name_list);
3426 list_init(&pTypeLibImpl->string_list);
3427 list_init(&pTypeLibImpl->guid_list);
3428 list_init(&pTypeLibImpl->ref_list);
3429 pTypeLibImpl->dispatch_href = -1;
3431 return pTypeLibImpl;
3434 /****************************************************************************
3435 * ITypeLib2_Constructor_MSFT
3437 * loading an MSFT typelib from an in-memory image
3439 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3441 TLBContext cx;
3442 LONG lPSegDir;
3443 MSFT_Header tlbHeader;
3444 MSFT_SegDir tlbSegDir;
3445 ITypeLibImpl * pTypeLibImpl;
3446 int i;
3448 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3450 pTypeLibImpl = TypeLibImpl_Constructor();
3451 if (!pTypeLibImpl) return NULL;
3453 /* get pointer to beginning of typelib data */
3454 cx.pos = 0;
3455 cx.oStart=0;
3456 cx.mapping = pLib;
3457 cx.pLibInfo = pTypeLibImpl;
3458 cx.length = dwTLBLength;
3460 /* read header */
3461 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3462 TRACE_(typelib)("header:\n");
3463 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3464 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3465 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3466 return NULL;
3468 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3470 /* there is a small amount of information here until the next important
3471 * part:
3472 * the segment directory . Try to calculate the amount of data */
3473 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3475 /* now read the segment directory */
3476 TRACE("read segment directory (at %d)\n",lPSegDir);
3477 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3478 cx.pTblDir = &tlbSegDir;
3480 /* just check two entries */
3481 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3483 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3484 heap_free(pTypeLibImpl);
3485 return NULL;
3488 MSFT_ReadAllNames(&cx);
3489 MSFT_ReadAllStrings(&cx);
3490 MSFT_ReadAllGuids(&cx);
3492 /* now fill our internal data */
3493 /* TLIBATTR fields */
3494 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3496 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3497 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3498 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3499 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3500 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3502 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3503 pTypeLibImpl->lcid = tlbHeader.lcid;
3505 /* name, eventually add to a hash table */
3506 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3508 /* help info */
3509 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3510 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3512 if( tlbHeader.varflags & HELPDLLFLAG)
3514 int offset;
3515 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3516 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3519 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3521 /* custom data */
3522 if(tlbHeader.CustomDataOffset >= 0)
3524 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3527 /* fill in type descriptions */
3528 if(tlbSegDir.pTypdescTab.length > 0)
3530 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3531 INT16 td[4];
3532 pTypeLibImpl->ctTypeDesc = cTD;
3533 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3534 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3535 for(i=0; i<cTD; )
3537 /* FIXME: add several sanity checks here */
3538 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3539 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3541 /* FIXME: check safearray */
3542 if(td[3] < 0)
3543 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3544 else
3545 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3547 else if(td[0] == VT_CARRAY)
3549 /* array descr table here */
3550 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3552 else if(td[0] == VT_USERDEFINED)
3554 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3556 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3559 /* second time around to fill the array subscript info */
3560 for(i=0;i<cTD;i++)
3562 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3563 if(tlbSegDir.pArrayDescriptions.offset>0)
3565 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3566 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3568 if(td[1]<0)
3569 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3570 else
3571 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3573 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3575 for(j = 0; j<td[2]; j++)
3577 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3578 sizeof(INT), &cx, DO_NOT_SEEK);
3579 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3580 sizeof(INT), &cx, DO_NOT_SEEK);
3583 else
3585 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3586 ERR("didn't find array description data\n");
3591 /* imported type libs */
3592 if(tlbSegDir.pImpFiles.offset>0)
3594 TLBImpLib *pImpLib;
3595 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3596 UINT16 size;
3598 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3600 char *name;
3602 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3603 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3604 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3606 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3607 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3608 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3609 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3611 size >>= 2;
3612 name = heap_alloc_zero(size+1);
3613 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3614 pImpLib->name = TLB_MultiByteToBSTR(name);
3615 heap_free(name);
3617 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3618 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3620 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3624 MSFT_ReadAllRefs(&cx);
3626 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3628 /* type infos */
3629 if(tlbHeader.nrtypeinfos >= 0 )
3631 ITypeInfoImpl **ppTI;
3633 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3635 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3637 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3639 ++ppTI;
3640 (pTypeLibImpl->TypeInfoCount)++;
3644 #ifdef _WIN64
3645 if(pTypeLibImpl->syskind == SYS_WIN32){
3646 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3647 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3649 #endif
3651 TRACE("(%p)\n", pTypeLibImpl);
3652 return &pTypeLibImpl->ITypeLib2_iface;
3656 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3658 char b[3];
3659 int i;
3660 short s;
3662 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3663 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3664 return FALSE;
3667 guid->Data4[0] = s >> 8;
3668 guid->Data4[1] = s & 0xff;
3670 b[2] = '\0';
3671 for(i = 0; i < 6; i++) {
3672 memcpy(b, str + 24 + 2 * i, 2);
3673 guid->Data4[i + 2] = strtol(b, NULL, 16);
3675 return TRUE;
3678 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3680 WORD bytelen;
3681 DWORD len;
3682 BSTR tmp_str;
3684 *pStr = NULL;
3685 bytelen = *(const WORD*)ptr;
3686 if(bytelen == 0xffff) return 2;
3688 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3689 tmp_str = SysAllocStringLen(NULL, len);
3690 if (tmp_str) {
3691 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3692 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3693 SysFreeString(tmp_str);
3695 return bytelen + 2;
3698 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3700 WORD bytelen;
3702 *str = NULL;
3703 bytelen = *(const WORD*)ptr;
3704 if(bytelen == 0xffff) return 2;
3705 *str = heap_alloc(bytelen + 1);
3706 memcpy(*str, ptr + 2, bytelen);
3707 (*str)[bytelen] = '\0';
3708 return bytelen + 2;
3711 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3713 BSTR tmp_str;
3714 TLBString *tlbstr;
3716 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3717 if (tlbstr->offset == offset)
3718 return tlbstr;
3721 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3722 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3723 SysFreeString(tmp_str);
3725 return tlbstr;
3728 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3730 char *ptr = pLibBlk;
3731 WORD w;
3733 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3734 FIXME("libblk magic = %04x\n", w);
3735 return 0;
3738 ptr += 6;
3739 if((w = *(WORD*)ptr) != 0xffff) {
3740 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3741 ptr += w;
3743 ptr += 2;
3745 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3747 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3749 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3750 ptr += 4;
3752 pTypeLibImpl->syskind = *(WORD*)ptr;
3753 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3754 ptr += 2;
3756 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3757 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3758 else
3759 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3760 ptr += 2;
3762 ptr += 4; /* skip res12 */
3764 pTypeLibImpl->libflags = *(WORD*)ptr;
3765 ptr += 2;
3767 pTypeLibImpl->ver_major = *(WORD*)ptr;
3768 ptr += 2;
3770 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3771 ptr += 2;
3773 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3774 ptr += sizeof(GUID);
3776 return ptr - (char*)pLibBlk;
3779 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3780 typedef struct
3782 unsigned int num;
3783 HREFTYPE refs[1];
3784 } sltg_ref_lookup_t;
3786 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3787 HREFTYPE *typelib_ref)
3789 if(table && typeinfo_ref < table->num)
3791 *typelib_ref = table->refs[typeinfo_ref];
3792 return S_OK;
3795 ERR_(typelib)("Unable to find reference\n");
3796 *typelib_ref = -1;
3797 return E_FAIL;
3800 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3802 BOOL done = FALSE;
3804 while(!done) {
3805 if((*pType & 0xe00) == 0xe00) {
3806 pTD->vt = VT_PTR;
3807 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3808 pTD = pTD->u.lptdesc;
3810 switch(*pType & 0x3f) {
3811 case VT_PTR:
3812 pTD->vt = VT_PTR;
3813 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3814 pTD = pTD->u.lptdesc;
3815 break;
3817 case VT_USERDEFINED:
3818 pTD->vt = VT_USERDEFINED;
3819 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3820 done = TRUE;
3821 break;
3823 case VT_CARRAY:
3825 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3826 array */
3828 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3830 pTD->vt = VT_CARRAY;
3831 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3832 pTD->u.lpadesc->cDims = pSA->cDims;
3833 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3834 pSA->cDims * sizeof(SAFEARRAYBOUND));
3836 pTD = &pTD->u.lpadesc->tdescElem;
3837 break;
3840 case VT_SAFEARRAY:
3842 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3843 useful? */
3845 pType++;
3846 pTD->vt = VT_SAFEARRAY;
3847 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3848 pTD = pTD->u.lptdesc;
3849 break;
3851 default:
3852 pTD->vt = *pType & 0x3f;
3853 done = TRUE;
3854 break;
3856 pType++;
3858 return pType;
3861 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3862 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3864 /* Handle [in/out] first */
3865 if((*pType & 0xc000) == 0xc000)
3866 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3867 else if(*pType & 0x8000)
3868 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3869 else if(*pType & 0x4000)
3870 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3871 else
3872 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3874 if(*pType & 0x2000)
3875 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3877 if(*pType & 0x80)
3878 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3880 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3884 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3885 char *pNameTable)
3887 unsigned int ref;
3888 char *name;
3889 TLBRefType *ref_type;
3890 sltg_ref_lookup_t *table;
3891 HREFTYPE typelib_ref;
3893 if(pRef->magic != SLTG_REF_MAGIC) {
3894 FIXME("Ref magic = %x\n", pRef->magic);
3895 return NULL;
3897 name = ( (char*)pRef->names + pRef->number);
3899 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3900 table->num = pRef->number >> 3;
3902 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3904 /* We don't want the first href to be 0 */
3905 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3907 for(ref = 0; ref < pRef->number >> 3; ref++) {
3908 char *refname;
3909 unsigned int lib_offs, type_num;
3911 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3913 name += SLTG_ReadStringA(name, &refname);
3914 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3915 FIXME_(typelib)("Can't sscanf ref\n");
3916 if(lib_offs != 0xffff) {
3917 TLBImpLib *import;
3919 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3920 if(import->offset == lib_offs)
3921 break;
3923 if(&import->entry == &pTL->implib_list) {
3924 char fname[MAX_PATH+1];
3925 int len;
3926 GUID tmpguid;
3928 import = heap_alloc_zero(sizeof(*import));
3929 import->offset = lib_offs;
3930 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3931 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3932 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3933 &import->wVersionMajor,
3934 &import->wVersionMinor,
3935 &import->lcid, fname) != 4) {
3936 FIXME_(typelib)("can't sscanf ref %s\n",
3937 pNameTable + lib_offs + 40);
3939 len = strlen(fname);
3940 if(fname[len-1] != '#')
3941 FIXME("fname = %s\n", fname);
3942 fname[len-1] = '\0';
3943 import->name = TLB_MultiByteToBSTR(fname);
3944 list_add_tail(&pTL->implib_list, &import->entry);
3946 ref_type->pImpTLInfo = import;
3948 /* Store a reference to IDispatch */
3949 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3950 pTL->dispatch_href = typelib_ref;
3952 } else { /* internal ref */
3953 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3955 ref_type->reference = typelib_ref;
3956 ref_type->index = type_num;
3958 heap_free(refname);
3959 list_add_tail(&pTL->ref_list, &ref_type->entry);
3961 table->refs[ref] = typelib_ref;
3962 typelib_ref += 4;
3964 if((BYTE)*name != SLTG_REF_MAGIC)
3965 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3966 dump_TLBRefType(pTL);
3967 return table;
3970 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3971 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3973 SLTG_ImplInfo *info;
3974 TLBImplType *pImplType;
3975 /* I don't really get this structure, usually it's 0x16 bytes
3976 long, but iuser.tlb contains some that are 0x18 bytes long.
3977 That's ok because we can use the next ptr to jump to the next
3978 one. But how do we know the length of the last one? The WORD
3979 at offs 0x8 might be the clue. For now I'm just assuming that
3980 the last one is the regular 0x16 bytes. */
3982 info = (SLTG_ImplInfo*)pBlk;
3983 while(1){
3984 pTI->typeattr.cImplTypes++;
3985 if(info->next == 0xffff)
3986 break;
3987 info = (SLTG_ImplInfo*)(pBlk + info->next);
3990 info = (SLTG_ImplInfo*)pBlk;
3991 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3992 pImplType = pTI->impltypes;
3993 while(1) {
3994 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3995 pImplType->implflags = info->impltypeflags;
3996 ++pImplType;
3998 if(info->next == 0xffff)
3999 break;
4000 if(OneOnly)
4001 FIXME_(typelib)("Interface inheriting more than one interface\n");
4002 info = (SLTG_ImplInfo*)(pBlk + info->next);
4004 info++; /* see comment at top of function */
4005 return (char*)info;
4008 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4009 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4011 TLBVarDesc *pVarDesc;
4012 const TLBString *prevName = NULL;
4013 SLTG_Variable *pItem;
4014 unsigned short i;
4015 WORD *pType;
4017 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4019 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4020 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4022 pVarDesc->vardesc.memid = pItem->memid;
4024 if (pItem->magic != SLTG_VAR_MAGIC &&
4025 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4026 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4027 return;
4030 if (pItem->name == 0xfffe)
4031 pVarDesc->Name = prevName;
4032 else
4033 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4035 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4036 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4037 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4039 if(pItem->flags & 0x02)
4040 pType = &pItem->type;
4041 else
4042 pType = (WORD*)(pBlk + pItem->type);
4044 if (pItem->flags & ~0xda)
4045 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4047 SLTG_DoElem(pType, pBlk,
4048 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4050 if (TRACE_ON(typelib)) {
4051 char buf[300];
4052 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4053 TRACE_(typelib)("elemdescVar: %s\n", buf);
4056 if (pItem->flags & 0x40) {
4057 TRACE_(typelib)("VAR_DISPATCH\n");
4058 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4060 else if (pItem->flags & 0x10) {
4061 TRACE_(typelib)("VAR_CONST\n");
4062 pVarDesc->vardesc.varkind = VAR_CONST;
4063 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4064 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4065 if (pItem->flags & 0x08)
4066 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4067 else {
4068 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4070 case VT_LPSTR:
4071 case VT_LPWSTR:
4072 case VT_BSTR:
4074 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4075 BSTR str;
4076 TRACE_(typelib)("len = %u\n", len);
4077 if (len == 0xffff) {
4078 str = NULL;
4079 } else {
4080 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4081 str = SysAllocStringLen(NULL, alloc_len);
4082 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4084 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4085 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4086 break;
4088 case VT_I2:
4089 case VT_UI2:
4090 case VT_I4:
4091 case VT_UI4:
4092 case VT_INT:
4093 case VT_UINT:
4094 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4095 *(INT*)(pBlk + pItem->byte_offs);
4096 break;
4097 default:
4098 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4102 else {
4103 TRACE_(typelib)("VAR_PERINSTANCE\n");
4104 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4105 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4108 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4109 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4111 if (pItem->flags & 0x80)
4112 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4114 prevName = pVarDesc->Name;
4116 pTI->typeattr.cVars = cVars;
4119 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4120 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4122 SLTG_Function *pFunc;
4123 unsigned short i;
4124 TLBFuncDesc *pFuncDesc;
4126 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4128 pFuncDesc = pTI->funcdescs;
4129 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4130 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4132 int param;
4133 WORD *pType, *pArg;
4135 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4136 case SLTG_FUNCTION_MAGIC:
4137 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4138 break;
4139 case SLTG_DISPATCH_FUNCTION_MAGIC:
4140 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4141 break;
4142 case SLTG_STATIC_FUNCTION_MAGIC:
4143 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4144 break;
4145 default:
4146 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4147 continue;
4149 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4151 pFuncDesc->funcdesc.memid = pFunc->dispid;
4152 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4153 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4154 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4155 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4156 if (pFuncDesc->funcdesc.funckind == FUNC_DISPATCH)
4157 pFuncDesc->funcdesc.oVft = 0;
4158 else
4159 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4161 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4162 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4164 if(pFunc->retnextopt & 0x80)
4165 pType = &pFunc->rettype;
4166 else
4167 pType = (WORD*)(pBlk + pFunc->rettype);
4169 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4171 pFuncDesc->funcdesc.lprgelemdescParam =
4172 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4173 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4175 pArg = (WORD*)(pBlk + pFunc->arg_off);
4177 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4178 char *paramName = pNameTable + *pArg;
4179 BOOL HaveOffs;
4180 /* If arg type follows then paramName points to the 2nd
4181 letter of the name, else the next WORD is an offset to
4182 the arg type and paramName points to the first letter.
4183 So let's take one char off paramName and see if we're
4184 pointing at an alphanumeric char. However if *pArg is
4185 0xffff or 0xfffe then the param has no name, the former
4186 meaning that the next WORD is the type, the latter
4187 meaning that the next WORD is an offset to the type. */
4189 HaveOffs = FALSE;
4190 if(*pArg == 0xffff)
4191 paramName = NULL;
4192 else if(*pArg == 0xfffe) {
4193 paramName = NULL;
4194 HaveOffs = TRUE;
4196 else if(paramName[-1] && !isalnum(paramName[-1]))
4197 HaveOffs = TRUE;
4199 pArg++;
4201 if(HaveOffs) { /* the next word is an offset to type */
4202 pType = (WORD*)(pBlk + *pArg);
4203 SLTG_DoElem(pType, pBlk,
4204 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4205 pArg++;
4206 } else {
4207 if(paramName)
4208 paramName--;
4209 pArg = SLTG_DoElem(pArg, pBlk,
4210 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4213 /* Are we an optional param ? */
4214 if(pFuncDesc->funcdesc.cParams - param <=
4215 pFuncDesc->funcdesc.cParamsOpt)
4216 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4218 if(paramName) {
4219 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4220 paramName - pNameTable, pTI->pTypeLib);
4221 } else {
4222 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4226 pTI->typeattr.cFuncs = cFuncs;
4229 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4230 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4231 SLTG_TypeInfoTail *pTITail)
4233 char *pFirstItem;
4234 sltg_ref_lookup_t *ref_lookup = NULL;
4236 if(pTIHeader->href_table != 0xffffffff) {
4237 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4238 pNameTable);
4241 pFirstItem = pBlk;
4243 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4244 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4246 heap_free(ref_lookup);
4250 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4251 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4252 const SLTG_TypeInfoTail *pTITail)
4254 char *pFirstItem;
4255 sltg_ref_lookup_t *ref_lookup = NULL;
4257 if(pTIHeader->href_table != 0xffffffff) {
4258 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4259 pNameTable);
4262 pFirstItem = pBlk;
4264 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4265 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4268 if (pTITail->funcs_off != 0xffff)
4269 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4271 heap_free(ref_lookup);
4273 if (TRACE_ON(typelib))
4274 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4277 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4278 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4279 const SLTG_TypeInfoTail *pTITail)
4281 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4284 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4285 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4286 const SLTG_TypeInfoTail *pTITail)
4288 WORD *pType;
4289 sltg_ref_lookup_t *ref_lookup = NULL;
4291 if (pTITail->simple_alias) {
4292 /* if simple alias, no more processing required */
4293 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4294 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4295 return;
4298 if(pTIHeader->href_table != 0xffffffff) {
4299 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4300 pNameTable);
4303 /* otherwise it is an offset to a type */
4304 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4306 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4307 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4309 heap_free(ref_lookup);
4312 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4313 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4314 const SLTG_TypeInfoTail *pTITail)
4316 sltg_ref_lookup_t *ref_lookup = NULL;
4317 if (pTIHeader->href_table != 0xffffffff)
4318 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4319 pNameTable);
4321 if (pTITail->vars_off != 0xffff)
4322 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4324 if (pTITail->funcs_off != 0xffff)
4325 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4327 if (pTITail->impls_off != 0xffff)
4328 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4330 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4331 * of dispinterface functions including the IDispatch ones, so
4332 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4333 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4335 heap_free(ref_lookup);
4336 if (TRACE_ON(typelib))
4337 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4340 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4341 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4342 const SLTG_TypeInfoTail *pTITail)
4344 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4347 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4348 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4349 const SLTG_TypeInfoTail *pTITail)
4351 sltg_ref_lookup_t *ref_lookup = NULL;
4352 if (pTIHeader->href_table != 0xffffffff)
4353 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4354 pNameTable);
4356 if (pTITail->vars_off != 0xffff)
4357 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4359 if (pTITail->funcs_off != 0xffff)
4360 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4361 heap_free(ref_lookup);
4362 if (TRACE_ON(typelib))
4363 dump_TypeInfo(pTI);
4366 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4367 manageable copy of it into this */
4368 typedef struct {
4369 WORD small_no;
4370 char *index_name;
4371 char *other_name;
4372 WORD res1a;
4373 WORD name_offs;
4374 WORD more_bytes;
4375 char *extra;
4376 WORD res20;
4377 DWORD helpcontext;
4378 WORD res26;
4379 GUID uuid;
4380 } SLTG_InternalOtherTypeInfo;
4382 /****************************************************************************
4383 * ITypeLib2_Constructor_SLTG
4385 * loading a SLTG typelib from an in-memory image
4387 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4389 ITypeLibImpl *pTypeLibImpl;
4390 SLTG_Header *pHeader;
4391 SLTG_BlkEntry *pBlkEntry;
4392 SLTG_Magic *pMagic;
4393 SLTG_Index *pIndex;
4394 SLTG_Pad9 *pPad9;
4395 LPVOID pBlk, pFirstBlk;
4396 SLTG_LibBlk *pLibBlk;
4397 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4398 char *pAfterOTIBlks = NULL;
4399 char *pNameTable, *ptr;
4400 int i;
4401 DWORD len, order;
4402 ITypeInfoImpl **ppTypeInfoImpl;
4404 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4407 pTypeLibImpl = TypeLibImpl_Constructor();
4408 if (!pTypeLibImpl) return NULL;
4410 pHeader = pLib;
4412 TRACE_(typelib)("header:\n");
4413 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4414 pHeader->nrOfFileBlks );
4415 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4416 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4417 pHeader->SLTG_magic);
4418 return NULL;
4421 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4422 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4424 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4425 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4427 /* Next we have a magic block */
4428 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4430 /* Let's see if we're still in sync */
4431 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4432 sizeof(SLTG_COMPOBJ_MAGIC))) {
4433 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4434 return NULL;
4436 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4437 sizeof(SLTG_DIR_MAGIC))) {
4438 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4439 return NULL;
4442 pIndex = (SLTG_Index*)(pMagic+1);
4444 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4446 pFirstBlk = pPad9 + 1;
4448 /* We'll set up a ptr to the main library block, which is the last one. */
4450 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4451 pBlkEntry[order].next != 0;
4452 order = pBlkEntry[order].next - 1) {
4453 pBlk = (char*)pBlk + pBlkEntry[order].len;
4455 pLibBlk = pBlk;
4457 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4459 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4460 interspersed */
4462 len += 0x40;
4464 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4466 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4469 ptr = (char*)pLibBlk + len;
4471 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4472 WORD w, extra;
4473 len = 0;
4475 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4477 w = *(WORD*)(ptr + 2);
4478 if(w != 0xffff) {
4479 len += w;
4480 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4481 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4482 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4484 w = *(WORD*)(ptr + 4 + len);
4485 if(w != 0xffff) {
4486 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4487 len += w;
4488 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4489 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4490 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4492 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4493 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4494 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4495 if(extra) {
4496 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4497 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4498 len += extra;
4500 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4501 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4502 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4503 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4504 len += sizeof(SLTG_OtherTypeInfo);
4505 ptr += len;
4508 pAfterOTIBlks = ptr;
4510 /* Skip this WORD and get the next DWORD */
4511 len = *(DWORD*)(pAfterOTIBlks + 2);
4513 /* Now add this to pLibBLk look at what we're pointing at and
4514 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4515 dust and we should be pointing at the beginning of the name
4516 table */
4518 pNameTable = (char*)pLibBlk + len;
4520 switch(*(WORD*)pNameTable) {
4521 case 0xffff:
4522 break;
4523 case 0x0200:
4524 pNameTable += 0x20;
4525 break;
4526 default:
4527 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4528 break;
4531 pNameTable += 0x216;
4533 pNameTable += 2;
4535 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4537 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4540 /* Hopefully we now have enough ptrs set up to actually read in
4541 some TypeInfos. It's not clear which order to do them in, so
4542 I'll just follow the links along the BlkEntry chain and read
4543 them in the order in which they are in the file */
4545 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4546 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4548 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4549 pBlkEntry[order].next != 0;
4550 order = pBlkEntry[order].next - 1, i++) {
4552 SLTG_TypeInfoHeader *pTIHeader;
4553 SLTG_TypeInfoTail *pTITail;
4554 SLTG_MemberHeader *pMemHeader;
4556 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4557 FIXME_(typelib)("Index strings don't match\n");
4558 heap_free(pOtherTypeInfoBlks);
4559 return NULL;
4562 pTIHeader = pBlk;
4563 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4564 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4565 heap_free(pOtherTypeInfoBlks);
4566 return NULL;
4568 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4569 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4570 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4572 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4573 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4574 (*ppTypeInfoImpl)->index = i;
4575 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4576 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4577 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4578 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4579 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4580 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4581 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4582 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4584 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4585 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4587 if((pTIHeader->typeflags1 & 7) != 2)
4588 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4589 if(pTIHeader->typeflags3 != 2)
4590 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4592 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4593 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4594 typekind_desc[pTIHeader->typekind],
4595 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4596 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4598 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4600 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4602 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4603 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4604 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4606 switch(pTIHeader->typekind) {
4607 case TKIND_ENUM:
4608 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4609 pTIHeader, pTITail);
4610 break;
4612 case TKIND_RECORD:
4613 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4614 pTIHeader, pTITail);
4615 break;
4617 case TKIND_INTERFACE:
4618 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4619 pTIHeader, pTITail);
4620 break;
4622 case TKIND_COCLASS:
4623 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4624 pTIHeader, pTITail);
4625 break;
4627 case TKIND_ALIAS:
4628 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4629 pTIHeader, pTITail);
4630 break;
4632 case TKIND_DISPATCH:
4633 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4634 pTIHeader, pTITail);
4635 break;
4637 case TKIND_MODULE:
4638 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4639 pTIHeader, pTITail);
4640 break;
4642 default:
4643 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4644 break;
4648 /* could get cFuncs, cVars and cImplTypes from here
4649 but we've already set those */
4650 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4651 X(06);
4652 X(16);
4653 X(18);
4654 X(1a);
4655 X(1e);
4656 X(24);
4657 X(26);
4658 X(2a);
4659 X(2c);
4660 X(2e);
4661 X(30);
4662 X(32);
4663 X(34);
4664 #undef X
4665 ++ppTypeInfoImpl;
4666 pBlk = (char*)pBlk + pBlkEntry[order].len;
4669 if(i != pTypeLibImpl->TypeInfoCount) {
4670 FIXME("Somehow processed %d TypeInfos\n", i);
4671 heap_free(pOtherTypeInfoBlks);
4672 return NULL;
4675 heap_free(pOtherTypeInfoBlks);
4676 return &pTypeLibImpl->ITypeLib2_iface;
4679 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4681 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4683 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4685 if(IsEqualIID(riid, &IID_IUnknown) ||
4686 IsEqualIID(riid,&IID_ITypeLib)||
4687 IsEqualIID(riid,&IID_ITypeLib2))
4689 *ppv = &This->ITypeLib2_iface;
4691 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4692 IsEqualIID(riid, &IID_ICreateTypeLib2))
4694 *ppv = &This->ICreateTypeLib2_iface;
4696 else
4698 *ppv = NULL;
4699 TRACE("-- Interface: E_NOINTERFACE\n");
4700 return E_NOINTERFACE;
4703 IUnknown_AddRef((IUnknown*)*ppv);
4704 return S_OK;
4707 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4709 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4710 ULONG ref = InterlockedIncrement(&This->ref);
4712 TRACE("(%p) ref=%u\n", This, ref);
4714 return ref;
4717 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4719 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4720 ULONG ref = InterlockedDecrement(&This->ref);
4722 TRACE("(%p) ref=%u\n",This, ref);
4724 if (!ref)
4726 TLBImpLib *pImpLib, *pImpLibNext;
4727 TLBRefType *ref_type, *ref_type_next;
4728 TLBString *tlbstr, *tlbstr_next;
4729 TLBGuid *tlbguid, *tlbguid_next;
4730 int i;
4732 /* remove cache entry */
4733 if(This->path)
4735 TRACE("removing from cache list\n");
4736 EnterCriticalSection(&cache_section);
4737 if(This->entry.next)
4738 list_remove(&This->entry);
4739 LeaveCriticalSection(&cache_section);
4740 heap_free(This->path);
4742 TRACE(" destroying ITypeLib(%p)\n",This);
4744 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4745 list_remove(&tlbstr->entry);
4746 SysFreeString(tlbstr->str);
4747 heap_free(tlbstr);
4750 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4751 list_remove(&tlbstr->entry);
4752 SysFreeString(tlbstr->str);
4753 heap_free(tlbstr);
4756 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4757 list_remove(&tlbguid->entry);
4758 heap_free(tlbguid);
4761 TLB_FreeCustData(&This->custdata_list);
4763 for (i = 0; i < This->ctTypeDesc; i++)
4764 if (This->pTypeDesc[i].vt == VT_CARRAY)
4765 heap_free(This->pTypeDesc[i].u.lpadesc);
4767 heap_free(This->pTypeDesc);
4769 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4771 if (pImpLib->pImpTypeLib)
4772 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4773 SysFreeString(pImpLib->name);
4775 list_remove(&pImpLib->entry);
4776 heap_free(pImpLib);
4779 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4781 list_remove(&ref_type->entry);
4782 heap_free(ref_type);
4785 for (i = 0; i < This->TypeInfoCount; ++i){
4786 heap_free(This->typeinfos[i]->tdescAlias);
4787 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4789 heap_free(This->typeinfos);
4790 heap_free(This);
4791 return 0;
4794 return ref;
4797 /* ITypeLib::GetTypeInfoCount
4799 * Returns the number of type descriptions in the type library
4801 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4803 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4804 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4805 return This->TypeInfoCount;
4808 /* ITypeLib::GetTypeInfo
4810 * retrieves the specified type description in the library.
4812 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4813 ITypeLib2 *iface,
4814 UINT index,
4815 ITypeInfo **ppTInfo)
4817 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4819 TRACE("%p %u %p\n", This, index, ppTInfo);
4821 if(!ppTInfo)
4822 return E_INVALIDARG;
4824 if(index >= This->TypeInfoCount)
4825 return TYPE_E_ELEMENTNOTFOUND;
4827 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4828 ITypeInfo_AddRef(*ppTInfo);
4830 return S_OK;
4834 /* ITypeLibs::GetTypeInfoType
4836 * Retrieves the type of a type description.
4838 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4839 ITypeLib2 *iface,
4840 UINT index,
4841 TYPEKIND *pTKind)
4843 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4845 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4847 if(!pTKind)
4848 return E_INVALIDARG;
4850 if(index >= This->TypeInfoCount)
4851 return TYPE_E_ELEMENTNOTFOUND;
4853 *pTKind = This->typeinfos[index]->typeattr.typekind;
4855 return S_OK;
4858 /* ITypeLib::GetTypeInfoOfGuid
4860 * Retrieves the type description that corresponds to the specified GUID.
4863 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4864 ITypeLib2 *iface,
4865 REFGUID guid,
4866 ITypeInfo **ppTInfo)
4868 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4869 int i;
4871 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4873 for(i = 0; i < This->TypeInfoCount; ++i){
4874 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4875 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4876 ITypeInfo_AddRef(*ppTInfo);
4877 return S_OK;
4881 return TYPE_E_ELEMENTNOTFOUND;
4884 /* ITypeLib::GetLibAttr
4886 * Retrieves the structure that contains the library's attributes.
4889 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4890 ITypeLib2 *iface,
4891 LPTLIBATTR *attr)
4893 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4895 TRACE("(%p, %p)\n", This, attr);
4897 if (!attr) return E_INVALIDARG;
4899 *attr = heap_alloc(sizeof(**attr));
4900 if (!*attr) return E_OUTOFMEMORY;
4902 (*attr)->guid = *TLB_get_guid_null(This->guid);
4903 (*attr)->lcid = This->set_lcid;
4904 (*attr)->syskind = This->syskind;
4905 (*attr)->wMajorVerNum = This->ver_major;
4906 (*attr)->wMinorVerNum = This->ver_minor;
4907 (*attr)->wLibFlags = This->libflags;
4909 return S_OK;
4912 /* ITypeLib::GetTypeComp
4914 * Enables a client compiler to bind to a library's types, variables,
4915 * constants, and global functions.
4918 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4919 ITypeLib2 *iface,
4920 ITypeComp **ppTComp)
4922 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4924 TRACE("(%p)->(%p)\n",This,ppTComp);
4925 *ppTComp = &This->ITypeComp_iface;
4926 ITypeComp_AddRef(*ppTComp);
4928 return S_OK;
4931 /* ITypeLib::GetDocumentation
4933 * Retrieves the library's documentation string, the complete Help file name
4934 * and path, and the context identifier for the library Help topic in the Help
4935 * file.
4937 * On a successful return all non-null BSTR pointers will have been set,
4938 * possibly to NULL.
4940 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4941 ITypeLib2 *iface,
4942 INT index,
4943 BSTR *pBstrName,
4944 BSTR *pBstrDocString,
4945 DWORD *pdwHelpContext,
4946 BSTR *pBstrHelpFile)
4948 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4949 HRESULT result = E_INVALIDARG;
4950 ITypeInfo *pTInfo;
4952 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4953 This, index,
4954 pBstrName, pBstrDocString,
4955 pdwHelpContext, pBstrHelpFile);
4957 if(index<0)
4959 /* documentation for the typelib */
4960 if(pBstrName)
4962 if (This->Name)
4964 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4965 goto memerr1;
4967 else
4968 *pBstrName = NULL;
4970 if(pBstrDocString)
4972 if (This->DocString)
4974 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4975 goto memerr2;
4977 else
4978 *pBstrDocString = NULL;
4980 if(pdwHelpContext)
4982 *pdwHelpContext = This->dwHelpContext;
4984 if(pBstrHelpFile)
4986 if (This->HelpFile)
4988 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4989 goto memerr3;
4991 else
4992 *pBstrHelpFile = NULL;
4995 result = S_OK;
4997 else
4999 /* for a typeinfo */
5000 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5002 if(SUCCEEDED(result))
5004 result = ITypeInfo_GetDocumentation(pTInfo,
5005 MEMBERID_NIL,
5006 pBstrName,
5007 pBstrDocString,
5008 pdwHelpContext, pBstrHelpFile);
5010 ITypeInfo_Release(pTInfo);
5013 return result;
5014 memerr3:
5015 if (pBstrDocString) SysFreeString (*pBstrDocString);
5016 memerr2:
5017 if (pBstrName) SysFreeString (*pBstrName);
5018 memerr1:
5019 return STG_E_INSUFFICIENTMEMORY;
5022 /* ITypeLib::IsName
5024 * Indicates whether a passed-in string contains the name of a type or member
5025 * described in the library.
5028 static HRESULT WINAPI ITypeLib2_fnIsName(
5029 ITypeLib2 *iface,
5030 LPOLESTR szNameBuf,
5031 ULONG lHashVal,
5032 BOOL *pfName)
5034 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5035 int tic;
5036 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5038 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5039 pfName);
5041 *pfName=TRUE;
5042 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5043 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5044 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5045 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5046 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5047 int pc;
5048 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5049 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5050 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5051 goto ITypeLib2_fnIsName_exit;
5054 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5055 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5056 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5060 *pfName=FALSE;
5062 ITypeLib2_fnIsName_exit:
5063 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5064 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5066 return S_OK;
5069 /* ITypeLib::FindName
5071 * Finds occurrences of a type description in a type library. This may be used
5072 * to quickly verify that a name exists in a type library.
5075 static HRESULT WINAPI ITypeLib2_fnFindName(
5076 ITypeLib2 *iface,
5077 LPOLESTR name,
5078 ULONG hash,
5079 ITypeInfo **ppTInfo,
5080 MEMBERID *memid,
5081 UINT16 *found)
5083 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5084 int tic;
5085 UINT count = 0;
5086 UINT len;
5088 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5090 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5091 return E_INVALIDARG;
5093 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5094 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5095 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5096 TLBVarDesc *var;
5097 UINT fdc;
5099 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5100 memid[count] = MEMBERID_NIL;
5101 goto ITypeLib2_fnFindName_exit;
5104 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5105 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5107 if(!TLB_str_memcmp(name, func->Name, len)) {
5108 memid[count] = func->funcdesc.memid;
5109 goto ITypeLib2_fnFindName_exit;
5113 var = TLB_get_vardesc_by_name(pTInfo, name);
5114 if (var) {
5115 memid[count] = var->vardesc.memid;
5116 goto ITypeLib2_fnFindName_exit;
5119 continue;
5120 ITypeLib2_fnFindName_exit:
5121 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5122 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5123 count++;
5125 TRACE("found %d typeinfos\n", count);
5127 *found = count;
5129 return S_OK;
5132 /* ITypeLib::ReleaseTLibAttr
5134 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5137 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5138 ITypeLib2 *iface,
5139 TLIBATTR *pTLibAttr)
5141 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5142 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5143 heap_free(pTLibAttr);
5146 /* ITypeLib2::GetCustData
5148 * gets the custom data
5150 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5151 ITypeLib2 * iface,
5152 REFGUID guid,
5153 VARIANT *pVarVal)
5155 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5156 TLBCustData *pCData;
5158 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5160 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5161 if(!pCData)
5162 return TYPE_E_ELEMENTNOTFOUND;
5164 VariantInit(pVarVal);
5165 VariantCopy(pVarVal, &pCData->data);
5167 return S_OK;
5170 /* ITypeLib2::GetLibStatistics
5172 * Returns statistics about a type library that are required for efficient
5173 * sizing of hash tables.
5176 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5177 ITypeLib2 * iface,
5178 ULONG *pcUniqueNames,
5179 ULONG *pcchUniqueNames)
5181 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5183 FIXME("(%p): stub!\n", This);
5185 if(pcUniqueNames) *pcUniqueNames=1;
5186 if(pcchUniqueNames) *pcchUniqueNames=1;
5187 return S_OK;
5190 /* ITypeLib2::GetDocumentation2
5192 * Retrieves the library's documentation string, the complete Help file name
5193 * and path, the localization context to use, and the context ID for the
5194 * library Help topic in the Help file.
5197 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5198 ITypeLib2 * iface,
5199 INT index,
5200 LCID lcid,
5201 BSTR *pbstrHelpString,
5202 DWORD *pdwHelpStringContext,
5203 BSTR *pbstrHelpStringDll)
5205 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5206 HRESULT result;
5207 ITypeInfo *pTInfo;
5209 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5211 /* the help string should be obtained from the helpstringdll,
5212 * using the _DLLGetDocumentation function, based on the supplied
5213 * lcid. Nice to do sometime...
5215 if(index<0)
5217 /* documentation for the typelib */
5218 if(pbstrHelpString)
5219 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5220 if(pdwHelpStringContext)
5221 *pdwHelpStringContext=This->dwHelpContext;
5222 if(pbstrHelpStringDll)
5223 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5225 result = S_OK;
5227 else
5229 /* for a typeinfo */
5230 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5232 if(SUCCEEDED(result))
5234 ITypeInfo2 * pTInfo2;
5235 result = ITypeInfo_QueryInterface(pTInfo,
5236 &IID_ITypeInfo2,
5237 (LPVOID*) &pTInfo2);
5239 if(SUCCEEDED(result))
5241 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5242 MEMBERID_NIL,
5243 lcid,
5244 pbstrHelpString,
5245 pdwHelpStringContext,
5246 pbstrHelpStringDll);
5248 ITypeInfo2_Release(pTInfo2);
5251 ITypeInfo_Release(pTInfo);
5254 return result;
5257 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5259 TLBCustData *pCData;
5260 unsigned int ct;
5261 CUSTDATAITEM *cdi;
5262 HRESULT hr = S_OK;
5264 ct = list_count(custdata_list);
5266 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5267 if(!pCustData->prgCustData)
5268 return E_OUTOFMEMORY;
5270 pCustData->cCustData = ct;
5272 cdi = pCustData->prgCustData;
5273 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5274 cdi->guid = *TLB_get_guid_null(pCData->guid);
5275 VariantInit(&cdi->varValue);
5276 hr = VariantCopy(&cdi->varValue, &pCData->data);
5277 if(FAILED(hr)) break;
5278 ++cdi;
5281 return hr;
5285 /* ITypeLib2::GetAllCustData
5287 * Gets all custom data items for the library.
5290 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5291 ITypeLib2 * iface,
5292 CUSTDATA *pCustData)
5294 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5295 TRACE("(%p)->(%p)\n", This, pCustData);
5296 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5299 static const ITypeLib2Vtbl tlbvt = {
5300 ITypeLib2_fnQueryInterface,
5301 ITypeLib2_fnAddRef,
5302 ITypeLib2_fnRelease,
5303 ITypeLib2_fnGetTypeInfoCount,
5304 ITypeLib2_fnGetTypeInfo,
5305 ITypeLib2_fnGetTypeInfoType,
5306 ITypeLib2_fnGetTypeInfoOfGuid,
5307 ITypeLib2_fnGetLibAttr,
5308 ITypeLib2_fnGetTypeComp,
5309 ITypeLib2_fnGetDocumentation,
5310 ITypeLib2_fnIsName,
5311 ITypeLib2_fnFindName,
5312 ITypeLib2_fnReleaseTLibAttr,
5314 ITypeLib2_fnGetCustData,
5315 ITypeLib2_fnGetLibStatistics,
5316 ITypeLib2_fnGetDocumentation2,
5317 ITypeLib2_fnGetAllCustData
5321 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5323 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5325 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5328 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5330 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5332 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5335 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5337 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5339 return ITypeLib2_Release(&This->ITypeLib2_iface);
5342 static HRESULT WINAPI ITypeLibComp_fnBind(
5343 ITypeComp * iface,
5344 OLECHAR * szName,
5345 ULONG lHash,
5346 WORD wFlags,
5347 ITypeInfo ** ppTInfo,
5348 DESCKIND * pDescKind,
5349 BINDPTR * pBindPtr)
5351 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5352 BOOL typemismatch = FALSE;
5353 int i;
5355 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5357 *pDescKind = DESCKIND_NONE;
5358 pBindPtr->lptcomp = NULL;
5359 *ppTInfo = NULL;
5361 for(i = 0; i < This->TypeInfoCount; ++i){
5362 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5363 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5365 /* FIXME: check wFlags here? */
5366 /* FIXME: we should use a hash table to look this info up using lHash
5367 * instead of an O(n) search */
5368 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5369 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5371 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5373 *pDescKind = DESCKIND_TYPECOMP;
5374 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5375 ITypeComp_AddRef(pBindPtr->lptcomp);
5376 TRACE("module or enum: %s\n", debugstr_w(szName));
5377 return S_OK;
5381 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5382 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5384 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5385 HRESULT hr;
5387 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5388 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5390 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5391 return S_OK;
5393 else if (hr == TYPE_E_TYPEMISMATCH)
5394 typemismatch = TRUE;
5397 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5398 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5400 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5401 HRESULT hr;
5402 ITypeInfo *subtypeinfo;
5403 BINDPTR subbindptr;
5404 DESCKIND subdesckind;
5406 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5407 &subtypeinfo, &subdesckind, &subbindptr);
5408 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5410 TYPEDESC tdesc_appobject;
5411 const VARDESC vardesc_appobject =
5413 -2, /* memid */
5414 NULL, /* lpstrSchema */
5416 0 /* oInst */
5419 /* ELEMDESC */
5421 /* TYPEDESC */
5423 &tdesc_appobject
5425 VT_PTR
5428 0, /* wVarFlags */
5429 VAR_STATIC /* varkind */
5432 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5433 tdesc_appobject.vt = VT_USERDEFINED;
5435 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5437 /* cleanup things filled in by Bind call so we can put our
5438 * application object data in there instead */
5439 switch (subdesckind)
5441 case DESCKIND_FUNCDESC:
5442 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5443 break;
5444 case DESCKIND_VARDESC:
5445 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5446 break;
5447 default:
5448 break;
5450 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5452 if (pTypeInfo->hreftype == -1)
5453 FIXME("no hreftype for interface %p\n", pTypeInfo);
5455 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5456 if (FAILED(hr))
5457 return hr;
5459 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5460 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5461 ITypeInfo_AddRef(*ppTInfo);
5462 return S_OK;
5464 else if (hr == TYPE_E_TYPEMISMATCH)
5465 typemismatch = TRUE;
5469 if (typemismatch)
5471 TRACE("type mismatch %s\n", debugstr_w(szName));
5472 return TYPE_E_TYPEMISMATCH;
5474 else
5476 TRACE("name not found %s\n", debugstr_w(szName));
5477 return S_OK;
5481 static HRESULT WINAPI ITypeLibComp_fnBindType(
5482 ITypeComp * iface,
5483 OLECHAR * szName,
5484 ULONG lHash,
5485 ITypeInfo ** ppTInfo,
5486 ITypeComp ** ppTComp)
5488 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5489 ITypeInfoImpl *info;
5491 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5493 if(!szName || !ppTInfo || !ppTComp)
5494 return E_INVALIDARG;
5496 info = TLB_get_typeinfo_by_name(This, szName);
5497 if(!info){
5498 *ppTInfo = NULL;
5499 *ppTComp = NULL;
5500 return S_OK;
5503 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5504 ITypeInfo_AddRef(*ppTInfo);
5505 *ppTComp = &info->ITypeComp_iface;
5506 ITypeComp_AddRef(*ppTComp);
5508 return S_OK;
5511 static const ITypeCompVtbl tlbtcvt =
5514 ITypeLibComp_fnQueryInterface,
5515 ITypeLibComp_fnAddRef,
5516 ITypeLibComp_fnRelease,
5518 ITypeLibComp_fnBind,
5519 ITypeLibComp_fnBindType
5522 /*================== ITypeInfo(2) Methods ===================================*/
5523 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5525 ITypeInfoImpl *pTypeInfoImpl;
5527 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5528 if (pTypeInfoImpl)
5530 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5531 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5532 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5533 pTypeInfoImpl->ref = 0;
5534 pTypeInfoImpl->hreftype = -1;
5535 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5536 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5537 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5538 list_init(pTypeInfoImpl->pcustdata_list);
5540 TRACE("(%p)\n", pTypeInfoImpl);
5541 return pTypeInfoImpl;
5544 /* ITypeInfo::QueryInterface
5546 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5547 ITypeInfo2 *iface,
5548 REFIID riid,
5549 VOID **ppvObject)
5551 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5553 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5555 *ppvObject=NULL;
5556 if(IsEqualIID(riid, &IID_IUnknown) ||
5557 IsEqualIID(riid,&IID_ITypeInfo)||
5558 IsEqualIID(riid,&IID_ITypeInfo2))
5559 *ppvObject = &This->ITypeInfo2_iface;
5560 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5561 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5562 *ppvObject = &This->ICreateTypeInfo2_iface;
5563 else if(IsEqualIID(riid, &IID_ITypeComp))
5564 *ppvObject = &This->ITypeComp_iface;
5566 if(*ppvObject){
5567 IUnknown_AddRef((IUnknown*)*ppvObject);
5568 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5569 return S_OK;
5571 TRACE("-- Interface: E_NOINTERFACE\n");
5572 return E_NOINTERFACE;
5575 /* ITypeInfo::AddRef
5577 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5579 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5580 ULONG ref = InterlockedIncrement(&This->ref);
5582 TRACE("(%p)->ref is %u\n",This, ref);
5584 if (ref == 1 /* incremented from 0 */)
5585 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5587 return ref;
5590 static void typeinfo_release_funcdesc(TLBFuncDesc *func)
5592 unsigned int i;
5594 for (i = 0; i < func->funcdesc.cParams; ++i)
5596 ELEMDESC *elemdesc = &func->funcdesc.lprgelemdescParam[i];
5597 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5598 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5599 TLB_FreeCustData(&func->pParamDesc[i].custdata_list);
5601 heap_free(func->funcdesc.lprgelemdescParam);
5602 heap_free(func->pParamDesc);
5603 TLB_FreeCustData(&func->custdata_list);
5606 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5608 UINT i;
5610 TRACE("destroying ITypeInfo(%p)\n",This);
5612 for (i = 0; i < This->typeattr.cFuncs; ++i)
5614 typeinfo_release_funcdesc(&This->funcdescs[i]);
5616 heap_free(This->funcdescs);
5618 for(i = 0; i < This->typeattr.cVars; ++i)
5620 TLBVarDesc *pVInfo = &This->vardescs[i];
5621 if (pVInfo->vardesc_create) {
5622 TLB_FreeVarDesc(pVInfo->vardesc_create);
5623 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5624 VariantClear(pVInfo->vardesc.u.lpvarValue);
5625 heap_free(pVInfo->vardesc.u.lpvarValue);
5627 TLB_FreeCustData(&pVInfo->custdata_list);
5629 heap_free(This->vardescs);
5631 if(This->impltypes){
5632 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5633 TLBImplType *pImpl = &This->impltypes[i];
5634 TLB_FreeCustData(&pImpl->custdata_list);
5636 heap_free(This->impltypes);
5639 TLB_FreeCustData(&This->custdata_list);
5641 heap_free(This);
5644 /* ITypeInfo::Release
5646 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5648 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5649 ULONG ref = InterlockedDecrement(&This->ref);
5651 TRACE("(%p)->(%u)\n",This, ref);
5653 if (!ref)
5655 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5656 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5657 if (not_attached_to_typelib)
5658 heap_free(This);
5659 /* otherwise This will be freed when typelib is freed */
5662 return ref;
5665 /* ITypeInfo::GetTypeAttr
5667 * Retrieves a TYPEATTR structure that contains the attributes of the type
5668 * description.
5671 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5672 LPTYPEATTR *ppTypeAttr)
5674 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5675 SIZE_T size;
5677 TRACE("(%p)\n",This);
5679 size = sizeof(**ppTypeAttr);
5680 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5681 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5683 *ppTypeAttr = heap_alloc(size);
5684 if (!*ppTypeAttr)
5685 return E_OUTOFMEMORY;
5687 **ppTypeAttr = This->typeattr;
5688 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5690 if (This->tdescAlias)
5691 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5693 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5694 /* This should include all the inherited funcs */
5695 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5696 /* This is always the size of IDispatch's vtbl */
5697 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5698 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5700 return S_OK;
5703 /* ITypeInfo::GetTypeComp
5705 * Retrieves the ITypeComp interface for the type description, which enables a
5706 * client compiler to bind to the type description's members.
5709 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5710 ITypeComp * *ppTComp)
5712 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5714 TRACE("(%p)->(%p)\n", This, ppTComp);
5716 *ppTComp = &This->ITypeComp_iface;
5717 ITypeComp_AddRef(*ppTComp);
5718 return S_OK;
5721 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5723 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5724 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5725 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5726 return size;
5729 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5731 *dest = *src;
5732 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5733 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5735 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5736 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5737 *buffer += sizeof(PARAMDESCEX);
5738 *pparamdescex_dest = *pparamdescex_src;
5739 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5740 VariantInit(&pparamdescex_dest->varDefaultValue);
5741 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5742 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5744 else
5745 dest->u.paramdesc.pparamdescex = NULL;
5746 return S_OK;
5749 static HRESULT TLB_SanitizeBSTR(BSTR str)
5751 UINT len = SysStringLen(str), i;
5752 for (i = 0; i < len; ++i)
5753 if (str[i] > 0x7f)
5754 str[i] = '?';
5755 return S_OK;
5758 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5760 if (V_VT(var) == VT_INT)
5761 return VariantChangeType(var, var, 0, VT_I4);
5762 else if (V_VT(var) == VT_UINT)
5763 return VariantChangeType(var, var, 0, VT_UI4);
5764 else if (V_VT(var) == VT_BSTR)
5765 return TLB_SanitizeBSTR(V_BSTR(var));
5767 return S_OK;
5770 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5772 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5773 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5776 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5778 FUNCDESC *dest;
5779 char *buffer;
5780 SIZE_T size = sizeof(*src);
5781 SHORT i;
5782 HRESULT hr;
5784 size += sizeof(*src->lprgscode) * src->cScodes;
5785 size += TLB_SizeElemDesc(&src->elemdescFunc);
5786 for (i = 0; i < src->cParams; i++)
5788 size += sizeof(ELEMDESC);
5789 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5792 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5793 if (!dest) return E_OUTOFMEMORY;
5795 *dest = *src;
5796 if (dispinterface) /* overwrite funckind */
5797 dest->funckind = FUNC_DISPATCH;
5798 buffer = (char *)(dest + 1);
5800 dest->oVft = dest->oVft & 0xFFFC;
5802 if (dest->cScodes) {
5803 dest->lprgscode = (SCODE *)buffer;
5804 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5805 buffer += sizeof(*src->lprgscode) * src->cScodes;
5806 } else
5807 dest->lprgscode = NULL;
5809 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5810 if (FAILED(hr))
5812 SysFreeString((BSTR)dest);
5813 return hr;
5816 if (dest->cParams) {
5817 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5818 buffer += sizeof(ELEMDESC) * src->cParams;
5819 for (i = 0; i < src->cParams; i++)
5821 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5822 if (FAILED(hr))
5823 break;
5825 if (FAILED(hr))
5827 /* undo the above actions */
5828 for (i = i - 1; i >= 0; i--)
5829 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5830 TLB_FreeElemDesc(&dest->elemdescFunc);
5831 SysFreeString((BSTR)dest);
5832 return hr;
5834 } else
5835 dest->lprgelemdescParam = NULL;
5837 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5838 * This accounts for several arguments that are separate in the signature of
5839 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5840 if (dispinterface && (src->funckind != FUNC_DISPATCH))
5842 /* functions that have a [retval] parameter return this value into pVarResult.
5843 * [retval] is always the last parameter (if present) */
5844 if (dest->cParams &&
5845 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5847 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5848 if (elemdesc->tdesc.vt != VT_PTR)
5850 ERR("elemdesc should have started with VT_PTR instead of:\n");
5851 if (ERR_ON(ole))
5852 dump_ELEMDESC(elemdesc);
5853 return E_UNEXPECTED;
5856 /* the type pointed to by this [retval] becomes elemdescFunc,
5857 * i.e. the function signature's return type.
5858 * We are using a flat buffer so there is no danger of leaking memory */
5859 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5861 /* remove the last parameter */
5862 dest->cParams--;
5864 else if (dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5865 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5866 * not pVarResult. So the function signature should show no return value. */
5867 dest->elemdescFunc.tdesc.vt = VT_VOID;
5869 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5870 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5871 if (dest->cParams && (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
5872 dest->cParams--;
5875 *dest_ptr = dest;
5876 return S_OK;
5879 static void TLB_FreeVarDesc(VARDESC *var_desc)
5881 TLB_FreeElemDesc(&var_desc->elemdescVar);
5882 if (var_desc->varkind == VAR_CONST)
5883 VariantClear(var_desc->u.lpvarValue);
5884 SysFreeString((BSTR)var_desc);
5887 /* internal function to make the inherited interfaces' methods appear
5888 * part of the interface */
5889 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5890 UINT index, const TLBFuncDesc **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5892 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5893 HRESULT hr;
5894 UINT implemented_funcs = 0;
5896 if (funcs)
5897 *funcs = 0;
5898 else
5899 *hrefoffset = DISPATCH_HREF_OFFSET;
5901 if(This->impltypes)
5903 ITypeInfo *pSubTypeInfo;
5904 UINT sub_funcs;
5906 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5907 if (FAILED(hr))
5908 return hr;
5910 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5911 index,
5912 ppFuncDesc,
5913 &sub_funcs, hrefoffset);
5914 implemented_funcs += sub_funcs;
5915 ITypeInfo_Release(pSubTypeInfo);
5916 if (SUCCEEDED(hr))
5917 return hr;
5918 *hrefoffset += DISPATCH_HREF_OFFSET;
5921 if (funcs)
5922 *funcs = implemented_funcs + This->typeattr.cFuncs;
5923 else
5924 *hrefoffset = 0;
5926 if (index < implemented_funcs)
5927 return E_INVALIDARG;
5928 index -= implemented_funcs;
5930 if (index >= This->typeattr.cFuncs)
5931 return TYPE_E_ELEMENTNOTFOUND;
5933 *ppFuncDesc = &This->funcdescs[index];
5934 return S_OK;
5937 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5939 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5941 if (This->typeattr.typekind == TKIND_DISPATCH)
5942 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5944 if (index >= This->typeattr.cFuncs)
5945 return TYPE_E_ELEMENTNOTFOUND;
5947 *func_desc = &This->funcdescs[index];
5948 return S_OK;
5951 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5953 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5954 while (TRUE)
5956 switch (pTypeDesc->vt)
5958 case VT_USERDEFINED:
5959 pTypeDesc->u.hreftype += hrefoffset;
5960 return;
5961 case VT_PTR:
5962 case VT_SAFEARRAY:
5963 pTypeDesc = pTypeDesc->u.lptdesc;
5964 break;
5965 case VT_CARRAY:
5966 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5967 break;
5968 default:
5969 return;
5974 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5976 SHORT i;
5977 for (i = 0; i < pFuncDesc->cParams; i++)
5978 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5979 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5982 /* ITypeInfo::GetFuncDesc
5984 * Retrieves the FUNCDESC structure that contains information about a
5985 * specified function.
5988 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5989 LPFUNCDESC *ppFuncDesc)
5991 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5992 const TLBFuncDesc *internal_funcdesc;
5993 HRESULT hr;
5994 UINT hrefoffset = 0;
5996 TRACE("(%p) index %d\n", This, index);
5998 if (!ppFuncDesc)
5999 return E_INVALIDARG;
6001 if (This->needs_layout)
6002 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6004 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6005 &internal_funcdesc, &hrefoffset);
6006 if (FAILED(hr))
6008 WARN("description for function %d not found\n", index);
6009 return hr;
6012 hr = TLB_AllocAndInitFuncDesc(
6013 &internal_funcdesc->funcdesc,
6014 ppFuncDesc,
6015 This->typeattr.typekind == TKIND_DISPATCH);
6017 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6018 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6020 TRACE("-- 0x%08x\n", hr);
6021 return hr;
6024 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6026 VARDESC *dest;
6027 char *buffer;
6028 SIZE_T size = sizeof(*src);
6029 HRESULT hr;
6031 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6032 if (src->varkind == VAR_CONST)
6033 size += sizeof(VARIANT);
6034 size += TLB_SizeElemDesc(&src->elemdescVar);
6036 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6037 if (!dest) return E_OUTOFMEMORY;
6039 *dest = *src;
6040 buffer = (char *)(dest + 1);
6041 if (src->lpstrSchema)
6043 int len;
6044 dest->lpstrSchema = (LPOLESTR)buffer;
6045 len = lstrlenW(src->lpstrSchema);
6046 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6047 buffer += (len + 1) * sizeof(WCHAR);
6050 if (src->varkind == VAR_CONST)
6052 HRESULT hr;
6054 dest->u.lpvarValue = (VARIANT *)buffer;
6055 *dest->u.lpvarValue = *src->u.lpvarValue;
6056 buffer += sizeof(VARIANT);
6057 VariantInit(dest->u.lpvarValue);
6058 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6059 if (FAILED(hr))
6061 SysFreeString((BSTR)dest);
6062 return hr;
6065 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6066 if (FAILED(hr))
6068 if (src->varkind == VAR_CONST)
6069 VariantClear(dest->u.lpvarValue);
6070 SysFreeString((BSTR)dest);
6071 return hr;
6073 *dest_ptr = dest;
6074 return S_OK;
6077 /* ITypeInfo::GetVarDesc
6079 * Retrieves a VARDESC structure that describes the specified variable.
6082 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6083 LPVARDESC *ppVarDesc)
6085 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6086 const TLBVarDesc *pVDesc = &This->vardescs[index];
6088 TRACE("(%p) index %d\n", This, index);
6090 if(index >= This->typeattr.cVars)
6091 return TYPE_E_ELEMENTNOTFOUND;
6093 if (This->needs_layout)
6094 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6096 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6099 /* internal function to make the inherited interfaces' methods appear
6100 * part of the interface, remembering if the top-level was dispinterface */
6101 static HRESULT typeinfo_getnames( ITypeInfo *iface, MEMBERID memid, BSTR *names,
6102 UINT max_names, UINT *num_names, BOOL dispinterface)
6104 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6105 const TLBFuncDesc *func_desc;
6106 const TLBVarDesc *var_desc;
6107 int i;
6109 *num_names = 0;
6111 func_desc = TLB_get_funcdesc_by_memberid(This, memid);
6112 if (func_desc)
6114 UINT params = func_desc->funcdesc.cParams;
6115 if (!max_names || !func_desc->Name)
6116 return S_OK;
6118 *names = SysAllocString(TLB_get_bstr(func_desc->Name));
6119 ++(*num_names);
6121 if (dispinterface && (func_desc->funcdesc.funckind != FUNC_DISPATCH))
6123 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6124 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
6125 --params; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6126 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
6127 --params; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6130 for (i = 0; i < params; i++)
6132 if (*num_names >= max_names || !func_desc->pParamDesc[i].Name)
6133 return S_OK;
6134 names[*num_names] = SysAllocString(TLB_get_bstr(func_desc->pParamDesc[i].Name));
6135 ++(*num_names);
6137 return S_OK;
6140 var_desc = TLB_get_vardesc_by_memberid(This, memid);
6141 if (var_desc)
6143 *names = SysAllocString(TLB_get_bstr(var_desc->Name));
6144 *num_names = 1;
6146 else
6148 if (This->impltypes &&
6149 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH))
6151 /* recursive search */
6152 ITypeInfo *parent;
6153 HRESULT result;
6154 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &parent);
6155 if (SUCCEEDED(result))
6157 result = typeinfo_getnames(parent, memid, names, max_names, num_names, dispinterface);
6158 ITypeInfo_Release(parent);
6159 return result;
6161 WARN("Could not search inherited interface!\n");
6163 else
6165 WARN("no names found\n");
6167 *num_names = 0;
6168 return TYPE_E_ELEMENTNOTFOUND;
6170 return S_OK;
6173 /* ITypeInfo_GetNames
6175 * Retrieves the variable with the specified member ID (or the name of the
6176 * property or method and its parameters) that correspond to the specified
6177 * function ID.
6179 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6180 BSTR *names, UINT max_names, UINT *num_names)
6182 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6184 TRACE("(%p) memid 0x%08x max_names %d\n", This, memid, max_names);
6186 if (!names) return E_INVALIDARG;
6188 return typeinfo_getnames((ITypeInfo *)iface, memid, names, max_names, num_names,
6189 This->typeattr.typekind == TKIND_DISPATCH);
6192 /* ITypeInfo::GetRefTypeOfImplType
6194 * If a type description describes a COM class, it retrieves the type
6195 * description of the implemented interface types. For an interface,
6196 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6197 * if any exist.
6200 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6201 ITypeInfo2 *iface,
6202 UINT index,
6203 HREFTYPE *pRefType)
6205 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6206 HRESULT hr = S_OK;
6208 TRACE("(%p) index %d\n", This, index);
6209 if (TRACE_ON(ole)) dump_TypeInfo(This);
6211 if(index==(UINT)-1)
6213 /* only valid on dual interfaces;
6214 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6217 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6219 *pRefType = -2;
6221 else
6223 hr = TYPE_E_ELEMENTNOTFOUND;
6226 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6228 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6229 *pRefType = This->pTypeLib->dispatch_href;
6231 else
6233 if(index >= This->typeattr.cImplTypes)
6234 hr = TYPE_E_ELEMENTNOTFOUND;
6235 else{
6236 *pRefType = This->impltypes[index].hRef;
6237 if (This->typeattr.typekind == TKIND_INTERFACE)
6238 *pRefType |= 0x2;
6242 if(TRACE_ON(ole))
6244 if(SUCCEEDED(hr))
6245 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6246 else
6247 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6250 return hr;
6253 /* ITypeInfo::GetImplTypeFlags
6255 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6256 * or base interface in a type description.
6258 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6259 UINT index, INT *pImplTypeFlags)
6261 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6263 TRACE("(%p) index %d\n", This, index);
6265 if(!pImplTypeFlags)
6266 return E_INVALIDARG;
6268 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6269 *pImplTypeFlags = 0;
6270 return S_OK;
6273 if(index >= This->typeattr.cImplTypes)
6274 return TYPE_E_ELEMENTNOTFOUND;
6276 *pImplTypeFlags = This->impltypes[index].implflags;
6278 return S_OK;
6281 /* GetIDsOfNames
6282 * Maps between member names and member IDs, and parameter names and
6283 * parameter IDs.
6285 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6286 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6288 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6289 const TLBVarDesc *pVDesc;
6290 HRESULT ret=S_OK;
6291 UINT i, fdc;
6293 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6294 cNames);
6296 /* init out parameters in case of failure */
6297 for (i = 0; i < cNames; i++)
6298 pMemId[i] = MEMBERID_NIL;
6300 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6301 int j;
6302 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6303 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6304 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6305 for(i=1; i < cNames; i++){
6306 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6307 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6308 break;
6309 if( j<pFDesc->funcdesc.cParams)
6310 pMemId[i]=j;
6311 else
6312 ret=DISP_E_UNKNOWNNAME;
6314 TRACE("-- 0x%08x\n", ret);
6315 return ret;
6318 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6319 if(pVDesc){
6320 if(cNames)
6321 *pMemId = pVDesc->vardesc.memid;
6322 return ret;
6324 /* not found, see if it can be found in an inherited interface */
6325 if(This->impltypes) {
6326 /* recursive search */
6327 ITypeInfo *pTInfo;
6328 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6329 if(SUCCEEDED(ret)){
6330 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6331 ITypeInfo_Release(pTInfo);
6332 return ret;
6334 WARN("Could not search inherited interface!\n");
6335 } else
6336 WARN("no names found\n");
6337 return DISP_E_UNKNOWNNAME;
6341 #ifdef __i386__
6343 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6344 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6345 __ASM_GLOBAL_FUNC( call_method,
6346 "pushl %ebp\n\t"
6347 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6348 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6349 "movl %esp,%ebp\n\t"
6350 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6351 "pushl %esi\n\t"
6352 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6353 "pushl %edi\n\t"
6354 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6355 "movl 12(%ebp),%edx\n\t"
6356 "movl %esp,%edi\n\t"
6357 "shll $2,%edx\n\t"
6358 "jz 1f\n\t"
6359 "subl %edx,%edi\n\t"
6360 "andl $~15,%edi\n\t"
6361 "movl %edi,%esp\n\t"
6362 "movl 12(%ebp),%ecx\n\t"
6363 "movl 16(%ebp),%esi\n\t"
6364 "cld\n\t"
6365 "rep; movsl\n"
6366 "1:\tcall *8(%ebp)\n\t"
6367 "subl %esp,%edi\n\t"
6368 "movl 20(%ebp),%ecx\n\t"
6369 "movl %edi,(%ecx)\n\t"
6370 "leal -8(%ebp),%esp\n\t"
6371 "popl %edi\n\t"
6372 __ASM_CFI(".cfi_same_value %edi\n\t")
6373 "popl %esi\n\t"
6374 __ASM_CFI(".cfi_same_value %esi\n\t")
6375 "popl %ebp\n\t"
6376 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6377 __ASM_CFI(".cfi_same_value %ebp\n\t")
6378 "ret" )
6379 __ASM_GLOBAL_FUNC( call_double_method,
6380 "jmp " __ASM_NAME("call_method") )
6382 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6383 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6385 int argspos = 0, stack_offset;
6386 void *func;
6387 UINT i;
6388 DWORD *args;
6390 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6391 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6392 pvargResult, V_VT(pvargResult));
6394 if (cc != CC_STDCALL && cc != CC_CDECL)
6396 FIXME("unsupported calling convention %d\n",cc);
6397 return E_INVALIDARG;
6400 /* maximum size for an argument is sizeof(VARIANT) */
6401 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6403 if (pvInstance)
6405 const FARPROC *vtable = *(FARPROC **)pvInstance;
6406 func = vtable[oVft/sizeof(void *)];
6407 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6409 else func = (void *)oVft;
6411 switch (vtReturn)
6413 case VT_DECIMAL:
6414 case VT_VARIANT:
6415 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6416 break;
6417 case VT_HRESULT:
6418 WARN("invalid return type %u\n", vtReturn);
6419 heap_free( args );
6420 return E_INVALIDARG;
6421 default:
6422 break;
6425 for (i = 0; i < cActuals; i++)
6427 VARIANT *arg = prgpvarg[i];
6429 switch (prgvt[i])
6431 case VT_EMPTY:
6432 break;
6433 case VT_I8:
6434 case VT_UI8:
6435 case VT_R8:
6436 case VT_DATE:
6437 case VT_CY:
6438 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6439 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6440 break;
6441 case VT_DECIMAL:
6442 case VT_VARIANT:
6443 memcpy( &args[argspos], arg, sizeof(*arg) );
6444 argspos += sizeof(*arg) / sizeof(DWORD);
6445 break;
6446 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6447 args[argspos++] = V_BOOL(arg);
6448 break;
6449 default:
6450 args[argspos++] = V_UI4(arg);
6451 break;
6453 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6456 switch (vtReturn)
6458 case VT_EMPTY:
6459 case VT_DECIMAL:
6460 case VT_VARIANT:
6461 call_method( func, argspos, args, &stack_offset );
6462 break;
6463 case VT_R4:
6464 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6465 break;
6466 case VT_R8:
6467 case VT_DATE:
6468 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6469 break;
6470 case VT_I8:
6471 case VT_UI8:
6472 case VT_CY:
6473 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6474 break;
6475 default:
6476 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6477 break;
6479 heap_free( args );
6480 if (stack_offset && cc == CC_STDCALL)
6482 WARN( "stack pointer off by %d\n", stack_offset );
6483 return DISP_E_BADCALLEE;
6485 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6486 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6487 return S_OK;
6490 #elif defined(__x86_64__)
6492 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6493 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6494 __ASM_GLOBAL_FUNC( call_method,
6495 "pushq %rbp\n\t"
6496 __ASM_SEH(".seh_pushreg %rbp\n\t")
6497 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6498 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6499 "movq %rsp,%rbp\n\t"
6500 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6501 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6502 "pushq %rsi\n\t"
6503 __ASM_SEH(".seh_pushreg %rsi\n\t")
6504 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6505 "pushq %rdi\n\t"
6506 __ASM_SEH(".seh_pushreg %rdi\n\t")
6507 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6508 __ASM_SEH(".seh_endprologue\n\t")
6509 "movq %rcx,%rax\n\t"
6510 "movq $4,%rcx\n\t"
6511 "cmp %rcx,%rdx\n\t"
6512 "cmovgq %rdx,%rcx\n\t"
6513 "leaq 0(,%rcx,8),%rdx\n\t"
6514 "subq %rdx,%rsp\n\t"
6515 "andq $~15,%rsp\n\t"
6516 "movq %rsp,%rdi\n\t"
6517 "movq %r8,%rsi\n\t"
6518 "rep; movsq\n\t"
6519 "movq 0(%rsp),%rcx\n\t"
6520 "movq 8(%rsp),%rdx\n\t"
6521 "movq 16(%rsp),%r8\n\t"
6522 "movq 24(%rsp),%r9\n\t"
6523 "movq 0(%rsp),%xmm0\n\t"
6524 "movq 8(%rsp),%xmm1\n\t"
6525 "movq 16(%rsp),%xmm2\n\t"
6526 "movq 24(%rsp),%xmm3\n\t"
6527 "callq *%rax\n\t"
6528 "leaq -16(%rbp),%rsp\n\t"
6529 "popq %rdi\n\t"
6530 __ASM_CFI(".cfi_same_value %rdi\n\t")
6531 "popq %rsi\n\t"
6532 __ASM_CFI(".cfi_same_value %rsi\n\t")
6533 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6534 "popq %rbp\n\t"
6535 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6536 __ASM_CFI(".cfi_same_value %rbp\n\t")
6537 "ret")
6538 __ASM_GLOBAL_FUNC( call_double_method,
6539 "jmp " __ASM_NAME("call_method") )
6541 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6542 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6544 int argspos = 0;
6545 UINT i;
6546 DWORD_PTR *args;
6547 void *func;
6549 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6550 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6551 pvargResult, V_VT(pvargResult));
6553 if (cc != CC_STDCALL && cc != CC_CDECL)
6555 FIXME("unsupported calling convention %d\n",cc);
6556 return E_INVALIDARG;
6559 /* maximum size for an argument is sizeof(DWORD_PTR) */
6560 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6562 if (pvInstance)
6564 const FARPROC *vtable = *(FARPROC **)pvInstance;
6565 func = vtable[oVft/sizeof(void *)];
6566 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6568 else func = (void *)oVft;
6570 switch (vtReturn)
6572 case VT_DECIMAL:
6573 case VT_VARIANT:
6574 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6575 break;
6576 case VT_HRESULT:
6577 WARN("invalid return type %u\n", vtReturn);
6578 heap_free( args );
6579 return E_INVALIDARG;
6580 default:
6581 break;
6584 for (i = 0; i < cActuals; i++)
6586 VARIANT *arg = prgpvarg[i];
6588 switch (prgvt[i])
6590 case VT_DECIMAL:
6591 case VT_VARIANT:
6592 args[argspos++] = (ULONG_PTR)arg;
6593 break;
6594 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6595 args[argspos++] = V_BOOL(arg);
6596 break;
6597 default:
6598 args[argspos++] = V_UI8(arg);
6599 break;
6601 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6604 switch (vtReturn)
6606 case VT_R4:
6607 V_R4(pvargResult) = call_double_method( func, argspos, args );
6608 break;
6609 case VT_R8:
6610 case VT_DATE:
6611 V_R8(pvargResult) = call_double_method( func, argspos, args );
6612 break;
6613 case VT_DECIMAL:
6614 case VT_VARIANT:
6615 call_method( func, argspos, args );
6616 break;
6617 default:
6618 V_UI8(pvargResult) = call_method( func, argspos, args );
6619 break;
6621 heap_free( args );
6622 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6623 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6624 return S_OK;
6627 #elif defined(__arm__)
6629 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6630 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6631 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6632 __ASM_GLOBAL_FUNC( call_method,
6633 /* r0 = *func
6634 * r1 = nb_stk_args
6635 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6636 * 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)
6639 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6640 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6642 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6643 "beq 1f\n\t" /* Skip allocation if no stack args */
6644 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6645 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6646 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6647 "subs r1, r1, #4\n\t" /* Decrement count */
6648 "bgt 2b\n\t" /* Loop till done */
6650 "1:\n\t"
6651 #ifndef __SOFTFP__
6652 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6653 #endif
6654 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6655 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6657 "blx ip\n\t" /* Call the target function */
6659 "mov sp, fp\n\t" /* Clean the stack using fp */
6660 "pop {fp, pc}\n\t" /* Restore fp and return */
6662 __ASM_GLOBAL_FUNC( call_float_method,
6663 "b " __ASM_NAME("call_method") )
6664 __ASM_GLOBAL_FUNC( call_double_method,
6665 "b " __ASM_NAME("call_method") )
6667 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6668 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6670 int argspos;
6671 void *func;
6672 UINT i;
6673 DWORD *args;
6674 struct {
6675 #ifndef __SOFTFP__
6676 union {
6677 float s[16];
6678 double d[8];
6679 } sd;
6680 #endif
6681 DWORD r[4];
6682 } regs;
6683 int rcount; /* 32-bit register index count */
6684 #ifndef __SOFTFP__
6685 int scount = 0; /* single-precision float register index count */
6686 int dcount = 0; /* double-precision float register index count */
6687 #endif
6689 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6690 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6692 if (cc != CC_STDCALL && cc != CC_CDECL)
6694 FIXME("unsupported calling convention %d\n",cc);
6695 return E_INVALIDARG;
6698 argspos = 0;
6699 rcount = 0;
6701 if (pvInstance)
6703 const FARPROC *vtable = *(FARPROC **)pvInstance;
6704 func = vtable[oVft/sizeof(void *)];
6705 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6707 else func = (void *)oVft;
6709 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6710 /* first as it will need to be in the 'r' registers: */
6711 switch (vtReturn)
6713 case VT_DECIMAL:
6714 case VT_VARIANT:
6715 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6716 break;
6717 case VT_HRESULT:
6718 WARN("invalid return type %u\n", vtReturn);
6719 return E_INVALIDARG;
6720 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6721 break;
6724 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6725 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6727 for (i = 0; i < cActuals; i++)
6729 VARIANT *arg = prgpvarg[i];
6730 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6731 int ntemp; /* Used for counting words split between registers and stack */
6733 switch (prgvt[i])
6735 case VT_EMPTY:
6736 break;
6737 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6738 case VT_DATE:
6739 #ifndef __SOFTFP__
6740 dcount = max( (scount + 1) / 2, dcount );
6741 if (dcount < 8)
6743 regs.sd.d[dcount++] = V_R8(arg);
6745 else
6747 argspos += (argspos % 2); /* align argspos to 8-bytes */
6748 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6749 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6751 break;
6752 #endif
6753 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6754 case VT_UI8:
6755 case VT_CY:
6756 if (rcount < 3)
6758 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6759 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6760 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6762 else
6764 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6765 argspos += (argspos % 2); /* align argspos to 8-bytes */
6766 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6767 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6769 break;
6770 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6771 case VT_VARIANT:
6772 /* 8-byte align 'r' and/or stack: */
6773 if (rcount < 3)
6774 rcount += (rcount % 2);
6775 else
6777 rcount = 4;
6778 argspos += (argspos % 2);
6780 ntemp = sizeof(*arg) / sizeof(DWORD);
6781 while (ntemp > 0)
6783 if (rcount < 4)
6784 regs.r[rcount++] = *pdwarg++;
6785 else
6786 args[argspos++] = *pdwarg++;
6787 --ntemp;
6789 break;
6790 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6791 if (rcount < 4)
6792 regs.r[rcount++] = V_BOOL(arg);
6793 else
6794 args[argspos++] = V_BOOL(arg);
6795 break;
6796 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6797 #ifndef __SOFTFP__
6798 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6799 if (scount < 16)
6800 regs.sd.s[scount++] = V_R4(arg);
6801 else
6802 args[argspos++] = V_UI4(arg);
6803 break;
6804 #endif
6805 default:
6806 if (rcount < 4)
6807 regs.r[rcount++] = V_UI4(arg);
6808 else
6809 args[argspos++] = V_UI4(arg);
6810 break;
6812 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6815 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6817 switch (vtReturn)
6819 case VT_EMPTY: /* EMPTY = no return value */
6820 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6821 case VT_VARIANT:
6822 call_method( func, argspos, args, (DWORD*)&regs );
6823 break;
6824 case VT_R4:
6825 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6826 break;
6827 case VT_R8:
6828 case VT_DATE:
6829 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6830 break;
6831 case VT_I8:
6832 case VT_UI8:
6833 case VT_CY:
6834 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6835 break;
6836 default:
6837 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6838 break;
6840 heap_free( args );
6841 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6842 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6843 return S_OK;
6846 #elif defined(__aarch64__)
6848 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6849 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6850 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6851 __ASM_GLOBAL_FUNC( call_method,
6852 "stp x29, x30, [sp, #-16]!\n\t"
6853 "mov x29, sp\n\t"
6854 "sub sp, sp, x1, lsl #3\n\t"
6855 "cbz x1, 2f\n"
6856 "1:\tsub x1, x1, #1\n\t"
6857 "ldr x4, [x2, x1, lsl #3]\n\t"
6858 "str x4, [sp, x1, lsl #3]\n\t"
6859 "cbnz x1, 1b\n"
6860 "2:\tmov x16, x0\n\t"
6861 "mov x9, x3\n\t"
6862 "ldp d0, d1, [x9]\n\t"
6863 "ldp d2, d3, [x9, #0x10]\n\t"
6864 "ldp d4, d5, [x9, #0x20]\n\t"
6865 "ldp d6, d7, [x9, #0x30]\n\t"
6866 "ldp x0, x1, [x9, #0x40]\n\t"
6867 "ldp x2, x3, [x9, #0x50]\n\t"
6868 "ldp x4, x5, [x9, #0x60]\n\t"
6869 "ldp x6, x7, [x9, #0x70]\n\t"
6870 "ldr x8, [x9, #0x80]\n\t"
6871 "blr x16\n\t"
6872 "mov sp, x29\n\t"
6873 "ldp x29, x30, [sp], #16\n\t"
6874 "ret" )
6875 __ASM_GLOBAL_FUNC( call_float_method,
6876 "b " __ASM_NAME("call_method") )
6877 __ASM_GLOBAL_FUNC( call_double_method,
6878 "b " __ASM_NAME("call_method") )
6880 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6881 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6883 int argspos;
6884 void *func;
6885 UINT i;
6886 DWORD_PTR *args;
6887 struct
6889 union
6891 float f;
6892 double d;
6893 } fp[8];
6894 DWORD_PTR x[9];
6895 } regs;
6896 int rcount; /* 64-bit register index count */
6897 int fpcount = 0; /* float register index count */
6899 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6900 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6902 if (cc != CC_STDCALL && cc != CC_CDECL)
6904 FIXME("unsupported calling convention %d\n",cc);
6905 return E_INVALIDARG;
6908 argspos = 0;
6909 rcount = 0;
6911 if (instance)
6913 const FARPROC *vtable = *(FARPROC **)instance;
6914 func = vtable[offset/sizeof(void *)];
6915 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6917 else func = (void *)offset;
6919 /* maximum size for an argument is 16 */
6920 args = heap_alloc( 16 * count );
6922 for (i = 0; i < count; i++)
6924 VARIANT *arg = vargs[i];
6926 switch (types[i])
6928 case VT_R4:
6929 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6930 else *(float *)&args[argspos++] = V_R4(arg);
6931 break;
6932 case VT_R8:
6933 case VT_DATE:
6934 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6935 else *(double *)&args[argspos++] = V_R8(arg);
6936 break;
6937 case VT_DECIMAL:
6938 if (rcount < 7)
6940 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6941 rcount += 2;
6943 else
6945 memcpy( &args[argspos], arg, sizeof(*arg) );
6946 argspos += 2;
6948 break;
6949 case VT_VARIANT:
6950 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6951 else args[argspos++] = (DWORD_PTR)arg;
6952 break;
6953 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6954 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6955 else args[argspos++] = V_BOOL(arg);
6956 break;
6957 default:
6958 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6959 else args[argspos++] = V_UI8(arg);
6960 break;
6962 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6965 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6967 switch (ret_type)
6969 case VT_HRESULT:
6970 heap_free( args );
6971 return E_INVALIDARG;
6972 case VT_DECIMAL:
6973 case VT_VARIANT:
6974 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6975 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6976 break;
6977 case VT_R4:
6978 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6979 break;
6980 case VT_R8:
6981 case VT_DATE:
6982 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6983 break;
6984 default:
6985 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6986 break;
6988 heap_free( args );
6989 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6990 TRACE("retval: %s\n", debugstr_variant(result));
6991 return S_OK;
6994 #else /* __aarch64__ */
6996 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6997 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6999 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7000 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
7001 return E_NOTIMPL;
7004 #endif
7006 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7008 HRESULT hr = S_OK;
7009 ITypeInfo *tinfo2 = NULL;
7010 TYPEATTR *tattr = NULL;
7012 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
7013 if (hr)
7015 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
7016 "hr = 0x%08x\n",
7017 tdesc->u.hreftype, hr);
7018 return hr;
7020 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7021 if (hr)
7023 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
7024 ITypeInfo_Release(tinfo2);
7025 return hr;
7028 switch (tattr->typekind)
7030 case TKIND_ENUM:
7031 *vt |= VT_I4;
7032 break;
7034 case TKIND_ALIAS:
7035 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7036 break;
7038 case TKIND_INTERFACE:
7039 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7040 *vt |= VT_DISPATCH;
7041 else
7042 *vt |= VT_UNKNOWN;
7043 break;
7045 case TKIND_DISPATCH:
7046 *vt |= VT_DISPATCH;
7047 break;
7049 case TKIND_COCLASS:
7050 *vt |= VT_DISPATCH;
7051 break;
7053 case TKIND_RECORD:
7054 FIXME("TKIND_RECORD unhandled.\n");
7055 hr = E_NOTIMPL;
7056 break;
7058 case TKIND_UNION:
7059 FIXME("TKIND_UNION unhandled.\n");
7060 hr = E_NOTIMPL;
7061 break;
7063 default:
7064 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7065 hr = E_NOTIMPL;
7066 break;
7068 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7069 ITypeInfo_Release(tinfo2);
7070 return hr;
7073 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7075 HRESULT hr = S_OK;
7077 /* enforce only one level of pointer indirection */
7078 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7080 tdesc = tdesc->u.lptdesc;
7082 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7083 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7084 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7085 if ((tdesc->vt == VT_USERDEFINED) ||
7086 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
7088 VARTYPE vt_userdefined = 0;
7089 const TYPEDESC *tdesc_userdefined = tdesc;
7090 if (tdesc->vt == VT_PTR)
7092 vt_userdefined = VT_BYREF;
7093 tdesc_userdefined = tdesc->u.lptdesc;
7095 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7096 if ((hr == S_OK) &&
7097 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7098 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7100 *vt |= vt_userdefined;
7101 return S_OK;
7104 *vt = VT_BYREF;
7107 switch (tdesc->vt)
7109 case VT_HRESULT:
7110 *vt |= VT_ERROR;
7111 break;
7112 case VT_USERDEFINED:
7113 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7114 break;
7115 case VT_VOID:
7116 case VT_CARRAY:
7117 case VT_PTR:
7118 case VT_LPSTR:
7119 case VT_LPWSTR:
7120 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7121 hr = DISP_E_BADVARTYPE;
7122 break;
7123 case VT_SAFEARRAY:
7124 *vt |= VT_ARRAY;
7125 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
7126 break;
7127 case VT_INT:
7128 *vt |= VT_I4;
7129 break;
7130 case VT_UINT:
7131 *vt |= VT_UI4;
7132 break;
7133 default:
7134 *vt |= tdesc->vt;
7135 break;
7137 return hr;
7140 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7142 ITypeInfo *tinfo2;
7143 TYPEATTR *tattr;
7144 HRESULT hres;
7145 int flags, i;
7147 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7148 if(FAILED(hres))
7149 return hres;
7151 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7152 if(FAILED(hres)) {
7153 ITypeInfo_Release(tinfo2);
7154 return hres;
7157 switch(tattr->typekind) {
7158 case TKIND_ALIAS:
7159 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
7160 break;
7162 case TKIND_INTERFACE:
7163 case TKIND_DISPATCH:
7164 *guid = tattr->guid;
7165 break;
7167 case TKIND_COCLASS:
7168 for (i = 0; i < tattr->cImplTypes; i++)
7170 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7171 if (flags & IMPLTYPEFLAG_FDEFAULT)
7172 break;
7175 if (i == tattr->cImplTypes)
7176 i = 0;
7178 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7179 if (SUCCEEDED(hres))
7180 hres = get_iface_guid(tinfo2, href, guid);
7181 break;
7183 default:
7184 ERR("Unexpected typekind %d\n", tattr->typekind);
7185 hres = E_UNEXPECTED;
7188 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7189 ITypeInfo_Release(tinfo2);
7190 return hres;
7193 static inline BOOL func_restricted( const FUNCDESC *desc )
7195 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7198 #define INVBUF_ELEMENT_SIZE \
7199 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7200 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7201 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7202 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7203 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7204 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7205 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7206 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7208 static HRESULT WINAPI ITypeInfo_fnInvoke(
7209 ITypeInfo2 *iface,
7210 VOID *pIUnk,
7211 MEMBERID memid,
7212 UINT16 wFlags,
7213 DISPPARAMS *pDispParams,
7214 VARIANT *pVarResult,
7215 EXCEPINFO *pExcepInfo,
7216 UINT *pArgErr)
7218 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7219 int i;
7220 unsigned int var_index;
7221 TYPEKIND type_kind;
7222 HRESULT hres;
7223 const TLBFuncDesc *pFuncInfo;
7224 UINT fdc;
7226 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7227 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7230 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7231 return DISP_E_MEMBERNOTFOUND;
7233 if (!pDispParams)
7235 ERR("NULL pDispParams not allowed\n");
7236 return E_INVALIDARG;
7239 dump_DispParms(pDispParams);
7241 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7243 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7244 pDispParams->cNamedArgs, pDispParams->cArgs);
7245 return E_INVALIDARG;
7248 /* we do this instead of using GetFuncDesc since it will return a fake
7249 * FUNCDESC for dispinterfaces and we want the real function description */
7250 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7251 pFuncInfo = &This->funcdescs[fdc];
7252 if ((memid == pFuncInfo->funcdesc.memid) &&
7253 (wFlags & pFuncInfo->funcdesc.invkind) &&
7254 !func_restricted( &pFuncInfo->funcdesc ))
7255 break;
7258 if (fdc < This->typeattr.cFuncs) {
7259 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7261 if (TRACE_ON(ole))
7263 TRACE("invoking:\n");
7264 dump_TLBFuncDescOne(pFuncInfo);
7267 switch (func_desc->funckind) {
7268 case FUNC_PUREVIRTUAL:
7269 case FUNC_VIRTUAL: {
7270 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7271 VARIANT varresult;
7272 VARIANT retval; /* pointer for storing byref retvals in */
7273 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7274 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7275 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7276 UINT cNamedArgs = pDispParams->cNamedArgs;
7277 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7278 UINT vargs_converted=0;
7279 SAFEARRAY *a;
7281 hres = S_OK;
7283 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7285 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7287 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7288 hres = DISP_E_PARAMNOTFOUND;
7289 goto func_fail;
7293 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7295 ERR("functions with the vararg attribute do not support named arguments\n");
7296 hres = DISP_E_NONAMEDARGS;
7297 goto func_fail;
7300 for (i = 0; i < func_desc->cParams; i++)
7302 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7303 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7304 if (FAILED(hres))
7305 goto func_fail;
7308 TRACE("changing args\n");
7309 for (i = 0; i < func_desc->cParams; i++)
7311 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7312 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7313 VARIANTARG *src_arg;
7315 if (wParamFlags & PARAMFLAG_FLCID)
7317 VARIANTARG *arg;
7318 arg = prgpvarg[i] = &rgvarg[i];
7319 V_VT(arg) = VT_I4;
7320 V_I4(arg) = This->pTypeLib->lcid;
7321 continue;
7324 src_arg = NULL;
7326 if (cNamedArgs)
7328 USHORT j;
7329 for (j = 0; j < cNamedArgs; j++)
7330 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7332 src_arg = &pDispParams->rgvarg[j];
7333 break;
7337 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7339 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7340 vargs_converted++;
7343 if (wParamFlags & PARAMFLAG_FRETVAL)
7345 /* under most conditions the caller is not allowed to
7346 * pass in a dispparam arg in the index of what would be
7347 * the retval parameter. however, there is an exception
7348 * where the extra parameter is used in an extra
7349 * IDispatch::Invoke below */
7350 if ((i < pDispParams->cArgs) &&
7351 ((func_desc->cParams != 1) || !pVarResult ||
7352 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7354 hres = DISP_E_BADPARAMCOUNT;
7355 break;
7358 /* note: this check is placed so that if the caller passes
7359 * in a VARIANTARG for the retval we just ignore it, like
7360 * native does */
7361 if (i == func_desc->cParams - 1)
7363 VARIANTARG *arg;
7364 arg = prgpvarg[i] = &rgvarg[i];
7365 memset(arg, 0, sizeof(*arg));
7366 V_VT(arg) = rgvt[i];
7367 memset(&retval, 0, sizeof(retval));
7368 V_BYREF(arg) = &retval;
7370 else
7372 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7373 hres = E_UNEXPECTED;
7374 break;
7377 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7378 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7380 TRACE("%s\n", debugstr_variant(src_arg));
7382 if(rgvt[i]!=V_VT(src_arg))
7384 if (rgvt[i] == VT_VARIANT)
7385 hres = VariantCopy(&rgvarg[i], src_arg);
7386 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7388 if (rgvt[i] == V_VT(src_arg))
7389 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7390 else
7392 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7393 if (wParamFlags & PARAMFLAG_FIN)
7394 hres = VariantCopy(&missing_arg[i], src_arg);
7395 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7397 V_VT(&rgvarg[i]) = rgvt[i];
7399 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7401 SAFEARRAYBOUND bound;
7402 VARIANT *v;
7403 LONG j;
7404 bound.lLbound = 0;
7405 bound.cElements = pDispParams->cArgs-i;
7406 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7408 ERR("SafeArrayCreate failed\n");
7409 break;
7411 hres = SafeArrayAccessData(a, (LPVOID)&v);
7412 if (hres != S_OK)
7414 ERR("SafeArrayAccessData failed with %x\n", hres);
7415 SafeArrayDestroy(a);
7416 break;
7418 for (j = 0; j < bound.cElements; j++)
7419 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7420 hres = SafeArrayUnaccessData(a);
7421 if (hres != S_OK)
7423 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7424 SafeArrayDestroy(a);
7425 break;
7427 if (rgvt[i] & VT_BYREF)
7428 V_BYREF(&rgvarg[i]) = &a;
7429 else
7430 V_ARRAY(&rgvarg[i]) = a;
7431 V_VT(&rgvarg[i]) = rgvt[i];
7433 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7435 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7436 if (wParamFlags & PARAMFLAG_FIN)
7437 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7438 else
7439 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7440 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7441 V_VT(&rgvarg[i]) = rgvt[i];
7443 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7445 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7446 V_VT(&rgvarg[i]) = rgvt[i];
7448 else
7450 /* FIXME: this doesn't work for VT_BYREF arguments if
7451 * they are not the same type as in the paramdesc */
7452 V_VT(&rgvarg[i]) = V_VT(src_arg);
7453 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7454 V_VT(&rgvarg[i]) = rgvt[i];
7457 if (FAILED(hres))
7459 ERR("failed to convert param %d to %s from %s\n", i,
7460 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7461 break;
7463 prgpvarg[i] = &rgvarg[i];
7465 else
7467 prgpvarg[i] = src_arg;
7470 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7471 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7472 && V_UNKNOWN(prgpvarg[i])) {
7473 IUnknown *userdefined_iface;
7474 GUID guid;
7476 if (tdesc->vt == VT_PTR)
7477 tdesc = tdesc->u.lptdesc;
7479 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7480 if(FAILED(hres))
7481 break;
7483 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7484 if(FAILED(hres)) {
7485 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7486 break;
7489 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7490 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7493 else if (wParamFlags & PARAMFLAG_FOPT)
7495 VARIANTARG *arg;
7496 arg = prgpvarg[i] = &rgvarg[i];
7497 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7499 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7500 if (FAILED(hres))
7501 break;
7503 else
7505 VARIANTARG *missing_arg;
7506 /* if the function wants a pointer to a variant then
7507 * set that up, otherwise just pass the VT_ERROR in
7508 * the argument by value */
7509 if (rgvt[i] & VT_BYREF)
7511 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7512 V_VT(arg) = VT_VARIANT | VT_BYREF;
7513 V_VARIANTREF(arg) = missing_arg;
7515 else
7516 missing_arg = arg;
7517 V_VT(missing_arg) = VT_ERROR;
7518 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7521 else
7523 hres = DISP_E_BADPARAMCOUNT;
7524 break;
7527 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7529 /* VT_VOID is a special case for return types, so it is not
7530 * handled in the general function */
7531 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7532 V_VT(&varresult) = VT_EMPTY;
7533 else
7535 V_VT(&varresult) = 0;
7536 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7537 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7540 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7541 V_VT(&varresult), func_desc->cParams, rgvt,
7542 prgpvarg, &varresult);
7544 vargs_converted = 0;
7546 for (i = 0; i < func_desc->cParams; i++)
7548 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7549 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7551 if (wParamFlags & PARAMFLAG_FLCID)
7552 continue;
7553 else if (wParamFlags & PARAMFLAG_FRETVAL)
7555 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7557 if (pVarResult)
7559 VariantInit(pVarResult);
7560 /* deref return value */
7561 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7564 VARIANT_ClearInd(prgpvarg[i]);
7566 else if (vargs_converted < pDispParams->cArgs)
7568 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7569 if (wParamFlags & PARAMFLAG_FOUT)
7571 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7573 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7575 if (FAILED(hres))
7577 ERR("failed to convert param %d to vt %d\n", i,
7578 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7579 break;
7583 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7584 func_desc->cParamsOpt < 0 &&
7585 i == func_desc->cParams-1)
7587 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7588 LONG j, ubound;
7589 VARIANT *v;
7590 hres = SafeArrayGetUBound(a, 1, &ubound);
7591 if (hres != S_OK)
7593 ERR("SafeArrayGetUBound failed with %x\n", hres);
7594 break;
7596 hres = SafeArrayAccessData(a, (LPVOID)&v);
7597 if (hres != S_OK)
7599 ERR("SafeArrayAccessData failed with %x\n", hres);
7600 break;
7602 for (j = 0; j <= ubound; j++)
7603 VariantClear(&v[j]);
7604 hres = SafeArrayUnaccessData(a);
7605 if (hres != S_OK)
7607 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7608 break;
7611 VariantClear(&rgvarg[i]);
7612 vargs_converted++;
7614 else if (wParamFlags & PARAMFLAG_FOPT)
7616 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7617 VariantClear(&rgvarg[i]);
7620 VariantClear(&missing_arg[i]);
7623 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7625 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7626 hres = DISP_E_EXCEPTION;
7627 if (pExcepInfo)
7629 IErrorInfo *pErrorInfo;
7630 pExcepInfo->scode = V_ERROR(&varresult);
7631 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7633 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7634 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7635 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7636 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7638 IErrorInfo_Release(pErrorInfo);
7642 if (V_VT(&varresult) != VT_ERROR)
7644 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7646 if (pVarResult)
7648 VariantClear(pVarResult);
7649 *pVarResult = varresult;
7651 else
7652 VariantClear(&varresult);
7655 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7656 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7657 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7658 (pDispParams->cArgs != 0))
7660 if (V_VT(pVarResult) == VT_DISPATCH)
7662 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7663 /* Note: not VariantClear; we still need the dispatch
7664 * pointer to be valid */
7665 VariantInit(pVarResult);
7666 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7667 GetSystemDefaultLCID(), wFlags,
7668 pDispParams, pVarResult, pExcepInfo, pArgErr);
7669 IDispatch_Release(pDispatch);
7671 else
7673 VariantClear(pVarResult);
7674 hres = DISP_E_NOTACOLLECTION;
7678 func_fail:
7679 heap_free(buffer);
7680 break;
7682 case FUNC_DISPATCH: {
7683 IDispatch *disp;
7685 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7686 if (SUCCEEDED(hres)) {
7687 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7688 hres = IDispatch_Invoke(
7689 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7690 pVarResult,pExcepInfo,pArgErr
7692 if (FAILED(hres))
7693 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7694 IDispatch_Release(disp);
7695 } else
7696 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7697 break;
7699 default:
7700 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7701 hres = E_FAIL;
7702 break;
7705 TRACE("-- 0x%08x\n", hres);
7706 return hres;
7708 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7709 VARDESC *var_desc;
7711 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7712 if(FAILED(hres)) return hres;
7714 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7715 dump_VARDESC(var_desc);
7716 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7717 return E_NOTIMPL;
7720 /* not found, look for it in inherited interfaces */
7721 ITypeInfo2_GetTypeKind(iface, &type_kind);
7722 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7723 if(This->impltypes) {
7724 /* recursive search */
7725 ITypeInfo *pTInfo;
7726 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7727 if(SUCCEEDED(hres)){
7728 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7729 ITypeInfo_Release(pTInfo);
7730 return hres;
7732 WARN("Could not search inherited interface!\n");
7735 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7736 return DISP_E_MEMBERNOTFOUND;
7739 /* ITypeInfo::GetDocumentation
7741 * Retrieves the documentation string, the complete Help file name and path,
7742 * and the context ID for the Help topic for a specified type description.
7744 * (Can be tested by the Visual Basic Editor in Word for instance.)
7746 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7747 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7748 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7750 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7751 const TLBFuncDesc *pFDesc;
7752 const TLBVarDesc *pVDesc;
7753 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7754 " HelpContext(%p) HelpFile(%p)\n",
7755 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7756 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7757 if(pBstrName)
7758 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7759 if(pBstrDocString)
7760 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7761 if(pdwHelpContext)
7762 *pdwHelpContext=This->dwHelpContext;
7763 if(pBstrHelpFile)
7764 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7765 return S_OK;
7766 }else {/* for a member */
7767 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7768 if(pFDesc){
7769 if(pBstrName)
7770 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7771 if(pBstrDocString)
7772 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7773 if(pdwHelpContext)
7774 *pdwHelpContext=pFDesc->helpcontext;
7775 if(pBstrHelpFile)
7776 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7777 return S_OK;
7779 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7780 if(pVDesc){
7781 if(pBstrName)
7782 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7783 if(pBstrDocString)
7784 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7785 if(pdwHelpContext)
7786 *pdwHelpContext=pVDesc->HelpContext;
7787 if(pBstrHelpFile)
7788 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7789 return S_OK;
7793 if(This->impltypes &&
7794 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7795 /* recursive search */
7796 ITypeInfo *pTInfo;
7797 HRESULT result;
7798 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7799 if(SUCCEEDED(result)) {
7800 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7801 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7802 ITypeInfo_Release(pTInfo);
7803 return result;
7805 WARN("Could not search inherited interface!\n");
7808 WARN("member %d not found\n", memid);
7809 return TYPE_E_ELEMENTNOTFOUND;
7812 /* ITypeInfo::GetDllEntry
7814 * Retrieves a description or specification of an entry point for a function
7815 * in a DLL.
7817 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7818 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7819 WORD *pwOrdinal)
7821 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7822 const TLBFuncDesc *pFDesc;
7824 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7826 if (pBstrDllName) *pBstrDllName = NULL;
7827 if (pBstrName) *pBstrName = NULL;
7828 if (pwOrdinal) *pwOrdinal = 0;
7830 if (This->typeattr.typekind != TKIND_MODULE)
7831 return TYPE_E_BADMODULEKIND;
7833 pFDesc = TLB_get_funcdesc_by_memberid_invkind(This, memid, invKind);
7834 if (!pFDesc) return TYPE_E_ELEMENTNOTFOUND;
7836 dump_TypeInfo(This);
7837 if (TRACE_ON(ole)) dump_TLBFuncDescOne(pFDesc);
7839 if (pBstrDllName) *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7841 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1))
7843 if (pBstrName) *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7844 if (pwOrdinal) *pwOrdinal = -1;
7846 else
7848 if (pBstrName) *pBstrName = NULL;
7849 if (pwOrdinal) *pwOrdinal = LOWORD(pFDesc->Entry);
7851 return S_OK;
7854 /* internal function to make the inherited interfaces' methods appear
7855 * part of the interface */
7856 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7857 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7859 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7860 HRESULT hr;
7862 TRACE("%p, 0x%x\n", iface, *hRefType);
7864 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7866 ITypeInfo *pSubTypeInfo;
7868 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7869 if (FAILED(hr))
7870 return hr;
7872 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7873 hRefType, ppTInfo);
7874 ITypeInfo_Release(pSubTypeInfo);
7875 if (SUCCEEDED(hr))
7876 return hr;
7878 *hRefType -= DISPATCH_HREF_OFFSET;
7880 if (!(*hRefType & DISPATCH_HREF_MASK))
7881 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7882 else
7883 return E_FAIL;
7886 struct search_res_tlb_params
7888 const GUID *guid;
7889 ITypeLib *pTLib;
7892 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7894 struct search_res_tlb_params *params = (LPVOID)lParam;
7895 WCHAR szPath[MAX_PATH+1];
7896 ITypeLib *pTLib = NULL;
7897 HRESULT ret;
7898 DWORD len;
7900 if (IS_INTRESOURCE(lpszName) == FALSE)
7901 return TRUE;
7903 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7904 return TRUE;
7906 if (swprintf(szPath + len, ARRAY_SIZE(szPath) - len, L"\\%d", LOWORD(lpszName)) < 0)
7907 return TRUE;
7909 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7910 if (SUCCEEDED(ret))
7912 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7913 if (IsEqualGUID(params->guid, impl->guid))
7915 params->pTLib = pTLib;
7916 return FALSE; /* stop enumeration */
7918 ITypeLib_Release(pTLib);
7921 return TRUE;
7924 /* ITypeInfo::GetRefTypeInfo
7926 * If a type description references other type descriptions, it retrieves
7927 * the referenced type descriptions.
7929 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7930 ITypeInfo2 *iface,
7931 HREFTYPE hRefType,
7932 ITypeInfo **ppTInfo)
7934 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7935 ITypeInfo *type_info = NULL;
7936 HRESULT result = E_FAIL;
7937 TLBRefType *ref_type;
7938 UINT i;
7940 if(!ppTInfo)
7941 return E_INVALIDARG;
7943 if ((INT)hRefType < 0) {
7944 ITypeInfoImpl *pTypeInfoImpl;
7946 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7947 !(This->typeattr.typekind == TKIND_INTERFACE ||
7948 This->typeattr.typekind == TKIND_DISPATCH))
7949 return TYPE_E_ELEMENTNOTFOUND;
7951 /* when we meet a DUAL typeinfo, we must create the alternate
7952 * version of it.
7954 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7956 *pTypeInfoImpl = *This;
7957 pTypeInfoImpl->ref = 0;
7958 list_init(&pTypeInfoImpl->custdata_list);
7960 if (This->typeattr.typekind == TKIND_INTERFACE)
7961 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7962 else
7963 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7965 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7966 /* the AddRef implicitly adds a reference to the parent typelib, which
7967 * stops the copied data from being destroyed until the new typeinfo's
7968 * refcount goes to zero, but we need to signal to the new instance to
7969 * not free its data structures when it is destroyed */
7970 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7971 ITypeInfo_AddRef(*ppTInfo);
7973 TRACE("got dual interface %p\n", *ppTInfo);
7974 return S_OK;
7977 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7978 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7980 if(!(hRefType & 0x1))
7982 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7984 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7986 result = S_OK;
7987 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7988 ITypeInfo_AddRef(type_info);
7989 break;
7994 if (!type_info)
7996 ITypeLib *pTLib = NULL;
7998 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
8000 if(ref_type->reference == (hRefType & (~0x3)))
8001 break;
8003 if(&ref_type->entry == &This->pTypeLib->ref_list)
8005 FIXME("Can't find pRefType for ref %x\n", hRefType);
8006 return E_FAIL;
8009 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
8010 UINT Index;
8011 TRACE("internal reference\n");
8012 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
8013 } else {
8014 if(ref_type->pImpTLInfo->pImpTypeLib) {
8015 TRACE("typeinfo in imported typelib that is already loaded\n");
8016 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
8017 ITypeLib_AddRef(pTLib);
8018 result = S_OK;
8019 } else {
8020 /* Search in cached typelibs */
8021 ITypeLibImpl *entry;
8023 EnterCriticalSection(&cache_section);
8024 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
8026 if (entry->guid
8027 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
8028 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
8029 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
8030 && entry->set_lcid == ref_type->pImpTLInfo->lcid)
8032 TRACE("got cached %p\n", entry);
8033 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
8034 ITypeLib_AddRef(pTLib);
8035 result = S_OK;
8036 break;
8039 LeaveCriticalSection(&cache_section);
8041 if (!pTLib)
8043 struct search_res_tlb_params params;
8045 TRACE("typeinfo in imported typelib that isn't already loaded\n");
8047 /* Search in resource table */
8048 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
8049 params.pTLib = NULL;
8050 EnumResourceNamesW(NULL, L"TYPELIB", search_res_tlb, (LONG_PTR)&params);
8051 if(params.pTLib)
8053 pTLib = params.pTLib;
8054 result = S_OK;
8058 if (!pTLib)
8060 BSTR libnam;
8062 /* Search on disk */
8063 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
8064 ref_type->pImpTLInfo->wVersionMajor,
8065 ref_type->pImpTLInfo->wVersionMinor,
8066 This->pTypeLib->syskind,
8067 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
8068 if (FAILED(result))
8069 libnam = SysAllocString(ref_type->pImpTLInfo->name);
8071 result = LoadTypeLib(libnam, &pTLib);
8072 SysFreeString(libnam);
8075 if(SUCCEEDED(result)) {
8076 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
8077 ITypeLib_AddRef(pTLib);
8081 if(SUCCEEDED(result)) {
8082 if(ref_type->index == TLB_REF_USE_GUID)
8083 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
8084 else
8085 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
8087 if (pTLib != NULL)
8088 ITypeLib_Release(pTLib);
8089 if (FAILED(result))
8091 WARN("(%p) failed hreftype 0x%04x\n", This, hRefType);
8092 return result;
8096 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
8097 ITypeInfo_Release(type_info);
8098 else *ppTInfo = type_info;
8100 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
8101 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8102 return result;
8105 /* ITypeInfo::AddressOfMember
8107 * Retrieves the addresses of static functions or variables, such as those
8108 * defined in a DLL.
8110 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8111 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8113 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8114 HRESULT hr;
8115 BSTR dll, entry;
8116 WORD ordinal;
8117 HMODULE module;
8119 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
8121 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8122 if (FAILED(hr))
8123 return hr;
8125 module = LoadLibraryW(dll);
8126 if (!module)
8128 ERR("couldn't load %s\n", debugstr_w(dll));
8129 SysFreeString(dll);
8130 SysFreeString(entry);
8131 return STG_E_FILENOTFOUND;
8133 /* FIXME: store library somewhere where we can free it */
8135 if (entry)
8137 LPSTR entryA;
8138 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8139 entryA = heap_alloc(len);
8140 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8142 *ppv = GetProcAddress(module, entryA);
8143 if (!*ppv)
8144 ERR("function not found %s\n", debugstr_a(entryA));
8146 heap_free(entryA);
8148 else
8150 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8151 if (!*ppv)
8152 ERR("function not found %d\n", ordinal);
8155 SysFreeString(dll);
8156 SysFreeString(entry);
8158 if (!*ppv)
8159 return TYPE_E_DLLFUNCTIONNOTFOUND;
8161 return S_OK;
8164 /* ITypeInfo::CreateInstance
8166 * Creates a new instance of a type that describes a component object class
8167 * (coclass).
8169 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8170 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8172 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8173 HRESULT hr;
8174 TYPEATTR *pTA;
8176 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8178 *ppvObj = NULL;
8180 if(pOuterUnk)
8182 WARN("Not able to aggregate\n");
8183 return CLASS_E_NOAGGREGATION;
8186 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8187 if(FAILED(hr)) return hr;
8189 if(pTA->typekind != TKIND_COCLASS)
8191 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8192 hr = E_INVALIDARG;
8193 goto end;
8196 hr = S_FALSE;
8197 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8199 IUnknown *pUnk;
8200 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8201 TRACE("GetActiveObject rets %08x\n", hr);
8202 if(hr == S_OK)
8204 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8205 IUnknown_Release(pUnk);
8209 if(hr != S_OK)
8210 hr = CoCreateInstance(&pTA->guid, NULL,
8211 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8212 riid, ppvObj);
8214 end:
8215 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8216 return hr;
8219 /* ITypeInfo::GetMops
8221 * Retrieves marshalling information.
8223 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8224 BSTR *pBstrMops)
8226 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8227 FIXME("(%p %d) stub!\n", This, memid);
8228 *pBstrMops = NULL;
8229 return S_OK;
8232 /* ITypeInfo::GetContainingTypeLib
8234 * Retrieves the containing type library and the index of the type description
8235 * within that type library.
8237 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8238 ITypeLib * *ppTLib, UINT *pIndex)
8240 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8242 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8243 if (pIndex) {
8244 *pIndex=This->index;
8245 TRACE("returning pIndex=%d\n", *pIndex);
8248 if (ppTLib) {
8249 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8250 ITypeLib_AddRef(*ppTLib);
8251 TRACE("returning ppTLib=%p\n", *ppTLib);
8254 return S_OK;
8257 /* ITypeInfo::ReleaseTypeAttr
8259 * Releases a TYPEATTR previously returned by Get
8262 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8263 TYPEATTR* pTypeAttr)
8265 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8266 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8267 heap_free(pTypeAttr);
8270 /* ITypeInfo::ReleaseFuncDesc
8272 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8274 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8275 ITypeInfo2 *iface,
8276 FUNCDESC *pFuncDesc)
8278 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8279 SHORT i;
8281 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8283 for (i = 0; i < pFuncDesc->cParams; i++)
8284 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8285 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8287 SysFreeString((BSTR)pFuncDesc);
8290 /* ITypeInfo::ReleaseVarDesc
8292 * Releases a VARDESC previously returned by GetVarDesc.
8294 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8295 VARDESC *pVarDesc)
8297 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8298 TRACE("(%p)->(%p)\n", This, pVarDesc);
8300 TLB_FreeVarDesc(pVarDesc);
8303 /* ITypeInfo2::GetTypeKind
8305 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8308 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8309 TYPEKIND *pTypeKind)
8311 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8312 *pTypeKind = This->typeattr.typekind;
8313 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8314 return S_OK;
8317 /* ITypeInfo2::GetTypeFlags
8319 * Returns the type flags without any allocations. This returns a DWORD type
8320 * flag, which expands the type flags without growing the TYPEATTR (type
8321 * attribute).
8324 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8326 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8327 *pTypeFlags=This->typeattr.wTypeFlags;
8328 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8329 return S_OK;
8332 /* ITypeInfo2::GetFuncIndexOfMemId
8333 * Binds to a specific member based on a known DISPID, where the member name
8334 * is not known (for example, when binding to a default member).
8337 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8338 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8340 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8341 UINT fdc;
8342 HRESULT result;
8344 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8345 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8346 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8347 break;
8349 if(fdc < This->typeattr.cFuncs) {
8350 *pFuncIndex = fdc;
8351 result = S_OK;
8352 } else
8353 result = TYPE_E_ELEMENTNOTFOUND;
8355 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8356 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8357 return result;
8360 /* TypeInfo2::GetVarIndexOfMemId
8362 * Binds to a specific member based on a known DISPID, where the member name
8363 * is not known (for example, when binding to a default member).
8366 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8367 MEMBERID memid, UINT *pVarIndex)
8369 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8370 TLBVarDesc *pVarInfo;
8372 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8374 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8375 if(!pVarInfo)
8376 return TYPE_E_ELEMENTNOTFOUND;
8378 *pVarIndex = (pVarInfo - This->vardescs);
8380 return S_OK;
8383 /* ITypeInfo2::GetCustData
8385 * Gets the custom data
8387 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8388 ITypeInfo2 * iface,
8389 REFGUID guid,
8390 VARIANT *pVarVal)
8392 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8393 TLBCustData *pCData;
8395 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8397 if(!guid || !pVarVal)
8398 return E_INVALIDARG;
8400 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8402 VariantInit( pVarVal);
8403 if (pCData)
8404 VariantCopy( pVarVal, &pCData->data);
8405 else
8406 VariantClear( pVarVal );
8407 return S_OK;
8410 /* ITypeInfo2::GetFuncCustData
8412 * Gets the custom data
8414 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8415 ITypeInfo2 * iface,
8416 UINT index,
8417 REFGUID guid,
8418 VARIANT *pVarVal)
8420 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8421 const TLBFuncDesc *desc;
8422 TLBCustData *data;
8423 UINT hrefoffset;
8424 HRESULT hr;
8426 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8428 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8429 if (FAILED(hr))
8431 WARN("description for function %d not found\n", index);
8432 return hr;
8435 VariantInit(pVarVal);
8436 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8437 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8440 /* ITypeInfo2::GetParamCustData
8442 * Gets the custom data
8444 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8445 ITypeInfo2 * iface,
8446 UINT indexFunc,
8447 UINT indexParam,
8448 REFGUID guid,
8449 VARIANT *pVarVal)
8451 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8452 const TLBFuncDesc *pFDesc;
8453 TLBCustData *pCData;
8454 UINT hrefoffset;
8455 HRESULT hr;
8457 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8458 debugstr_guid(guid), pVarVal);
8460 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8461 if (FAILED(hr))
8462 return hr;
8464 if(indexParam >= pFDesc->funcdesc.cParams)
8465 return TYPE_E_ELEMENTNOTFOUND;
8467 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8468 if(!pCData)
8469 return TYPE_E_ELEMENTNOTFOUND;
8471 VariantInit(pVarVal);
8472 VariantCopy(pVarVal, &pCData->data);
8474 return S_OK;
8477 /* ITypeInfo2::GetVarCustData
8479 * Gets the custom data
8481 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8482 ITypeInfo2 * iface,
8483 UINT index,
8484 REFGUID guid,
8485 VARIANT *pVarVal)
8487 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8488 TLBCustData *pCData;
8489 TLBVarDesc *pVDesc = &This->vardescs[index];
8491 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8493 if(index >= This->typeattr.cVars)
8494 return TYPE_E_ELEMENTNOTFOUND;
8496 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8497 if(!pCData)
8498 return TYPE_E_ELEMENTNOTFOUND;
8500 VariantInit(pVarVal);
8501 VariantCopy(pVarVal, &pCData->data);
8503 return S_OK;
8506 /* ITypeInfo2::GetImplCustData
8508 * Gets the custom data
8510 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8511 ITypeInfo2 * iface,
8512 UINT index,
8513 REFGUID guid,
8514 VARIANT *pVarVal)
8516 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8517 TLBCustData *pCData;
8518 TLBImplType *pRDesc = &This->impltypes[index];
8520 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8522 if(index >= This->typeattr.cImplTypes)
8523 return TYPE_E_ELEMENTNOTFOUND;
8525 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8526 if(!pCData)
8527 return TYPE_E_ELEMENTNOTFOUND;
8529 VariantInit(pVarVal);
8530 VariantCopy(pVarVal, &pCData->data);
8532 return S_OK;
8535 /* ITypeInfo2::GetDocumentation2
8537 * Retrieves the documentation string, the complete Help file name and path,
8538 * the localization context to use, and the context ID for the library Help
8539 * topic in the Help file.
8542 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8543 ITypeInfo2 * iface,
8544 MEMBERID memid,
8545 LCID lcid,
8546 BSTR *pbstrHelpString,
8547 DWORD *pdwHelpStringContext,
8548 BSTR *pbstrHelpStringDll)
8550 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8551 const TLBFuncDesc *pFDesc;
8552 const TLBVarDesc *pVDesc;
8553 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8554 "HelpStringContext(%p) HelpStringDll(%p)\n",
8555 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8556 pbstrHelpStringDll );
8557 /* the help string should be obtained from the helpstringdll,
8558 * using the _DLLGetDocumentation function, based on the supplied
8559 * lcid. Nice to do sometime...
8561 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8562 if(pbstrHelpString)
8563 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8564 if(pdwHelpStringContext)
8565 *pdwHelpStringContext=This->dwHelpStringContext;
8566 if(pbstrHelpStringDll)
8567 *pbstrHelpStringDll=
8568 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8569 return S_OK;
8570 }else {/* for a member */
8571 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8572 if(pFDesc){
8573 if(pbstrHelpString)
8574 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8575 if(pdwHelpStringContext)
8576 *pdwHelpStringContext=pFDesc->HelpStringContext;
8577 if(pbstrHelpStringDll)
8578 *pbstrHelpStringDll=
8579 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8580 return S_OK;
8582 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8583 if(pVDesc){
8584 if(pbstrHelpString)
8585 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8586 if(pdwHelpStringContext)
8587 *pdwHelpStringContext=pVDesc->HelpStringContext;
8588 if(pbstrHelpStringDll)
8589 *pbstrHelpStringDll=
8590 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8591 return S_OK;
8594 return TYPE_E_ELEMENTNOTFOUND;
8597 /* ITypeInfo2::GetAllCustData
8599 * Gets all custom data items for the Type info.
8602 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8603 ITypeInfo2 * iface,
8604 CUSTDATA *pCustData)
8606 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8608 TRACE("%p %p\n", This, pCustData);
8610 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8613 /* ITypeInfo2::GetAllFuncCustData
8615 * Gets all custom data items for the specified Function
8618 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8619 ITypeInfo2 * iface,
8620 UINT index,
8621 CUSTDATA *pCustData)
8623 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8624 const TLBFuncDesc *pFDesc;
8625 UINT hrefoffset;
8626 HRESULT hr;
8628 TRACE("%p %u %p\n", This, index, pCustData);
8630 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8631 if (FAILED(hr))
8632 return hr;
8634 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8637 /* ITypeInfo2::GetAllParamCustData
8639 * Gets all custom data items for the Functions
8642 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8643 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8645 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8646 const TLBFuncDesc *pFDesc;
8647 UINT hrefoffset;
8648 HRESULT hr;
8650 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8652 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8653 if (FAILED(hr))
8654 return hr;
8656 if(indexParam >= pFDesc->funcdesc.cParams)
8657 return TYPE_E_ELEMENTNOTFOUND;
8659 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8662 /* ITypeInfo2::GetAllVarCustData
8664 * Gets all custom data items for the specified Variable
8667 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8668 UINT index, CUSTDATA *pCustData)
8670 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8671 TLBVarDesc * pVDesc = &This->vardescs[index];
8673 TRACE("%p %u %p\n", This, index, pCustData);
8675 if(index >= This->typeattr.cVars)
8676 return TYPE_E_ELEMENTNOTFOUND;
8678 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8681 /* ITypeInfo2::GetAllImplCustData
8683 * Gets all custom data items for the specified implementation type
8686 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8687 ITypeInfo2 * iface,
8688 UINT index,
8689 CUSTDATA *pCustData)
8691 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8692 TLBImplType *pRDesc = &This->impltypes[index];
8694 TRACE("%p %u %p\n", This, index, pCustData);
8696 if(index >= This->typeattr.cImplTypes)
8697 return TYPE_E_ELEMENTNOTFOUND;
8699 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8702 static const ITypeInfo2Vtbl tinfvt =
8705 ITypeInfo_fnQueryInterface,
8706 ITypeInfo_fnAddRef,
8707 ITypeInfo_fnRelease,
8709 ITypeInfo_fnGetTypeAttr,
8710 ITypeInfo_fnGetTypeComp,
8711 ITypeInfo_fnGetFuncDesc,
8712 ITypeInfo_fnGetVarDesc,
8713 ITypeInfo_fnGetNames,
8714 ITypeInfo_fnGetRefTypeOfImplType,
8715 ITypeInfo_fnGetImplTypeFlags,
8716 ITypeInfo_fnGetIDsOfNames,
8717 ITypeInfo_fnInvoke,
8718 ITypeInfo_fnGetDocumentation,
8719 ITypeInfo_fnGetDllEntry,
8720 ITypeInfo_fnGetRefTypeInfo,
8721 ITypeInfo_fnAddressOfMember,
8722 ITypeInfo_fnCreateInstance,
8723 ITypeInfo_fnGetMops,
8724 ITypeInfo_fnGetContainingTypeLib,
8725 ITypeInfo_fnReleaseTypeAttr,
8726 ITypeInfo_fnReleaseFuncDesc,
8727 ITypeInfo_fnReleaseVarDesc,
8729 ITypeInfo2_fnGetTypeKind,
8730 ITypeInfo2_fnGetTypeFlags,
8731 ITypeInfo2_fnGetFuncIndexOfMemId,
8732 ITypeInfo2_fnGetVarIndexOfMemId,
8733 ITypeInfo2_fnGetCustData,
8734 ITypeInfo2_fnGetFuncCustData,
8735 ITypeInfo2_fnGetParamCustData,
8736 ITypeInfo2_fnGetVarCustData,
8737 ITypeInfo2_fnGetImplTypeCustData,
8738 ITypeInfo2_fnGetDocumentation2,
8739 ITypeInfo2_fnGetAllCustData,
8740 ITypeInfo2_fnGetAllFuncCustData,
8741 ITypeInfo2_fnGetAllParamCustData,
8742 ITypeInfo2_fnGetAllVarCustData,
8743 ITypeInfo2_fnGetAllImplTypeCustData,
8746 /******************************************************************************
8747 * CreateDispTypeInfo [OLEAUT32.31]
8749 * Build type information for an object so it can be called through an
8750 * IDispatch interface.
8752 * RETURNS
8753 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8754 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8756 * NOTES
8757 * This call allows an objects methods to be accessed through IDispatch, by
8758 * building an ITypeInfo object that IDispatch can use to call through.
8760 HRESULT WINAPI CreateDispTypeInfo(
8761 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8762 LCID lcid, /* [I] Locale Id */
8763 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8765 ITypeInfoImpl *pTIClass, *pTIIface;
8766 ITypeLibImpl *pTypeLibImpl;
8767 unsigned int param, func;
8768 TLBFuncDesc *pFuncDesc;
8769 TLBRefType *ref;
8771 TRACE("\n");
8772 pTypeLibImpl = TypeLibImpl_Constructor();
8773 if (!pTypeLibImpl) return E_FAIL;
8775 pTypeLibImpl->TypeInfoCount = 2;
8776 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8778 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8779 pTIIface->pTypeLib = pTypeLibImpl;
8780 pTIIface->index = 0;
8781 pTIIface->Name = NULL;
8782 pTIIface->dwHelpContext = -1;
8783 pTIIface->guid = NULL;
8784 pTIIface->typeattr.lcid = lcid;
8785 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8786 pTIIface->typeattr.wMajorVerNum = 0;
8787 pTIIface->typeattr.wMinorVerNum = 0;
8788 pTIIface->typeattr.cbAlignment = 2;
8789 pTIIface->typeattr.cbSizeInstance = -1;
8790 pTIIface->typeattr.cbSizeVft = -1;
8791 pTIIface->typeattr.cFuncs = 0;
8792 pTIIface->typeattr.cImplTypes = 0;
8793 pTIIface->typeattr.cVars = 0;
8794 pTIIface->typeattr.wTypeFlags = 0;
8795 pTIIface->hreftype = 0;
8797 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8798 pFuncDesc = pTIIface->funcdescs;
8799 for(func = 0; func < pidata->cMembers; func++) {
8800 METHODDATA *md = pidata->pmethdata + func;
8801 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8802 pFuncDesc->funcdesc.memid = md->dispid;
8803 pFuncDesc->funcdesc.lprgscode = NULL;
8804 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8805 pFuncDesc->funcdesc.invkind = md->wFlags;
8806 pFuncDesc->funcdesc.callconv = md->cc;
8807 pFuncDesc->funcdesc.cParams = md->cArgs;
8808 pFuncDesc->funcdesc.cParamsOpt = 0;
8809 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8810 pFuncDesc->funcdesc.cScodes = 0;
8811 pFuncDesc->funcdesc.wFuncFlags = 0;
8812 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8813 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8814 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8815 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8816 md->cArgs * sizeof(ELEMDESC));
8817 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8818 for(param = 0; param < md->cArgs; param++) {
8819 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8820 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8822 pFuncDesc->helpcontext = 0;
8823 pFuncDesc->HelpStringContext = 0;
8824 pFuncDesc->HelpString = NULL;
8825 pFuncDesc->Entry = NULL;
8826 list_init(&pFuncDesc->custdata_list);
8827 pTIIface->typeattr.cFuncs++;
8828 ++pFuncDesc;
8831 dump_TypeInfo(pTIIface);
8833 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8834 pTIClass->pTypeLib = pTypeLibImpl;
8835 pTIClass->index = 1;
8836 pTIClass->Name = NULL;
8837 pTIClass->dwHelpContext = -1;
8838 pTIClass->guid = NULL;
8839 pTIClass->typeattr.lcid = lcid;
8840 pTIClass->typeattr.typekind = TKIND_COCLASS;
8841 pTIClass->typeattr.wMajorVerNum = 0;
8842 pTIClass->typeattr.wMinorVerNum = 0;
8843 pTIClass->typeattr.cbAlignment = 2;
8844 pTIClass->typeattr.cbSizeInstance = -1;
8845 pTIClass->typeattr.cbSizeVft = -1;
8846 pTIClass->typeattr.cFuncs = 0;
8847 pTIClass->typeattr.cImplTypes = 1;
8848 pTIClass->typeattr.cVars = 0;
8849 pTIClass->typeattr.wTypeFlags = 0;
8850 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8852 pTIClass->impltypes = TLBImplType_Alloc(1);
8854 ref = heap_alloc_zero(sizeof(*ref));
8855 ref->pImpTLInfo = TLB_REF_INTERNAL;
8856 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8858 dump_TypeInfo(pTIClass);
8860 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8862 ITypeInfo_AddRef(*pptinfo);
8863 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8865 return S_OK;
8869 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8871 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8873 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8876 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8878 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8880 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8883 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8885 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8887 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8890 static HRESULT WINAPI ITypeComp_fnBind(
8891 ITypeComp * iface,
8892 OLECHAR * szName,
8893 ULONG lHash,
8894 WORD wFlags,
8895 ITypeInfo ** ppTInfo,
8896 DESCKIND * pDescKind,
8897 BINDPTR * pBindPtr)
8899 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8900 const TLBFuncDesc *pFDesc;
8901 const TLBVarDesc *pVDesc;
8902 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8903 UINT fdc;
8905 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8907 *pDescKind = DESCKIND_NONE;
8908 pBindPtr->lpfuncdesc = NULL;
8909 *ppTInfo = NULL;
8911 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8912 pFDesc = &This->funcdescs[fdc];
8913 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8914 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8915 break;
8916 else
8917 /* name found, but wrong flags */
8918 hr = TYPE_E_TYPEMISMATCH;
8922 if (fdc < This->typeattr.cFuncs)
8924 HRESULT hr = TLB_AllocAndInitFuncDesc(
8925 &pFDesc->funcdesc,
8926 &pBindPtr->lpfuncdesc,
8927 This->typeattr.typekind == TKIND_DISPATCH);
8928 if (FAILED(hr))
8929 return hr;
8930 *pDescKind = DESCKIND_FUNCDESC;
8931 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8932 ITypeInfo_AddRef(*ppTInfo);
8933 return S_OK;
8934 } else {
8935 pVDesc = TLB_get_vardesc_by_name(This, szName);
8936 if(pVDesc){
8937 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8938 if (FAILED(hr))
8939 return hr;
8940 *pDescKind = DESCKIND_VARDESC;
8941 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8942 ITypeInfo_AddRef(*ppTInfo);
8943 return S_OK;
8947 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8948 /* recursive search */
8949 ITypeInfo *pTInfo;
8950 ITypeComp *pTComp;
8951 HRESULT hr;
8952 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8953 if (SUCCEEDED(hr))
8955 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8956 ITypeInfo_Release(pTInfo);
8958 if (SUCCEEDED(hr))
8960 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8961 ITypeComp_Release(pTComp);
8962 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8963 This->typeattr.typekind == TKIND_DISPATCH)
8965 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8966 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8967 SysFreeString((BSTR)tmp);
8969 return hr;
8971 WARN("Could not search inherited interface!\n");
8973 if (hr == DISP_E_MEMBERNOTFOUND)
8974 hr = S_OK;
8975 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8976 return hr;
8979 static HRESULT WINAPI ITypeComp_fnBindType(
8980 ITypeComp * iface,
8981 OLECHAR * szName,
8982 ULONG lHash,
8983 ITypeInfo ** ppTInfo,
8984 ITypeComp ** ppTComp)
8986 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8988 /* strange behaviour (does nothing) but like the
8989 * original */
8991 if (!ppTInfo || !ppTComp)
8992 return E_POINTER;
8994 *ppTInfo = NULL;
8995 *ppTComp = NULL;
8997 return S_OK;
9000 static const ITypeCompVtbl tcompvt =
9003 ITypeComp_fnQueryInterface,
9004 ITypeComp_fnAddRef,
9005 ITypeComp_fnRelease,
9007 ITypeComp_fnBind,
9008 ITypeComp_fnBindType
9011 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
9012 ICreateTypeLib2** ppctlib)
9014 ITypeLibImpl *This;
9015 HRESULT hres;
9017 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
9019 if (!szFile) return E_INVALIDARG;
9021 This = TypeLibImpl_Constructor();
9022 if (!This)
9023 return E_OUTOFMEMORY;
9025 This->lcid = GetSystemDefaultLCID();
9026 This->syskind = syskind;
9027 This->ptr_size = get_ptr_size(syskind);
9029 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
9030 if (!This->path) {
9031 ITypeLib2_Release(&This->ITypeLib2_iface);
9032 return E_OUTOFMEMORY;
9034 lstrcpyW(This->path, szFile);
9036 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
9037 ITypeLib2_Release(&This->ITypeLib2_iface);
9038 return hres;
9041 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
9042 REFIID riid, void **object)
9044 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9046 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
9049 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
9051 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9053 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
9056 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
9058 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9060 return ITypeLib2_Release(&This->ITypeLib2_iface);
9063 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
9064 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
9066 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9067 ITypeInfoImpl *info;
9068 HRESULT hres;
9070 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
9072 if (!ctinfo || !name)
9073 return E_INVALIDARG;
9075 info = TLB_get_typeinfo_by_name(This, name);
9076 if (info)
9077 return TYPE_E_NAMECONFLICT;
9079 if (This->typeinfos)
9080 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
9081 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
9082 else
9083 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
9085 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
9087 info->pTypeLib = This;
9088 info->Name = TLB_append_str(&This->name_list, name);
9089 info->index = This->TypeInfoCount;
9090 info->typeattr.typekind = kind;
9091 info->typeattr.cbAlignment = 4;
9093 switch (info->typeattr.typekind) {
9094 case TKIND_ENUM:
9095 case TKIND_INTERFACE:
9096 case TKIND_DISPATCH:
9097 case TKIND_COCLASS:
9098 info->typeattr.cbSizeInstance = This->ptr_size;
9099 break;
9100 case TKIND_RECORD:
9101 case TKIND_UNION:
9102 info->typeattr.cbSizeInstance = 0;
9103 break;
9104 case TKIND_MODULE:
9105 info->typeattr.cbSizeInstance = 2;
9106 break;
9107 case TKIND_ALIAS:
9108 info->typeattr.cbSizeInstance = -0x75;
9109 break;
9110 default:
9111 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9112 info->typeattr.cbSizeInstance = 0xdeadbeef;
9113 break;
9116 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9117 &IID_ICreateTypeInfo, (void **)ctinfo);
9118 if (FAILED(hres)) {
9119 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9120 return hres;
9123 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9125 ++This->TypeInfoCount;
9127 return S_OK;
9130 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9131 LPOLESTR name)
9133 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9135 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9137 if (!name)
9138 return E_INVALIDARG;
9140 This->Name = TLB_append_str(&This->name_list, name);
9142 return S_OK;
9145 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9146 WORD majorVerNum, WORD minorVerNum)
9148 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9150 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9152 This->ver_major = majorVerNum;
9153 This->ver_minor = minorVerNum;
9155 return S_OK;
9158 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9159 REFGUID guid)
9161 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9163 TRACE("%p %s\n", This, debugstr_guid(guid));
9165 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9167 return S_OK;
9170 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9171 LPOLESTR doc)
9173 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9175 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9177 if (!doc)
9178 return E_INVALIDARG;
9180 This->DocString = TLB_append_str(&This->string_list, doc);
9182 return S_OK;
9185 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9186 LPOLESTR helpFileName)
9188 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9190 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9192 if (!helpFileName)
9193 return E_INVALIDARG;
9195 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9197 return S_OK;
9200 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9201 DWORD helpContext)
9203 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9205 TRACE("%p %d\n", This, helpContext);
9207 This->dwHelpContext = helpContext;
9209 return S_OK;
9212 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9213 LCID lcid)
9215 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9217 TRACE("%p %x\n", This, lcid);
9219 This->set_lcid = lcid;
9221 return S_OK;
9224 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9225 UINT libFlags)
9227 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9229 TRACE("%p %x\n", This, libFlags);
9231 This->libflags = libFlags;
9233 return S_OK;
9236 typedef struct tagWMSFT_SegContents {
9237 DWORD len;
9238 void *data;
9239 } WMSFT_SegContents;
9241 typedef struct tagWMSFT_TLBFile {
9242 MSFT_Header header;
9243 WMSFT_SegContents typeinfo_seg;
9244 WMSFT_SegContents impfile_seg;
9245 WMSFT_SegContents impinfo_seg;
9246 WMSFT_SegContents ref_seg;
9247 WMSFT_SegContents guidhash_seg;
9248 WMSFT_SegContents guid_seg;
9249 WMSFT_SegContents namehash_seg;
9250 WMSFT_SegContents name_seg;
9251 WMSFT_SegContents string_seg;
9252 WMSFT_SegContents typdesc_seg;
9253 WMSFT_SegContents arraydesc_seg;
9254 WMSFT_SegContents custdata_seg;
9255 WMSFT_SegContents cdguids_seg;
9256 MSFT_SegDir segdir;
9257 WMSFT_SegContents aux_seg;
9258 } WMSFT_TLBFile;
9260 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9261 WMSFT_TLBFile *file)
9263 TLBString *str;
9264 UINT last_offs;
9265 char *data;
9267 file->string_seg.len = 0;
9268 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9269 int size;
9271 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9272 if (size == 0)
9273 return E_UNEXPECTED;
9275 size += sizeof(INT16);
9276 if (size % 4)
9277 size = (size + 4) & ~0x3;
9278 if (size < 8)
9279 size = 8;
9281 file->string_seg.len += size;
9283 /* temporarily use str->offset to store the length of the aligned,
9284 * converted string */
9285 str->offset = size;
9288 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9290 last_offs = 0;
9291 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9292 int size;
9294 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9295 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9296 if (size == 0) {
9297 heap_free(file->string_seg.data);
9298 return E_UNEXPECTED;
9301 *((INT16*)data) = size;
9303 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9305 size = str->offset;
9306 data += size;
9307 str->offset = last_offs;
9308 last_offs += size;
9311 return S_OK;
9314 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9315 WMSFT_TLBFile *file)
9317 TLBString *str;
9318 UINT last_offs;
9319 char *data;
9320 MSFT_NameIntro *last_intro = NULL;
9322 file->header.nametablecount = 0;
9323 file->header.nametablechars = 0;
9325 file->name_seg.len = 0;
9326 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9327 int size;
9329 size = lstrlenW(str->str);
9330 file->header.nametablechars += size;
9331 file->header.nametablecount++;
9333 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9334 if (size == 0)
9335 return E_UNEXPECTED;
9337 size += sizeof(MSFT_NameIntro);
9338 if (size % 4)
9339 size = (size + 4) & ~0x3;
9340 if (size < 8)
9341 size = 8;
9343 file->name_seg.len += size;
9345 /* temporarily use str->offset to store the length of the aligned,
9346 * converted string */
9347 str->offset = size;
9350 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9351 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9353 last_offs = 0;
9354 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9355 int size, hash;
9356 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9358 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9359 data + sizeof(MSFT_NameIntro),
9360 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9361 if (size == 0) {
9362 heap_free(file->name_seg.data);
9363 return E_UNEXPECTED;
9365 data[sizeof(MSFT_NameIntro) + size] = '\0';
9367 intro->hreftype = -1; /* TODO? */
9368 intro->namelen = size & 0xFF;
9369 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9370 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9371 intro->namelen |= hash << 16;
9372 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9373 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9375 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9376 str->offset - size - sizeof(MSFT_NameIntro));
9378 /* update str->offset to actual value to use in other
9379 * compilation functions that require positions within
9380 * the string table */
9381 last_intro = intro;
9382 size = str->offset;
9383 data += size;
9384 str->offset = last_offs;
9385 last_offs += size;
9388 if(last_intro)
9389 last_intro->hreftype = 0; /* last one is 0? */
9391 return S_OK;
9394 static inline int hash_guid(GUID *guid)
9396 int i, hash = 0;
9398 for (i = 0; i < 8; i ++)
9399 hash ^= ((const short *)guid)[i];
9401 return hash & 0x1f;
9404 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9406 TLBGuid *guid;
9407 MSFT_GuidEntry *entry;
9408 DWORD offs;
9409 int hash_key, *guidhashtab;
9411 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9412 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9414 entry = file->guid_seg.data;
9415 offs = 0;
9416 guidhashtab = file->guidhash_seg.data;
9417 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9418 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9419 entry->hreftype = guid->hreftype;
9421 hash_key = hash_guid(&guid->guid);
9422 entry->next_hash = guidhashtab[hash_key];
9423 guidhashtab[hash_key] = offs;
9425 guid->offset = offs;
9426 offs += sizeof(MSFT_GuidEntry);
9427 ++entry;
9430 return S_OK;
9433 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9435 VARIANT v = *value;
9436 VARTYPE arg_type = V_VT(value);
9437 int mask = 0;
9438 HRESULT hres;
9439 DWORD ret = file->custdata_seg.len;
9441 if(arg_type == VT_INT)
9442 arg_type = VT_I4;
9443 if(arg_type == VT_UINT)
9444 arg_type = VT_UI4;
9446 v = *value;
9447 if(V_VT(value) != arg_type) {
9448 hres = VariantChangeType(&v, value, 0, arg_type);
9449 if(FAILED(hres)){
9450 ERR("VariantChangeType failed: %08x\n", hres);
9451 return -1;
9455 /* Check if default value can be stored in-place */
9456 switch(arg_type){
9457 case VT_I4:
9458 case VT_UI4:
9459 mask = 0x3ffffff;
9460 if(V_UI4(&v) > 0x3ffffff)
9461 break;
9462 /* fall through */
9463 case VT_I1:
9464 case VT_UI1:
9465 case VT_BOOL:
9466 if(!mask)
9467 mask = 0xff;
9468 /* fall through */
9469 case VT_I2:
9470 case VT_UI2:
9471 if(!mask)
9472 mask = 0xffff;
9473 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9476 /* have to allocate space in custdata_seg */
9477 switch(arg_type) {
9478 case VT_I4:
9479 case VT_R4:
9480 case VT_UI4:
9481 case VT_INT:
9482 case VT_UINT:
9483 case VT_HRESULT:
9484 case VT_PTR: {
9485 /* Construct the data to be allocated */
9486 int *data;
9488 if(file->custdata_seg.data){
9489 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9490 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9491 file->custdata_seg.len += sizeof(int) * 2;
9492 }else{
9493 file->custdata_seg.len = sizeof(int) * 2;
9494 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9497 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9498 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9500 /* TODO: Check if the encoded data is already present in custdata_seg */
9502 return ret;
9505 case VT_BSTR: {
9506 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9507 char *data;
9509 if(file->custdata_seg.data){
9510 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9511 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9512 file->custdata_seg.len += len;
9513 }else{
9514 file->custdata_seg.len = len;
9515 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9518 *((unsigned short *)data) = V_VT(value);
9519 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9520 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9521 if(V_BSTR(&v)[i] <= 0x7f)
9522 data[i+6] = V_BSTR(&v)[i];
9523 else
9524 data[i+6] = '?';
9526 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9527 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9528 data[i] = 0x57;
9530 /* TODO: Check if the encoded data is already present in custdata_seg */
9532 return ret;
9534 default:
9535 FIXME("Argument type not yet handled\n");
9536 return -1;
9540 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9542 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9544 DWORD offs = file->arraydesc_seg.len;
9545 DWORD *encoded;
9546 USHORT i;
9548 /* TODO: we should check for duplicates, but that's harder because each
9549 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9550 * at the library-level) */
9552 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9553 if(!file->arraydesc_seg.data)
9554 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9555 else
9556 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9557 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9559 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9560 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9561 for(i = 0; i < desc->cDims; ++i){
9562 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9563 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9566 return offs;
9569 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9571 DWORD junk;
9572 INT16 junk2;
9573 DWORD offs = 0;
9574 DWORD encoded[2];
9575 VARTYPE vt, subtype;
9576 char *data;
9578 if(!desc)
9579 return -1;
9581 if(!out_mix)
9582 out_mix = &junk;
9583 if(!out_size)
9584 out_size = &junk2;
9586 vt = desc->vt & VT_TYPEMASK;
9588 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9589 DWORD mix;
9590 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9591 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9592 *out_mix = 0x7FFF;
9593 *out_size += 2 * sizeof(DWORD);
9594 }else if(vt == VT_CARRAY){
9595 encoded[0] = desc->vt | (0x7FFE << 16);
9596 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9597 *out_mix = 0x7FFE;
9598 }else if(vt == VT_USERDEFINED){
9599 encoded[0] = desc->vt | (0x7FFF << 16);
9600 encoded[1] = desc->u.hreftype;
9601 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9602 }else{
9603 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9605 switch(vt){
9606 case VT_INT:
9607 subtype = VT_I4;
9608 break;
9609 case VT_UINT:
9610 subtype = VT_UI4;
9611 break;
9612 case VT_VOID:
9613 subtype = VT_EMPTY;
9614 break;
9615 default:
9616 subtype = vt;
9617 break;
9620 *out_mix = subtype;
9621 return 0x80000000 | (subtype << 16) | desc->vt;
9624 data = file->typdesc_seg.data;
9625 while(offs < file->typdesc_seg.len){
9626 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9627 return offs;
9628 offs += sizeof(encoded);
9631 file->typdesc_seg.len += sizeof(encoded);
9632 if(!file->typdesc_seg.data)
9633 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9634 else
9635 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9637 memcpy(&data[offs], encoded, sizeof(encoded));
9639 return offs;
9642 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9644 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9645 DWORD ret = cdguids_seg->len, offs;
9646 MSFT_CDGuid *cdguid;
9647 TLBCustData *cd;
9649 if(list_empty(custdata_list))
9650 return -1;
9652 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9653 if(!cdguids_seg->data){
9654 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9655 }else {
9656 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9657 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9660 offs = ret + sizeof(MSFT_CDGuid);
9661 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9662 cdguid->GuidOffset = cd->guid->offset;
9663 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9664 cdguid->next = offs;
9665 offs += sizeof(MSFT_CDGuid);
9666 ++cdguid;
9669 --cdguid;
9670 cdguid->next = -1;
9672 return ret;
9675 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9676 WMSFT_TLBFile *file)
9678 WMSFT_SegContents *aux_seg = &file->aux_seg;
9679 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9680 MSFT_VarRecord *varrecord;
9681 MSFT_FuncRecord *funcrecord;
9682 MEMBERID *memid;
9683 DWORD *name, *offsets, offs;
9685 for(i = 0; i < info->typeattr.cFuncs; ++i){
9686 TLBFuncDesc *desc = &info->funcdescs[i];
9688 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9690 /* optional fields */
9691 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9692 if(!list_empty(&desc->custdata_list))
9693 recorded_size += 7 * sizeof(INT);
9694 else if(desc->HelpStringContext != 0)
9695 recorded_size += 6 * sizeof(INT);
9696 /* res9? resA? */
9697 else if(desc->Entry)
9698 recorded_size += 3 * sizeof(INT);
9699 else if(desc->HelpString)
9700 recorded_size += 2 * sizeof(INT);
9701 else if(desc->helpcontext)
9702 recorded_size += sizeof(INT);
9704 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9706 for(j = 0; j < desc->funcdesc.cParams; ++j){
9707 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9708 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9709 break;
9713 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9716 for(i = 0; i < info->typeattr.cVars; ++i){
9717 TLBVarDesc *desc = &info->vardescs[i];
9719 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9721 /* optional fields */
9722 if(desc->HelpStringContext != 0)
9723 recorded_size += 5 * sizeof(INT);
9724 else if(!list_empty(&desc->custdata_list))
9725 recorded_size += 4 * sizeof(INT);
9726 /* res9? */
9727 else if(desc->HelpString)
9728 recorded_size += 2 * sizeof(INT);
9729 else if(desc->HelpContext != 0)
9730 recorded_size += sizeof(INT);
9732 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9735 if(!recorded_size && !extra_size)
9736 return ret;
9738 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9740 aux_seg->len += recorded_size + extra_size;
9742 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9744 if(aux_seg->data)
9745 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9746 else
9747 aux_seg->data = heap_alloc(aux_seg->len);
9749 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9751 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9752 offs = 0;
9754 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9755 for(i = 0; i < info->typeattr.cFuncs; ++i){
9756 TLBFuncDesc *desc = &info->funcdescs[i];
9757 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9759 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9760 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9761 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9762 funcrecord->VtableOffset = desc->funcdesc.oVft;
9764 /* FKCCIC:
9765 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9766 * ^^^funckind
9767 * ^^^ ^invkind
9768 * ^has_cust_data
9769 * ^^^^callconv
9770 * ^has_param_defaults
9771 * ^oEntry_is_intresource
9773 funcrecord->FKCCIC =
9774 desc->funcdesc.funckind |
9775 (desc->funcdesc.invkind << 3) |
9776 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9777 (desc->funcdesc.callconv << 8);
9779 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9780 funcrecord->FKCCIC |= 0x2000;
9782 for(j = 0; j < desc->funcdesc.cParams; ++j){
9783 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9784 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9785 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9788 if(paramdefault_size > 0)
9789 funcrecord->FKCCIC |= 0x1000;
9791 funcrecord->nrargs = desc->funcdesc.cParams;
9792 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9794 /* optional fields */
9795 /* res9? resA? */
9796 if(!list_empty(&desc->custdata_list)){
9797 size += 7 * sizeof(INT);
9798 funcrecord->HelpContext = desc->helpcontext;
9799 if(desc->HelpString)
9800 funcrecord->oHelpString = desc->HelpString->offset;
9801 else
9802 funcrecord->oHelpString = -1;
9803 if(!desc->Entry)
9804 funcrecord->oEntry = -1;
9805 else if(IS_INTRESOURCE(desc->Entry))
9806 funcrecord->oEntry = LOWORD(desc->Entry);
9807 else
9808 funcrecord->oEntry = desc->Entry->offset;
9809 funcrecord->res9 = -1;
9810 funcrecord->resA = -1;
9811 funcrecord->HelpStringContext = desc->HelpStringContext;
9812 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9813 }else if(desc->HelpStringContext != 0){
9814 size += 6 * sizeof(INT);
9815 funcrecord->HelpContext = desc->helpcontext;
9816 if(desc->HelpString)
9817 funcrecord->oHelpString = desc->HelpString->offset;
9818 else
9819 funcrecord->oHelpString = -1;
9820 if(!desc->Entry)
9821 funcrecord->oEntry = -1;
9822 else if(IS_INTRESOURCE(desc->Entry))
9823 funcrecord->oEntry = LOWORD(desc->Entry);
9824 else
9825 funcrecord->oEntry = desc->Entry->offset;
9826 funcrecord->res9 = -1;
9827 funcrecord->resA = -1;
9828 funcrecord->HelpStringContext = desc->HelpStringContext;
9829 }else if(desc->Entry){
9830 size += 3 * sizeof(INT);
9831 funcrecord->HelpContext = desc->helpcontext;
9832 if(desc->HelpString)
9833 funcrecord->oHelpString = desc->HelpString->offset;
9834 else
9835 funcrecord->oHelpString = -1;
9836 if(!desc->Entry)
9837 funcrecord->oEntry = -1;
9838 else if(IS_INTRESOURCE(desc->Entry))
9839 funcrecord->oEntry = LOWORD(desc->Entry);
9840 else
9841 funcrecord->oEntry = desc->Entry->offset;
9842 }else if(desc->HelpString){
9843 size += 2 * sizeof(INT);
9844 funcrecord->HelpContext = desc->helpcontext;
9845 funcrecord->oHelpString = desc->HelpString->offset;
9846 }else if(desc->helpcontext){
9847 size += sizeof(INT);
9848 funcrecord->HelpContext = desc->helpcontext;
9851 paramdefault = (DWORD*)((char *)funcrecord + size);
9852 size += paramdefault_size;
9854 for(j = 0; j < desc->funcdesc.cParams; ++j){
9855 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9857 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9858 if(desc->pParamDesc[j].Name)
9859 info->oName = desc->pParamDesc[j].Name->offset;
9860 else
9861 info->oName = -1;
9862 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9864 if(paramdefault_size){
9865 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9866 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9867 else if(paramdefault_size)
9868 *paramdefault = -1;
9869 ++paramdefault;
9872 size += sizeof(MSFT_ParameterInfo);
9875 funcrecord->Info = size | (i << 16); /* is it just the index? */
9877 *offsets = offs;
9878 offs += size;
9879 ++offsets;
9881 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9884 varrecord = (MSFT_VarRecord*)funcrecord;
9885 for(i = 0; i < info->typeattr.cVars; ++i){
9886 TLBVarDesc *desc = &info->vardescs[i];
9887 DWORD size = 5 * sizeof(INT);
9889 varrecord->vardescsize = sizeof(desc->vardesc);
9890 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9891 varrecord->Flags = desc->vardesc.wVarFlags;
9892 varrecord->VarKind = desc->vardesc.varkind;
9894 if(desc->vardesc.varkind == VAR_CONST){
9895 varrecord->vardescsize += sizeof(VARIANT);
9896 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9897 }else
9898 varrecord->OffsValue = desc->vardesc.u.oInst;
9900 /* res9? */
9901 if(desc->HelpStringContext != 0){
9902 size += 5 * sizeof(INT);
9903 varrecord->HelpContext = desc->HelpContext;
9904 if(desc->HelpString)
9905 varrecord->HelpString = desc->HelpString->offset;
9906 else
9907 varrecord->HelpString = -1;
9908 varrecord->res9 = -1;
9909 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9910 varrecord->HelpStringContext = desc->HelpStringContext;
9911 }else if(!list_empty(&desc->custdata_list)){
9912 size += 4 * sizeof(INT);
9913 varrecord->HelpContext = desc->HelpContext;
9914 if(desc->HelpString)
9915 varrecord->HelpString = desc->HelpString->offset;
9916 else
9917 varrecord->HelpString = -1;
9918 varrecord->res9 = -1;
9919 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9920 }else if(desc->HelpString){
9921 size += 2 * sizeof(INT);
9922 varrecord->HelpContext = desc->HelpContext;
9923 if(desc->HelpString)
9924 varrecord->HelpString = desc->HelpString->offset;
9925 else
9926 varrecord->HelpString = -1;
9927 }else if(desc->HelpContext != 0){
9928 size += sizeof(INT);
9929 varrecord->HelpContext = desc->HelpContext;
9932 varrecord->Info = size | (i << 16);
9934 *offsets = offs;
9935 offs += size;
9936 ++offsets;
9938 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9941 memid = (MEMBERID*)varrecord;
9942 for(i = 0; i < info->typeattr.cFuncs; ++i){
9943 TLBFuncDesc *desc = &info->funcdescs[i];
9944 *memid = desc->funcdesc.memid;
9945 ++memid;
9947 for(i = 0; i < info->typeattr.cVars; ++i){
9948 TLBVarDesc *desc = &info->vardescs[i];
9949 *memid = desc->vardesc.memid;
9950 ++memid;
9953 name = (UINT*)memid;
9954 for(i = 0; i < info->typeattr.cFuncs; ++i){
9955 TLBFuncDesc *desc = &info->funcdescs[i];
9956 if(desc->Name)
9957 *name = desc->Name->offset;
9958 else
9959 *name = -1;
9960 ++name;
9962 for(i = 0; i < info->typeattr.cVars; ++i){
9963 TLBVarDesc *desc = &info->vardescs[i];
9964 if(desc->Name)
9965 *name = desc->Name->offset;
9966 else
9967 *name = -1;
9968 ++name;
9971 return ret;
9974 typedef struct tagWMSFT_RefChunk {
9975 DWORD href;
9976 DWORD res04;
9977 DWORD res08;
9978 DWORD next;
9979 } WMSFT_RefChunk;
9981 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9983 DWORD offs = file->ref_seg.len, i;
9984 WMSFT_RefChunk *chunk;
9986 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9987 if(!file->ref_seg.data)
9988 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9989 else
9990 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9992 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9994 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9995 chunk->href = info->impltypes[i].hRef;
9996 chunk->res04 = info->impltypes[i].implflags;
9997 chunk->res08 = -1;
9998 if(i < info->typeattr.cImplTypes - 1)
9999 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
10000 else
10001 chunk->next = -1;
10002 ++chunk;
10005 return offs;
10008 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
10010 DWORD size;
10012 size = sizeof(MSFT_TypeInfoBase);
10014 if(data){
10015 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
10016 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
10017 base->typekind = TKIND_DISPATCH;
10018 else
10019 base->typekind = info->typeattr.typekind;
10020 base->typekind |= index << 16; /* TODO: There are some other flags here */
10021 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
10022 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
10023 base->res2 = 0;
10024 base->res3 = 0;
10025 base->res4 = 3;
10026 base->res5 = 0;
10027 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
10028 base->res7 = 0;
10029 base->res8 = 0;
10030 base->res9 = 0;
10031 base->resA = 0;
10032 if(info->guid)
10033 base->posguid = info->guid->offset;
10034 else
10035 base->posguid = -1;
10036 base->flags = info->typeattr.wTypeFlags;
10037 if(info->Name) {
10038 base->NameOffset = info->Name->offset;
10040 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
10041 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
10042 }else {
10043 base->NameOffset = -1;
10045 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
10046 if(info->DocString)
10047 base->docstringoffs = info->DocString->offset;
10048 else
10049 base->docstringoffs = -1;
10050 base->helpstringcontext = info->dwHelpStringContext;
10051 base->helpcontext = info->dwHelpContext;
10052 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
10053 base->cImplTypes = info->typeattr.cImplTypes;
10054 base->cbSizeVft = info->typeattr.cbSizeVft;
10055 base->size = info->typeattr.cbSizeInstance;
10056 if(info->typeattr.typekind == TKIND_COCLASS){
10057 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
10058 }else if(info->typeattr.typekind == TKIND_ALIAS){
10059 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
10060 }else if(info->typeattr.typekind == TKIND_MODULE){
10061 if(info->DllName)
10062 base->datatype1 = info->DllName->offset;
10063 else
10064 base->datatype1 = -1;
10065 }else{
10066 if(info->typeattr.cImplTypes > 0)
10067 base->datatype1 = info->impltypes[0].hRef;
10068 else
10069 base->datatype1 = -1;
10071 base->datatype2 = index; /* FIXME: i think there's more here */
10072 base->res18 = 0;
10073 base->res19 = -1;
10076 return size;
10079 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
10081 UINT i;
10083 file->typeinfo_seg.len = 0;
10084 for(i = 0; i < This->TypeInfoCount; ++i){
10085 ITypeInfoImpl *info = This->typeinfos[i];
10086 *junk = file->typeinfo_seg.len;
10087 ++junk;
10088 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
10091 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
10092 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
10094 file->aux_seg.len = 0;
10095 file->aux_seg.data = NULL;
10097 file->typeinfo_seg.len = 0;
10098 for(i = 0; i < This->TypeInfoCount; ++i){
10099 ITypeInfoImpl *info = This->typeinfos[i];
10100 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
10101 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
10105 typedef struct tagWMSFT_ImpFile {
10106 INT guid_offs;
10107 LCID lcid;
10108 DWORD version;
10109 } WMSFT_ImpFile;
10111 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
10113 TLBImpLib *implib;
10114 WMSFT_ImpFile *impfile;
10115 char *data;
10116 DWORD last_offs = 0;
10118 file->impfile_seg.len = 0;
10119 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10120 int size = 0;
10122 if(implib->name){
10123 WCHAR *path = wcsrchr(implib->name, '\\');
10124 if(path)
10125 ++path;
10126 else
10127 path = implib->name;
10128 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10129 if (size == 0)
10130 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10133 size += sizeof(INT16);
10134 if (size % 4)
10135 size = (size + 4) & ~0x3;
10136 if (size < 8)
10137 size = 8;
10139 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10142 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
10144 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10145 int strlen = 0, size;
10147 impfile = (WMSFT_ImpFile*)data;
10148 impfile->guid_offs = implib->guid->offset;
10149 impfile->lcid = implib->lcid;
10150 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10152 data += sizeof(WMSFT_ImpFile);
10154 if(implib->name){
10155 WCHAR *path= wcsrchr(implib->name, '\\');
10156 if(path)
10157 ++path;
10158 else
10159 path = implib->name;
10160 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10161 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10162 if (strlen == 0)
10163 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10166 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10168 size = strlen + sizeof(INT16);
10169 if (size % 4)
10170 size = (size + 4) & ~0x3;
10171 if (size < 8)
10172 size = 8;
10173 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10175 data += size;
10176 implib->offset = last_offs;
10177 last_offs += size + sizeof(WMSFT_ImpFile);
10181 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10183 MSFT_ImpInfo *info;
10184 TLBRefType *ref_type;
10185 UINT i = 0;
10187 WMSFT_compile_impfile(This, file);
10189 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10190 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10192 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10193 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10194 if(ref_type->index == TLB_REF_USE_GUID){
10195 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10196 info->oGuid = ref_type->guid->offset;
10197 }else
10198 info->oGuid = ref_type->index;
10199 info->oImpFile = ref_type->pImpTLInfo->offset;
10200 ++i;
10201 ++info;
10205 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10207 file->guidhash_seg.len = 0x80;
10208 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10209 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10212 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10214 file->namehash_seg.len = 0x200;
10215 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10216 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10219 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10221 if(contents && contents->len){
10222 segdir->offset = *running_offset;
10223 segdir->length = contents->len;
10224 *running_offset += segdir->length;
10225 }else{
10226 segdir->offset = -1;
10227 segdir->length = 0;
10230 /* TODO: do these ever change? */
10231 segdir->res08 = -1;
10232 segdir->res0c = 0xf;
10235 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10237 DWORD written;
10238 if(segment)
10239 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10242 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10243 DWORD file_len)
10245 DWORD i;
10246 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10248 for(i = 0; i < This->TypeInfoCount; ++i){
10249 base->memoffset += file_len;
10250 ++base;
10253 return S_OK;
10256 static void WMSFT_free_file(WMSFT_TLBFile *file)
10258 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10259 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10260 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10261 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10262 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10263 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10264 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10265 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10266 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10267 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10268 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10269 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10270 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10271 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10274 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10276 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10277 WMSFT_TLBFile file;
10278 DWORD written, junk_size, junk_offs, running_offset;
10279 BOOL br;
10280 HANDLE outfile;
10281 HRESULT hres;
10282 DWORD *junk;
10283 UINT i;
10285 TRACE("%p\n", This);
10287 for(i = 0; i < This->TypeInfoCount; ++i)
10288 if(This->typeinfos[i]->needs_layout)
10289 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10291 memset(&file, 0, sizeof(file));
10293 file.header.magic1 = 0x5446534D;
10294 file.header.magic2 = 0x00010002;
10295 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10296 file.header.lcid2 = This->set_lcid;
10297 file.header.varflags = 0x40 | This->syskind;
10298 if (This->HelpFile)
10299 file.header.varflags |= 0x10;
10300 if (This->HelpStringDll)
10301 file.header.varflags |= HELPDLLFLAG;
10302 file.header.version = (This->ver_minor << 16) | This->ver_major;
10303 file.header.flags = This->libflags;
10304 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10305 file.header.helpcontext = This->dwHelpContext;
10306 file.header.res44 = 0x20;
10307 file.header.res48 = 0x80;
10308 file.header.dispatchpos = This->dispatch_href;
10310 WMSFT_compile_namehash(This, &file);
10311 /* do name and string compilation to get offsets for other compilations */
10312 hres = WMSFT_compile_names(This, &file);
10313 if (FAILED(hres)){
10314 WMSFT_free_file(&file);
10315 return hres;
10318 hres = WMSFT_compile_strings(This, &file);
10319 if (FAILED(hres)){
10320 WMSFT_free_file(&file);
10321 return hres;
10324 WMSFT_compile_guidhash(This, &file);
10325 hres = WMSFT_compile_guids(This, &file);
10326 if (FAILED(hres)){
10327 WMSFT_free_file(&file);
10328 return hres;
10331 if(This->HelpFile)
10332 file.header.helpfile = This->HelpFile->offset;
10333 else
10334 file.header.helpfile = -1;
10336 if(This->DocString)
10337 file.header.helpstring = This->DocString->offset;
10338 else
10339 file.header.helpstring = -1;
10341 /* do some more segment compilation */
10342 file.header.nimpinfos = list_count(&This->ref_list);
10343 file.header.nrtypeinfos = This->TypeInfoCount;
10345 if(This->Name)
10346 file.header.NameOffset = This->Name->offset;
10347 else
10348 file.header.NameOffset = -1;
10350 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10352 if(This->guid)
10353 file.header.posguid = This->guid->offset;
10354 else
10355 file.header.posguid = -1;
10357 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10358 if(file.header.varflags & HELPDLLFLAG)
10359 junk_size += sizeof(DWORD);
10360 if(junk_size){
10361 junk = heap_alloc_zero(junk_size);
10362 if(file.header.varflags & HELPDLLFLAG){
10363 *junk = This->HelpStringDll->offset;
10364 junk_offs = 1;
10365 }else
10366 junk_offs = 0;
10367 }else{
10368 junk = NULL;
10369 junk_offs = 0;
10372 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10373 WMSFT_compile_impinfo(This, &file);
10375 running_offset = 0;
10377 TRACE("header at: 0x%x\n", running_offset);
10378 running_offset += sizeof(file.header);
10380 TRACE("junk at: 0x%x\n", running_offset);
10381 running_offset += junk_size;
10383 TRACE("segdir at: 0x%x\n", running_offset);
10384 running_offset += sizeof(file.segdir);
10386 TRACE("typeinfo at: 0x%x\n", running_offset);
10387 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10389 TRACE("guidhashtab at: 0x%x\n", running_offset);
10390 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10392 TRACE("guidtab at: 0x%x\n", running_offset);
10393 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10395 TRACE("reftab at: 0x%x\n", running_offset);
10396 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10398 TRACE("impinfo at: 0x%x\n", running_offset);
10399 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10401 TRACE("impfiles at: 0x%x\n", running_offset);
10402 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10404 TRACE("namehashtab at: 0x%x\n", running_offset);
10405 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10407 TRACE("nametab at: 0x%x\n", running_offset);
10408 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10410 TRACE("stringtab at: 0x%x\n", running_offset);
10411 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10413 TRACE("typdesc at: 0x%x\n", running_offset);
10414 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10416 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10417 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10419 TRACE("custdata at: 0x%x\n", running_offset);
10420 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10422 TRACE("cdguids at: 0x%x\n", running_offset);
10423 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10425 TRACE("res0e at: 0x%x\n", running_offset);
10426 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10428 TRACE("res0f at: 0x%x\n", running_offset);
10429 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10431 TRACE("aux_seg at: 0x%x\n", running_offset);
10433 WMSFT_fixup_typeinfos(This, &file, running_offset);
10435 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10436 FILE_ATTRIBUTE_NORMAL, 0);
10437 if (outfile == INVALID_HANDLE_VALUE){
10438 WMSFT_free_file(&file);
10439 heap_free(junk);
10440 return TYPE_E_IOERROR;
10443 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10444 if (!br) {
10445 WMSFT_free_file(&file);
10446 CloseHandle(outfile);
10447 heap_free(junk);
10448 return TYPE_E_IOERROR;
10451 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10452 heap_free(junk);
10453 if (!br) {
10454 WMSFT_free_file(&file);
10455 CloseHandle(outfile);
10456 return TYPE_E_IOERROR;
10459 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10460 if (!br) {
10461 WMSFT_free_file(&file);
10462 CloseHandle(outfile);
10463 return TYPE_E_IOERROR;
10466 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10467 WMSFT_write_segment(outfile, &file.guidhash_seg);
10468 WMSFT_write_segment(outfile, &file.guid_seg);
10469 WMSFT_write_segment(outfile, &file.ref_seg);
10470 WMSFT_write_segment(outfile, &file.impinfo_seg);
10471 WMSFT_write_segment(outfile, &file.impfile_seg);
10472 WMSFT_write_segment(outfile, &file.namehash_seg);
10473 WMSFT_write_segment(outfile, &file.name_seg);
10474 WMSFT_write_segment(outfile, &file.string_seg);
10475 WMSFT_write_segment(outfile, &file.typdesc_seg);
10476 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10477 WMSFT_write_segment(outfile, &file.custdata_seg);
10478 WMSFT_write_segment(outfile, &file.cdguids_seg);
10479 WMSFT_write_segment(outfile, &file.aux_seg);
10481 WMSFT_free_file(&file);
10483 CloseHandle(outfile);
10485 return S_OK;
10488 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10489 LPOLESTR name)
10491 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10492 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10493 return E_NOTIMPL;
10496 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10497 REFGUID guid, VARIANT *varVal)
10499 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10500 TLBGuid *tlbguid;
10502 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10504 if (!guid || !varVal)
10505 return E_INVALIDARG;
10507 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10509 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10512 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10513 ULONG helpStringContext)
10515 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10516 FIXME("%p %u - stub\n", This, helpStringContext);
10517 return E_NOTIMPL;
10520 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10521 LPOLESTR filename)
10523 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10524 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10526 if (!filename)
10527 return E_INVALIDARG;
10529 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10531 return S_OK;
10534 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10535 ICreateTypeLib2_fnQueryInterface,
10536 ICreateTypeLib2_fnAddRef,
10537 ICreateTypeLib2_fnRelease,
10538 ICreateTypeLib2_fnCreateTypeInfo,
10539 ICreateTypeLib2_fnSetName,
10540 ICreateTypeLib2_fnSetVersion,
10541 ICreateTypeLib2_fnSetGuid,
10542 ICreateTypeLib2_fnSetDocString,
10543 ICreateTypeLib2_fnSetHelpFileName,
10544 ICreateTypeLib2_fnSetHelpContext,
10545 ICreateTypeLib2_fnSetLcid,
10546 ICreateTypeLib2_fnSetLibFlags,
10547 ICreateTypeLib2_fnSaveAllChanges,
10548 ICreateTypeLib2_fnDeleteTypeInfo,
10549 ICreateTypeLib2_fnSetCustData,
10550 ICreateTypeLib2_fnSetHelpStringContext,
10551 ICreateTypeLib2_fnSetHelpStringDll
10554 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10555 REFIID riid, void **object)
10557 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10559 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10562 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10564 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10566 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10569 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10571 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10573 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10576 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10577 REFGUID guid)
10579 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10581 TRACE("%p %s\n", This, debugstr_guid(guid));
10583 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10585 return S_OK;
10588 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10589 UINT typeFlags)
10591 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10592 WORD old_flags;
10593 HRESULT hres;
10595 TRACE("%p %x\n", This, typeFlags);
10597 if (typeFlags & TYPEFLAG_FDUAL) {
10598 ITypeLib *stdole;
10599 ITypeInfo *dispatch;
10600 HREFTYPE hreftype;
10601 HRESULT hres;
10603 hres = LoadTypeLib(L"stdole2.tlb", &stdole);
10604 if(FAILED(hres))
10605 return hres;
10607 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10608 ITypeLib_Release(stdole);
10609 if(FAILED(hres))
10610 return hres;
10612 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10613 ITypeInfo_Release(dispatch);
10614 if(FAILED(hres))
10615 return hres;
10618 old_flags = This->typeattr.wTypeFlags;
10619 This->typeattr.wTypeFlags = typeFlags;
10621 hres = ICreateTypeInfo2_LayOut(iface);
10622 if (FAILED(hres)) {
10623 This->typeattr.wTypeFlags = old_flags;
10624 return hres;
10627 return S_OK;
10630 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10631 LPOLESTR doc)
10633 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10635 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10637 if (!doc)
10638 return E_INVALIDARG;
10640 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10642 return S_OK;
10645 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10646 DWORD helpContext)
10648 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10650 TRACE("%p %d\n", This, helpContext);
10652 This->dwHelpContext = helpContext;
10654 return S_OK;
10657 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10658 WORD majorVerNum, WORD minorVerNum)
10660 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10662 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10664 This->typeattr.wMajorVerNum = majorVerNum;
10665 This->typeattr.wMinorVerNum = minorVerNum;
10667 return S_OK;
10670 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10671 ITypeInfo *typeInfo, HREFTYPE *refType)
10673 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10674 UINT index;
10675 ITypeLib *container;
10676 TLBRefType *ref_type;
10677 TLBImpLib *implib;
10678 TYPEATTR *typeattr;
10679 TLIBATTR *libattr;
10680 HRESULT hres;
10682 TRACE("%p %p %p\n", This, typeInfo, refType);
10684 if (!typeInfo || !refType)
10685 return E_INVALIDARG;
10687 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10688 if (FAILED(hres))
10689 return hres;
10691 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10692 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10694 ITypeLib_Release(container);
10696 *refType = target->hreftype;
10698 return S_OK;
10701 hres = ITypeLib_GetLibAttr(container, &libattr);
10702 if (FAILED(hres)) {
10703 ITypeLib_Release(container);
10704 return hres;
10707 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10708 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10709 implib->lcid == libattr->lcid &&
10710 implib->wVersionMajor == libattr->wMajorVerNum &&
10711 implib->wVersionMinor == libattr->wMinorVerNum)
10712 break;
10715 if(&implib->entry == &This->pTypeLib->implib_list){
10716 implib = heap_alloc_zero(sizeof(TLBImpLib));
10718 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10719 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10720 implib->name = SysAllocString(our_container->path);
10721 }else{
10722 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10723 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10724 if(FAILED(hres)){
10725 implib->name = NULL;
10726 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10730 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10731 implib->lcid = libattr->lcid;
10732 implib->wVersionMajor = libattr->wMajorVerNum;
10733 implib->wVersionMinor = libattr->wMinorVerNum;
10735 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10738 ITypeLib_ReleaseTLibAttr(container, libattr);
10739 ITypeLib_Release(container);
10741 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10742 if (FAILED(hres))
10743 return hres;
10745 index = 0;
10746 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10747 if(ref_type->index == TLB_REF_USE_GUID &&
10748 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10749 ref_type->tkind == typeattr->typekind)
10750 break;
10751 ++index;
10754 if(&ref_type->entry == &This->pTypeLib->ref_list){
10755 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10757 ref_type->tkind = typeattr->typekind;
10758 ref_type->pImpTLInfo = implib;
10759 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10761 ref_type->index = TLB_REF_USE_GUID;
10763 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10765 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10768 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10770 *refType = ref_type->reference | 0x1;
10772 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10773 This->pTypeLib->dispatch_href = *refType;
10775 return S_OK;
10778 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10779 UINT index, FUNCDESC *funcDesc)
10781 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10782 TLBFuncDesc tmp_func_desc, *func_desc;
10783 int buf_size, i;
10784 char *buffer;
10785 HRESULT hres;
10787 TRACE("%p %u %p\n", This, index, funcDesc);
10789 if (!funcDesc || funcDesc->oVft & 3)
10790 return E_INVALIDARG;
10792 switch (This->typeattr.typekind) {
10793 case TKIND_MODULE:
10794 if (funcDesc->funckind != FUNC_STATIC)
10795 return TYPE_E_BADMODULEKIND;
10796 break;
10797 case TKIND_DISPATCH:
10798 if (funcDesc->funckind != FUNC_DISPATCH)
10799 return TYPE_E_BADMODULEKIND;
10800 break;
10801 default:
10802 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10803 return TYPE_E_BADMODULEKIND;
10806 if (index > This->typeattr.cFuncs)
10807 return TYPE_E_ELEMENTNOTFOUND;
10809 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10810 !funcDesc->cParams)
10811 return TYPE_E_INCONSISTENTPROPFUNCS;
10813 #ifdef _WIN64
10814 if(This->pTypeLib->syskind == SYS_WIN64 &&
10815 funcDesc->oVft % 8 != 0)
10816 return E_INVALIDARG;
10817 #endif
10819 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10820 TLBFuncDesc_Constructor(&tmp_func_desc);
10822 tmp_func_desc.funcdesc = *funcDesc;
10824 if (tmp_func_desc.funcdesc.oVft != 0)
10825 tmp_func_desc.funcdesc.oVft |= 1;
10827 if (funcDesc->cScodes && funcDesc->lprgscode) {
10828 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10829 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10830 } else {
10831 tmp_func_desc.funcdesc.lprgscode = NULL;
10832 tmp_func_desc.funcdesc.cScodes = 0;
10835 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10836 for (i = 0; i < funcDesc->cParams; ++i) {
10837 buf_size += sizeof(ELEMDESC);
10838 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10840 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10841 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10843 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10844 if (FAILED(hres)) {
10845 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10846 heap_free(tmp_func_desc.funcdesc.lprgscode);
10847 return hres;
10850 for (i = 0; i < funcDesc->cParams; ++i) {
10851 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10852 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10853 if (FAILED(hres)) {
10854 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10855 heap_free(tmp_func_desc.funcdesc.lprgscode);
10856 return hres;
10858 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10859 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10860 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10861 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10862 if (FAILED(hres)) {
10863 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10864 heap_free(tmp_func_desc.funcdesc.lprgscode);
10865 return hres;
10870 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10872 if (This->funcdescs) {
10873 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10874 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10876 if (index < This->typeattr.cFuncs) {
10877 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10878 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10879 func_desc = This->funcdescs + index;
10880 } else
10881 func_desc = This->funcdescs + This->typeattr.cFuncs;
10883 /* move custdata lists to the new memory location */
10884 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10885 if(index != i)
10886 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10888 } else
10889 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10891 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10892 list_init(&func_desc->custdata_list);
10894 ++This->typeattr.cFuncs;
10896 This->needs_layout = TRUE;
10898 return S_OK;
10901 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10902 UINT index, HREFTYPE refType)
10904 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10905 TLBImplType *impl_type;
10906 HRESULT hres;
10908 TRACE("%p %u %d\n", This, index, refType);
10910 switch(This->typeattr.typekind){
10911 case TKIND_COCLASS: {
10912 if (index == -1) {
10913 FIXME("Unhandled index: -1\n");
10914 return E_NOTIMPL;
10917 if(index != This->typeattr.cImplTypes)
10918 return TYPE_E_ELEMENTNOTFOUND;
10920 break;
10922 case TKIND_INTERFACE:
10923 case TKIND_DISPATCH:
10924 if (index != 0 || This->typeattr.cImplTypes)
10925 return TYPE_E_ELEMENTNOTFOUND;
10926 break;
10927 default:
10928 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10929 return E_NOTIMPL;
10932 if (This->impltypes){
10933 UINT i;
10935 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10936 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10938 if (index < This->typeattr.cImplTypes) {
10939 memmove(This->impltypes + index + 1, This->impltypes + index,
10940 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10941 impl_type = This->impltypes + index;
10942 } else
10943 impl_type = This->impltypes + This->typeattr.cImplTypes;
10945 /* move custdata lists to the new memory location */
10946 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10947 if(index != i)
10948 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10950 } else
10951 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10953 memset(impl_type, 0, sizeof(TLBImplType));
10954 TLBImplType_Constructor(impl_type);
10955 impl_type->hRef = refType;
10957 ++This->typeattr.cImplTypes;
10959 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10960 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10962 hres = ICreateTypeInfo2_LayOut(iface);
10963 if (FAILED(hres))
10964 return hres;
10966 return S_OK;
10969 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10970 UINT index, INT implTypeFlags)
10972 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10973 TLBImplType *impl_type = &This->impltypes[index];
10975 TRACE("%p %u %x\n", This, index, implTypeFlags);
10977 if (This->typeattr.typekind != TKIND_COCLASS)
10978 return TYPE_E_BADMODULEKIND;
10980 if (index >= This->typeattr.cImplTypes)
10981 return TYPE_E_ELEMENTNOTFOUND;
10983 impl_type->implflags = implTypeFlags;
10985 return S_OK;
10988 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10989 WORD alignment)
10991 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10993 TRACE("%p %d\n", This, alignment);
10995 This->typeattr.cbAlignment = alignment;
10997 return S_OK;
11000 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
11001 LPOLESTR schema)
11003 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11005 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
11007 if (!schema)
11008 return E_INVALIDARG;
11010 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
11012 This->typeattr.lpstrSchema = This->Schema->str;
11014 return S_OK;
11017 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
11018 UINT index, VARDESC *varDesc)
11020 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11021 TLBVarDesc *var_desc;
11023 TRACE("%p %u %p\n", This, index, varDesc);
11025 if (This->vardescs){
11026 UINT i;
11028 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
11029 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
11031 if (index < This->typeattr.cVars) {
11032 memmove(This->vardescs + index + 1, This->vardescs + index,
11033 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
11034 var_desc = This->vardescs + index;
11035 } else
11036 var_desc = This->vardescs + This->typeattr.cVars;
11038 /* move custdata lists to the new memory location */
11039 for(i = 0; i < This->typeattr.cVars + 1; ++i){
11040 if(index != i)
11041 TLB_relink_custdata(&This->vardescs[i].custdata_list);
11043 } else
11044 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
11046 TLBVarDesc_Constructor(var_desc);
11047 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
11048 var_desc->vardesc = *var_desc->vardesc_create;
11050 ++This->typeattr.cVars;
11052 This->needs_layout = TRUE;
11054 return S_OK;
11057 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
11058 UINT index, LPOLESTR *names, UINT numNames)
11060 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11061 TLBFuncDesc *func_desc = &This->funcdescs[index];
11062 int i;
11064 TRACE("%p %u %p %u\n", This, index, names, numNames);
11066 if (!names)
11067 return E_INVALIDARG;
11069 if (index >= This->typeattr.cFuncs || numNames == 0)
11070 return TYPE_E_ELEMENTNOTFOUND;
11072 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
11073 if(numNames > func_desc->funcdesc.cParams)
11074 return TYPE_E_ELEMENTNOTFOUND;
11075 } else
11076 if(numNames > func_desc->funcdesc.cParams + 1)
11077 return TYPE_E_ELEMENTNOTFOUND;
11079 for(i = 0; i < This->typeattr.cFuncs; ++i) {
11080 TLBFuncDesc *iter = &This->funcdescs[i];
11081 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
11082 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11083 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11084 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
11085 continue;
11086 return TYPE_E_AMBIGUOUSNAME;
11090 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
11092 for (i = 1; i < numNames; ++i) {
11093 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
11094 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
11097 return S_OK;
11100 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
11101 UINT index, LPOLESTR name)
11103 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11105 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
11107 if(!name)
11108 return E_INVALIDARG;
11110 if(index >= This->typeattr.cVars)
11111 return TYPE_E_ELEMENTNOTFOUND;
11113 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
11114 return S_OK;
11117 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
11118 TYPEDESC *tdescAlias)
11120 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11121 HRESULT hr;
11123 TRACE("%p %p\n", This, tdescAlias);
11125 if(!tdescAlias)
11126 return E_INVALIDARG;
11128 if(This->typeattr.typekind != TKIND_ALIAS)
11129 return TYPE_E_BADMODULEKIND;
11131 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11132 if(FAILED(hr))
11133 return hr;
11135 heap_free(This->tdescAlias);
11136 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11137 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11139 return S_OK;
11142 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11143 UINT index, LPOLESTR dllName, LPOLESTR procName)
11145 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11146 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11147 return E_NOTIMPL;
11150 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11151 UINT index, LPOLESTR docString)
11153 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11154 TLBFuncDesc *func_desc = &This->funcdescs[index];
11156 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11158 if(!docString)
11159 return E_INVALIDARG;
11161 if(index >= This->typeattr.cFuncs)
11162 return TYPE_E_ELEMENTNOTFOUND;
11164 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11166 return S_OK;
11169 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11170 UINT index, LPOLESTR docString)
11172 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11173 TLBVarDesc *var_desc = &This->vardescs[index];
11175 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11177 if(!docString)
11178 return E_INVALIDARG;
11180 if(index >= This->typeattr.cVars)
11181 return TYPE_E_ELEMENTNOTFOUND;
11183 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11185 return S_OK;
11188 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11189 UINT index, DWORD helpContext)
11191 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11192 TLBFuncDesc *func_desc = &This->funcdescs[index];
11194 TRACE("%p %u %d\n", This, index, helpContext);
11196 if(index >= This->typeattr.cFuncs)
11197 return TYPE_E_ELEMENTNOTFOUND;
11199 func_desc->helpcontext = helpContext;
11201 return S_OK;
11204 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11205 UINT index, DWORD helpContext)
11207 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11208 TLBVarDesc *var_desc = &This->vardescs[index];
11210 TRACE("%p %u %d\n", This, index, helpContext);
11212 if(index >= This->typeattr.cVars)
11213 return TYPE_E_ELEMENTNOTFOUND;
11215 var_desc->HelpContext = helpContext;
11217 return S_OK;
11220 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11221 UINT index, BSTR bstrMops)
11223 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11224 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11225 return E_NOTIMPL;
11228 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11229 IDLDESC *idlDesc)
11231 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11233 TRACE("%p %p\n", This, idlDesc);
11235 if (!idlDesc)
11236 return E_INVALIDARG;
11238 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11239 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11241 return S_OK;
11244 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11246 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11247 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11248 TLBFuncDesc *func_desc;
11249 UINT user_vft = 0, i, depth = 0;
11250 HRESULT hres = S_OK;
11252 TRACE("%p\n", This);
11254 This->needs_layout = FALSE;
11256 if (This->typeattr.typekind == TKIND_INTERFACE) {
11257 ITypeInfo *inh;
11258 TYPEATTR *attr;
11259 HREFTYPE inh_href;
11261 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11263 if (SUCCEEDED(hres)) {
11264 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11266 if (SUCCEEDED(hres)) {
11267 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11268 if (FAILED(hres)) {
11269 ITypeInfo_Release(inh);
11270 return hres;
11272 This->typeattr.cbSizeVft = attr->cbSizeVft;
11273 ITypeInfo_ReleaseTypeAttr(inh, attr);
11276 ++depth;
11277 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11278 if(SUCCEEDED(hres)){
11279 ITypeInfo *next;
11280 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11281 if(SUCCEEDED(hres)){
11282 ITypeInfo_Release(inh);
11283 inh = next;
11286 }while(SUCCEEDED(hres));
11287 hres = S_OK;
11289 ITypeInfo_Release(inh);
11290 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11291 This->typeattr.cbSizeVft = 0;
11292 hres = S_OK;
11293 } else
11294 return hres;
11295 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11296 This->typeattr.cbSizeVft = 0;
11297 hres = S_OK;
11298 } else
11299 return hres;
11300 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11301 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11302 else
11303 This->typeattr.cbSizeVft = 0;
11305 func_desc = This->funcdescs;
11306 i = 0;
11307 while (i < This->typeattr.cFuncs) {
11308 if (!(func_desc->funcdesc.oVft & 0x1))
11309 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11311 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11312 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11314 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11316 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11317 TLBFuncDesc *iter;
11318 UINT j = 0;
11319 BOOL reset = FALSE;
11321 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11323 iter = This->funcdescs;
11324 while (j < This->typeattr.cFuncs) {
11325 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11326 if (!reset) {
11327 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11328 reset = TRUE;
11329 } else
11330 ++func_desc->funcdesc.memid;
11331 iter = This->funcdescs;
11332 j = 0;
11333 } else {
11334 ++iter;
11335 ++j;
11340 ++func_desc;
11341 ++i;
11344 if (user_vft > This->typeattr.cbSizeVft)
11345 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11347 for(i = 0; i < This->typeattr.cVars; ++i){
11348 TLBVarDesc *var_desc = &This->vardescs[i];
11349 if(var_desc->vardesc.memid == MEMBERID_NIL){
11350 UINT j = 0;
11351 BOOL reset = FALSE;
11352 TLBVarDesc *iter;
11354 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11356 iter = This->vardescs;
11357 while (j < This->typeattr.cVars) {
11358 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11359 if (!reset) {
11360 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11361 reset = TRUE;
11362 } else
11363 ++var_desc->vardesc.memid;
11364 iter = This->vardescs;
11365 j = 0;
11366 } else {
11367 ++iter;
11368 ++j;
11374 return hres;
11377 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11378 UINT index)
11380 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11381 unsigned int i;
11383 TRACE("%p %u\n", This, index);
11385 if (index >= This->typeattr.cFuncs)
11386 return TYPE_E_ELEMENTNOTFOUND;
11388 typeinfo_release_funcdesc(&This->funcdescs[index]);
11390 --This->typeattr.cFuncs;
11391 if (index != This->typeattr.cFuncs)
11393 memmove(This->funcdescs + index, This->funcdescs + index + 1,
11394 sizeof(*This->funcdescs) * (This->typeattr.cFuncs - index));
11395 for (i = index; i < This->typeattr.cFuncs; ++i)
11396 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
11399 This->needs_layout = TRUE;
11401 return S_OK;
11404 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11405 MEMBERID memid, INVOKEKIND invKind)
11407 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11408 FIXME("%p %x %d - stub\n", This, memid, invKind);
11409 return E_NOTIMPL;
11412 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11413 UINT index)
11415 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11416 FIXME("%p %u - stub\n", This, index);
11417 return E_NOTIMPL;
11420 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11421 MEMBERID memid)
11423 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11424 FIXME("%p %x - stub\n", This, memid);
11425 return E_NOTIMPL;
11428 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11429 UINT index)
11431 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11432 int i;
11434 TRACE("%p %u\n", This, index);
11436 if (index >= This->typeattr.cImplTypes)
11437 return TYPE_E_ELEMENTNOTFOUND;
11439 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11440 --This->typeattr.cImplTypes;
11442 if (index < This->typeattr.cImplTypes)
11444 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11445 sizeof(*This->impltypes));
11446 for (i = index; i < This->typeattr.cImplTypes; ++i)
11447 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11450 return S_OK;
11453 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11454 REFGUID guid, VARIANT *varVal)
11456 TLBGuid *tlbguid;
11458 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11460 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11462 if (!guid || !varVal)
11463 return E_INVALIDARG;
11465 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11467 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11470 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11471 UINT index, REFGUID guid, VARIANT *varVal)
11473 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11474 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11475 return E_NOTIMPL;
11478 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11479 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11481 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11482 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11483 return E_NOTIMPL;
11486 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11487 UINT index, REFGUID guid, VARIANT *varVal)
11489 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11490 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11491 return E_NOTIMPL;
11494 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11495 UINT index, REFGUID guid, VARIANT *varVal)
11497 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11498 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11499 return E_NOTIMPL;
11502 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11503 ULONG helpStringContext)
11505 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11507 TRACE("%p %u\n", This, helpStringContext);
11509 This->dwHelpStringContext = helpStringContext;
11511 return S_OK;
11514 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11515 UINT index, ULONG helpStringContext)
11517 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11518 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11519 return E_NOTIMPL;
11522 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11523 UINT index, ULONG helpStringContext)
11525 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11526 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11527 return E_NOTIMPL;
11530 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11532 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11533 FIXME("%p - stub\n", This);
11534 return E_NOTIMPL;
11537 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11538 LPOLESTR name)
11540 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11542 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11544 if (!name)
11545 return E_INVALIDARG;
11547 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11549 return S_OK;
11552 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11553 ICreateTypeInfo2_fnQueryInterface,
11554 ICreateTypeInfo2_fnAddRef,
11555 ICreateTypeInfo2_fnRelease,
11556 ICreateTypeInfo2_fnSetGuid,
11557 ICreateTypeInfo2_fnSetTypeFlags,
11558 ICreateTypeInfo2_fnSetDocString,
11559 ICreateTypeInfo2_fnSetHelpContext,
11560 ICreateTypeInfo2_fnSetVersion,
11561 ICreateTypeInfo2_fnAddRefTypeInfo,
11562 ICreateTypeInfo2_fnAddFuncDesc,
11563 ICreateTypeInfo2_fnAddImplType,
11564 ICreateTypeInfo2_fnSetImplTypeFlags,
11565 ICreateTypeInfo2_fnSetAlignment,
11566 ICreateTypeInfo2_fnSetSchema,
11567 ICreateTypeInfo2_fnAddVarDesc,
11568 ICreateTypeInfo2_fnSetFuncAndParamNames,
11569 ICreateTypeInfo2_fnSetVarName,
11570 ICreateTypeInfo2_fnSetTypeDescAlias,
11571 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11572 ICreateTypeInfo2_fnSetFuncDocString,
11573 ICreateTypeInfo2_fnSetVarDocString,
11574 ICreateTypeInfo2_fnSetFuncHelpContext,
11575 ICreateTypeInfo2_fnSetVarHelpContext,
11576 ICreateTypeInfo2_fnSetMops,
11577 ICreateTypeInfo2_fnSetTypeIdldesc,
11578 ICreateTypeInfo2_fnLayOut,
11579 ICreateTypeInfo2_fnDeleteFuncDesc,
11580 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11581 ICreateTypeInfo2_fnDeleteVarDesc,
11582 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11583 ICreateTypeInfo2_fnDeleteImplType,
11584 ICreateTypeInfo2_fnSetCustData,
11585 ICreateTypeInfo2_fnSetFuncCustData,
11586 ICreateTypeInfo2_fnSetParamCustData,
11587 ICreateTypeInfo2_fnSetVarCustData,
11588 ICreateTypeInfo2_fnSetImplTypeCustData,
11589 ICreateTypeInfo2_fnSetHelpStringContext,
11590 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11591 ICreateTypeInfo2_fnSetVarHelpStringContext,
11592 ICreateTypeInfo2_fnInvalidate,
11593 ICreateTypeInfo2_fnSetName
11596 /******************************************************************************
11597 * ClearCustData (OLEAUT32.171)
11599 * Clear a custom data type's data.
11601 * PARAMS
11602 * lpCust [I] The custom data type instance
11604 * RETURNS
11605 * Nothing.
11607 void WINAPI ClearCustData(CUSTDATA *lpCust)
11609 if (lpCust && lpCust->cCustData)
11611 if (lpCust->prgCustData)
11613 DWORD i;
11615 for (i = 0; i < lpCust->cCustData; i++)
11616 VariantClear(&lpCust->prgCustData[i].varValue);
11618 CoTaskMemFree(lpCust->prgCustData);
11619 lpCust->prgCustData = NULL;
11621 lpCust->cCustData = 0;