include: Add ID2D1PathGeometry1 definition.
[wine.git] / dlls / oleaut32 / typelib.c
blob7f10bcc968de5348724e794d3cc96af24765123b
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include <stdlib.h>
51 #include <string.h>
52 #include <stdarg.h>
53 #include <stdio.h>
54 #include <ctype.h>
56 #define COBJMACROS
57 #define NONAMELESSUNION
59 #include "winerror.h"
60 #include "windef.h"
61 #include "winbase.h"
62 #include "winnls.h"
63 #include "winreg.h"
64 #include "winuser.h"
65 #include "winternl.h"
66 #include "lzexpand.h"
68 #include "objbase.h"
69 #include "typelib.h"
70 #include "wine/debug.h"
71 #include "variant.h"
72 #include "wine/asm.h"
73 #include "wine/heap.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
101 static void TLB_FreeVarDesc(VARDESC*);
103 /****************************************************************************
104 * FromLExxx
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
109 #ifdef WORDS_BIGENDIAN
110 static WORD FromLEWord(WORD p_iVal)
112 return (((p_iVal & 0x00FF) << 8) |
113 ((p_iVal & 0xFF00) >> 8));
117 static DWORD FromLEDWord(DWORD p_iVal)
119 return (((p_iVal & 0x000000FF) << 24) |
120 ((p_iVal & 0x0000FF00) << 8) |
121 ((p_iVal & 0x00FF0000) >> 8) |
122 ((p_iVal & 0xFF000000) >> 24));
124 #else
125 #define FromLEWord(X) (X)
126 #define FromLEDWord(X) (X)
127 #endif
129 #define DISPATCH_HREF_OFFSET 0x01000000
130 #define DISPATCH_HREF_MASK 0xff000000
132 /****************************************************************************
133 * FromLExxx
135 * Fix byte order in any structure if necessary
137 #ifdef WORDS_BIGENDIAN
138 static void FromLEWords(void *p_Val, int p_iSize)
140 WORD *Val = p_Val;
142 p_iSize /= sizeof(WORD);
144 while (p_iSize) {
145 *Val = FromLEWord(*Val);
146 Val++;
147 p_iSize--;
152 static void FromLEDWords(void *p_Val, int p_iSize)
154 DWORD *Val = p_Val;
156 p_iSize /= sizeof(DWORD);
158 while (p_iSize) {
159 *Val = FromLEDWord(*Val);
160 Val++;
161 p_iSize--;
164 #else
165 #define FromLEWords(X,Y) /*nothing*/
166 #define FromLEDWords(X,Y) /*nothing*/
167 #endif
170 * Find a typelib key which matches a requested maj.min version.
172 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
180 lstrcpyW( buffer, L"Typelib\\" );
181 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min >= *wMin && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 lstrcpyW( buffer, L"Typelib\\" );
242 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
243 swprintf( buffer + lstrlenW(buffer), 20, L"\\%x.%x", wMaj, wMin );
244 return buffer;
247 /* get the path of an interface key, in the form "Interface\\<guid>" */
248 /* buffer must be at least 50 characters long */
249 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
251 lstrcpyW( buffer, L"Interface\\" );
252 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
253 return buffer;
256 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
257 /* buffer must be at least 16 characters long */
258 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
260 swprintf( buffer, 16, L"%lx\\", lcid );
261 switch(syskind)
263 case SYS_WIN16: lstrcatW( buffer, L"win16" ); break;
264 case SYS_WIN32: lstrcatW( buffer, L"win32" ); break;
265 case SYS_WIN64: lstrcatW( buffer, L"win64" ); break;
266 default:
267 TRACE("Typelib is for unsupported syskind %i\n", syskind);
268 return NULL;
270 return buffer;
273 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
275 struct tlibredirect_data
277 ULONG size;
278 DWORD res;
279 ULONG name_len;
280 ULONG name_offset;
281 LANGID langid;
282 WORD flags;
283 ULONG help_len;
284 ULONG help_offset;
285 WORD major_version;
286 WORD minor_version;
289 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
290 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
291 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
293 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
294 LCID myLCID = lcid;
295 HKEY hkey;
296 WCHAR buffer[60];
297 WCHAR Path[MAX_PATH];
298 LONG res;
300 TRACE_(typelib)("%s, %x.%x, %#lx, %p\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
302 if (redir)
304 ACTCTX_SECTION_KEYED_DATA data;
306 data.cbSize = sizeof(data);
307 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
309 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
310 WCHAR *nameW;
311 DWORD len;
313 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
314 return TYPE_E_LIBNOTREGISTERED;
316 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
317 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
318 if (!len) return TYPE_E_LIBNOTREGISTERED;
320 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
321 *path = SysAllocString( Path );
322 return S_OK;
326 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
327 get_typelib_key( guid, wMaj, wMin, buffer );
329 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
330 if (res == ERROR_FILE_NOT_FOUND)
332 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
333 return TYPE_E_LIBNOTREGISTERED;
335 else if (res != ERROR_SUCCESS)
337 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
338 return TYPE_E_REGISTRYACCESS;
341 while (hr != S_OK)
343 LONG dwPathLen = sizeof(Path);
345 get_lcid_subkey( myLCID, syskind, buffer );
347 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
349 if (!lcid)
350 break;
351 else if (myLCID == lcid)
353 /* try with sub-langid */
354 myLCID = SUBLANGID(lcid);
356 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
358 /* try with system langid */
359 myLCID = 0;
361 else
363 break;
366 else
368 *path = SysAllocString( Path );
369 hr = S_OK;
372 RegCloseKey( hkey );
373 TRACE_(typelib)("-- %#lx\n", hr);
374 return hr;
377 /****************************************************************************
378 * QueryPathOfRegTypeLib [OLEAUT32.164]
380 * Gets the path to a registered type library.
382 * PARAMS
383 * guid [I] referenced guid
384 * wMaj [I] major version
385 * wMin [I] minor version
386 * lcid [I] locale id
387 * path [O] path of typelib
389 * RETURNS
390 * Success: S_OK.
391 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
392 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
393 * opened.
395 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
397 BOOL redir = TRUE;
398 #ifdef _WIN64
399 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
400 if(SUCCEEDED(hres))
401 return hres;
402 redir = FALSE;
403 #endif
404 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
407 /******************************************************************************
408 * CreateTypeLib [OLEAUT32.160] creates a typelib
410 * RETURNS
411 * Success: S_OK
412 * Failure: Status
414 HRESULT WINAPI CreateTypeLib(
415 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
417 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
418 return E_FAIL;
421 /******************************************************************************
422 * LoadTypeLib [OLEAUT32.161]
424 * Loads a type library
426 * PARAMS
427 * szFile [I] Name of file to load from.
428 * pptLib [O] Pointer that receives ITypeLib object on success.
430 * RETURNS
431 * Success: S_OK
432 * Failure: Status
434 * SEE
435 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
437 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
439 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
440 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
443 /******************************************************************************
444 * LoadTypeLibEx [OLEAUT32.183]
446 * Loads and optionally registers a type library
448 * RETURNS
449 * Success: S_OK
450 * Failure: Status
452 HRESULT WINAPI LoadTypeLibEx(
453 LPCOLESTR szFile, /* [in] Name of file to load from */
454 REGKIND regkind, /* [in] Specify kind of registration */
455 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
457 WCHAR szPath[MAX_PATH+1];
458 HRESULT res;
460 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
462 if (!szFile || !pptLib)
463 return E_INVALIDARG;
465 *pptLib = NULL;
467 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
469 if (SUCCEEDED(res))
470 switch(regkind)
472 case REGKIND_DEFAULT:
473 /* don't register typelibs supplied with full path. Experimentation confirms the following */
474 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
475 (szFile[0] && (szFile[1] == ':'))) break;
476 /* else fall-through */
478 case REGKIND_REGISTER:
479 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
481 ITypeLib_Release(*pptLib);
482 *pptLib = 0;
484 break;
485 case REGKIND_NONE:
486 break;
489 TRACE(" returns %#lx\n",res);
490 return res;
493 /******************************************************************************
494 * LoadRegTypeLib [OLEAUT32.162]
496 * Loads a registered type library.
498 * PARAMS
499 * rguid [I] GUID of the registered type library.
500 * wVerMajor [I] major version.
501 * wVerMinor [I] minor version.
502 * lcid [I] locale ID.
503 * ppTLib [O] pointer that receives an ITypeLib object on success.
505 * RETURNS
506 * Success: S_OK.
507 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
508 * LoadTypeLib.
510 HRESULT WINAPI LoadRegTypeLib(
511 REFGUID rguid,
512 WORD wVerMajor,
513 WORD wVerMinor,
514 LCID lcid,
515 ITypeLib **ppTLib)
517 BSTR bstr=NULL;
518 HRESULT res;
520 *ppTLib = NULL;
522 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
524 if(SUCCEEDED(res))
526 res= LoadTypeLib(bstr, ppTLib);
527 SysFreeString(bstr);
529 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
531 TLIBATTR *attr;
533 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
534 if (res == S_OK)
536 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
537 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
539 if (mismatch)
541 ITypeLib_Release(*ppTLib);
542 *ppTLib = NULL;
543 res = TYPE_E_LIBNOTREGISTERED;
549 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
551 return res;
554 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
556 WCHAR keyName[60];
557 HKEY key, subKey;
559 get_interface_key( &tattr->guid, keyName );
560 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
561 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
563 const WCHAR *proxy_clsid;
565 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
566 proxy_clsid = L"{00020424-0000-0000-C000-000000000046}";
567 else
568 proxy_clsid = L"{00020420-0000-0000-C000-000000000046}";
570 if (name)
571 RegSetValueExW(key, NULL, 0, REG_SZ,
572 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR));
574 if (!RegCreateKeyExW(key, L"ProxyStubClsid", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
576 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
577 RegCloseKey(subKey);
580 if (!RegCreateKeyExW(key, L"ProxyStubClsid32", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
582 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
583 RegCloseKey(subKey);
586 if (RegCreateKeyExW(key, L"TypeLib", 0, NULL, 0,
587 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
589 WCHAR buffer[40];
591 StringFromGUID2(&libattr->guid, buffer, 40);
592 RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
594 swprintf(buffer, ARRAY_SIZE(buffer), L"%x.%x", libattr->wMajorVerNum, libattr->wMinorVerNum);
595 RegSetValueExW(subKey, L"Version", 0, REG_SZ, (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
596 RegCloseKey(subKey);
599 RegCloseKey(key);
603 /******************************************************************************
604 * RegisterTypeLib [OLEAUT32.163]
605 * Adds information about a type library to the System Registry
606 * NOTES
607 * Docs: ITypeLib FAR * ptlib
608 * Docs: OLECHAR FAR* szFullPath
609 * Docs: OLECHAR FAR* szHelpDir
611 * RETURNS
612 * Success: S_OK
613 * Failure: Status
615 HRESULT WINAPI RegisterTypeLib(ITypeLib *ptlib, const WCHAR *szFullPath, const WCHAR *szHelpDir)
617 HRESULT res;
618 TLIBATTR *attr;
619 WCHAR keyName[60];
620 WCHAR tmp[16];
621 HKEY key, subKey;
622 UINT types, tidx;
623 TYPEKIND kind;
624 DWORD disposition;
626 if (ptlib == NULL || szFullPath == NULL)
627 return E_INVALIDARG;
629 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
630 return E_FAIL;
632 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
634 res = S_OK;
635 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
636 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
638 LPOLESTR doc;
639 LPOLESTR libName;
641 /* Set the human-readable name of the typelib to
642 the typelib's doc, if it exists, else to the typelib's name. */
643 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, &libName, &doc, NULL, NULL)))
644 res = E_FAIL;
645 else if (doc || libName)
647 WCHAR *name = doc ? doc : libName;
649 if (RegSetValueExW(key, NULL, 0, REG_SZ,
650 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
651 res = E_FAIL;
653 SysFreeString(doc);
654 SysFreeString(libName);
657 /* Make up the name of the typelib path subkey */
658 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
660 /* Create the typelib path subkey */
661 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
662 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
664 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
665 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
666 res = E_FAIL;
668 RegCloseKey(subKey);
670 else
671 res = E_FAIL;
673 /* Create the flags subkey */
674 if (res == S_OK && RegCreateKeyExW(key, L"FLAGS", 0, NULL, 0,
675 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
677 WCHAR buf[20];
679 /* FIXME: is %u correct? */
680 swprintf(buf, ARRAY_SIZE(buf), L"%u", attr->wLibFlags);
681 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
682 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
683 res = E_FAIL;
685 RegCloseKey(subKey);
687 else
688 res = E_FAIL;
690 /* create the helpdir subkey */
691 if (res == S_OK && RegCreateKeyExW(key, L"HELPDIR", 0, NULL, 0,
692 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
694 BSTR freeHelpDir = NULL;
695 WCHAR *file_name;
697 /* if we created a new key, and helpDir was null, set the helpdir
698 to the directory which contains the typelib. However,
699 if we just opened an existing key, we leave the helpdir alone */
700 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
701 szHelpDir = freeHelpDir = SysAllocString(szFullPath);
702 file_name = wcsrchr(szHelpDir, '\\');
703 if (file_name && file_name[1]) {
704 /* possible remove a numeric \index (resource-id) */
705 WCHAR *end_ptr = file_name + 1;
706 while ('0' <= *end_ptr && *end_ptr <= '9') end_ptr++;
707 if (!*end_ptr)
709 *file_name = 0;
710 file_name = wcsrchr(szHelpDir, '\\');
713 if (file_name)
714 *file_name = 0;
717 /* if we have an szHelpDir, set it! */
718 if (szHelpDir != NULL) {
719 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
721 res = E_FAIL;
725 SysFreeString(freeHelpDir);
726 RegCloseKey(subKey);
727 } else {
728 res = E_FAIL;
731 RegCloseKey(key);
733 else
734 res = E_FAIL;
736 /* register OLE Automation-compatible interfaces for this typelib */
737 types = ITypeLib_GetTypeInfoCount(ptlib);
738 for (tidx=0; tidx<types; tidx++) {
739 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
740 LPOLESTR name = NULL;
741 ITypeInfo *tinfo = NULL;
743 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
745 switch (kind) {
746 case TKIND_INTERFACE:
747 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
748 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
749 break;
751 case TKIND_DISPATCH:
752 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
753 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
754 break;
756 default:
757 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
758 break;
761 if (tinfo) {
762 TYPEATTR *tattr = NULL;
763 ITypeInfo_GetTypeAttr(tinfo, &tattr);
765 if (tattr) {
766 TRACE_(typelib)("guid=%s, flags=%04x (",
767 debugstr_guid(&tattr->guid),
768 tattr->wTypeFlags);
770 if (TRACE_ON(typelib)) {
771 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
772 XX(FAPPOBJECT);
773 XX(FCANCREATE);
774 XX(FLICENSED);
775 XX(FPREDECLID);
776 XX(FHIDDEN);
777 XX(FCONTROL);
778 XX(FDUAL);
779 XX(FNONEXTENSIBLE);
780 XX(FOLEAUTOMATION);
781 XX(FRESTRICTED);
782 XX(FAGGREGATABLE);
783 XX(FREPLACEABLE);
784 XX(FDISPATCHABLE);
785 XX(FREVERSEBIND);
786 XX(FPROXY);
787 #undef XX
788 MESSAGE("\n");
791 /* Register all dispinterfaces (which includes dual interfaces) and
792 oleautomation interfaces */
793 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
794 kind == TKIND_DISPATCH)
796 BOOL is_wow64;
797 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
799 /* register interface<->typelib coupling */
800 TLB_register_interface(attr, name, tattr, 0);
802 /* register TLBs into the opposite registry view, too */
803 if(opposite == KEY_WOW64_32KEY ||
804 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
805 TLB_register_interface(attr, name, tattr, opposite);
808 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
811 ITypeInfo_Release(tinfo);
814 SysFreeString(name);
818 ITypeLib_ReleaseTLibAttr(ptlib, attr);
820 return res;
823 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
825 WCHAR subKeyName[50];
826 HKEY subKey;
828 /* the path to the type */
829 get_interface_key( guid, subKeyName );
831 /* Delete its bits */
832 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
833 return;
835 RegDeleteKeyW(subKey, L"ProxyStubClsid");
836 RegDeleteKeyW(subKey, L"ProxyStubClsid32");
837 RegDeleteKeyW(subKey, L"TypeLib");
838 RegCloseKey(subKey);
839 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
842 /******************************************************************************
843 * UnRegisterTypeLib [OLEAUT32.186]
844 * Removes information about a type library from the System Registry
845 * NOTES
847 * RETURNS
848 * Success: S_OK
849 * Failure: Status
851 HRESULT WINAPI UnRegisterTypeLib(
852 REFGUID libid, /* [in] Guid of the library */
853 WORD wVerMajor, /* [in] major version */
854 WORD wVerMinor, /* [in] minor version */
855 LCID lcid, /* [in] locale id */
856 SYSKIND syskind)
858 BSTR tlibPath = NULL;
859 DWORD tmpLength;
860 WCHAR keyName[60];
861 WCHAR subKeyName[50];
862 int result = S_OK;
863 DWORD i = 0;
864 BOOL deleteOtherStuff;
865 HKEY key = NULL;
866 TYPEATTR* typeAttr = NULL;
867 TYPEKIND kind;
868 ITypeInfo* typeInfo = NULL;
869 ITypeLib* typeLib = NULL;
870 int numTypes;
872 TRACE("(IID: %s)\n",debugstr_guid(libid));
874 /* Create the path to the key */
875 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
877 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
879 TRACE("Unsupported syskind %i\n", syskind);
880 result = E_INVALIDARG;
881 goto end;
884 /* get the path to the typelib on disk */
885 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
886 result = E_INVALIDARG;
887 goto end;
890 /* Try and open the key to the type library. */
891 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
892 result = E_INVALIDARG;
893 goto end;
896 /* Try and load the type library */
897 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
898 result = TYPE_E_INVALIDSTATE;
899 goto end;
902 /* remove any types registered with this typelib */
903 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
904 for (i=0; i<numTypes; i++) {
905 /* get the kind of type */
906 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
907 goto enddeleteloop;
910 /* skip non-interfaces, and get type info for the type */
911 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
912 goto enddeleteloop;
914 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
915 goto enddeleteloop;
917 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
918 goto enddeleteloop;
921 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
922 kind == TKIND_DISPATCH)
924 BOOL is_wow64;
925 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
927 TLB_unregister_interface(&typeAttr->guid, 0);
929 /* unregister TLBs into the opposite registry view, too */
930 if(opposite == KEY_WOW64_32KEY ||
931 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
932 TLB_unregister_interface(&typeAttr->guid, opposite);
936 enddeleteloop:
937 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
938 typeAttr = NULL;
939 if (typeInfo) ITypeInfo_Release(typeInfo);
940 typeInfo = NULL;
943 /* Now, delete the type library path subkey */
944 get_lcid_subkey( lcid, syskind, subKeyName );
945 RegDeleteKeyW(key, subKeyName);
946 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
947 RegDeleteKeyW(key, subKeyName);
949 /* check if there is anything besides the FLAGS/HELPDIR keys.
950 If there is, we don't delete them */
951 tmpLength = ARRAY_SIZE(subKeyName);
952 deleteOtherStuff = TRUE;
953 i = 0;
954 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
955 tmpLength = ARRAY_SIZE(subKeyName);
957 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
958 if (!wcscmp(subKeyName, L"FLAGS")) continue;
959 if (!wcscmp(subKeyName, L"HELPDIR")) continue;
960 deleteOtherStuff = FALSE;
961 break;
964 /* only delete the other parts of the key if we're absolutely sure */
965 if (deleteOtherStuff) {
966 RegDeleteKeyW(key, L"FLAGS");
967 RegDeleteKeyW(key, L"HELPDIR");
968 RegCloseKey(key);
969 key = NULL;
971 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
972 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
973 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
976 end:
977 SysFreeString(tlibPath);
978 if (typeLib) ITypeLib_Release(typeLib);
979 if (key) RegCloseKey(key);
980 return result;
983 /******************************************************************************
984 * RegisterTypeLibForUser [OLEAUT32.442]
985 * Adds information about a type library to the user registry
986 * NOTES
987 * Docs: ITypeLib FAR * ptlib
988 * Docs: OLECHAR FAR* szFullPath
989 * Docs: OLECHAR FAR* szHelpDir
991 * RETURNS
992 * Success: S_OK
993 * Failure: Status
995 HRESULT WINAPI RegisterTypeLibForUser(
996 ITypeLib * ptlib, /* [in] Pointer to the library*/
997 OLECHAR * szFullPath, /* [in] full Path of the library*/
998 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
999 may be NULL*/
1001 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1002 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1003 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1006 /******************************************************************************
1007 * UnRegisterTypeLibForUser [OLEAUT32.443]
1008 * Removes information about a type library from the user registry
1010 * RETURNS
1011 * Success: S_OK
1012 * Failure: Status
1014 HRESULT WINAPI UnRegisterTypeLibForUser(
1015 REFGUID libid, /* [in] GUID of the library */
1016 WORD wVerMajor, /* [in] major version */
1017 WORD wVerMinor, /* [in] minor version */
1018 LCID lcid, /* [in] locale id */
1019 SYSKIND syskind)
1021 FIXME("%s, %u, %u, %#lx, %u unregistering the typelib system-wide\n",
1022 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1023 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1026 /*======================= ITypeLib implementation =======================*/
1028 typedef struct tagTLBGuid {
1029 GUID guid;
1030 INT hreftype;
1031 UINT offset;
1032 struct list entry;
1033 } TLBGuid;
1035 typedef struct tagTLBCustData
1037 TLBGuid *guid;
1038 VARIANT data;
1039 struct list entry;
1040 } TLBCustData;
1042 /* data structure for import typelibs */
1043 typedef struct tagTLBImpLib
1045 int offset; /* offset in the file (MSFT)
1046 offset in nametable (SLTG)
1047 just used to identify library while reading
1048 data from file */
1049 TLBGuid *guid; /* libid */
1050 BSTR name; /* name */
1052 LCID lcid; /* lcid of imported typelib */
1054 WORD wVersionMajor; /* major version number */
1055 WORD wVersionMinor; /* minor version number */
1057 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1058 NULL if not yet loaded */
1059 struct list entry;
1060 } TLBImpLib;
1062 typedef struct tagTLBString {
1063 BSTR str;
1064 UINT offset;
1065 struct list entry;
1066 } TLBString;
1068 /* internal ITypeLib data */
1069 typedef struct tagITypeLibImpl
1071 ITypeLib2 ITypeLib2_iface;
1072 ITypeComp ITypeComp_iface;
1073 ICreateTypeLib2 ICreateTypeLib2_iface;
1074 LONG ref;
1075 TLBGuid *guid;
1076 LCID lcid;
1077 SYSKIND syskind;
1078 int ptr_size;
1079 WORD ver_major;
1080 WORD ver_minor;
1081 WORD libflags;
1082 LCID set_lcid;
1084 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1085 * exported to the application as a UNICODE string.
1087 struct list string_list;
1088 struct list name_list;
1089 struct list guid_list;
1091 const TLBString *Name;
1092 const TLBString *DocString;
1093 const TLBString *HelpFile;
1094 const TLBString *HelpStringDll;
1095 DWORD dwHelpContext;
1096 int TypeInfoCount; /* nr of typeinfo's in librarry */
1097 struct tagITypeInfoImpl **typeinfos;
1098 struct list custdata_list;
1099 struct list implib_list;
1100 int ctTypeDesc; /* number of items in type desc array */
1101 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1102 library. Only used while reading MSFT
1103 typelibs */
1104 struct list ref_list; /* list of ref types in this typelib */
1105 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1108 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1109 struct list entry;
1110 WCHAR *path;
1111 INT index;
1112 } ITypeLibImpl;
1114 static const ITypeLib2Vtbl tlbvt;
1115 static const ITypeCompVtbl tlbtcvt;
1116 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1118 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1120 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1123 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1125 return impl_from_ITypeLib2((ITypeLib2*)iface);
1128 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1130 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1133 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1135 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1138 /* ITypeLib methods */
1139 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1140 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1142 /*======================= ITypeInfo implementation =======================*/
1144 /* data for referenced types */
1145 typedef struct tagTLBRefType
1147 INT index; /* Type index for internal ref or for external ref
1148 it the format is SLTG. -2 indicates to
1149 use guid */
1151 TYPEKIND tkind;
1152 TLBGuid *guid; /* guid of the referenced type */
1153 /* if index == TLB_REF_USE_GUID */
1155 HREFTYPE reference; /* The href of this ref */
1156 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1157 TLB_REF_INTERNAL for internal refs
1158 TLB_REF_NOT_FOUND for broken refs */
1160 struct list entry;
1161 } TLBRefType;
1163 #define TLB_REF_USE_GUID -2
1165 #define TLB_REF_INTERNAL (void*)-2
1166 #define TLB_REF_NOT_FOUND (void*)-1
1168 /* internal Parameter data */
1169 typedef struct tagTLBParDesc
1171 const TLBString *Name;
1172 struct list custdata_list;
1173 } TLBParDesc;
1175 /* internal Function data */
1176 typedef struct tagTLBFuncDesc
1178 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1179 const TLBString *Name; /* the name of this function */
1180 TLBParDesc *pParamDesc; /* array with param names and custom data */
1181 int helpcontext;
1182 int HelpStringContext;
1183 const TLBString *HelpString;
1184 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1185 struct list custdata_list;
1186 } TLBFuncDesc;
1188 /* internal Variable data */
1189 typedef struct tagTLBVarDesc
1191 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1192 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1193 const TLBString *Name; /* the name of this variable */
1194 int HelpContext;
1195 int HelpStringContext;
1196 const TLBString *HelpString;
1197 struct list custdata_list;
1198 } TLBVarDesc;
1200 /* internal implemented interface data */
1201 typedef struct tagTLBImplType
1203 HREFTYPE hRef; /* hRef of interface */
1204 int implflags; /* IMPLFLAG_*s */
1205 struct list custdata_list;
1206 } TLBImplType;
1208 /* internal TypeInfo data */
1209 typedef struct tagITypeInfoImpl
1211 ITypeInfo2 ITypeInfo2_iface;
1212 ITypeComp ITypeComp_iface;
1213 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1214 LONG ref;
1215 BOOL not_attached_to_typelib;
1216 BOOL needs_layout;
1218 TLBGuid *guid;
1219 TYPEATTR typeattr;
1220 TYPEDESC *tdescAlias;
1222 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1223 int index; /* index in this typelib; */
1224 HREFTYPE hreftype; /* hreftype for app object binding */
1225 /* type libs seem to store the doc strings in ascii
1226 * so why should we do it in unicode?
1228 const TLBString *Name;
1229 const TLBString *DocString;
1230 const TLBString *DllName;
1231 const TLBString *Schema;
1232 DWORD dwHelpContext;
1233 DWORD dwHelpStringContext;
1235 /* functions */
1236 TLBFuncDesc *funcdescs;
1238 /* variables */
1239 TLBVarDesc *vardescs;
1241 /* Implemented Interfaces */
1242 TLBImplType *impltypes;
1244 struct list *pcustdata_list;
1245 struct list custdata_list;
1246 } ITypeInfoImpl;
1248 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1250 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1253 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1255 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1258 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1260 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1263 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1265 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1268 static const ITypeInfo2Vtbl tinfvt;
1269 static const ITypeCompVtbl tcompvt;
1270 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1272 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1273 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1275 typedef struct tagTLBContext
1277 unsigned int oStart; /* start of TLB in file */
1278 unsigned int pos; /* current pos */
1279 unsigned int length; /* total length */
1280 void *mapping; /* memory mapping */
1281 MSFT_SegDir * pTblDir;
1282 ITypeLibImpl* pLibInfo;
1283 } TLBContext;
1286 static inline BSTR TLB_get_bstr(const TLBString *str)
1288 return str != NULL ? str->str : NULL;
1291 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1293 if(!str)
1294 return 1;
1295 return memcmp(left, str->str, len);
1298 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1300 return guid != NULL ? &guid->guid : NULL;
1303 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1305 return guid != NULL ? &guid->guid : &GUID_NULL;
1308 static int get_ptr_size(SYSKIND syskind)
1310 switch(syskind){
1311 case SYS_WIN64:
1312 return 8;
1313 case SYS_WIN32:
1314 case SYS_MAC:
1315 case SYS_WIN16:
1316 return 4;
1318 WARN("Unhandled syskind: 0x%x\n", syskind);
1319 return 4;
1323 debug
1325 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1326 if (pTD->vt & VT_RESERVED)
1327 szVarType += strlen(strcpy(szVarType, "reserved | "));
1328 if (pTD->vt & VT_BYREF)
1329 szVarType += strlen(strcpy(szVarType, "ref to "));
1330 if (pTD->vt & VT_ARRAY)
1331 szVarType += strlen(strcpy(szVarType, "array of "));
1332 if (pTD->vt & VT_VECTOR)
1333 szVarType += strlen(strcpy(szVarType, "vector of "));
1334 switch(pTD->vt & VT_TYPEMASK) {
1335 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1336 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1337 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1338 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1339 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1340 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1341 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1342 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1343 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1344 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1345 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1346 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1347 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1348 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1349 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1350 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1351 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1352 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1353 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1354 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1355 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx", pTD->u.hreftype); break;
1356 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1357 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1358 case VT_PTR: sprintf(szVarType, "ptr to ");
1359 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1360 break;
1361 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1362 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1363 break;
1364 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1365 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1366 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1367 break;
1369 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1373 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1374 char buf[200];
1375 USHORT flags = edesc->u.paramdesc.wParamFlags;
1376 dump_TypeDesc(&edesc->tdesc,buf);
1377 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1378 MESSAGE("\t\tu.paramdesc.wParamFlags");
1379 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1380 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1381 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1382 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1383 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1384 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1385 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1386 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1387 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1389 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1390 int i;
1391 MESSAGE("memid is %#lx\n", funcdesc->memid);
1392 for (i=0;i<funcdesc->cParams;i++) {
1393 MESSAGE("Param %d:\n",i);
1394 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1396 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1397 switch (funcdesc->funckind) {
1398 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1399 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1400 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1401 case FUNC_STATIC: MESSAGE("static");break;
1402 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1403 default: MESSAGE("unknown");break;
1405 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1406 switch (funcdesc->invkind) {
1407 case INVOKE_FUNC: MESSAGE("func");break;
1408 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1409 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1410 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1412 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1413 switch (funcdesc->callconv) {
1414 case CC_CDECL: MESSAGE("cdecl");break;
1415 case CC_PASCAL: MESSAGE("pascal");break;
1416 case CC_STDCALL: MESSAGE("stdcall");break;
1417 case CC_SYSCALL: MESSAGE("syscall");break;
1418 default:break;
1420 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1421 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1422 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1424 MESSAGE("\telemdescFunc (return value type):\n");
1425 dump_ELEMDESC(&funcdesc->elemdescFunc);
1428 static const char * const typekind_desc[] =
1430 "TKIND_ENUM",
1431 "TKIND_RECORD",
1432 "TKIND_MODULE",
1433 "TKIND_INTERFACE",
1434 "TKIND_DISPATCH",
1435 "TKIND_COCLASS",
1436 "TKIND_ALIAS",
1437 "TKIND_UNION",
1438 "TKIND_MAX"
1441 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1443 int i;
1444 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1445 for (i=0;i<pfd->funcdesc.cParams;i++)
1446 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1449 dump_FUNCDESC(&(pfd->funcdesc));
1451 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1452 if(pfd->Entry == NULL)
1453 MESSAGE("\tentry: (null)\n");
1454 else if(pfd->Entry == (void*)-1)
1455 MESSAGE("\tentry: invalid\n");
1456 else if(IS_INTRESOURCE(pfd->Entry))
1457 MESSAGE("\tentry: %p\n", pfd->Entry);
1458 else
1459 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1461 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1463 while (n)
1465 dump_TLBFuncDescOne(pfd);
1466 ++pfd;
1467 --n;
1470 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1472 while (n)
1474 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1475 ++pvd;
1476 --n;
1480 static void dump_TLBImpLib(const TLBImpLib *import)
1482 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1483 debugstr_w(import->name));
1484 TRACE_(typelib)("v%d.%d lcid %#lx offset=%x\n", import->wVersionMajor, import->wVersionMinor, import->lcid, import->offset);
1487 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1489 TLBRefType *ref;
1491 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1493 TRACE_(typelib)("href:%#lx\n", ref->reference);
1494 if(ref->index == -1)
1495 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1496 else
1497 TRACE_(typelib)("type no: %d\n", ref->index);
1499 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1501 TRACE_(typelib)("in lib\n");
1502 dump_TLBImpLib(ref->pImpTLInfo);
1507 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1509 if(!impl)
1510 return;
1511 while (n) {
1512 TRACE_(typelib)("implementing/inheriting interface hRef = %lx implflags %x\n",
1513 impl->hRef, impl->implflags);
1514 ++impl;
1515 --n;
1519 static void dump_DispParms(const DISPPARAMS * pdp)
1521 unsigned int index;
1523 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1525 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1527 TRACE("named args:\n");
1528 for (index = 0; index < pdp->cNamedArgs; index++)
1529 TRACE( "\t0x%lx\n", pdp->rgdispidNamedArgs[index] );
1532 if (pdp->cArgs && pdp->rgvarg)
1534 TRACE("args:\n");
1535 for (index = 0; index < pdp->cArgs; index++)
1536 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1540 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1542 TRACE("%p ref %lu\n", pty, pty->ref);
1543 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1544 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1545 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1546 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1547 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1548 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1549 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1550 if (TRACE_ON(ole))
1551 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1552 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1553 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1556 static void dump_VARDESC(const VARDESC *v)
1558 MESSAGE("memid %ld\n",v->memid);
1559 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1560 MESSAGE("oInst %ld\n", v->u.oInst);
1561 dump_ELEMDESC(&(v->elemdescVar));
1562 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1563 MESSAGE("varkind %d\n",v->varkind);
1566 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1568 /* VT_LPWSTR is largest type that, may appear in type description */
1569 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1570 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1571 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1572 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1573 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1574 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1575 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1576 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1579 static void TLB_abort(void)
1581 DebugBreak();
1584 /* returns the size required for a deep copy of a typedesc into a
1585 * flat buffer */
1586 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1588 SIZE_T size = 0;
1590 if (alloc_initial_space)
1591 size += sizeof(TYPEDESC);
1593 switch (tdesc->vt)
1595 case VT_PTR:
1596 case VT_SAFEARRAY:
1597 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1598 break;
1599 case VT_CARRAY:
1600 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1601 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1602 break;
1604 return size;
1607 /* deep copy a typedesc into a flat buffer */
1608 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1610 if (!dest)
1612 dest = buffer;
1613 buffer = (char *)buffer + sizeof(TYPEDESC);
1616 *dest = *src;
1618 switch (src->vt)
1620 case VT_PTR:
1621 case VT_SAFEARRAY:
1622 dest->u.lptdesc = buffer;
1623 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1624 break;
1625 case VT_CARRAY:
1626 dest->u.lpadesc = buffer;
1627 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1628 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1629 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1630 break;
1632 return buffer;
1635 /* free custom data allocated by MSFT_CustData */
1636 static inline void TLB_FreeCustData(struct list *custdata_list)
1638 TLBCustData *cd, *cdn;
1639 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1641 list_remove(&cd->entry);
1642 VariantClear(&cd->data);
1643 heap_free(cd);
1647 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1649 DWORD len;
1650 BSTR ret;
1652 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1653 ret = SysAllocStringLen(NULL, len - 1);
1654 if (!ret) return ret;
1655 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1656 return ret;
1659 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1661 int i;
1663 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1665 if (typeinfo->funcdescs[i].funcdesc.memid == memid)
1666 return &typeinfo->funcdescs[i];
1669 return NULL;
1672 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl *typeinfo, MEMBERID memid, INVOKEKIND invkind)
1674 int i;
1676 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1678 if (typeinfo->funcdescs[i].funcdesc.memid == memid && typeinfo->funcdescs[i].funcdesc.invkind == invkind)
1679 return &typeinfo->funcdescs[i];
1682 return NULL;
1685 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1687 int i;
1689 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1691 if (typeinfo->vardescs[i].vardesc.memid == memid)
1692 return &typeinfo->vardescs[i];
1695 return NULL;
1698 static inline TLBVarDesc *TLB_get_vardesc_by_name(ITypeInfoImpl *typeinfo, const OLECHAR *name)
1700 int i;
1702 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1704 if (!lstrcmpiW(TLB_get_bstr(typeinfo->vardescs[i].Name), name))
1705 return &typeinfo->vardescs[i];
1708 return NULL;
1711 static inline TLBCustData *TLB_get_custdata_by_guid(const struct list *custdata_list, REFGUID guid)
1713 TLBCustData *cust_data;
1714 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1715 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1716 return cust_data;
1717 return NULL;
1720 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeLibImpl *typelib, const OLECHAR *name)
1722 int i;
1724 for (i = 0; i < typelib->TypeInfoCount; ++i)
1726 if (!lstrcmpiW(TLB_get_bstr(typelib->typeinfos[i]->Name), name))
1727 return typelib->typeinfos[i];
1730 return NULL;
1733 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1735 list_init(&var_desc->custdata_list);
1738 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1740 TLBVarDesc *ret;
1742 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1743 if(!ret)
1744 return NULL;
1746 while(n){
1747 TLBVarDesc_Constructor(&ret[n-1]);
1748 --n;
1751 return ret;
1754 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1756 TLBParDesc *ret;
1758 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1759 if(!ret)
1760 return NULL;
1762 while(n){
1763 list_init(&ret[n-1].custdata_list);
1764 --n;
1767 return ret;
1770 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1772 list_init(&func_desc->custdata_list);
1775 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1777 TLBFuncDesc *ret;
1779 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1780 if(!ret)
1781 return NULL;
1783 while(n){
1784 TLBFuncDesc_Constructor(&ret[n-1]);
1785 --n;
1788 return ret;
1791 static void TLBImplType_Constructor(TLBImplType *impl)
1793 list_init(&impl->custdata_list);
1796 static TLBImplType *TLBImplType_Alloc(UINT n)
1798 TLBImplType *ret;
1800 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1801 if(!ret)
1802 return NULL;
1804 while(n){
1805 TLBImplType_Constructor(&ret[n-1]);
1806 --n;
1809 return ret;
1812 static TLBGuid *TLB_append_guid(struct list *guid_list,
1813 const GUID *new_guid, HREFTYPE hreftype)
1815 TLBGuid *guid;
1817 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1818 if (IsEqualGUID(&guid->guid, new_guid))
1819 return guid;
1822 guid = heap_alloc(sizeof(TLBGuid));
1823 if (!guid)
1824 return NULL;
1826 memcpy(&guid->guid, new_guid, sizeof(GUID));
1827 guid->hreftype = hreftype;
1829 list_add_tail(guid_list, &guid->entry);
1831 return guid;
1834 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1836 TLBCustData *cust_data;
1838 switch(V_VT(var)){
1839 case VT_I4:
1840 case VT_R4:
1841 case VT_UI4:
1842 case VT_INT:
1843 case VT_UINT:
1844 case VT_HRESULT:
1845 case VT_BSTR:
1846 break;
1847 default:
1848 return DISP_E_BADVARTYPE;
1851 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1853 if (!cust_data) {
1854 cust_data = heap_alloc(sizeof(TLBCustData));
1855 if (!cust_data)
1856 return E_OUTOFMEMORY;
1858 cust_data->guid = tlbguid;
1859 VariantInit(&cust_data->data);
1861 list_add_tail(custdata_list, &cust_data->entry);
1862 }else
1863 VariantClear(&cust_data->data);
1865 return VariantCopy(&cust_data->data, var);
1868 /* Used to update list pointers after list itself was moved. */
1869 static void TLB_relink_custdata(struct list *custdata_list)
1871 if (custdata_list->prev == custdata_list->next)
1872 list_init(custdata_list);
1873 else
1875 custdata_list->prev->next = custdata_list;
1876 custdata_list->next->prev = custdata_list;
1880 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1882 TLBString *str;
1884 if(!new_str)
1885 return NULL;
1887 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1888 if (wcscmp(str->str, new_str) == 0)
1889 return str;
1892 str = heap_alloc(sizeof(TLBString));
1893 if (!str)
1894 return NULL;
1896 str->str = SysAllocString(new_str);
1897 if (!str->str) {
1898 heap_free(str);
1899 return NULL;
1902 list_add_tail(string_list, &str->entry);
1904 return str;
1907 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1908 ULONG *size, WORD *align)
1910 ITypeInfo *other;
1911 TYPEATTR *attr;
1912 HRESULT hr;
1914 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1915 if(FAILED(hr))
1916 return hr;
1918 hr = ITypeInfo_GetTypeAttr(other, &attr);
1919 if(FAILED(hr)){
1920 ITypeInfo_Release(other);
1921 return hr;
1924 if(size)
1925 *size = attr->cbSizeInstance;
1926 if(align)
1927 *align = attr->cbAlignment;
1929 ITypeInfo_ReleaseTypeAttr(other, attr);
1930 ITypeInfo_Release(other);
1932 return S_OK;
1935 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1936 TYPEDESC *tdesc, ULONG *size, WORD *align)
1938 ULONG i, sub, ptr_size;
1939 HRESULT hr;
1941 ptr_size = get_ptr_size(sys);
1943 switch(tdesc->vt){
1944 case VT_VOID:
1945 *size = 0;
1946 break;
1947 case VT_I1:
1948 case VT_UI1:
1949 *size = 1;
1950 break;
1951 case VT_I2:
1952 case VT_BOOL:
1953 case VT_UI2:
1954 *size = 2;
1955 break;
1956 case VT_I4:
1957 case VT_R4:
1958 case VT_ERROR:
1959 case VT_UI4:
1960 case VT_INT:
1961 case VT_UINT:
1962 case VT_HRESULT:
1963 *size = 4;
1964 break;
1965 case VT_R8:
1966 case VT_I8:
1967 case VT_UI8:
1968 *size = 8;
1969 break;
1970 case VT_BSTR:
1971 case VT_DISPATCH:
1972 case VT_UNKNOWN:
1973 case VT_PTR:
1974 case VT_SAFEARRAY:
1975 case VT_LPSTR:
1976 case VT_LPWSTR:
1977 *size = ptr_size;
1978 break;
1979 case VT_DATE:
1980 *size = sizeof(DATE);
1981 break;
1982 case VT_VARIANT:
1983 *size = sizeof(VARIANT);
1984 #ifdef _WIN64
1985 if(sys == SYS_WIN32)
1986 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1987 #endif
1988 break;
1989 case VT_DECIMAL:
1990 *size = sizeof(DECIMAL);
1991 break;
1992 case VT_CY:
1993 *size = sizeof(CY);
1994 break;
1995 case VT_CARRAY:
1996 *size = 0;
1997 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
1998 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
1999 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2000 if(FAILED(hr))
2001 return hr;
2002 *size *= sub;
2003 return S_OK;
2004 case VT_USERDEFINED:
2005 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2006 default:
2007 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2008 return E_FAIL;
2011 if(align){
2012 if(*size < 4)
2013 *align = *size;
2014 else
2015 *align = 4;
2018 return S_OK;
2021 /**********************************************************************
2023 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2026 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2028 if (where != DO_NOT_SEEK)
2030 where += pcx->oStart;
2031 if (where > pcx->length)
2033 /* FIXME */
2034 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
2035 TLB_abort();
2037 pcx->pos = where;
2041 /* read function */
2042 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2044 TRACE_(typelib)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2045 pcx->pos, count, pcx->oStart, pcx->length, where);
2047 MSFT_Seek(pcx, where);
2048 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2049 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2050 pcx->pos += count;
2051 return count;
2054 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2055 LONG where )
2057 DWORD ret;
2059 ret = MSFT_Read(buffer, count, pcx, where);
2060 FromLEDWords(buffer, ret);
2062 return ret;
2065 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2066 LONG where )
2068 DWORD ret;
2070 ret = MSFT_Read(buffer, count, pcx, where);
2071 FromLEWords(buffer, ret);
2073 return ret;
2076 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2078 TLBGuid *guid;
2079 MSFT_GuidEntry entry;
2080 int offs = 0;
2082 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2083 while (1) {
2084 if (offs >= pcx->pTblDir->pGuidTab.length)
2085 return S_OK;
2087 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2089 guid = heap_alloc(sizeof(TLBGuid));
2091 guid->offset = offs;
2092 guid->guid = entry.guid;
2093 guid->hreftype = entry.hreftype;
2095 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2097 offs += sizeof(MSFT_GuidEntry);
2101 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2103 TLBGuid *ret;
2105 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2106 if(ret->offset == offset){
2107 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2108 return ret;
2112 return NULL;
2115 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2117 MSFT_NameIntro niName;
2119 if (offset < 0)
2121 ERR_(typelib)("bad offset %d\n", offset);
2122 return -1;
2125 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2126 pcx->pTblDir->pNametab.offset+offset);
2128 return niName.hreftype;
2131 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2133 char *string;
2134 MSFT_NameIntro intro;
2135 INT16 len_piece;
2136 int offs = 0, lengthInChars;
2138 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2139 while (1) {
2140 TLBString *tlbstr;
2142 if (offs >= pcx->pTblDir->pNametab.length)
2143 return S_OK;
2145 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2146 intro.namelen &= 0xFF;
2147 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2148 if(len_piece % 4)
2149 len_piece = (len_piece + 4) & ~0x3;
2150 if(len_piece < 8)
2151 len_piece = 8;
2153 string = heap_alloc(len_piece + 1);
2154 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2155 string[intro.namelen] = '\0';
2157 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2158 string, -1, NULL, 0);
2159 if (!lengthInChars) {
2160 heap_free(string);
2161 return E_UNEXPECTED;
2164 tlbstr = heap_alloc(sizeof(TLBString));
2166 tlbstr->offset = offs;
2167 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2168 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2170 heap_free(string);
2172 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2174 offs += len_piece;
2178 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2180 TLBString *tlbstr;
2182 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2183 if (tlbstr->offset == offset) {
2184 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2185 return tlbstr;
2189 return NULL;
2192 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2194 TLBString *tlbstr;
2196 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2197 if (tlbstr->offset == offset) {
2198 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2199 return tlbstr;
2203 return NULL;
2207 * read a value and fill a VARIANT structure
2209 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2211 int size;
2213 TRACE_(typelib)("\n");
2215 if(offset <0) { /* data are packed in here */
2216 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2217 V_I4(pVar) = offset & 0x3ffffff;
2218 return;
2220 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2221 pcx->pTblDir->pCustData.offset + offset );
2222 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2223 switch (V_VT(pVar)){
2224 case VT_EMPTY: /* FIXME: is this right? */
2225 case VT_NULL: /* FIXME: is this right? */
2226 case VT_I2 : /* this should not happen */
2227 case VT_I4 :
2228 case VT_R4 :
2229 case VT_ERROR :
2230 case VT_BOOL :
2231 case VT_I1 :
2232 case VT_UI1 :
2233 case VT_UI2 :
2234 case VT_UI4 :
2235 case VT_INT :
2236 case VT_UINT :
2237 case VT_VOID : /* FIXME: is this right? */
2238 case VT_HRESULT :
2239 size=4; break;
2240 case VT_R8 :
2241 case VT_CY :
2242 case VT_DATE :
2243 case VT_I8 :
2244 case VT_UI8 :
2245 case VT_DECIMAL : /* FIXME: is this right? */
2246 case VT_FILETIME :
2247 size=8;break;
2248 /* pointer types with known behaviour */
2249 case VT_BSTR :{
2250 char * ptr;
2251 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2252 if(size == -1){
2253 V_BSTR(pVar) = NULL;
2254 }else{
2255 ptr = heap_alloc_zero(size);
2256 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2257 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2258 /* FIXME: do we need a AtoW conversion here? */
2259 V_UNION(pVar, bstrVal[size])='\0';
2260 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2261 heap_free(ptr);
2264 size=-4; break;
2265 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2266 case VT_DISPATCH :
2267 case VT_VARIANT :
2268 case VT_UNKNOWN :
2269 case VT_PTR :
2270 case VT_SAFEARRAY :
2271 case VT_CARRAY :
2272 case VT_USERDEFINED :
2273 case VT_LPSTR :
2274 case VT_LPWSTR :
2275 case VT_BLOB :
2276 case VT_STREAM :
2277 case VT_STORAGE :
2278 case VT_STREAMED_OBJECT :
2279 case VT_STORED_OBJECT :
2280 case VT_BLOB_OBJECT :
2281 case VT_CF :
2282 case VT_CLSID :
2283 default:
2284 size=0;
2285 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2286 V_VT(pVar));
2289 if(size>0) /* (big|small) endian correct? */
2290 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2291 return;
2294 * create a linked list with custom data
2296 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2298 MSFT_CDGuid entry;
2299 TLBCustData* pNew;
2300 int count=0;
2302 TRACE_(typelib)("\n");
2304 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2306 while(offset >=0){
2307 count++;
2308 pNew=heap_alloc_zero(sizeof(TLBCustData));
2309 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2310 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2311 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2312 list_add_head(custdata_list, &pNew->entry);
2313 offset = entry.next;
2315 return count;
2318 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2320 if(type <0)
2321 pTd->vt=type & VT_TYPEMASK;
2322 else
2323 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2325 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2328 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2330 return (invkind == INVOKE_PROPERTYGET ||
2331 invkind == INVOKE_PROPERTYPUT ||
2332 invkind == INVOKE_PROPERTYPUTREF);
2335 static void
2336 MSFT_DoFuncs(TLBContext* pcx,
2337 ITypeInfoImpl* pTI,
2338 int cFuncs,
2339 int cVars,
2340 int offset,
2341 TLBFuncDesc** pptfd)
2344 * member information is stored in a data structure at offset
2345 * indicated by the memoffset field of the typeinfo structure
2346 * There are several distinctive parts.
2347 * The first part starts with a field that holds the total length
2348 * of this (first) part excluding this field. Then follow the records,
2349 * for each member there is one record.
2351 * The first entry is always the length of the record (including this
2352 * length word).
2353 * The rest of the record depends on the type of the member. If there is
2354 * a field indicating the member type (function, variable, interface, etc)
2355 * I have not found it yet. At this time we depend on the information
2356 * in the type info and the usual order how things are stored.
2358 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2359 * for each member;
2361 * Third is an equal sized array with file offsets to the name entry
2362 * of each member.
2364 * The fourth and last (?) part is an array with offsets to the records
2365 * in the first part of this file segment.
2368 int infolen, nameoffset, reclength, i;
2369 int recoffset = offset + sizeof(INT);
2371 char *recbuf = heap_alloc(0xffff);
2372 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2373 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2375 TRACE_(typelib)("\n");
2377 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2379 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2380 ptfd = *pptfd;
2381 for ( i = 0; i < cFuncs ; i++ )
2383 int optional;
2385 /* name, eventually add to a hash table */
2386 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2387 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2389 /* read the function information record */
2390 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2392 reclength &= 0xffff;
2394 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2396 /* size without argument data */
2397 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2398 if (pFuncRec->FKCCIC & 0x1000)
2399 optional -= pFuncRec->nrargs * sizeof(INT);
2401 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2402 ptfd->helpcontext = pFuncRec->HelpContext;
2404 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2405 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2407 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2409 if (pFuncRec->FKCCIC & 0x2000 )
2411 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2412 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2413 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2415 else
2416 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2418 else
2419 ptfd->Entry = (TLBString*)-1;
2421 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2422 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2424 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2425 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2427 /* fill the FuncDesc Structure */
2428 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2429 offset + infolen + ( i + 1) * sizeof(INT));
2431 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2432 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2433 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2434 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2435 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2436 if (ptfd->funcdesc.funckind == FUNC_DISPATCH)
2437 ptfd->funcdesc.oVft = 0;
2438 else
2439 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2440 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2442 /* nameoffset is sometimes -1 on the second half of a propget/propput
2443 * pair of functions */
2444 if ((nameoffset == -1) && (i > 0) &&
2445 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2446 TLB_is_propgetput(ptfd->funcdesc.invkind))
2447 ptfd->Name = ptfd_prev->Name;
2448 else
2449 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2451 MSFT_GetTdesc(pcx,
2452 pFuncRec->DataType,
2453 &ptfd->funcdesc.elemdescFunc.tdesc);
2455 /* do the parameters/arguments */
2456 if(pFuncRec->nrargs)
2458 int j = 0;
2459 MSFT_ParameterInfo paraminfo;
2461 ptfd->funcdesc.lprgelemdescParam =
2462 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2464 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2466 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2467 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2469 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2471 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2473 MSFT_GetTdesc(pcx,
2474 paraminfo.DataType,
2475 &elemdesc->tdesc);
2477 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2479 /* name */
2480 if (paraminfo.oName != -1)
2481 ptfd->pParamDesc[j].Name =
2482 MSFT_ReadName( pcx, paraminfo.oName );
2483 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2485 /* default value */
2486 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2487 (pFuncRec->FKCCIC & 0x1000) )
2489 INT* pInt = (INT *)((char *)pFuncRec +
2490 reclength -
2491 (pFuncRec->nrargs * 4) * sizeof(INT) );
2493 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2495 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2496 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2498 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2499 pInt[j], pcx);
2501 else
2502 elemdesc->u.paramdesc.pparamdescex = NULL;
2504 /* custom info */
2505 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2506 j*sizeof(pFuncRec->oArgCustData[0])) &&
2507 pFuncRec->FKCCIC & 0x80 )
2509 MSFT_CustData(pcx,
2510 pFuncRec->oArgCustData[j],
2511 &ptfd->pParamDesc[j].custdata_list);
2514 /* SEEK value = jump to offset,
2515 * from there jump to the end of record,
2516 * go back by (j-1) arguments
2518 MSFT_ReadLEDWords( &paraminfo ,
2519 sizeof(MSFT_ParameterInfo), pcx,
2520 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2521 * sizeof(MSFT_ParameterInfo)));
2525 /* scode is not used: archaic win16 stuff FIXME: right? */
2526 ptfd->funcdesc.cScodes = 0 ;
2527 ptfd->funcdesc.lprgscode = NULL ;
2529 ptfd_prev = ptfd;
2530 ++ptfd;
2531 recoffset += reclength;
2533 heap_free(recbuf);
2536 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2537 int cVars, int offset, TLBVarDesc ** pptvd)
2539 int infolen, nameoffset, reclength;
2540 char recbuf[256];
2541 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2542 TLBVarDesc *ptvd;
2543 int i;
2544 int recoffset;
2546 TRACE_(typelib)("\n");
2548 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2549 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2550 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2551 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2552 recoffset += offset+sizeof(INT);
2553 for(i=0;i<cVars;i++, ++ptvd){
2554 /* name, eventually add to a hash table */
2555 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2556 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2557 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2558 /* read the variable information record */
2559 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2560 reclength &= 0xff;
2561 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2563 /* optional data */
2564 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2565 ptvd->HelpContext = pVarRec->HelpContext;
2567 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2568 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2570 if (reclength > FIELD_OFFSET(MSFT_VarRecord, oCustData))
2571 MSFT_CustData(pcx, pVarRec->oCustData, &ptvd->custdata_list);
2573 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2574 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2576 /* fill the VarDesc Structure */
2577 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2578 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2579 ptvd->vardesc.varkind = pVarRec->VarKind;
2580 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2581 MSFT_GetTdesc(pcx, pVarRec->DataType,
2582 &ptvd->vardesc.elemdescVar.tdesc);
2583 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2584 if(pVarRec->VarKind == VAR_CONST ){
2585 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2586 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2587 pVarRec->OffsValue, pcx);
2588 } else
2589 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2590 recoffset += reclength;
2594 /* process Implemented Interfaces of a com class */
2595 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2596 int offset)
2598 int i;
2599 MSFT_RefRecord refrec;
2600 TLBImplType *pImpl;
2602 TRACE_(typelib)("\n");
2604 pTI->impltypes = TLBImplType_Alloc(count);
2605 pImpl = pTI->impltypes;
2606 for(i=0;i<count;i++){
2607 if(offset<0) break; /* paranoia */
2608 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2609 pImpl->hRef = refrec.reftype;
2610 pImpl->implflags=refrec.flags;
2611 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2612 offset=refrec.onext;
2613 ++pImpl;
2617 #ifdef _WIN64
2618 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2619 * and some structures, and fix the alignment */
2620 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2622 if(info->typeattr.typekind == TKIND_ALIAS){
2623 switch(info->tdescAlias->vt){
2624 case VT_BSTR:
2625 case VT_DISPATCH:
2626 case VT_UNKNOWN:
2627 case VT_PTR:
2628 case VT_SAFEARRAY:
2629 case VT_LPSTR:
2630 case VT_LPWSTR:
2631 info->typeattr.cbSizeInstance = sizeof(void*);
2632 info->typeattr.cbAlignment = sizeof(void*);
2633 break;
2634 case VT_CARRAY:
2635 case VT_USERDEFINED:
2636 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2637 break;
2638 case VT_VARIANT:
2639 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2640 info->typeattr.cbAlignment = 8;
2641 default:
2642 if(info->typeattr.cbSizeInstance < sizeof(void*))
2643 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2644 else
2645 info->typeattr.cbAlignment = sizeof(void*);
2646 break;
2648 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2649 info->typeattr.typekind == TKIND_DISPATCH ||
2650 info->typeattr.typekind == TKIND_COCLASS){
2651 info->typeattr.cbSizeInstance = sizeof(void*);
2652 info->typeattr.cbAlignment = sizeof(void*);
2655 #endif
2658 * process a typeinfo record
2660 static ITypeInfoImpl * MSFT_DoTypeInfo(
2661 TLBContext *pcx,
2662 int count,
2663 ITypeLibImpl * pLibInfo)
2665 MSFT_TypeInfoBase tiBase;
2666 ITypeInfoImpl *ptiRet;
2668 TRACE_(typelib)("count=%u\n", count);
2670 ptiRet = ITypeInfoImpl_Constructor();
2671 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2672 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2674 /* this is where we are coming from */
2675 ptiRet->pTypeLib = pLibInfo;
2676 ptiRet->index=count;
2678 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2679 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2680 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2681 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2682 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2683 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2684 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2685 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2686 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2687 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2688 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2689 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2690 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2691 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2692 TYPEDESC tmp;
2693 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2694 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2695 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2698 /* FIXME: */
2699 /* IDLDESC idldescType; *//* never saw this one != zero */
2701 /* name, eventually add to a hash table */
2702 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2703 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2704 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2705 /* help info */
2706 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2707 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2708 ptiRet->dwHelpContext=tiBase.helpcontext;
2710 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2711 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2713 /* note: InfoType's Help file and HelpStringDll come from the containing
2714 * library. Further HelpString and Docstring appear to be the same thing :(
2716 /* functions */
2717 if(ptiRet->typeattr.cFuncs >0 )
2718 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2719 ptiRet->typeattr.cVars,
2720 tiBase.memoffset, &ptiRet->funcdescs);
2721 /* variables */
2722 if(ptiRet->typeattr.cVars >0 )
2723 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2724 ptiRet->typeattr.cVars,
2725 tiBase.memoffset, &ptiRet->vardescs);
2726 if(ptiRet->typeattr.cImplTypes >0 ) {
2727 switch(ptiRet->typeattr.typekind)
2729 case TKIND_COCLASS:
2730 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2731 tiBase.datatype1);
2732 break;
2733 case TKIND_DISPATCH:
2734 /* This is not -1 when the interface is a non-base dual interface or
2735 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2736 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2737 not this interface.
2740 if (tiBase.datatype1 != -1)
2742 ptiRet->impltypes = TLBImplType_Alloc(1);
2743 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2745 break;
2746 default:
2747 ptiRet->impltypes = TLBImplType_Alloc(1);
2748 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2749 break;
2752 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2754 TRACE_(typelib)("%s guid: %s kind:%s\n",
2755 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2756 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2757 typekind_desc[ptiRet->typeattr.typekind]);
2758 if (TRACE_ON(typelib))
2759 dump_TypeInfo(ptiRet);
2761 return ptiRet;
2764 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2766 char *string;
2767 INT16 len_str, len_piece;
2768 int offs = 0, lengthInChars;
2770 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2771 while (1) {
2772 TLBString *tlbstr;
2774 if (offs >= pcx->pTblDir->pStringtab.length)
2775 return S_OK;
2777 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2778 len_piece = len_str + sizeof(INT16);
2779 if(len_piece % 4)
2780 len_piece = (len_piece + 4) & ~0x3;
2781 if(len_piece < 8)
2782 len_piece = 8;
2784 string = heap_alloc(len_piece + 1);
2785 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2786 string[len_str] = '\0';
2788 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2789 string, -1, NULL, 0);
2790 if (!lengthInChars) {
2791 heap_free(string);
2792 return E_UNEXPECTED;
2795 tlbstr = heap_alloc(sizeof(TLBString));
2797 tlbstr->offset = offs;
2798 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2799 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2801 heap_free(string);
2803 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2805 offs += len_piece;
2809 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2811 TLBRefType *ref;
2812 int offs = 0;
2814 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2815 while (offs < pcx->pTblDir->pImpInfo.length) {
2816 MSFT_ImpInfo impinfo;
2817 TLBImpLib *pImpLib;
2819 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2821 ref = heap_alloc_zero(sizeof(TLBRefType));
2822 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2824 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2825 if(pImpLib->offset==impinfo.oImpFile)
2826 break;
2828 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2829 ref->reference = offs;
2830 ref->pImpTLInfo = pImpLib;
2831 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2832 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2833 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2834 ref->index = TLB_REF_USE_GUID;
2835 } else
2836 ref->index = impinfo.oGuid;
2837 }else{
2838 ERR("Cannot find a reference\n");
2839 ref->reference = -1;
2840 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2843 offs += sizeof(impinfo);
2846 return S_OK;
2849 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2850 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2851 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2852 * tradeoff here.
2854 static struct list tlb_cache = LIST_INIT(tlb_cache);
2855 static CRITICAL_SECTION cache_section;
2856 static CRITICAL_SECTION_DEBUG cache_section_debug =
2858 0, 0, &cache_section,
2859 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2860 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2862 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2865 typedef struct TLB_PEFile
2867 IUnknown IUnknown_iface;
2868 LONG refs;
2869 HMODULE dll;
2870 HRSRC typelib_resource;
2871 HGLOBAL typelib_global;
2872 LPVOID typelib_base;
2873 } TLB_PEFile;
2875 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2877 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2880 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2882 if (IsEqualIID(riid, &IID_IUnknown))
2884 *ppv = iface;
2885 IUnknown_AddRef(iface);
2886 return S_OK;
2888 *ppv = NULL;
2889 return E_NOINTERFACE;
2892 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2894 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2895 return InterlockedIncrement(&This->refs);
2898 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2900 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2901 ULONG refs = InterlockedDecrement(&This->refs);
2902 if (!refs)
2904 if (This->typelib_global)
2905 FreeResource(This->typelib_global);
2906 if (This->dll)
2907 FreeLibrary(This->dll);
2908 heap_free(This);
2910 return refs;
2913 static const IUnknownVtbl TLB_PEFile_Vtable =
2915 TLB_PEFile_QueryInterface,
2916 TLB_PEFile_AddRef,
2917 TLB_PEFile_Release
2920 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2922 TLB_PEFile *This;
2923 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2925 This = heap_alloc(sizeof(TLB_PEFile));
2926 if (!This)
2927 return E_OUTOFMEMORY;
2929 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2930 This->refs = 1;
2931 This->dll = NULL;
2932 This->typelib_resource = NULL;
2933 This->typelib_global = NULL;
2934 This->typelib_base = NULL;
2936 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2937 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2939 if (This->dll)
2941 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), L"TYPELIB");
2942 if (This->typelib_resource)
2944 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2945 if (This->typelib_global)
2947 This->typelib_base = LockResource(This->typelib_global);
2949 if (This->typelib_base)
2951 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2952 *ppBase = This->typelib_base;
2953 *ppFile = &This->IUnknown_iface;
2954 return S_OK;
2959 TRACE("No TYPELIB resource found\n");
2960 hr = E_FAIL;
2963 TLB_PEFile_Release(&This->IUnknown_iface);
2964 return hr;
2967 typedef struct TLB_NEFile
2969 IUnknown IUnknown_iface;
2970 LONG refs;
2971 LPVOID typelib_base;
2972 } TLB_NEFile;
2974 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2976 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2979 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2981 if (IsEqualIID(riid, &IID_IUnknown))
2983 *ppv = iface;
2984 IUnknown_AddRef(iface);
2985 return S_OK;
2987 *ppv = NULL;
2988 return E_NOINTERFACE;
2991 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2993 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2994 return InterlockedIncrement(&This->refs);
2997 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2999 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3000 ULONG refs = InterlockedDecrement(&This->refs);
3001 if (!refs)
3003 heap_free(This->typelib_base);
3004 heap_free(This);
3006 return refs;
3009 static const IUnknownVtbl TLB_NEFile_Vtable =
3011 TLB_NEFile_QueryInterface,
3012 TLB_NEFile_AddRef,
3013 TLB_NEFile_Release
3016 /***********************************************************************
3017 * read_xx_header [internal]
3019 static int read_xx_header( HFILE lzfd )
3021 IMAGE_DOS_HEADER mzh;
3022 char magic[3];
3024 LZSeek( lzfd, 0, SEEK_SET );
3025 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3026 return 0;
3027 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3028 return 0;
3030 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3031 if ( 2 != LZRead( lzfd, magic, 2 ) )
3032 return 0;
3034 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3036 if ( magic[0] == 'N' && magic[1] == 'E' )
3037 return IMAGE_OS2_SIGNATURE;
3038 if ( magic[0] == 'P' && magic[1] == 'E' )
3039 return IMAGE_NT_SIGNATURE;
3041 magic[2] = '\0';
3042 WARN("Can't handle %s files.\n", magic );
3043 return 0;
3047 /***********************************************************************
3048 * find_ne_resource [internal]
3050 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3051 DWORD *resLen, DWORD *resOff )
3053 IMAGE_OS2_HEADER nehd;
3054 NE_TYPEINFO *typeInfo;
3055 NE_NAMEINFO *nameInfo;
3056 DWORD nehdoffset;
3057 LPBYTE resTab;
3058 DWORD resTabSize;
3059 int count;
3061 /* Read in NE header */
3062 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3063 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3065 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3066 if ( !resTabSize )
3068 TRACE("No resources in NE dll\n" );
3069 return FALSE;
3072 /* Read in resource table */
3073 resTab = heap_alloc( resTabSize );
3074 if ( !resTab ) return FALSE;
3076 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3077 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3079 heap_free( resTab );
3080 return FALSE;
3083 /* Find resource */
3084 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3086 if (!IS_INTRESOURCE(typeid)) /* named type */
3088 BYTE len = strlen( typeid );
3089 while (typeInfo->type_id)
3091 if (!(typeInfo->type_id & 0x8000))
3093 BYTE *p = resTab + typeInfo->type_id;
3094 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3096 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3097 typeInfo->count * sizeof(NE_NAMEINFO));
3100 else /* numeric type id */
3102 WORD id = LOWORD(typeid) | 0x8000;
3103 while (typeInfo->type_id)
3105 if (typeInfo->type_id == id) goto found_type;
3106 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3107 typeInfo->count * sizeof(NE_NAMEINFO));
3110 TRACE("No typeid entry found for %p\n", typeid );
3111 heap_free( resTab );
3112 return FALSE;
3114 found_type:
3115 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3117 if (!IS_INTRESOURCE(resid)) /* named resource */
3119 BYTE len = strlen( resid );
3120 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3122 BYTE *p = resTab + nameInfo->id;
3123 if (nameInfo->id & 0x8000) continue;
3124 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3127 else /* numeric resource id */
3129 WORD id = LOWORD(resid) | 0x8000;
3130 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3131 if (nameInfo->id == id) goto found_name;
3133 TRACE("No resid entry found for %p\n", typeid );
3134 heap_free( resTab );
3135 return FALSE;
3137 found_name:
3138 /* Return resource data */
3139 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3140 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3142 heap_free( resTab );
3143 return TRUE;
3146 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3148 HFILE lzfd = -1;
3149 OFSTRUCT ofs;
3150 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3151 TLB_NEFile *This;
3153 This = heap_alloc(sizeof(TLB_NEFile));
3154 if (!This) return E_OUTOFMEMORY;
3156 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3157 This->refs = 1;
3158 This->typelib_base = NULL;
3160 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3161 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3163 DWORD reslen, offset;
3164 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3166 This->typelib_base = heap_alloc(reslen);
3167 if( !This->typelib_base )
3168 hr = E_OUTOFMEMORY;
3169 else
3171 LZSeek( lzfd, offset, SEEK_SET );
3172 reslen = LZRead( lzfd, This->typelib_base, reslen );
3173 LZClose( lzfd );
3174 *ppBase = This->typelib_base;
3175 *pdwTLBLength = reslen;
3176 *ppFile = &This->IUnknown_iface;
3177 return S_OK;
3182 if( lzfd >= 0) LZClose( lzfd );
3183 TLB_NEFile_Release(&This->IUnknown_iface);
3184 return hr;
3187 typedef struct TLB_Mapping
3189 IUnknown IUnknown_iface;
3190 LONG refs;
3191 HANDLE file;
3192 HANDLE mapping;
3193 LPVOID typelib_base;
3194 } TLB_Mapping;
3196 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3198 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3201 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3203 if (IsEqualIID(riid, &IID_IUnknown))
3205 *ppv = iface;
3206 IUnknown_AddRef(iface);
3207 return S_OK;
3209 *ppv = NULL;
3210 return E_NOINTERFACE;
3213 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3215 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3216 return InterlockedIncrement(&This->refs);
3219 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3221 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3222 ULONG refs = InterlockedDecrement(&This->refs);
3223 if (!refs)
3225 if (This->typelib_base)
3226 UnmapViewOfFile(This->typelib_base);
3227 if (This->mapping)
3228 CloseHandle(This->mapping);
3229 if (This->file != INVALID_HANDLE_VALUE)
3230 CloseHandle(This->file);
3231 heap_free(This);
3233 return refs;
3236 static const IUnknownVtbl TLB_Mapping_Vtable =
3238 TLB_Mapping_QueryInterface,
3239 TLB_Mapping_AddRef,
3240 TLB_Mapping_Release
3243 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3245 TLB_Mapping *This;
3247 This = heap_alloc(sizeof(TLB_Mapping));
3248 if (!This)
3249 return E_OUTOFMEMORY;
3251 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3252 This->refs = 1;
3253 This->file = INVALID_HANDLE_VALUE;
3254 This->mapping = NULL;
3255 This->typelib_base = NULL;
3257 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3258 if (INVALID_HANDLE_VALUE != This->file)
3260 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3261 if (This->mapping)
3263 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3264 if(This->typelib_base)
3266 /* retrieve file size */
3267 *pdwTLBLength = GetFileSize(This->file, NULL);
3268 *ppBase = This->typelib_base;
3269 *ppFile = &This->IUnknown_iface;
3270 return S_OK;
3275 IUnknown_Release(&This->IUnknown_iface);
3276 return TYPE_E_CANTLOADLIBRARY;
3279 /****************************************************************************
3280 * TLB_ReadTypeLib
3282 * find the type of the typelib file and map the typelib resource into
3283 * the memory
3286 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3289 ITypeLibImpl *entry;
3290 HRESULT ret;
3291 INT index = 1;
3292 LPWSTR index_str, file = (LPWSTR)pszFileName;
3293 LPVOID pBase = NULL;
3294 DWORD dwTLBLength = 0;
3295 IUnknown *pFile = NULL;
3296 HANDLE h;
3298 *ppTypeLib = NULL;
3300 index_str = wcsrchr(pszFileName, '\\');
3301 if(index_str && *++index_str != '\0')
3303 LPWSTR end_ptr;
3304 LONG idx = wcstol(index_str, &end_ptr, 10);
3305 if(*end_ptr == '\0')
3307 int str_len = index_str - pszFileName - 1;
3308 index = idx;
3309 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3310 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3311 file[str_len] = 0;
3315 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3317 if(wcschr(file, '\\'))
3319 lstrcpyW(pszPath, file);
3321 else
3323 int len = GetSystemDirectoryW(pszPath, cchPath);
3324 pszPath[len] = '\\';
3325 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3329 if(file != pszFileName) heap_free(file);
3331 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3332 if(h != INVALID_HANDLE_VALUE){
3333 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3334 CloseHandle(h);
3337 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3339 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3340 EnterCriticalSection(&cache_section);
3341 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3343 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3345 TRACE("cache hit\n");
3346 *ppTypeLib = &entry->ITypeLib2_iface;
3347 ITypeLib2_AddRef(*ppTypeLib);
3348 LeaveCriticalSection(&cache_section);
3349 return S_OK;
3352 LeaveCriticalSection(&cache_section);
3354 /* now actually load and parse the typelib */
3356 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3357 if (ret == TYPE_E_CANTLOADLIBRARY)
3358 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3359 if (ret == TYPE_E_CANTLOADLIBRARY)
3360 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3361 if (SUCCEEDED(ret))
3363 if (dwTLBLength >= 4)
3365 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3366 if (dwSignature == MSFT_SIGNATURE)
3367 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3368 else if (dwSignature == SLTG_SIGNATURE)
3369 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3370 else
3372 FIXME("Header type magic %#lx not supported.\n", dwSignature);
3373 ret = TYPE_E_CANTLOADLIBRARY;
3376 else
3377 ret = TYPE_E_CANTLOADLIBRARY;
3378 IUnknown_Release(pFile);
3381 if(*ppTypeLib) {
3382 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3384 TRACE("adding to cache\n");
3385 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3386 lstrcpyW(impl->path, pszPath);
3387 /* We should really canonicalise the path here. */
3388 impl->index = index;
3390 /* FIXME: check if it has added already in the meantime */
3391 EnterCriticalSection(&cache_section);
3392 list_add_head(&tlb_cache, &impl->entry);
3393 LeaveCriticalSection(&cache_section);
3394 ret = S_OK;
3396 else
3398 if(ret != E_FAIL)
3399 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
3401 ret = TYPE_E_CANTLOADLIBRARY;
3405 return ret;
3408 /*================== ITypeLib(2) Methods ===================================*/
3410 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3412 ITypeLibImpl* pTypeLibImpl;
3414 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3415 if (!pTypeLibImpl) return NULL;
3417 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3418 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3419 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3420 pTypeLibImpl->ref = 1;
3422 list_init(&pTypeLibImpl->implib_list);
3423 list_init(&pTypeLibImpl->custdata_list);
3424 list_init(&pTypeLibImpl->name_list);
3425 list_init(&pTypeLibImpl->string_list);
3426 list_init(&pTypeLibImpl->guid_list);
3427 list_init(&pTypeLibImpl->ref_list);
3428 pTypeLibImpl->dispatch_href = -1;
3430 return pTypeLibImpl;
3433 /****************************************************************************
3434 * ITypeLib2_Constructor_MSFT
3436 * loading an MSFT typelib from an in-memory image
3438 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3440 TLBContext cx;
3441 LONG lPSegDir;
3442 MSFT_Header tlbHeader;
3443 MSFT_SegDir tlbSegDir;
3444 ITypeLibImpl * pTypeLibImpl;
3445 int i;
3447 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3449 pTypeLibImpl = TypeLibImpl_Constructor();
3450 if (!pTypeLibImpl) return NULL;
3452 /* get pointer to beginning of typelib data */
3453 cx.pos = 0;
3454 cx.oStart=0;
3455 cx.mapping = pLib;
3456 cx.pLibInfo = pTypeLibImpl;
3457 cx.length = dwTLBLength;
3459 /* read header */
3460 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3461 TRACE_(typelib)("header:\n");
3462 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3463 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3464 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3465 return NULL;
3467 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3469 /* there is a small amount of information here until the next important
3470 * part:
3471 * the segment directory . Try to calculate the amount of data */
3472 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3474 /* now read the segment directory */
3475 TRACE("read segment directory (at %ld)\n",lPSegDir);
3476 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3477 cx.pTblDir = &tlbSegDir;
3479 /* just check two entries */
3480 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3482 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir);
3483 heap_free(pTypeLibImpl);
3484 return NULL;
3487 MSFT_ReadAllNames(&cx);
3488 MSFT_ReadAllStrings(&cx);
3489 MSFT_ReadAllGuids(&cx);
3491 /* now fill our internal data */
3492 /* TLIBATTR fields */
3493 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3495 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3496 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3497 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3498 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3499 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3501 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3502 pTypeLibImpl->lcid = tlbHeader.lcid;
3504 /* name, eventually add to a hash table */
3505 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3507 /* help info */
3508 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3509 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3511 if( tlbHeader.varflags & HELPDLLFLAG)
3513 int offset;
3514 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3515 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3518 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3520 /* custom data */
3521 if(tlbHeader.CustomDataOffset >= 0)
3523 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3526 /* fill in type descriptions */
3527 if(tlbSegDir.pTypdescTab.length > 0)
3529 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3530 INT16 td[4];
3531 pTypeLibImpl->ctTypeDesc = cTD;
3532 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3533 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3534 for(i=0; i<cTD; )
3536 /* FIXME: add several sanity checks here */
3537 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3538 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3540 /* FIXME: check safearray */
3541 if(td[3] < 0)
3542 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3543 else
3544 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3546 else if(td[0] == VT_CARRAY)
3548 /* array descr table here */
3549 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3551 else if(td[0] == VT_USERDEFINED)
3553 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3555 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3558 /* second time around to fill the array subscript info */
3559 for(i=0;i<cTD;i++)
3561 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3562 if(tlbSegDir.pArrayDescriptions.offset>0)
3564 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3565 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3567 if(td[1]<0)
3568 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3569 else
3570 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3572 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3574 for(j = 0; j<td[2]; j++)
3576 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3577 sizeof(INT), &cx, DO_NOT_SEEK);
3578 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3579 sizeof(INT), &cx, DO_NOT_SEEK);
3582 else
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3585 ERR("didn't find array description data\n");
3590 /* imported type libs */
3591 if(tlbSegDir.pImpFiles.offset>0)
3593 TLBImpLib *pImpLib;
3594 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3595 UINT16 size;
3597 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3599 char *name;
3601 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3602 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3603 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3605 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3606 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3607 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3608 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3610 size >>= 2;
3611 name = heap_alloc_zero(size+1);
3612 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3613 pImpLib->name = TLB_MultiByteToBSTR(name);
3614 heap_free(name);
3616 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3617 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3619 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3623 MSFT_ReadAllRefs(&cx);
3625 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3627 /* type infos */
3628 if(tlbHeader.nrtypeinfos >= 0 )
3630 ITypeInfoImpl **ppTI;
3632 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3634 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3636 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3638 ++ppTI;
3639 (pTypeLibImpl->TypeInfoCount)++;
3643 #ifdef _WIN64
3644 if(pTypeLibImpl->syskind == SYS_WIN32){
3645 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3646 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3648 #endif
3650 TRACE("(%p)\n", pTypeLibImpl);
3651 return &pTypeLibImpl->ITypeLib2_iface;
3655 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3657 char b[3];
3658 int i;
3659 short s;
3661 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3662 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3663 return FALSE;
3666 guid->Data4[0] = s >> 8;
3667 guid->Data4[1] = s & 0xff;
3669 b[2] = '\0';
3670 for(i = 0; i < 6; i++) {
3671 memcpy(b, str + 24 + 2 * i, 2);
3672 guid->Data4[i + 2] = strtol(b, NULL, 16);
3674 return TRUE;
3677 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3679 WORD bytelen;
3680 DWORD len;
3681 BSTR tmp_str;
3683 *pStr = NULL;
3684 bytelen = *(const WORD*)ptr;
3685 if(bytelen == 0xffff) return 2;
3687 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3688 tmp_str = SysAllocStringLen(NULL, len);
3689 if (tmp_str) {
3690 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3691 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3692 SysFreeString(tmp_str);
3694 return bytelen + 2;
3697 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3699 WORD bytelen;
3701 *str = NULL;
3702 bytelen = *(const WORD*)ptr;
3703 if(bytelen == 0xffff) return 2;
3704 *str = heap_alloc(bytelen + 1);
3705 memcpy(*str, ptr + 2, bytelen);
3706 (*str)[bytelen] = '\0';
3707 return bytelen + 2;
3710 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3712 BSTR tmp_str;
3713 TLBString *tlbstr;
3715 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3716 if (tlbstr->offset == offset)
3717 return tlbstr;
3720 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3721 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3722 SysFreeString(tmp_str);
3724 return tlbstr;
3727 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3729 char *ptr = pLibBlk;
3730 WORD w;
3732 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3733 FIXME("libblk magic = %04x\n", w);
3734 return 0;
3737 ptr += 6;
3738 if((w = *(WORD*)ptr) != 0xffff) {
3739 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3740 ptr += w;
3742 ptr += 2;
3744 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3746 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3748 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3749 ptr += 4;
3751 pTypeLibImpl->syskind = *(WORD*)ptr;
3752 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3753 ptr += 2;
3755 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3756 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3757 else
3758 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3759 ptr += 2;
3761 ptr += 4; /* skip res12 */
3763 pTypeLibImpl->libflags = *(WORD*)ptr;
3764 ptr += 2;
3766 pTypeLibImpl->ver_major = *(WORD*)ptr;
3767 ptr += 2;
3769 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3770 ptr += 2;
3772 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3773 ptr += sizeof(GUID);
3775 return ptr - (char*)pLibBlk;
3778 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3779 typedef struct
3781 unsigned int num;
3782 HREFTYPE refs[1];
3783 } sltg_ref_lookup_t;
3785 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3786 HREFTYPE *typelib_ref)
3788 if(table && typeinfo_ref < table->num)
3790 *typelib_ref = table->refs[typeinfo_ref];
3791 return S_OK;
3794 ERR_(typelib)("Unable to find reference\n");
3795 *typelib_ref = -1;
3796 return E_FAIL;
3799 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3801 BOOL done = FALSE;
3803 while(!done) {
3804 if((*pType & 0xe00) == 0xe00) {
3805 pTD->vt = VT_PTR;
3806 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3807 pTD = pTD->u.lptdesc;
3809 switch(*pType & 0x3f) {
3810 case VT_PTR:
3811 pTD->vt = VT_PTR;
3812 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3813 pTD = pTD->u.lptdesc;
3814 break;
3816 case VT_USERDEFINED:
3817 pTD->vt = VT_USERDEFINED;
3818 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3819 done = TRUE;
3820 break;
3822 case VT_CARRAY:
3824 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3825 array */
3827 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3829 pTD->vt = VT_CARRAY;
3830 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3831 pTD->u.lpadesc->cDims = pSA->cDims;
3832 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3833 pSA->cDims * sizeof(SAFEARRAYBOUND));
3835 pTD = &pTD->u.lpadesc->tdescElem;
3836 break;
3839 case VT_SAFEARRAY:
3841 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3842 useful? */
3844 pType++;
3845 pTD->vt = VT_SAFEARRAY;
3846 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3847 pTD = pTD->u.lptdesc;
3848 break;
3850 default:
3851 pTD->vt = *pType & 0x3f;
3852 done = TRUE;
3853 break;
3855 pType++;
3857 return pType;
3860 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3861 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3863 /* Handle [in/out] first */
3864 if((*pType & 0xc000) == 0xc000)
3865 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3866 else if(*pType & 0x8000)
3867 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3868 else if(*pType & 0x4000)
3869 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3870 else
3871 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3873 if(*pType & 0x2000)
3874 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3876 if(*pType & 0x80)
3877 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3879 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3883 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3884 char *pNameTable)
3886 unsigned int ref;
3887 char *name;
3888 TLBRefType *ref_type;
3889 sltg_ref_lookup_t *table;
3890 HREFTYPE typelib_ref;
3892 if(pRef->magic != SLTG_REF_MAGIC) {
3893 FIXME("Ref magic = %x\n", pRef->magic);
3894 return NULL;
3896 name = ( (char*)pRef->names + pRef->number);
3898 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3899 table->num = pRef->number >> 3;
3901 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3903 /* We don't want the first href to be 0 */
3904 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3906 for(ref = 0; ref < pRef->number >> 3; ref++) {
3907 char *refname;
3908 unsigned int lib_offs, type_num;
3910 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3912 name += SLTG_ReadStringA(name, &refname);
3913 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3914 FIXME_(typelib)("Can't sscanf ref\n");
3915 if(lib_offs != 0xffff) {
3916 TLBImpLib *import;
3918 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3919 if(import->offset == lib_offs)
3920 break;
3922 if(&import->entry == &pTL->implib_list) {
3923 char fname[MAX_PATH+1];
3924 int len;
3925 GUID tmpguid;
3927 import = heap_alloc_zero(sizeof(*import));
3928 import->offset = lib_offs;
3929 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3930 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3931 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
3932 &import->wVersionMajor,
3933 &import->wVersionMinor,
3934 &import->lcid, fname) != 4) {
3935 FIXME_(typelib)("can't sscanf ref %s\n",
3936 pNameTable + lib_offs + 40);
3938 len = strlen(fname);
3939 if(fname[len-1] != '#')
3940 FIXME("fname = %s\n", fname);
3941 fname[len-1] = '\0';
3942 import->name = TLB_MultiByteToBSTR(fname);
3943 list_add_tail(&pTL->implib_list, &import->entry);
3945 ref_type->pImpTLInfo = import;
3947 /* Store a reference to IDispatch */
3948 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3949 pTL->dispatch_href = typelib_ref;
3951 } else { /* internal ref */
3952 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3954 ref_type->reference = typelib_ref;
3955 ref_type->index = type_num;
3957 heap_free(refname);
3958 list_add_tail(&pTL->ref_list, &ref_type->entry);
3960 table->refs[ref] = typelib_ref;
3961 typelib_ref += 4;
3963 if((BYTE)*name != SLTG_REF_MAGIC)
3964 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3965 dump_TLBRefType(pTL);
3966 return table;
3969 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3970 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3972 SLTG_ImplInfo *info;
3973 TLBImplType *pImplType;
3974 /* I don't really get this structure, usually it's 0x16 bytes
3975 long, but iuser.tlb contains some that are 0x18 bytes long.
3976 That's ok because we can use the next ptr to jump to the next
3977 one. But how do we know the length of the last one? The WORD
3978 at offs 0x8 might be the clue. For now I'm just assuming that
3979 the last one is the regular 0x16 bytes. */
3981 info = (SLTG_ImplInfo*)pBlk;
3982 while(1){
3983 pTI->typeattr.cImplTypes++;
3984 if(info->next == 0xffff)
3985 break;
3986 info = (SLTG_ImplInfo*)(pBlk + info->next);
3989 info = (SLTG_ImplInfo*)pBlk;
3990 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3991 pImplType = pTI->impltypes;
3992 while(1) {
3993 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3994 pImplType->implflags = info->impltypeflags;
3995 ++pImplType;
3997 if(info->next == 0xffff)
3998 break;
3999 if(OneOnly)
4000 FIXME_(typelib)("Interface inheriting more than one interface\n");
4001 info = (SLTG_ImplInfo*)(pBlk + info->next);
4003 info++; /* see comment at top of function */
4004 return (char*)info;
4007 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4008 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4010 TLBVarDesc *pVarDesc;
4011 const TLBString *prevName = NULL;
4012 SLTG_Variable *pItem;
4013 unsigned short i;
4014 WORD *pType;
4016 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4018 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4019 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4021 pVarDesc->vardesc.memid = pItem->memid;
4023 if (pItem->magic != SLTG_VAR_MAGIC &&
4024 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4025 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4026 return;
4029 if (pItem->name == 0xfffe)
4030 pVarDesc->Name = prevName;
4031 else
4032 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4034 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4035 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4036 TRACE_(typelib)("memid = %#lx\n", pItem->memid);
4038 if(pItem->flags & 0x02)
4039 pType = &pItem->type;
4040 else
4041 pType = (WORD*)(pBlk + pItem->type);
4043 if (pItem->flags & ~0xda)
4044 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4046 SLTG_DoElem(pType, pBlk,
4047 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4049 if (TRACE_ON(typelib)) {
4050 char buf[300];
4051 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4052 TRACE_(typelib)("elemdescVar: %s\n", buf);
4055 if (pItem->flags & 0x40) {
4056 TRACE_(typelib)("VAR_DISPATCH\n");
4057 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4059 else if (pItem->flags & 0x10) {
4060 TRACE_(typelib)("VAR_CONST\n");
4061 pVarDesc->vardesc.varkind = VAR_CONST;
4062 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4063 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4064 if (pItem->flags & 0x08)
4065 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4066 else {
4067 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4069 case VT_LPSTR:
4070 case VT_LPWSTR:
4071 case VT_BSTR:
4073 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4074 BSTR str;
4075 TRACE_(typelib)("len = %u\n", len);
4076 if (len == 0xffff) {
4077 str = NULL;
4078 } else {
4079 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4080 str = SysAllocStringLen(NULL, alloc_len);
4081 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4083 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4084 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4085 break;
4087 case VT_I2:
4088 case VT_UI2:
4089 case VT_I4:
4090 case VT_UI4:
4091 case VT_INT:
4092 case VT_UINT:
4093 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4094 *(INT*)(pBlk + pItem->byte_offs);
4095 break;
4096 default:
4097 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4101 else {
4102 TRACE_(typelib)("VAR_PERINSTANCE\n");
4103 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4104 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4107 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4108 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4110 if (pItem->flags & 0x80)
4111 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4113 prevName = pVarDesc->Name;
4115 pTI->typeattr.cVars = cVars;
4118 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4119 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4121 SLTG_Function *pFunc;
4122 unsigned short i;
4123 TLBFuncDesc *pFuncDesc;
4125 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4127 pFuncDesc = pTI->funcdescs;
4128 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4129 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4131 int param;
4132 WORD *pType, *pArg;
4134 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4135 case SLTG_FUNCTION_MAGIC:
4136 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4137 break;
4138 case SLTG_DISPATCH_FUNCTION_MAGIC:
4139 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4140 break;
4141 case SLTG_STATIC_FUNCTION_MAGIC:
4142 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4143 break;
4144 default:
4145 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4146 continue;
4148 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4150 pFuncDesc->funcdesc.memid = pFunc->dispid;
4151 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4152 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4153 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4154 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4155 if (pFuncDesc->funcdesc.funckind == FUNC_DISPATCH)
4156 pFuncDesc->funcdesc.oVft = 0;
4157 else
4158 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4160 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4161 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4163 if(pFunc->retnextopt & 0x80)
4164 pType = &pFunc->rettype;
4165 else
4166 pType = (WORD*)(pBlk + pFunc->rettype);
4168 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4170 pFuncDesc->funcdesc.lprgelemdescParam =
4171 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4172 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4174 pArg = (WORD*)(pBlk + pFunc->arg_off);
4176 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4177 char *paramName = pNameTable + *pArg;
4178 BOOL HaveOffs;
4179 /* If arg type follows then paramName points to the 2nd
4180 letter of the name, else the next WORD is an offset to
4181 the arg type and paramName points to the first letter.
4182 So let's take one char off paramName and see if we're
4183 pointing at an alphanumeric char. However if *pArg is
4184 0xffff or 0xfffe then the param has no name, the former
4185 meaning that the next WORD is the type, the latter
4186 meaning that the next WORD is an offset to the type. */
4188 HaveOffs = FALSE;
4189 if(*pArg == 0xffff)
4190 paramName = NULL;
4191 else if(*pArg == 0xfffe) {
4192 paramName = NULL;
4193 HaveOffs = TRUE;
4195 else if(paramName[-1] && !isalnum(paramName[-1]))
4196 HaveOffs = TRUE;
4198 pArg++;
4200 if(HaveOffs) { /* the next word is an offset to type */
4201 pType = (WORD*)(pBlk + *pArg);
4202 SLTG_DoElem(pType, pBlk,
4203 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4204 pArg++;
4205 } else {
4206 if(paramName)
4207 paramName--;
4208 pArg = SLTG_DoElem(pArg, pBlk,
4209 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4212 /* Are we an optional param ? */
4213 if(pFuncDesc->funcdesc.cParams - param <=
4214 pFuncDesc->funcdesc.cParamsOpt)
4215 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4217 if(paramName) {
4218 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4219 paramName - pNameTable, pTI->pTypeLib);
4220 } else {
4221 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4225 pTI->typeattr.cFuncs = cFuncs;
4228 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4229 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4230 SLTG_TypeInfoTail *pTITail)
4232 char *pFirstItem;
4233 sltg_ref_lookup_t *ref_lookup = NULL;
4235 if(pTIHeader->href_table != 0xffffffff) {
4236 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4237 pNameTable);
4240 pFirstItem = pBlk;
4242 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4243 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4245 heap_free(ref_lookup);
4249 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4250 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4251 const SLTG_TypeInfoTail *pTITail)
4253 char *pFirstItem;
4254 sltg_ref_lookup_t *ref_lookup = NULL;
4256 if(pTIHeader->href_table != 0xffffffff) {
4257 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4258 pNameTable);
4261 pFirstItem = pBlk;
4263 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4264 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4267 if (pTITail->funcs_off != 0xffff)
4268 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4270 heap_free(ref_lookup);
4272 if (TRACE_ON(typelib))
4273 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4276 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4277 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4278 const SLTG_TypeInfoTail *pTITail)
4280 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4283 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4284 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4285 const SLTG_TypeInfoTail *pTITail)
4287 WORD *pType;
4288 sltg_ref_lookup_t *ref_lookup = NULL;
4290 if (pTITail->simple_alias) {
4291 /* if simple alias, no more processing required */
4292 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4293 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4294 return;
4297 if(pTIHeader->href_table != 0xffffffff) {
4298 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4299 pNameTable);
4302 /* otherwise it is an offset to a type */
4303 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4305 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4306 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4308 heap_free(ref_lookup);
4311 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4312 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4313 const SLTG_TypeInfoTail *pTITail)
4315 sltg_ref_lookup_t *ref_lookup = NULL;
4316 if (pTIHeader->href_table != 0xffffffff)
4317 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4318 pNameTable);
4320 if (pTITail->vars_off != 0xffff)
4321 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4323 if (pTITail->funcs_off != 0xffff)
4324 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4326 if (pTITail->impls_off != 0xffff)
4327 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4329 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4330 * of dispinterface functions including the IDispatch ones, so
4331 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4332 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4334 heap_free(ref_lookup);
4335 if (TRACE_ON(typelib))
4336 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4339 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4340 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4341 const SLTG_TypeInfoTail *pTITail)
4343 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4346 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4347 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4348 const SLTG_TypeInfoTail *pTITail)
4350 sltg_ref_lookup_t *ref_lookup = NULL;
4351 if (pTIHeader->href_table != 0xffffffff)
4352 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4353 pNameTable);
4355 if (pTITail->vars_off != 0xffff)
4356 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4358 if (pTITail->funcs_off != 0xffff)
4359 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4360 heap_free(ref_lookup);
4361 if (TRACE_ON(typelib))
4362 dump_TypeInfo(pTI);
4365 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4366 manageable copy of it into this */
4367 typedef struct {
4368 WORD small_no;
4369 char *index_name;
4370 char *other_name;
4371 WORD res1a;
4372 WORD name_offs;
4373 WORD more_bytes;
4374 char *extra;
4375 WORD res20;
4376 DWORD helpcontext;
4377 WORD res26;
4378 GUID uuid;
4379 } SLTG_InternalOtherTypeInfo;
4381 /****************************************************************************
4382 * ITypeLib2_Constructor_SLTG
4384 * loading a SLTG typelib from an in-memory image
4386 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4388 ITypeLibImpl *pTypeLibImpl;
4389 SLTG_Header *pHeader;
4390 SLTG_BlkEntry *pBlkEntry;
4391 SLTG_Magic *pMagic;
4392 SLTG_Index *pIndex;
4393 SLTG_Pad9 *pPad9;
4394 LPVOID pBlk, pFirstBlk;
4395 SLTG_LibBlk *pLibBlk;
4396 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4397 char *pAfterOTIBlks = NULL;
4398 char *pNameTable, *ptr;
4399 int i;
4400 DWORD len, order;
4401 ITypeInfoImpl **ppTypeInfoImpl;
4403 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
4406 pTypeLibImpl = TypeLibImpl_Constructor();
4407 if (!pTypeLibImpl) return NULL;
4409 pHeader = pLib;
4411 TRACE_(typelib)("header:\n");
4412 TRACE_(typelib)("\tmagic %#lx, file blocks = %d\n", pHeader->SLTG_magic,
4413 pHeader->nrOfFileBlks );
4414 if (pHeader->SLTG_magic != SLTG_SIGNATURE)
4416 FIXME_(typelib)("Header type magic %#lx not supported.\n", pHeader->SLTG_magic);
4417 return NULL;
4420 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4421 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4423 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4424 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4426 /* Next we have a magic block */
4427 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4429 /* Let's see if we're still in sync */
4430 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4431 sizeof(SLTG_COMPOBJ_MAGIC))) {
4432 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4433 return NULL;
4435 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4436 sizeof(SLTG_DIR_MAGIC))) {
4437 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4438 return NULL;
4441 pIndex = (SLTG_Index*)(pMagic+1);
4443 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4445 pFirstBlk = pPad9 + 1;
4447 /* We'll set up a ptr to the main library block, which is the last one. */
4449 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4450 pBlkEntry[order].next != 0;
4451 order = pBlkEntry[order].next - 1) {
4452 pBlk = (char*)pBlk + pBlkEntry[order].len;
4454 pLibBlk = pBlk;
4456 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4458 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4459 interspersed */
4461 len += 0x40;
4463 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4465 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4468 ptr = (char*)pLibBlk + len;
4470 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4471 WORD w, extra;
4472 len = 0;
4474 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4476 w = *(WORD*)(ptr + 2);
4477 if(w != 0xffff) {
4478 len += w;
4479 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4480 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4481 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4483 w = *(WORD*)(ptr + 4 + len);
4484 if(w != 0xffff) {
4485 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4486 len += w;
4487 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4488 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4489 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4491 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4492 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4493 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4494 if(extra) {
4495 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4496 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4497 len += extra;
4499 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4500 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4501 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4502 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4503 len += sizeof(SLTG_OtherTypeInfo);
4504 ptr += len;
4507 pAfterOTIBlks = ptr;
4509 /* Skip this WORD and get the next DWORD */
4510 len = *(DWORD*)(pAfterOTIBlks + 2);
4512 /* Now add this to pLibBLk look at what we're pointing at and
4513 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4514 dust and we should be pointing at the beginning of the name
4515 table */
4517 pNameTable = (char*)pLibBlk + len;
4519 switch(*(WORD*)pNameTable) {
4520 case 0xffff:
4521 break;
4522 case 0x0200:
4523 pNameTable += 0x20;
4524 break;
4525 default:
4526 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4527 break;
4530 pNameTable += 0x216;
4532 pNameTable += 2;
4534 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4536 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4539 /* Hopefully we now have enough ptrs set up to actually read in
4540 some TypeInfos. It's not clear which order to do them in, so
4541 I'll just follow the links along the BlkEntry chain and read
4542 them in the order in which they are in the file */
4544 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4545 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4547 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4548 pBlkEntry[order].next != 0;
4549 order = pBlkEntry[order].next - 1, i++) {
4551 SLTG_TypeInfoHeader *pTIHeader;
4552 SLTG_TypeInfoTail *pTITail;
4553 SLTG_MemberHeader *pMemHeader;
4555 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4556 FIXME_(typelib)("Index strings don't match\n");
4557 heap_free(pOtherTypeInfoBlks);
4558 return NULL;
4561 pTIHeader = pBlk;
4562 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4563 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4564 heap_free(pOtherTypeInfoBlks);
4565 return NULL;
4567 TRACE_(typelib)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4568 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4569 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4571 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4572 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4573 (*ppTypeInfoImpl)->index = i;
4574 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4575 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4576 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4577 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4578 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4579 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4580 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4581 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4583 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4584 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4586 if((pTIHeader->typeflags1 & 7) != 2)
4587 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4588 if(pTIHeader->typeflags3 != 2)
4589 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4591 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4592 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4593 typekind_desc[pTIHeader->typekind],
4594 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4595 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4597 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4599 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4601 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4602 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4603 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4605 switch(pTIHeader->typekind) {
4606 case TKIND_ENUM:
4607 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4608 pTIHeader, pTITail);
4609 break;
4611 case TKIND_RECORD:
4612 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4613 pTIHeader, pTITail);
4614 break;
4616 case TKIND_INTERFACE:
4617 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4618 pTIHeader, pTITail);
4619 break;
4621 case TKIND_COCLASS:
4622 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4623 pTIHeader, pTITail);
4624 break;
4626 case TKIND_ALIAS:
4627 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4628 pTIHeader, pTITail);
4629 break;
4631 case TKIND_DISPATCH:
4632 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4633 pTIHeader, pTITail);
4634 break;
4636 case TKIND_MODULE:
4637 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4638 pTIHeader, pTITail);
4639 break;
4641 default:
4642 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4643 break;
4647 /* could get cFuncs, cVars and cImplTypes from here
4648 but we've already set those */
4649 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4650 X(06);
4651 X(16);
4652 X(18);
4653 X(1a);
4654 X(1e);
4655 X(24);
4656 X(26);
4657 X(2a);
4658 X(2c);
4659 X(2e);
4660 X(30);
4661 X(32);
4662 X(34);
4663 #undef X
4664 ++ppTypeInfoImpl;
4665 pBlk = (char*)pBlk + pBlkEntry[order].len;
4668 if(i != pTypeLibImpl->TypeInfoCount) {
4669 FIXME("Somehow processed %d TypeInfos\n", i);
4670 heap_free(pOtherTypeInfoBlks);
4671 return NULL;
4674 heap_free(pOtherTypeInfoBlks);
4675 return &pTypeLibImpl->ITypeLib2_iface;
4678 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4680 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4682 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4684 if(IsEqualIID(riid, &IID_IUnknown) ||
4685 IsEqualIID(riid,&IID_ITypeLib)||
4686 IsEqualIID(riid,&IID_ITypeLib2))
4688 *ppv = &This->ITypeLib2_iface;
4690 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4691 IsEqualIID(riid, &IID_ICreateTypeLib2))
4693 *ppv = &This->ICreateTypeLib2_iface;
4695 else
4697 *ppv = NULL;
4698 TRACE("-- Interface: E_NOINTERFACE\n");
4699 return E_NOINTERFACE;
4702 IUnknown_AddRef((IUnknown*)*ppv);
4703 return S_OK;
4706 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4708 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4709 ULONG ref = InterlockedIncrement(&This->ref);
4711 TRACE("%p, refcount %lu.\n", iface, ref);
4713 return ref;
4716 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4718 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4719 ULONG ref = InterlockedDecrement(&This->ref);
4721 TRACE("%p, refcount %lu.\n", iface, ref);
4723 if (!ref)
4725 TLBImpLib *pImpLib, *pImpLibNext;
4726 TLBRefType *ref_type, *ref_type_next;
4727 TLBString *tlbstr, *tlbstr_next;
4728 TLBGuid *tlbguid, *tlbguid_next;
4729 int i;
4731 /* remove cache entry */
4732 if(This->path)
4734 TRACE("removing from cache list\n");
4735 EnterCriticalSection(&cache_section);
4736 if(This->entry.next)
4737 list_remove(&This->entry);
4738 LeaveCriticalSection(&cache_section);
4739 heap_free(This->path);
4741 TRACE(" destroying ITypeLib(%p)\n",This);
4743 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4744 list_remove(&tlbstr->entry);
4745 SysFreeString(tlbstr->str);
4746 heap_free(tlbstr);
4749 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4750 list_remove(&tlbstr->entry);
4751 SysFreeString(tlbstr->str);
4752 heap_free(tlbstr);
4755 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4756 list_remove(&tlbguid->entry);
4757 heap_free(tlbguid);
4760 TLB_FreeCustData(&This->custdata_list);
4762 for (i = 0; i < This->ctTypeDesc; i++)
4763 if (This->pTypeDesc[i].vt == VT_CARRAY)
4764 heap_free(This->pTypeDesc[i].u.lpadesc);
4766 heap_free(This->pTypeDesc);
4768 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4770 if (pImpLib->pImpTypeLib)
4771 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4772 SysFreeString(pImpLib->name);
4774 list_remove(&pImpLib->entry);
4775 heap_free(pImpLib);
4778 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4780 list_remove(&ref_type->entry);
4781 heap_free(ref_type);
4784 for (i = 0; i < This->TypeInfoCount; ++i){
4785 heap_free(This->typeinfos[i]->tdescAlias);
4786 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4788 heap_free(This->typeinfos);
4789 heap_free(This);
4790 return 0;
4793 return ref;
4796 /* ITypeLib::GetTypeInfoCount
4798 * Returns the number of type descriptions in the type library
4800 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4802 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4803 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4804 return This->TypeInfoCount;
4807 /* ITypeLib::GetTypeInfo
4809 * retrieves the specified type description in the library.
4811 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4812 ITypeLib2 *iface,
4813 UINT index,
4814 ITypeInfo **ppTInfo)
4816 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4818 TRACE("%p %u %p\n", This, index, ppTInfo);
4820 if(!ppTInfo)
4821 return E_INVALIDARG;
4823 if(index >= This->TypeInfoCount)
4824 return TYPE_E_ELEMENTNOTFOUND;
4826 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4827 ITypeInfo_AddRef(*ppTInfo);
4829 return S_OK;
4833 /* ITypeLibs::GetTypeInfoType
4835 * Retrieves the type of a type description.
4837 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4838 ITypeLib2 *iface,
4839 UINT index,
4840 TYPEKIND *pTKind)
4842 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4844 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4846 if(!pTKind)
4847 return E_INVALIDARG;
4849 if(index >= This->TypeInfoCount)
4850 return TYPE_E_ELEMENTNOTFOUND;
4852 *pTKind = This->typeinfos[index]->typeattr.typekind;
4854 return S_OK;
4857 /* ITypeLib::GetTypeInfoOfGuid
4859 * Retrieves the type description that corresponds to the specified GUID.
4862 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4863 ITypeLib2 *iface,
4864 REFGUID guid,
4865 ITypeInfo **ppTInfo)
4867 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4868 int i;
4870 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4872 for(i = 0; i < This->TypeInfoCount; ++i){
4873 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4874 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4875 ITypeInfo_AddRef(*ppTInfo);
4876 return S_OK;
4880 return TYPE_E_ELEMENTNOTFOUND;
4883 /* ITypeLib::GetLibAttr
4885 * Retrieves the structure that contains the library's attributes.
4888 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4889 ITypeLib2 *iface,
4890 LPTLIBATTR *attr)
4892 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4894 TRACE("(%p, %p)\n", This, attr);
4896 if (!attr) return E_INVALIDARG;
4898 *attr = heap_alloc(sizeof(**attr));
4899 if (!*attr) return E_OUTOFMEMORY;
4901 (*attr)->guid = *TLB_get_guid_null(This->guid);
4902 (*attr)->lcid = This->set_lcid;
4903 (*attr)->syskind = This->syskind;
4904 (*attr)->wMajorVerNum = This->ver_major;
4905 (*attr)->wMinorVerNum = This->ver_minor;
4906 (*attr)->wLibFlags = This->libflags;
4908 return S_OK;
4911 /* ITypeLib::GetTypeComp
4913 * Enables a client compiler to bind to a library's types, variables,
4914 * constants, and global functions.
4917 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4918 ITypeLib2 *iface,
4919 ITypeComp **ppTComp)
4921 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4923 TRACE("(%p)->(%p)\n",This,ppTComp);
4924 *ppTComp = &This->ITypeComp_iface;
4925 ITypeComp_AddRef(*ppTComp);
4927 return S_OK;
4930 /* ITypeLib::GetDocumentation
4932 * Retrieves the library's documentation string, the complete Help file name
4933 * and path, and the context identifier for the library Help topic in the Help
4934 * file.
4936 * On a successful return all non-null BSTR pointers will have been set,
4937 * possibly to NULL.
4939 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4940 ITypeLib2 *iface,
4941 INT index,
4942 BSTR *pBstrName,
4943 BSTR *pBstrDocString,
4944 DWORD *pdwHelpContext,
4945 BSTR *pBstrHelpFile)
4947 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4948 HRESULT result = E_INVALIDARG;
4949 ITypeInfo *pTInfo;
4951 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4952 This, index,
4953 pBstrName, pBstrDocString,
4954 pdwHelpContext, pBstrHelpFile);
4956 if(index<0)
4958 /* documentation for the typelib */
4959 if(pBstrName)
4961 if (This->Name)
4963 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4964 goto memerr1;
4966 else
4967 *pBstrName = NULL;
4969 if(pBstrDocString)
4971 if (This->DocString)
4973 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4974 goto memerr2;
4976 else
4977 *pBstrDocString = NULL;
4979 if(pdwHelpContext)
4981 *pdwHelpContext = This->dwHelpContext;
4983 if(pBstrHelpFile)
4985 if (This->HelpFile)
4987 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4988 goto memerr3;
4990 else
4991 *pBstrHelpFile = NULL;
4994 result = S_OK;
4996 else
4998 /* for a typeinfo */
4999 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5001 if(SUCCEEDED(result))
5003 result = ITypeInfo_GetDocumentation(pTInfo,
5004 MEMBERID_NIL,
5005 pBstrName,
5006 pBstrDocString,
5007 pdwHelpContext, pBstrHelpFile);
5009 ITypeInfo_Release(pTInfo);
5012 return result;
5013 memerr3:
5014 if (pBstrDocString) SysFreeString (*pBstrDocString);
5015 memerr2:
5016 if (pBstrName) SysFreeString (*pBstrName);
5017 memerr1:
5018 return STG_E_INSUFFICIENTMEMORY;
5021 /* ITypeLib::IsName
5023 * Indicates whether a passed-in string contains the name of a type or member
5024 * described in the library.
5027 static HRESULT WINAPI ITypeLib2_fnIsName(
5028 ITypeLib2 *iface,
5029 LPOLESTR szNameBuf,
5030 ULONG lHashVal,
5031 BOOL *pfName)
5033 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5034 int tic;
5035 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5037 TRACE("%p, %s, %#lx, %p.\n", iface, debugstr_w(szNameBuf), lHashVal, pfName);
5039 *pfName=TRUE;
5040 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5041 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5042 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5043 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5044 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5045 int pc;
5046 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5047 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5048 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5049 goto ITypeLib2_fnIsName_exit;
5052 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5053 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5054 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5058 *pfName=FALSE;
5060 ITypeLib2_fnIsName_exit:
5061 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5062 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5064 return S_OK;
5067 /* ITypeLib::FindName
5069 * Finds occurrences of a type description in a type library. This may be used
5070 * to quickly verify that a name exists in a type library.
5073 static HRESULT WINAPI ITypeLib2_fnFindName(
5074 ITypeLib2 *iface,
5075 LPOLESTR name,
5076 ULONG hash,
5077 ITypeInfo **ppTInfo,
5078 MEMBERID *memid,
5079 UINT16 *found)
5081 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5082 int tic;
5083 UINT count = 0;
5084 UINT len;
5086 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface, debugstr_w(name), hash, ppTInfo, memid, found);
5088 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5089 return E_INVALIDARG;
5091 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5092 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5093 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5094 TLBVarDesc *var;
5095 UINT fdc;
5097 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5098 memid[count] = MEMBERID_NIL;
5099 goto ITypeLib2_fnFindName_exit;
5102 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5103 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5105 if(!TLB_str_memcmp(name, func->Name, len)) {
5106 memid[count] = func->funcdesc.memid;
5107 goto ITypeLib2_fnFindName_exit;
5111 var = TLB_get_vardesc_by_name(pTInfo, name);
5112 if (var) {
5113 memid[count] = var->vardesc.memid;
5114 goto ITypeLib2_fnFindName_exit;
5117 continue;
5118 ITypeLib2_fnFindName_exit:
5119 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5120 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5121 count++;
5123 TRACE("found %d typeinfos\n", count);
5125 *found = count;
5127 return S_OK;
5130 /* ITypeLib::ReleaseTLibAttr
5132 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5135 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5136 ITypeLib2 *iface,
5137 TLIBATTR *pTLibAttr)
5139 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5140 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5141 heap_free(pTLibAttr);
5144 /* ITypeLib2::GetCustData
5146 * gets the custom data
5148 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5149 ITypeLib2 * iface,
5150 REFGUID guid,
5151 VARIANT *pVarVal)
5153 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5154 TLBCustData *pCData;
5156 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5158 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5159 if(!pCData)
5160 return TYPE_E_ELEMENTNOTFOUND;
5162 VariantInit(pVarVal);
5163 VariantCopy(pVarVal, &pCData->data);
5165 return S_OK;
5168 /* ITypeLib2::GetLibStatistics
5170 * Returns statistics about a type library that are required for efficient
5171 * sizing of hash tables.
5174 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5175 ITypeLib2 * iface,
5176 ULONG *pcUniqueNames,
5177 ULONG *pcchUniqueNames)
5179 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5181 FIXME("(%p): stub!\n", This);
5183 if(pcUniqueNames) *pcUniqueNames=1;
5184 if(pcchUniqueNames) *pcchUniqueNames=1;
5185 return S_OK;
5188 /* ITypeLib2::GetDocumentation2
5190 * Retrieves the library's documentation string, the complete Help file name
5191 * and path, the localization context to use, and the context ID for the
5192 * library Help topic in the Help file.
5195 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5196 ITypeLib2 * iface,
5197 INT index,
5198 LCID lcid,
5199 BSTR *pbstrHelpString,
5200 DWORD *pdwHelpStringContext,
5201 BSTR *pbstrHelpStringDll)
5203 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5204 HRESULT result;
5205 ITypeInfo *pTInfo;
5207 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface, index, lcid);
5209 /* the help string should be obtained from the helpstringdll,
5210 * using the _DLLGetDocumentation function, based on the supplied
5211 * lcid. Nice to do sometime...
5213 if(index<0)
5215 /* documentation for the typelib */
5216 if(pbstrHelpString)
5217 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5218 if(pdwHelpStringContext)
5219 *pdwHelpStringContext=This->dwHelpContext;
5220 if(pbstrHelpStringDll)
5221 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5223 result = S_OK;
5225 else
5227 /* for a typeinfo */
5228 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5230 if(SUCCEEDED(result))
5232 ITypeInfo2 * pTInfo2;
5233 result = ITypeInfo_QueryInterface(pTInfo,
5234 &IID_ITypeInfo2,
5235 (LPVOID*) &pTInfo2);
5237 if(SUCCEEDED(result))
5239 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5240 MEMBERID_NIL,
5241 lcid,
5242 pbstrHelpString,
5243 pdwHelpStringContext,
5244 pbstrHelpStringDll);
5246 ITypeInfo2_Release(pTInfo2);
5249 ITypeInfo_Release(pTInfo);
5252 return result;
5255 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5257 TLBCustData *pCData;
5258 unsigned int ct;
5259 CUSTDATAITEM *cdi;
5260 HRESULT hr = S_OK;
5262 ct = list_count(custdata_list);
5264 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5265 if(!pCustData->prgCustData)
5266 return E_OUTOFMEMORY;
5268 pCustData->cCustData = ct;
5270 cdi = pCustData->prgCustData;
5271 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5272 cdi->guid = *TLB_get_guid_null(pCData->guid);
5273 VariantInit(&cdi->varValue);
5274 hr = VariantCopy(&cdi->varValue, &pCData->data);
5275 if(FAILED(hr)) break;
5276 ++cdi;
5279 return hr;
5283 /* ITypeLib2::GetAllCustData
5285 * Gets all custom data items for the library.
5288 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5289 ITypeLib2 * iface,
5290 CUSTDATA *pCustData)
5292 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5293 TRACE("(%p)->(%p)\n", This, pCustData);
5294 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5297 static const ITypeLib2Vtbl tlbvt = {
5298 ITypeLib2_fnQueryInterface,
5299 ITypeLib2_fnAddRef,
5300 ITypeLib2_fnRelease,
5301 ITypeLib2_fnGetTypeInfoCount,
5302 ITypeLib2_fnGetTypeInfo,
5303 ITypeLib2_fnGetTypeInfoType,
5304 ITypeLib2_fnGetTypeInfoOfGuid,
5305 ITypeLib2_fnGetLibAttr,
5306 ITypeLib2_fnGetTypeComp,
5307 ITypeLib2_fnGetDocumentation,
5308 ITypeLib2_fnIsName,
5309 ITypeLib2_fnFindName,
5310 ITypeLib2_fnReleaseTLibAttr,
5312 ITypeLib2_fnGetCustData,
5313 ITypeLib2_fnGetLibStatistics,
5314 ITypeLib2_fnGetDocumentation2,
5315 ITypeLib2_fnGetAllCustData
5319 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5321 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5323 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5326 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5328 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5330 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5333 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5335 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5337 return ITypeLib2_Release(&This->ITypeLib2_iface);
5340 static HRESULT WINAPI ITypeLibComp_fnBind(
5341 ITypeComp * iface,
5342 OLECHAR * szName,
5343 ULONG lHash,
5344 WORD wFlags,
5345 ITypeInfo ** ppTInfo,
5346 DESCKIND * pDescKind,
5347 BINDPTR * pBindPtr)
5349 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5350 BOOL typemismatch = FALSE;
5351 int i;
5353 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5355 *pDescKind = DESCKIND_NONE;
5356 pBindPtr->lptcomp = NULL;
5357 *ppTInfo = NULL;
5359 for(i = 0; i < This->TypeInfoCount; ++i){
5360 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5361 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5363 /* FIXME: check wFlags here? */
5364 /* FIXME: we should use a hash table to look this info up using lHash
5365 * instead of an O(n) search */
5366 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5367 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5369 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5371 *pDescKind = DESCKIND_TYPECOMP;
5372 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5373 ITypeComp_AddRef(pBindPtr->lptcomp);
5374 TRACE("module or enum: %s\n", debugstr_w(szName));
5375 return S_OK;
5379 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5380 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5382 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5383 HRESULT hr;
5385 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5386 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5388 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5389 return S_OK;
5391 else if (hr == TYPE_E_TYPEMISMATCH)
5392 typemismatch = TRUE;
5395 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5396 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5398 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5399 HRESULT hr;
5400 ITypeInfo *subtypeinfo;
5401 BINDPTR subbindptr;
5402 DESCKIND subdesckind;
5404 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5405 &subtypeinfo, &subdesckind, &subbindptr);
5406 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5408 TYPEDESC tdesc_appobject;
5409 const VARDESC vardesc_appobject =
5411 -2, /* memid */
5412 NULL, /* lpstrSchema */
5414 0 /* oInst */
5417 /* ELEMDESC */
5419 /* TYPEDESC */
5421 &tdesc_appobject
5423 VT_PTR
5426 0, /* wVarFlags */
5427 VAR_STATIC /* varkind */
5430 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5431 tdesc_appobject.vt = VT_USERDEFINED;
5433 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5435 /* cleanup things filled in by Bind call so we can put our
5436 * application object data in there instead */
5437 switch (subdesckind)
5439 case DESCKIND_FUNCDESC:
5440 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5441 break;
5442 case DESCKIND_VARDESC:
5443 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5444 break;
5445 default:
5446 break;
5448 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5450 if (pTypeInfo->hreftype == -1)
5451 FIXME("no hreftype for interface %p\n", pTypeInfo);
5453 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5454 if (FAILED(hr))
5455 return hr;
5457 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5458 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5459 ITypeInfo_AddRef(*ppTInfo);
5460 return S_OK;
5462 else if (hr == TYPE_E_TYPEMISMATCH)
5463 typemismatch = TRUE;
5467 if (typemismatch)
5469 TRACE("type mismatch %s\n", debugstr_w(szName));
5470 return TYPE_E_TYPEMISMATCH;
5472 else
5474 TRACE("name not found %s\n", debugstr_w(szName));
5475 return S_OK;
5479 static HRESULT WINAPI ITypeLibComp_fnBindType(
5480 ITypeComp * iface,
5481 OLECHAR * szName,
5482 ULONG lHash,
5483 ITypeInfo ** ppTInfo,
5484 ITypeComp ** ppTComp)
5486 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5487 ITypeInfoImpl *info;
5489 TRACE("%p, %s, %#lx, %p, %p.\n", iface, debugstr_w(szName), lHash, ppTInfo, ppTComp);
5491 if(!szName || !ppTInfo || !ppTComp)
5492 return E_INVALIDARG;
5494 info = TLB_get_typeinfo_by_name(This, szName);
5495 if(!info){
5496 *ppTInfo = NULL;
5497 *ppTComp = NULL;
5498 return S_OK;
5501 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5502 ITypeInfo_AddRef(*ppTInfo);
5503 *ppTComp = &info->ITypeComp_iface;
5504 ITypeComp_AddRef(*ppTComp);
5506 return S_OK;
5509 static const ITypeCompVtbl tlbtcvt =
5512 ITypeLibComp_fnQueryInterface,
5513 ITypeLibComp_fnAddRef,
5514 ITypeLibComp_fnRelease,
5516 ITypeLibComp_fnBind,
5517 ITypeLibComp_fnBindType
5520 /*================== ITypeInfo(2) Methods ===================================*/
5521 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5523 ITypeInfoImpl *pTypeInfoImpl;
5525 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5526 if (pTypeInfoImpl)
5528 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5529 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5530 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5531 pTypeInfoImpl->ref = 0;
5532 pTypeInfoImpl->hreftype = -1;
5533 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5534 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5535 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5536 list_init(pTypeInfoImpl->pcustdata_list);
5538 TRACE("(%p)\n", pTypeInfoImpl);
5539 return pTypeInfoImpl;
5542 /* ITypeInfo::QueryInterface
5544 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5545 ITypeInfo2 *iface,
5546 REFIID riid,
5547 VOID **ppvObject)
5549 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5551 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5553 *ppvObject=NULL;
5554 if(IsEqualIID(riid, &IID_IUnknown) ||
5555 IsEqualIID(riid,&IID_ITypeInfo)||
5556 IsEqualIID(riid,&IID_ITypeInfo2))
5557 *ppvObject = &This->ITypeInfo2_iface;
5558 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5559 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5560 *ppvObject = &This->ICreateTypeInfo2_iface;
5561 else if(IsEqualIID(riid, &IID_ITypeComp))
5562 *ppvObject = &This->ITypeComp_iface;
5564 if(*ppvObject){
5565 IUnknown_AddRef((IUnknown*)*ppvObject);
5566 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5567 return S_OK;
5569 TRACE("-- Interface: E_NOINTERFACE\n");
5570 return E_NOINTERFACE;
5573 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5575 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5576 ULONG ref = InterlockedIncrement(&This->ref);
5578 TRACE("%p, refcount %lu.\n", iface, ref);
5580 if (ref == 1 /* incremented from 0 */)
5581 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5583 return ref;
5586 static void typeinfo_release_funcdesc(TLBFuncDesc *func)
5588 unsigned int i;
5590 for (i = 0; i < func->funcdesc.cParams; ++i)
5592 ELEMDESC *elemdesc = &func->funcdesc.lprgelemdescParam[i];
5593 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5594 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5595 TLB_FreeCustData(&func->pParamDesc[i].custdata_list);
5597 heap_free(func->funcdesc.lprgelemdescParam);
5598 heap_free(func->pParamDesc);
5599 TLB_FreeCustData(&func->custdata_list);
5602 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5604 UINT i;
5606 TRACE("destroying ITypeInfo(%p)\n",This);
5608 for (i = 0; i < This->typeattr.cFuncs; ++i)
5610 typeinfo_release_funcdesc(&This->funcdescs[i]);
5612 heap_free(This->funcdescs);
5614 for(i = 0; i < This->typeattr.cVars; ++i)
5616 TLBVarDesc *pVInfo = &This->vardescs[i];
5617 if (pVInfo->vardesc_create) {
5618 TLB_FreeVarDesc(pVInfo->vardesc_create);
5619 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5620 VariantClear(pVInfo->vardesc.u.lpvarValue);
5621 heap_free(pVInfo->vardesc.u.lpvarValue);
5623 TLB_FreeCustData(&pVInfo->custdata_list);
5625 heap_free(This->vardescs);
5627 if(This->impltypes){
5628 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5629 TLBImplType *pImpl = &This->impltypes[i];
5630 TLB_FreeCustData(&pImpl->custdata_list);
5632 heap_free(This->impltypes);
5635 TLB_FreeCustData(&This->custdata_list);
5637 heap_free(This);
5640 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5642 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5643 ULONG ref = InterlockedDecrement(&This->ref);
5645 TRACE("%p, refcount %lu.\n", iface, ref);
5647 if (!ref)
5649 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5650 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5651 if (not_attached_to_typelib)
5652 heap_free(This);
5653 /* otherwise This will be freed when typelib is freed */
5656 return ref;
5659 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5660 LPTYPEATTR *ppTypeAttr)
5662 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5663 SIZE_T size;
5665 TRACE("(%p)\n",This);
5667 size = sizeof(**ppTypeAttr);
5668 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5669 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5671 *ppTypeAttr = heap_alloc(size);
5672 if (!*ppTypeAttr)
5673 return E_OUTOFMEMORY;
5675 **ppTypeAttr = This->typeattr;
5676 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5678 if (This->tdescAlias)
5679 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5681 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5682 /* This should include all the inherited funcs */
5683 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5684 /* This is always the size of IDispatch's vtbl */
5685 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5686 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5688 return S_OK;
5691 /* ITypeInfo::GetTypeComp
5693 * Retrieves the ITypeComp interface for the type description, which enables a
5694 * client compiler to bind to the type description's members.
5697 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5698 ITypeComp * *ppTComp)
5700 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5702 TRACE("(%p)->(%p)\n", This, ppTComp);
5704 *ppTComp = &This->ITypeComp_iface;
5705 ITypeComp_AddRef(*ppTComp);
5706 return S_OK;
5709 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5711 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5712 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5713 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5714 return size;
5717 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5719 *dest = *src;
5720 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5721 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5723 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5724 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5725 *buffer += sizeof(PARAMDESCEX);
5726 *pparamdescex_dest = *pparamdescex_src;
5727 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5728 VariantInit(&pparamdescex_dest->varDefaultValue);
5729 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5730 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5732 else
5733 dest->u.paramdesc.pparamdescex = NULL;
5734 return S_OK;
5737 static HRESULT TLB_SanitizeBSTR(BSTR str)
5739 UINT len = SysStringLen(str), i;
5740 for (i = 0; i < len; ++i)
5741 if (str[i] > 0x7f)
5742 str[i] = '?';
5743 return S_OK;
5746 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5748 if (V_VT(var) == VT_INT)
5749 return VariantChangeType(var, var, 0, VT_I4);
5750 else if (V_VT(var) == VT_UINT)
5751 return VariantChangeType(var, var, 0, VT_UI4);
5752 else if (V_VT(var) == VT_BSTR)
5753 return TLB_SanitizeBSTR(V_BSTR(var));
5755 return S_OK;
5758 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5760 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5761 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5764 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5766 FUNCDESC *dest;
5767 char *buffer;
5768 SIZE_T size = sizeof(*src);
5769 SHORT i;
5770 HRESULT hr;
5772 size += sizeof(*src->lprgscode) * src->cScodes;
5773 size += TLB_SizeElemDesc(&src->elemdescFunc);
5774 for (i = 0; i < src->cParams; i++)
5776 size += sizeof(ELEMDESC);
5777 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5780 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5781 if (!dest) return E_OUTOFMEMORY;
5783 *dest = *src;
5784 if (dispinterface) /* overwrite funckind */
5785 dest->funckind = FUNC_DISPATCH;
5786 buffer = (char *)(dest + 1);
5788 dest->oVft = dest->oVft & 0xFFFC;
5790 if (dest->cScodes) {
5791 dest->lprgscode = (SCODE *)buffer;
5792 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5793 buffer += sizeof(*src->lprgscode) * src->cScodes;
5794 } else
5795 dest->lprgscode = NULL;
5797 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5798 if (FAILED(hr))
5800 SysFreeString((BSTR)dest);
5801 return hr;
5804 if (dest->cParams) {
5805 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5806 buffer += sizeof(ELEMDESC) * src->cParams;
5807 for (i = 0; i < src->cParams; i++)
5809 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5810 if (FAILED(hr))
5811 break;
5813 if (FAILED(hr))
5815 /* undo the above actions */
5816 for (i = i - 1; i >= 0; i--)
5817 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5818 TLB_FreeElemDesc(&dest->elemdescFunc);
5819 SysFreeString((BSTR)dest);
5820 return hr;
5822 } else
5823 dest->lprgelemdescParam = NULL;
5825 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5826 * This accounts for several arguments that are separate in the signature of
5827 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5828 if (dispinterface && (src->funckind != FUNC_DISPATCH))
5830 /* functions that have a [retval] parameter return this value into pVarResult.
5831 * [retval] is always the last parameter (if present) */
5832 if (dest->cParams &&
5833 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5835 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5836 if (elemdesc->tdesc.vt != VT_PTR)
5838 ERR("elemdesc should have started with VT_PTR instead of:\n");
5839 if (ERR_ON(ole))
5840 dump_ELEMDESC(elemdesc);
5841 return E_UNEXPECTED;
5844 /* the type pointed to by this [retval] becomes elemdescFunc,
5845 * i.e. the function signature's return type.
5846 * We are using a flat buffer so there is no danger of leaking memory */
5847 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5849 /* remove the last parameter */
5850 dest->cParams--;
5852 else if (dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5853 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5854 * not pVarResult. So the function signature should show no return value. */
5855 dest->elemdescFunc.tdesc.vt = VT_VOID;
5857 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5858 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5859 if (dest->cParams && (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
5860 dest->cParams--;
5863 *dest_ptr = dest;
5864 return S_OK;
5867 static void TLB_FreeVarDesc(VARDESC *var_desc)
5869 TLB_FreeElemDesc(&var_desc->elemdescVar);
5870 if (var_desc->varkind == VAR_CONST)
5871 VariantClear(var_desc->u.lpvarValue);
5872 SysFreeString((BSTR)var_desc);
5875 /* internal function to make the inherited interfaces' methods appear
5876 * part of the interface */
5877 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5878 UINT index, const TLBFuncDesc **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5880 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5881 HRESULT hr;
5882 UINT implemented_funcs = 0;
5884 if (funcs)
5885 *funcs = 0;
5886 else
5887 *hrefoffset = DISPATCH_HREF_OFFSET;
5889 if(This->impltypes)
5891 ITypeInfo *pSubTypeInfo;
5892 UINT sub_funcs;
5894 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5895 if (FAILED(hr))
5896 return hr;
5898 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5899 index,
5900 ppFuncDesc,
5901 &sub_funcs, hrefoffset);
5902 implemented_funcs += sub_funcs;
5903 ITypeInfo_Release(pSubTypeInfo);
5904 if (SUCCEEDED(hr))
5905 return hr;
5906 *hrefoffset += DISPATCH_HREF_OFFSET;
5909 if (funcs)
5910 *funcs = implemented_funcs + This->typeattr.cFuncs;
5911 else
5912 *hrefoffset = 0;
5914 if (index < implemented_funcs)
5915 return E_INVALIDARG;
5916 index -= implemented_funcs;
5918 if (index >= This->typeattr.cFuncs)
5919 return TYPE_E_ELEMENTNOTFOUND;
5921 *ppFuncDesc = &This->funcdescs[index];
5922 return S_OK;
5925 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5927 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5929 if (This->typeattr.typekind == TKIND_DISPATCH)
5930 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5932 if (index >= This->typeattr.cFuncs)
5933 return TYPE_E_ELEMENTNOTFOUND;
5935 *func_desc = &This->funcdescs[index];
5936 return S_OK;
5939 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5941 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5942 while (TRUE)
5944 switch (pTypeDesc->vt)
5946 case VT_USERDEFINED:
5947 pTypeDesc->u.hreftype += hrefoffset;
5948 return;
5949 case VT_PTR:
5950 case VT_SAFEARRAY:
5951 pTypeDesc = pTypeDesc->u.lptdesc;
5952 break;
5953 case VT_CARRAY:
5954 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5955 break;
5956 default:
5957 return;
5962 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5964 SHORT i;
5965 for (i = 0; i < pFuncDesc->cParams; i++)
5966 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5967 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5970 /* ITypeInfo::GetFuncDesc
5972 * Retrieves the FUNCDESC structure that contains information about a
5973 * specified function.
5976 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5977 LPFUNCDESC *ppFuncDesc)
5979 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5980 const TLBFuncDesc *internal_funcdesc;
5981 HRESULT hr;
5982 UINT hrefoffset = 0;
5984 TRACE("(%p) index %d\n", This, index);
5986 if (!ppFuncDesc)
5987 return E_INVALIDARG;
5989 if (This->needs_layout)
5990 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5992 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5993 &internal_funcdesc, &hrefoffset);
5994 if (FAILED(hr))
5996 WARN("description for function %d not found\n", index);
5997 return hr;
6000 hr = TLB_AllocAndInitFuncDesc(
6001 &internal_funcdesc->funcdesc,
6002 ppFuncDesc,
6003 This->typeattr.typekind == TKIND_DISPATCH);
6005 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6006 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6008 TRACE("-- %#lx.\n", hr);
6009 return hr;
6012 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6014 VARDESC *dest;
6015 char *buffer;
6016 SIZE_T size = sizeof(*src);
6017 HRESULT hr;
6019 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6020 if (src->varkind == VAR_CONST)
6021 size += sizeof(VARIANT);
6022 size += TLB_SizeElemDesc(&src->elemdescVar);
6024 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6025 if (!dest) return E_OUTOFMEMORY;
6027 *dest = *src;
6028 buffer = (char *)(dest + 1);
6029 if (src->lpstrSchema)
6031 int len;
6032 dest->lpstrSchema = (LPOLESTR)buffer;
6033 len = lstrlenW(src->lpstrSchema);
6034 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6035 buffer += (len + 1) * sizeof(WCHAR);
6038 if (src->varkind == VAR_CONST)
6040 HRESULT hr;
6042 dest->u.lpvarValue = (VARIANT *)buffer;
6043 *dest->u.lpvarValue = *src->u.lpvarValue;
6044 buffer += sizeof(VARIANT);
6045 VariantInit(dest->u.lpvarValue);
6046 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6047 if (FAILED(hr))
6049 SysFreeString((BSTR)dest);
6050 return hr;
6053 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6054 if (FAILED(hr))
6056 if (src->varkind == VAR_CONST)
6057 VariantClear(dest->u.lpvarValue);
6058 SysFreeString((BSTR)dest);
6059 return hr;
6061 *dest_ptr = dest;
6062 return S_OK;
6065 /* ITypeInfo::GetVarDesc
6067 * Retrieves a VARDESC structure that describes the specified variable.
6070 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6071 LPVARDESC *ppVarDesc)
6073 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6074 const TLBVarDesc *pVDesc = &This->vardescs[index];
6076 TRACE("(%p) index %d\n", This, index);
6078 if(index >= This->typeattr.cVars)
6079 return TYPE_E_ELEMENTNOTFOUND;
6081 if (This->needs_layout)
6082 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6084 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6087 /* internal function to make the inherited interfaces' methods appear
6088 * part of the interface, remembering if the top-level was dispinterface */
6089 static HRESULT typeinfo_getnames( ITypeInfo *iface, MEMBERID memid, BSTR *names,
6090 UINT max_names, UINT *num_names, BOOL dispinterface)
6092 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6093 const TLBFuncDesc *func_desc;
6094 const TLBVarDesc *var_desc;
6095 int i;
6097 *num_names = 0;
6099 func_desc = TLB_get_funcdesc_by_memberid(This, memid);
6100 if (func_desc)
6102 UINT params = func_desc->funcdesc.cParams;
6103 if (!max_names || !func_desc->Name)
6104 return S_OK;
6106 *names = SysAllocString(TLB_get_bstr(func_desc->Name));
6107 ++(*num_names);
6109 if (dispinterface && (func_desc->funcdesc.funckind != FUNC_DISPATCH))
6111 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6112 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
6113 --params; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6114 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].u.paramdesc.wParamFlags & PARAMFLAG_FLCID))
6115 --params; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6118 for (i = 0; i < params; i++)
6120 if (*num_names >= max_names || !func_desc->pParamDesc[i].Name)
6121 return S_OK;
6122 names[*num_names] = SysAllocString(TLB_get_bstr(func_desc->pParamDesc[i].Name));
6123 ++(*num_names);
6125 return S_OK;
6128 var_desc = TLB_get_vardesc_by_memberid(This, memid);
6129 if (var_desc)
6131 *names = SysAllocString(TLB_get_bstr(var_desc->Name));
6132 *num_names = 1;
6134 else
6136 if (This->impltypes &&
6137 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH))
6139 /* recursive search */
6140 ITypeInfo *parent;
6141 HRESULT result;
6142 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &parent);
6143 if (SUCCEEDED(result))
6145 result = typeinfo_getnames(parent, memid, names, max_names, num_names, dispinterface);
6146 ITypeInfo_Release(parent);
6147 return result;
6149 WARN("Could not search inherited interface!\n");
6151 else
6153 WARN("no names found\n");
6155 *num_names = 0;
6156 return TYPE_E_ELEMENTNOTFOUND;
6158 return S_OK;
6161 /* ITypeInfo_GetNames
6163 * Retrieves the variable with the specified member ID (or the name of the
6164 * property or method and its parameters) that correspond to the specified
6165 * function ID.
6167 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6168 BSTR *names, UINT max_names, UINT *num_names)
6170 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6172 TRACE("%p, %#lx, %p, %d, %p\n", iface, memid, names, max_names, num_names);
6174 if (!names) return E_INVALIDARG;
6176 return typeinfo_getnames((ITypeInfo *)iface, memid, names, max_names, num_names,
6177 This->typeattr.typekind == TKIND_DISPATCH);
6180 /* ITypeInfo::GetRefTypeOfImplType
6182 * If a type description describes a COM class, it retrieves the type
6183 * description of the implemented interface types. For an interface,
6184 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6185 * if any exist.
6188 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6189 ITypeInfo2 *iface,
6190 UINT index,
6191 HREFTYPE *pRefType)
6193 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6194 HRESULT hr = S_OK;
6196 TRACE("(%p) index %d\n", This, index);
6197 if (TRACE_ON(ole)) dump_TypeInfo(This);
6199 if(index==(UINT)-1)
6201 /* only valid on dual interfaces;
6202 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6205 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6207 *pRefType = -2;
6209 else
6211 hr = TYPE_E_ELEMENTNOTFOUND;
6214 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6216 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6217 *pRefType = This->pTypeLib->dispatch_href;
6219 else
6221 if(index >= This->typeattr.cImplTypes)
6222 hr = TYPE_E_ELEMENTNOTFOUND;
6223 else{
6224 *pRefType = This->impltypes[index].hRef;
6225 if (This->typeattr.typekind == TKIND_INTERFACE)
6226 *pRefType |= 0x2;
6230 if(TRACE_ON(ole))
6232 if(SUCCEEDED(hr))
6233 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType );
6234 else
6235 TRACE("FAILURE -- hresult %#lx.\n", hr);
6238 return hr;
6241 /* ITypeInfo::GetImplTypeFlags
6243 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6244 * or base interface in a type description.
6246 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6247 UINT index, INT *pImplTypeFlags)
6249 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6251 TRACE("(%p) index %d\n", This, index);
6253 if(!pImplTypeFlags)
6254 return E_INVALIDARG;
6256 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6257 *pImplTypeFlags = 0;
6258 return S_OK;
6261 if(index >= This->typeattr.cImplTypes)
6262 return TYPE_E_ELEMENTNOTFOUND;
6264 *pImplTypeFlags = This->impltypes[index].implflags;
6266 return S_OK;
6269 /* GetIDsOfNames
6270 * Maps between member names and member IDs, and parameter names and
6271 * parameter IDs.
6273 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6274 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6276 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6277 const TLBVarDesc *pVDesc;
6278 HRESULT ret=S_OK;
6279 UINT i, fdc;
6281 TRACE("%p, %s, %d.\n", iface, debugstr_w(*rgszNames), cNames);
6283 /* init out parameters in case of failure */
6284 for (i = 0; i < cNames; i++)
6285 pMemId[i] = MEMBERID_NIL;
6287 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6288 int j;
6289 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6290 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6291 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6292 for(i=1; i < cNames; i++){
6293 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6294 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6295 break;
6296 if( j<pFDesc->funcdesc.cParams)
6297 pMemId[i]=j;
6298 else
6299 ret=DISP_E_UNKNOWNNAME;
6301 TRACE("-- %#lx.\n", ret);
6302 return ret;
6305 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6306 if(pVDesc){
6307 if(cNames)
6308 *pMemId = pVDesc->vardesc.memid;
6309 return ret;
6311 /* not found, see if it can be found in an inherited interface */
6312 if(This->impltypes) {
6313 /* recursive search */
6314 ITypeInfo *pTInfo;
6315 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6316 if(SUCCEEDED(ret)){
6317 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6318 ITypeInfo_Release(pTInfo);
6319 return ret;
6321 WARN("Could not search inherited interface!\n");
6322 } else
6323 WARN("no names found\n");
6324 return DISP_E_UNKNOWNNAME;
6328 #ifdef __i386__
6330 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6331 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6332 __ASM_GLOBAL_FUNC( call_method,
6333 "pushl %ebp\n\t"
6334 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6335 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6336 "movl %esp,%ebp\n\t"
6337 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6338 "pushl %esi\n\t"
6339 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6340 "pushl %edi\n\t"
6341 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6342 "movl 12(%ebp),%edx\n\t"
6343 "movl %esp,%edi\n\t"
6344 "shll $2,%edx\n\t"
6345 "jz 1f\n\t"
6346 "subl %edx,%edi\n\t"
6347 "andl $~15,%edi\n\t"
6348 "movl %edi,%esp\n\t"
6349 "movl 12(%ebp),%ecx\n\t"
6350 "movl 16(%ebp),%esi\n\t"
6351 "cld\n\t"
6352 "rep; movsl\n"
6353 "1:\tcall *8(%ebp)\n\t"
6354 "subl %esp,%edi\n\t"
6355 "movl 20(%ebp),%ecx\n\t"
6356 "movl %edi,(%ecx)\n\t"
6357 "leal -8(%ebp),%esp\n\t"
6358 "popl %edi\n\t"
6359 __ASM_CFI(".cfi_same_value %edi\n\t")
6360 "popl %esi\n\t"
6361 __ASM_CFI(".cfi_same_value %esi\n\t")
6362 "popl %ebp\n\t"
6363 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6364 __ASM_CFI(".cfi_same_value %ebp\n\t")
6365 "ret" )
6366 __ASM_GLOBAL_FUNC( call_double_method,
6367 "jmp " __ASM_NAME("call_method") )
6369 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6370 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6372 int argspos = 0, stack_offset;
6373 void *func;
6374 UINT i;
6375 DWORD *args;
6377 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6378 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6379 pvargResult, V_VT(pvargResult));
6381 if (cc != CC_STDCALL && cc != CC_CDECL)
6383 FIXME("unsupported calling convention %d\n",cc);
6384 return E_INVALIDARG;
6387 /* maximum size for an argument is sizeof(VARIANT) */
6388 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6390 if (pvInstance)
6392 const FARPROC *vtable = *(FARPROC **)pvInstance;
6393 func = vtable[oVft/sizeof(void *)];
6394 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6396 else func = (void *)oVft;
6398 switch (vtReturn)
6400 case VT_DECIMAL:
6401 case VT_VARIANT:
6402 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6403 break;
6404 case VT_HRESULT:
6405 WARN("invalid return type %u\n", vtReturn);
6406 heap_free( args );
6407 return E_INVALIDARG;
6408 default:
6409 break;
6412 for (i = 0; i < cActuals; i++)
6414 VARIANT *arg = prgpvarg[i];
6416 switch (prgvt[i])
6418 case VT_EMPTY:
6419 break;
6420 case VT_I8:
6421 case VT_UI8:
6422 case VT_R8:
6423 case VT_DATE:
6424 case VT_CY:
6425 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6426 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6427 break;
6428 case VT_DECIMAL:
6429 case VT_VARIANT:
6430 memcpy( &args[argspos], arg, sizeof(*arg) );
6431 argspos += sizeof(*arg) / sizeof(DWORD);
6432 break;
6433 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6434 args[argspos++] = V_BOOL(arg);
6435 break;
6436 default:
6437 args[argspos++] = V_UI4(arg);
6438 break;
6440 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6443 switch (vtReturn)
6445 case VT_EMPTY:
6446 case VT_DECIMAL:
6447 case VT_VARIANT:
6448 call_method( func, argspos, args, &stack_offset );
6449 break;
6450 case VT_R4:
6451 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6452 break;
6453 case VT_R8:
6454 case VT_DATE:
6455 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6456 break;
6457 case VT_I8:
6458 case VT_UI8:
6459 case VT_CY:
6460 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6461 break;
6462 default:
6463 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6464 break;
6466 heap_free( args );
6467 if (stack_offset && cc == CC_STDCALL)
6469 WARN( "stack pointer off by %d\n", stack_offset );
6470 return DISP_E_BADCALLEE;
6472 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6473 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6474 return S_OK;
6477 #elif defined(__x86_64__)
6479 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6480 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6481 __ASM_GLOBAL_FUNC( call_method,
6482 "pushq %rbp\n\t"
6483 __ASM_SEH(".seh_pushreg %rbp\n\t")
6484 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6485 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6486 "movq %rsp,%rbp\n\t"
6487 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6488 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6489 "pushq %rsi\n\t"
6490 __ASM_SEH(".seh_pushreg %rsi\n\t")
6491 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6492 "pushq %rdi\n\t"
6493 __ASM_SEH(".seh_pushreg %rdi\n\t")
6494 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6495 __ASM_SEH(".seh_endprologue\n\t")
6496 "movq %rcx,%rax\n\t"
6497 "movq $4,%rcx\n\t"
6498 "cmp %rcx,%rdx\n\t"
6499 "cmovgq %rdx,%rcx\n\t"
6500 "leaq 0(,%rcx,8),%rdx\n\t"
6501 "subq %rdx,%rsp\n\t"
6502 "andq $~15,%rsp\n\t"
6503 "movq %rsp,%rdi\n\t"
6504 "movq %r8,%rsi\n\t"
6505 "rep; movsq\n\t"
6506 "movq 0(%rsp),%rcx\n\t"
6507 "movq 8(%rsp),%rdx\n\t"
6508 "movq 16(%rsp),%r8\n\t"
6509 "movq 24(%rsp),%r9\n\t"
6510 "movq 0(%rsp),%xmm0\n\t"
6511 "movq 8(%rsp),%xmm1\n\t"
6512 "movq 16(%rsp),%xmm2\n\t"
6513 "movq 24(%rsp),%xmm3\n\t"
6514 "callq *%rax\n\t"
6515 "leaq -16(%rbp),%rsp\n\t"
6516 "popq %rdi\n\t"
6517 __ASM_CFI(".cfi_same_value %rdi\n\t")
6518 "popq %rsi\n\t"
6519 __ASM_CFI(".cfi_same_value %rsi\n\t")
6520 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6521 "popq %rbp\n\t"
6522 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6523 __ASM_CFI(".cfi_same_value %rbp\n\t")
6524 "ret")
6525 __ASM_GLOBAL_FUNC( call_double_method,
6526 "jmp " __ASM_NAME("call_method") )
6528 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6529 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6531 int argspos = 0;
6532 UINT i;
6533 DWORD_PTR *args;
6534 void *func;
6536 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6537 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6538 pvargResult, V_VT(pvargResult));
6540 if (cc != CC_STDCALL && cc != CC_CDECL)
6542 FIXME("unsupported calling convention %d\n",cc);
6543 return E_INVALIDARG;
6546 /* maximum size for an argument is sizeof(DWORD_PTR) */
6547 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6549 if (pvInstance)
6551 const FARPROC *vtable = *(FARPROC **)pvInstance;
6552 func = vtable[oVft/sizeof(void *)];
6553 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6555 else func = (void *)oVft;
6557 switch (vtReturn)
6559 case VT_DECIMAL:
6560 case VT_VARIANT:
6561 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6562 break;
6563 case VT_HRESULT:
6564 WARN("invalid return type %u\n", vtReturn);
6565 heap_free( args );
6566 return E_INVALIDARG;
6567 default:
6568 break;
6571 for (i = 0; i < cActuals; i++)
6573 VARIANT *arg = prgpvarg[i];
6575 switch (prgvt[i])
6577 case VT_DECIMAL:
6578 case VT_VARIANT:
6579 args[argspos++] = (ULONG_PTR)arg;
6580 break;
6581 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6582 args[argspos++] = V_BOOL(arg);
6583 break;
6584 default:
6585 args[argspos++] = V_UI8(arg);
6586 break;
6588 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6591 switch (vtReturn)
6593 case VT_R4:
6594 V_R4(pvargResult) = call_double_method( func, argspos, args );
6595 break;
6596 case VT_R8:
6597 case VT_DATE:
6598 V_R8(pvargResult) = call_double_method( func, argspos, args );
6599 break;
6600 case VT_DECIMAL:
6601 case VT_VARIANT:
6602 call_method( func, argspos, args );
6603 break;
6604 default:
6605 V_UI8(pvargResult) = call_method( func, argspos, args );
6606 break;
6608 heap_free( args );
6609 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6610 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6611 return S_OK;
6614 #elif defined(__arm__)
6616 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6617 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6618 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6619 __ASM_GLOBAL_FUNC( call_method,
6620 /* r0 = *func
6621 * r1 = nb_stk_args
6622 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6623 * 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)
6626 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6627 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6629 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6630 "beq 1f\n\t" /* Skip allocation if no stack args */
6631 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6632 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6633 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6634 "subs r1, r1, #4\n\t" /* Decrement count */
6635 "bgt 2b\n\t" /* Loop till done */
6637 "1:\n\t"
6638 #ifndef __SOFTFP__
6639 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6640 #endif
6641 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6642 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6644 "blx ip\n\t" /* Call the target function */
6646 "mov sp, fp\n\t" /* Clean the stack using fp */
6647 "pop {fp, pc}\n\t" /* Restore fp and return */
6649 __ASM_GLOBAL_FUNC( call_float_method,
6650 "b " __ASM_NAME("call_method") )
6651 __ASM_GLOBAL_FUNC( call_double_method,
6652 "b " __ASM_NAME("call_method") )
6654 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6655 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6657 int argspos;
6658 void *func;
6659 UINT i;
6660 DWORD *args;
6661 struct {
6662 #ifndef __SOFTFP__
6663 union {
6664 float s[16];
6665 double d[8];
6666 } sd;
6667 #endif
6668 DWORD r[4];
6669 } regs;
6670 int rcount; /* 32-bit register index count */
6671 #ifndef __SOFTFP__
6672 int scount = 0; /* single-precision float register index count */
6673 int dcount = 0; /* double-precision float register index count */
6674 #endif
6676 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6677 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6679 if (cc != CC_STDCALL && cc != CC_CDECL)
6681 FIXME("unsupported calling convention %d\n",cc);
6682 return E_INVALIDARG;
6685 argspos = 0;
6686 rcount = 0;
6688 if (pvInstance)
6690 const FARPROC *vtable = *(FARPROC **)pvInstance;
6691 func = vtable[oVft/sizeof(void *)];
6692 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6694 else func = (void *)oVft;
6696 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6697 /* first as it will need to be in the 'r' registers: */
6698 switch (vtReturn)
6700 case VT_DECIMAL:
6701 case VT_VARIANT:
6702 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6703 break;
6704 case VT_HRESULT:
6705 WARN("invalid return type %u\n", vtReturn);
6706 return E_INVALIDARG;
6707 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6708 break;
6711 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6712 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6714 for (i = 0; i < cActuals; i++)
6716 VARIANT *arg = prgpvarg[i];
6717 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6718 int ntemp; /* Used for counting words split between registers and stack */
6720 switch (prgvt[i])
6722 case VT_EMPTY:
6723 break;
6724 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6725 case VT_DATE:
6726 #ifndef __SOFTFP__
6727 dcount = max( (scount + 1) / 2, dcount );
6728 if (dcount < 8)
6730 regs.sd.d[dcount++] = V_R8(arg);
6732 else
6734 argspos += (argspos % 2); /* align argspos to 8-bytes */
6735 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6736 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6738 break;
6739 #endif
6740 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6741 case VT_UI8:
6742 case VT_CY:
6743 if (rcount < 3)
6745 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6746 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6747 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6749 else
6751 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6752 argspos += (argspos % 2); /* align argspos to 8-bytes */
6753 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6754 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6756 break;
6757 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6758 case VT_VARIANT:
6759 /* 8-byte align 'r' and/or stack: */
6760 if (rcount < 3)
6761 rcount += (rcount % 2);
6762 else
6764 rcount = 4;
6765 argspos += (argspos % 2);
6767 ntemp = sizeof(*arg) / sizeof(DWORD);
6768 while (ntemp > 0)
6770 if (rcount < 4)
6771 regs.r[rcount++] = *pdwarg++;
6772 else
6773 args[argspos++] = *pdwarg++;
6774 --ntemp;
6776 break;
6777 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6778 if (rcount < 4)
6779 regs.r[rcount++] = V_BOOL(arg);
6780 else
6781 args[argspos++] = V_BOOL(arg);
6782 break;
6783 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6784 #ifndef __SOFTFP__
6785 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6786 if (scount < 16)
6787 regs.sd.s[scount++] = V_R4(arg);
6788 else
6789 args[argspos++] = V_UI4(arg);
6790 break;
6791 #endif
6792 default:
6793 if (rcount < 4)
6794 regs.r[rcount++] = V_UI4(arg);
6795 else
6796 args[argspos++] = V_UI4(arg);
6797 break;
6799 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6802 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6804 switch (vtReturn)
6806 case VT_EMPTY: /* EMPTY = no return value */
6807 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6808 case VT_VARIANT:
6809 call_method( func, argspos, args, (DWORD*)&regs );
6810 break;
6811 case VT_R4:
6812 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6813 break;
6814 case VT_R8:
6815 case VT_DATE:
6816 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6817 break;
6818 case VT_I8:
6819 case VT_UI8:
6820 case VT_CY:
6821 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6822 break;
6823 default:
6824 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6825 break;
6827 heap_free( args );
6828 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6829 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6830 return S_OK;
6833 #elif defined(__aarch64__)
6835 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6836 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6837 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6838 __ASM_GLOBAL_FUNC( call_method,
6839 "stp x29, x30, [sp, #-16]!\n\t"
6840 "mov x29, sp\n\t"
6841 "sub sp, sp, x1, lsl #3\n\t"
6842 "cbz x1, 2f\n"
6843 "1:\tsub x1, x1, #1\n\t"
6844 "ldr x4, [x2, x1, lsl #3]\n\t"
6845 "str x4, [sp, x1, lsl #3]\n\t"
6846 "cbnz x1, 1b\n"
6847 "2:\tmov x16, x0\n\t"
6848 "mov x9, x3\n\t"
6849 "ldp d0, d1, [x9]\n\t"
6850 "ldp d2, d3, [x9, #0x10]\n\t"
6851 "ldp d4, d5, [x9, #0x20]\n\t"
6852 "ldp d6, d7, [x9, #0x30]\n\t"
6853 "ldp x0, x1, [x9, #0x40]\n\t"
6854 "ldp x2, x3, [x9, #0x50]\n\t"
6855 "ldp x4, x5, [x9, #0x60]\n\t"
6856 "ldp x6, x7, [x9, #0x70]\n\t"
6857 "ldr x8, [x9, #0x80]\n\t"
6858 "blr x16\n\t"
6859 "mov sp, x29\n\t"
6860 "ldp x29, x30, [sp], #16\n\t"
6861 "ret" )
6862 __ASM_GLOBAL_FUNC( call_float_method,
6863 "b " __ASM_NAME("call_method") )
6864 __ASM_GLOBAL_FUNC( call_double_method,
6865 "b " __ASM_NAME("call_method") )
6867 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6868 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6870 int argspos;
6871 void *func;
6872 UINT i;
6873 DWORD_PTR *args;
6874 struct
6876 union
6878 float f;
6879 double d;
6880 } fp[8];
6881 DWORD_PTR x[9];
6882 } regs;
6883 int rcount; /* 64-bit register index count */
6884 int fpcount = 0; /* float register index count */
6886 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6887 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6889 if (cc != CC_STDCALL && cc != CC_CDECL)
6891 FIXME("unsupported calling convention %d\n",cc);
6892 return E_INVALIDARG;
6895 argspos = 0;
6896 rcount = 0;
6898 if (instance)
6900 const FARPROC *vtable = *(FARPROC **)instance;
6901 func = vtable[offset/sizeof(void *)];
6902 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6904 else func = (void *)offset;
6906 /* maximum size for an argument is 16 */
6907 args = heap_alloc( 16 * count );
6909 for (i = 0; i < count; i++)
6911 VARIANT *arg = vargs[i];
6913 switch (types[i])
6915 case VT_R4:
6916 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6917 else *(float *)&args[argspos++] = V_R4(arg);
6918 break;
6919 case VT_R8:
6920 case VT_DATE:
6921 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6922 else *(double *)&args[argspos++] = V_R8(arg);
6923 break;
6924 case VT_DECIMAL:
6925 if (rcount < 7)
6927 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6928 rcount += 2;
6930 else
6932 memcpy( &args[argspos], arg, sizeof(*arg) );
6933 argspos += 2;
6935 break;
6936 case VT_VARIANT:
6937 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6938 else args[argspos++] = (DWORD_PTR)arg;
6939 break;
6940 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6941 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6942 else args[argspos++] = V_BOOL(arg);
6943 break;
6944 default:
6945 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6946 else args[argspos++] = V_UI8(arg);
6947 break;
6949 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6952 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6954 switch (ret_type)
6956 case VT_HRESULT:
6957 heap_free( args );
6958 return E_INVALIDARG;
6959 case VT_DECIMAL:
6960 case VT_VARIANT:
6961 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6962 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6963 break;
6964 case VT_R4:
6965 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6966 break;
6967 case VT_R8:
6968 case VT_DATE:
6969 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6970 break;
6971 default:
6972 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6973 break;
6975 heap_free( args );
6976 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6977 TRACE("retval: %s\n", debugstr_variant(result));
6978 return S_OK;
6981 #else /* __aarch64__ */
6983 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6984 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6986 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6987 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6988 return E_NOTIMPL;
6991 #endif
6993 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6995 HRESULT hr = S_OK;
6996 ITypeInfo *tinfo2 = NULL;
6997 TYPEATTR *tattr = NULL;
6999 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
7000 if (hr)
7002 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc->u.hreftype, hr);
7003 return hr;
7005 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7006 if (hr)
7008 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr);
7009 ITypeInfo_Release(tinfo2);
7010 return hr;
7013 switch (tattr->typekind)
7015 case TKIND_ENUM:
7016 *vt |= VT_I4;
7017 break;
7019 case TKIND_ALIAS:
7020 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7021 break;
7023 case TKIND_INTERFACE:
7024 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7025 *vt |= VT_DISPATCH;
7026 else
7027 *vt |= VT_UNKNOWN;
7028 break;
7030 case TKIND_DISPATCH:
7031 *vt |= VT_DISPATCH;
7032 break;
7034 case TKIND_COCLASS:
7035 *vt |= VT_DISPATCH;
7036 break;
7038 case TKIND_RECORD:
7039 FIXME("TKIND_RECORD unhandled.\n");
7040 hr = E_NOTIMPL;
7041 break;
7043 case TKIND_UNION:
7044 FIXME("TKIND_UNION unhandled.\n");
7045 hr = E_NOTIMPL;
7046 break;
7048 default:
7049 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7050 hr = E_NOTIMPL;
7051 break;
7053 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7054 ITypeInfo_Release(tinfo2);
7055 return hr;
7058 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7060 HRESULT hr = S_OK;
7062 /* enforce only one level of pointer indirection */
7063 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7065 tdesc = tdesc->u.lptdesc;
7067 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7068 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7069 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7070 if ((tdesc->vt == VT_USERDEFINED) ||
7071 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
7073 VARTYPE vt_userdefined = 0;
7074 const TYPEDESC *tdesc_userdefined = tdesc;
7075 if (tdesc->vt == VT_PTR)
7077 vt_userdefined = VT_BYREF;
7078 tdesc_userdefined = tdesc->u.lptdesc;
7080 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7081 if ((hr == S_OK) &&
7082 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7083 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7085 *vt |= vt_userdefined;
7086 return S_OK;
7089 *vt = VT_BYREF;
7092 switch (tdesc->vt)
7094 case VT_HRESULT:
7095 *vt |= VT_ERROR;
7096 break;
7097 case VT_USERDEFINED:
7098 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7099 break;
7100 case VT_VOID:
7101 case VT_CARRAY:
7102 case VT_PTR:
7103 case VT_LPSTR:
7104 case VT_LPWSTR:
7105 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7106 hr = DISP_E_BADVARTYPE;
7107 break;
7108 case VT_SAFEARRAY:
7109 *vt |= VT_ARRAY;
7110 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
7111 break;
7112 case VT_INT:
7113 *vt |= VT_I4;
7114 break;
7115 case VT_UINT:
7116 *vt |= VT_UI4;
7117 break;
7118 default:
7119 *vt |= tdesc->vt;
7120 break;
7122 return hr;
7125 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7127 ITypeInfo *tinfo2;
7128 TYPEATTR *tattr;
7129 HRESULT hres;
7130 int flags, i;
7132 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7133 if(FAILED(hres))
7134 return hres;
7136 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7137 if(FAILED(hres)) {
7138 ITypeInfo_Release(tinfo2);
7139 return hres;
7142 switch(tattr->typekind) {
7143 case TKIND_ALIAS:
7144 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
7145 break;
7147 case TKIND_INTERFACE:
7148 case TKIND_DISPATCH:
7149 *guid = tattr->guid;
7150 break;
7152 case TKIND_COCLASS:
7153 for (i = 0; i < tattr->cImplTypes; i++)
7155 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7156 if (flags & IMPLTYPEFLAG_FDEFAULT)
7157 break;
7160 if (i == tattr->cImplTypes)
7161 i = 0;
7163 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7164 if (SUCCEEDED(hres))
7165 hres = get_iface_guid(tinfo2, href, guid);
7166 break;
7168 default:
7169 ERR("Unexpected typekind %d\n", tattr->typekind);
7170 hres = E_UNEXPECTED;
7173 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7174 ITypeInfo_Release(tinfo2);
7175 return hres;
7178 static inline BOOL func_restricted( const FUNCDESC *desc )
7180 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7183 #define INVBUF_ELEMENT_SIZE \
7184 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7185 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7186 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7187 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7188 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7189 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7190 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7191 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7193 static HRESULT WINAPI ITypeInfo_fnInvoke(
7194 ITypeInfo2 *iface,
7195 VOID *pIUnk,
7196 MEMBERID memid,
7197 UINT16 wFlags,
7198 DISPPARAMS *pDispParams,
7199 VARIANT *pVarResult,
7200 EXCEPINFO *pExcepInfo,
7201 UINT *pArgErr)
7203 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7204 int i, j;
7205 unsigned int var_index;
7206 TYPEKIND type_kind;
7207 HRESULT hres;
7208 const TLBFuncDesc *pFuncInfo;
7209 UINT fdc;
7211 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface, pIUnk, memid, wFlags, pDispParams,
7212 pVarResult, pExcepInfo, pArgErr);
7214 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7215 return DISP_E_MEMBERNOTFOUND;
7217 if (!pDispParams)
7219 ERR("NULL pDispParams not allowed\n");
7220 return E_INVALIDARG;
7223 dump_DispParms(pDispParams);
7225 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7227 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7228 pDispParams->cNamedArgs, pDispParams->cArgs);
7229 return E_INVALIDARG;
7232 /* we do this instead of using GetFuncDesc since it will return a fake
7233 * FUNCDESC for dispinterfaces and we want the real function description */
7234 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7235 pFuncInfo = &This->funcdescs[fdc];
7236 if ((memid == pFuncInfo->funcdesc.memid) &&
7237 (wFlags & pFuncInfo->funcdesc.invkind) &&
7238 !func_restricted( &pFuncInfo->funcdesc ))
7239 break;
7242 if (fdc < This->typeattr.cFuncs) {
7243 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7245 if (TRACE_ON(ole))
7247 TRACE("invoking:\n");
7248 dump_TLBFuncDescOne(pFuncInfo);
7251 switch (func_desc->funckind) {
7252 case FUNC_PUREVIRTUAL:
7253 case FUNC_VIRTUAL: {
7254 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7255 VARIANT varresult;
7256 VARIANT retval = {{{0}}}; /* pointer for storing byref retvals in */
7257 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7258 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7259 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7260 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7261 UINT cNamedArgs = pDispParams->cNamedArgs;
7262 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7263 UINT vargs_converted=0;
7264 SAFEARRAY *a;
7266 hres = S_OK;
7268 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7270 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7272 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7273 hres = DISP_E_PARAMNOTFOUND;
7274 goto func_fail;
7278 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7280 ERR("functions with the vararg attribute do not support named arguments\n");
7281 hres = DISP_E_NONAMEDARGS;
7282 goto func_fail;
7285 for (i = 0; i < func_desc->cParams; i++)
7287 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7288 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7289 if (FAILED(hres))
7290 goto func_fail;
7293 TRACE("changing args\n");
7294 for (i = 0; i < func_desc->cParams; i++)
7296 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7297 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7298 VARIANTARG *src_arg;
7300 if (wParamFlags & PARAMFLAG_FLCID)
7302 prgpvarg[i] = &rgvarg[i];
7303 V_VT(prgpvarg[i]) = VT_I4;
7304 V_I4(prgpvarg[i]) = This->pTypeLib->lcid;
7305 continue;
7308 src_arg = NULL;
7310 for (j = 0; j < cNamedArgs; j++)
7312 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7314 src_arg = &pDispParams->rgvarg[j];
7315 break;
7319 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7321 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7322 vargs_converted++;
7325 if (wParamFlags & PARAMFLAG_FRETVAL)
7327 /* under most conditions the caller is not allowed to
7328 * pass in a dispparam arg in the index of what would be
7329 * the retval parameter. however, there is an exception
7330 * where the extra parameter is used in an extra
7331 * IDispatch::Invoke below */
7332 if ((i < pDispParams->cArgs) &&
7333 ((func_desc->cParams != 1) || !pVarResult ||
7334 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7336 hres = DISP_E_BADPARAMCOUNT;
7337 break;
7340 /* note: this check is placed so that if the caller passes
7341 * in a VARIANTARG for the retval we just ignore it, like
7342 * native does */
7343 if (i == func_desc->cParams - 1)
7345 prgpvarg[i] = &rgvarg[i];
7346 V_BYREF(prgpvarg[i]) = &retval;
7347 V_VT(prgpvarg[i]) = rgvt[i];
7349 else
7351 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7352 hres = E_UNEXPECTED;
7353 break;
7356 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7357 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7359 TRACE("%s\n", debugstr_variant(src_arg));
7361 if(rgvt[i]!=V_VT(src_arg))
7363 if (rgvt[i] == VT_VARIANT)
7364 hres = VariantCopy(&rgvarg[i], src_arg);
7365 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7367 if (rgvt[i] == V_VT(src_arg))
7368 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7369 else
7371 if (wParamFlags & PARAMFLAG_FIN)
7372 hres = VariantCopy(&missing_arg[i], src_arg);
7373 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7375 V_VT(&rgvarg[i]) = rgvt[i];
7377 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7379 SAFEARRAYBOUND bound;
7380 VARIANT *v;
7382 bound.lLbound = 0;
7383 bound.cElements = pDispParams->cArgs-i;
7384 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7386 ERR("SafeArrayCreate failed\n");
7387 break;
7389 hres = SafeArrayAccessData(a, (LPVOID)&v);
7390 if (hres != S_OK)
7392 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7393 SafeArrayDestroy(a);
7394 break;
7396 for (j = 0; j < bound.cElements; j++)
7397 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7398 hres = SafeArrayUnaccessData(a);
7399 if (hres != S_OK)
7401 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7402 SafeArrayDestroy(a);
7403 break;
7405 if (rgvt[i] & VT_BYREF)
7406 V_BYREF(&rgvarg[i]) = &a;
7407 else
7408 V_ARRAY(&rgvarg[i]) = a;
7409 V_VT(&rgvarg[i]) = rgvt[i];
7411 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7413 if (wParamFlags & PARAMFLAG_FIN)
7414 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7415 else
7416 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7417 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7418 V_VT(&rgvarg[i]) = rgvt[i];
7420 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7422 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7423 V_VT(&rgvarg[i]) = rgvt[i];
7425 else
7427 /* FIXME: this doesn't work for VT_BYREF arguments if
7428 * they are not the same type as in the paramdesc */
7429 V_VT(&rgvarg[i]) = V_VT(src_arg);
7430 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7431 V_VT(&rgvarg[i]) = rgvt[i];
7434 if (FAILED(hres))
7436 ERR("failed to convert param %d to %s from %s\n", i,
7437 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7438 break;
7440 prgpvarg[i] = &rgvarg[i];
7442 else
7444 prgpvarg[i] = src_arg;
7447 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7448 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7449 && V_UNKNOWN(prgpvarg[i])) {
7450 IUnknown *userdefined_iface;
7451 GUID guid;
7453 if (tdesc->vt == VT_PTR)
7454 tdesc = tdesc->u.lptdesc;
7456 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7457 if(FAILED(hres))
7458 break;
7460 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7461 if(FAILED(hres)) {
7462 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7463 break;
7466 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7467 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7470 else if (wParamFlags & PARAMFLAG_FOPT)
7472 VARIANTARG *arg;
7473 arg = prgpvarg[i] = &rgvarg[i];
7474 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7476 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7477 if (FAILED(hres))
7478 break;
7480 else
7482 /* if the function wants a pointer to a variant then
7483 * set that up, otherwise just pass the VT_ERROR in
7484 * the argument by value */
7485 if (rgvt[i] & VT_BYREF)
7487 V_VT(&missing_arg[i]) = VT_ERROR;
7488 V_ERROR(&missing_arg[i]) = DISP_E_PARAMNOTFOUND;
7490 V_VT(arg) = VT_VARIANT | VT_BYREF;
7491 V_VARIANTREF(arg) = &missing_arg[i];
7493 else
7495 V_VT(arg) = VT_ERROR;
7496 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
7500 else
7502 hres = DISP_E_BADPARAMCOUNT;
7503 break;
7506 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7508 /* VT_VOID is a special case for return types, so it is not
7509 * handled in the general function */
7510 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7511 V_VT(&varresult) = VT_EMPTY;
7512 else
7514 V_VT(&varresult) = 0;
7515 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7516 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7519 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7520 V_VT(&varresult), func_desc->cParams, rgvt,
7521 prgpvarg, &varresult);
7523 vargs_converted = 0;
7525 for (i = 0; i < func_desc->cParams; i++)
7527 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7529 if (wParamFlags & PARAMFLAG_FLCID)
7530 continue;
7531 else if (wParamFlags & PARAMFLAG_FRETVAL)
7533 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7535 if (pVarResult)
7537 VariantInit(pVarResult);
7538 /* deref return value */
7539 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7542 VARIANT_ClearInd(prgpvarg[i]);
7544 else if (vargs_converted < pDispParams->cArgs)
7546 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7547 if (wParamFlags & PARAMFLAG_FOUT)
7549 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7551 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7553 if (FAILED(hres))
7555 ERR("failed to convert param %d to vt %d\n", i,
7556 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7557 break;
7561 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7562 func_desc->cParamsOpt < 0 &&
7563 i == func_desc->cParams-1)
7565 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7566 LONG ubound;
7567 VARIANT *v;
7568 hres = SafeArrayGetUBound(a, 1, &ubound);
7569 if (hres != S_OK)
7571 ERR("SafeArrayGetUBound failed with %#lx.\n", hres);
7572 break;
7574 hres = SafeArrayAccessData(a, (LPVOID)&v);
7575 if (hres != S_OK)
7577 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7578 break;
7580 for (j = 0; j <= ubound; j++)
7581 VariantClear(&v[j]);
7582 hres = SafeArrayUnaccessData(a);
7583 if (hres != S_OK)
7585 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7586 break;
7589 VariantClear(&rgvarg[i]);
7590 vargs_converted++;
7592 else if (wParamFlags & PARAMFLAG_FOPT)
7594 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7595 VariantClear(&rgvarg[i]);
7598 VariantClear(&missing_arg[i]);
7601 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7603 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult));
7604 hres = DISP_E_EXCEPTION;
7605 if (pExcepInfo)
7607 IErrorInfo *pErrorInfo;
7608 pExcepInfo->scode = V_ERROR(&varresult);
7609 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7611 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7612 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7613 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7614 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7616 IErrorInfo_Release(pErrorInfo);
7620 if (V_VT(&varresult) != VT_ERROR)
7622 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7624 if (pVarResult)
7626 VariantClear(pVarResult);
7627 *pVarResult = varresult;
7629 else
7630 VariantClear(&varresult);
7633 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7634 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7635 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7636 (pDispParams->cArgs != 0))
7638 if (V_VT(pVarResult) == VT_DISPATCH)
7640 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7641 /* Note: not VariantClear; we still need the dispatch
7642 * pointer to be valid */
7643 VariantInit(pVarResult);
7644 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7645 GetSystemDefaultLCID(), wFlags,
7646 pDispParams, pVarResult, pExcepInfo, pArgErr);
7647 IDispatch_Release(pDispatch);
7649 else
7651 VariantClear(pVarResult);
7652 hres = DISP_E_NOTACOLLECTION;
7656 func_fail:
7657 heap_free(buffer);
7658 break;
7660 case FUNC_DISPATCH: {
7661 IDispatch *disp;
7663 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7664 if (SUCCEEDED(hres)) {
7665 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7666 hres = IDispatch_Invoke(
7667 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7668 pVarResult,pExcepInfo,pArgErr
7670 if (FAILED(hres))
7671 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres);
7672 IDispatch_Release(disp);
7673 } else
7674 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7675 break;
7677 default:
7678 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7679 hres = E_FAIL;
7680 break;
7683 TRACE("-- %#lx\n", hres);
7684 return hres;
7686 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7687 VARDESC *var_desc;
7689 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7690 if(FAILED(hres)) return hres;
7692 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7693 dump_VARDESC(var_desc);
7694 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7695 return E_NOTIMPL;
7698 /* not found, look for it in inherited interfaces */
7699 ITypeInfo2_GetTypeKind(iface, &type_kind);
7700 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7701 if(This->impltypes) {
7702 /* recursive search */
7703 ITypeInfo *pTInfo;
7704 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7705 if(SUCCEEDED(hres)){
7706 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7707 ITypeInfo_Release(pTInfo);
7708 return hres;
7710 WARN("Could not search inherited interface!\n");
7713 WARN("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
7714 return DISP_E_MEMBERNOTFOUND;
7717 /* ITypeInfo::GetDocumentation
7719 * Retrieves the documentation string, the complete Help file name and path,
7720 * and the context ID for the Help topic for a specified type description.
7722 * (Can be tested by the Visual Basic Editor in Word for instance.)
7724 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7725 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7726 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7728 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7729 const TLBFuncDesc *pFDesc;
7730 const TLBVarDesc *pVDesc;
7731 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7732 iface, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7733 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7734 if(pBstrName)
7735 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7736 if(pBstrDocString)
7737 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7738 if(pdwHelpContext)
7739 *pdwHelpContext=This->dwHelpContext;
7740 if(pBstrHelpFile)
7741 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7742 return S_OK;
7743 }else {/* for a member */
7744 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7745 if(pFDesc){
7746 if(pBstrName)
7747 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7748 if(pBstrDocString)
7749 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7750 if(pdwHelpContext)
7751 *pdwHelpContext=pFDesc->helpcontext;
7752 if(pBstrHelpFile)
7753 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7754 return S_OK;
7756 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7757 if(pVDesc){
7758 if(pBstrName)
7759 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7760 if(pBstrDocString)
7761 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7762 if(pdwHelpContext)
7763 *pdwHelpContext=pVDesc->HelpContext;
7764 if(pBstrHelpFile)
7765 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7766 return S_OK;
7770 if(This->impltypes &&
7771 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7772 /* recursive search */
7773 ITypeInfo *pTInfo;
7774 HRESULT result;
7775 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7776 if(SUCCEEDED(result)) {
7777 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7778 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7779 ITypeInfo_Release(pTInfo);
7780 return result;
7782 WARN("Could not search inherited interface!\n");
7785 WARN("member %ld not found\n", memid);
7786 return TYPE_E_ELEMENTNOTFOUND;
7789 /* ITypeInfo::GetDllEntry
7791 * Retrieves a description or specification of an entry point for a function
7792 * in a DLL.
7794 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7795 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7796 WORD *pwOrdinal)
7798 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7799 const TLBFuncDesc *pFDesc;
7801 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7803 if (pBstrDllName) *pBstrDllName = NULL;
7804 if (pBstrName) *pBstrName = NULL;
7805 if (pwOrdinal) *pwOrdinal = 0;
7807 if (This->typeattr.typekind != TKIND_MODULE)
7808 return TYPE_E_BADMODULEKIND;
7810 pFDesc = TLB_get_funcdesc_by_memberid_invkind(This, memid, invKind);
7811 if (!pFDesc) return TYPE_E_ELEMENTNOTFOUND;
7813 dump_TypeInfo(This);
7814 if (TRACE_ON(ole)) dump_TLBFuncDescOne(pFDesc);
7816 if (pBstrDllName) *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7818 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1))
7820 if (pBstrName) *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7821 if (pwOrdinal) *pwOrdinal = -1;
7823 else
7825 if (pBstrName) *pBstrName = NULL;
7826 if (pwOrdinal) *pwOrdinal = LOWORD(pFDesc->Entry);
7828 return S_OK;
7831 /* internal function to make the inherited interfaces' methods appear
7832 * part of the interface */
7833 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7834 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7836 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7837 HRESULT hr;
7839 TRACE("%p, %#lx.\n", iface, *hRefType);
7841 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7843 ITypeInfo *pSubTypeInfo;
7845 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7846 if (FAILED(hr))
7847 return hr;
7849 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7850 hRefType, ppTInfo);
7851 ITypeInfo_Release(pSubTypeInfo);
7852 if (SUCCEEDED(hr))
7853 return hr;
7855 *hRefType -= DISPATCH_HREF_OFFSET;
7857 if (!(*hRefType & DISPATCH_HREF_MASK))
7858 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7859 else
7860 return E_FAIL;
7863 /* ITypeInfo::GetRefTypeInfo
7865 * If a type description references other type descriptions, it retrieves
7866 * the referenced type descriptions.
7868 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7869 ITypeInfo2 *iface,
7870 HREFTYPE hRefType,
7871 ITypeInfo **ppTInfo)
7873 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7874 ITypeInfo *type_info = NULL;
7875 HRESULT result = E_FAIL;
7876 TLBRefType *ref_type;
7877 UINT i;
7879 if(!ppTInfo)
7880 return E_INVALIDARG;
7882 if ((INT)hRefType < 0) {
7883 ITypeInfoImpl *pTypeInfoImpl;
7885 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7886 !(This->typeattr.typekind == TKIND_INTERFACE ||
7887 This->typeattr.typekind == TKIND_DISPATCH))
7888 return TYPE_E_ELEMENTNOTFOUND;
7890 /* when we meet a DUAL typeinfo, we must create the alternate
7891 * version of it.
7893 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7895 *pTypeInfoImpl = *This;
7896 pTypeInfoImpl->ref = 0;
7897 list_init(&pTypeInfoImpl->custdata_list);
7899 if (This->typeattr.typekind == TKIND_INTERFACE)
7900 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7901 else
7902 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7904 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7905 /* the AddRef implicitly adds a reference to the parent typelib, which
7906 * stops the copied data from being destroyed until the new typeinfo's
7907 * refcount goes to zero, but we need to signal to the new instance to
7908 * not free its data structures when it is destroyed */
7909 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7910 ITypeInfo_AddRef(*ppTInfo);
7912 TRACE("got dual interface %p\n", *ppTInfo);
7913 return S_OK;
7916 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7917 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7919 if(!(hRefType & 0x1))
7921 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7923 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7925 result = S_OK;
7926 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7927 ITypeInfo_AddRef(type_info);
7928 break;
7933 if (!type_info)
7935 ITypeLib *pTLib = NULL;
7937 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7939 if(ref_type->reference == (hRefType & (~0x3)))
7940 break;
7942 if(&ref_type->entry == &This->pTypeLib->ref_list)
7944 FIXME("Can't find pRefType for ref %lx\n", hRefType);
7945 return E_FAIL;
7948 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7949 UINT Index;
7950 TRACE("internal reference\n");
7951 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7952 } else {
7953 if(ref_type->pImpTLInfo->pImpTypeLib) {
7954 TRACE("typeinfo in imported typelib that is already loaded\n");
7955 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7956 ITypeLib_AddRef(pTLib);
7957 result = S_OK;
7958 } else {
7959 /* Search in cached typelibs */
7960 ITypeLibImpl *entry;
7962 EnterCriticalSection(&cache_section);
7963 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
7965 if (entry->guid
7966 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
7967 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
7968 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
7969 && entry->set_lcid == ref_type->pImpTLInfo->lcid)
7971 TRACE("got cached %p\n", entry);
7972 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
7973 ITypeLib_AddRef(pTLib);
7974 result = S_OK;
7975 break;
7978 LeaveCriticalSection(&cache_section);
7980 if (!pTLib)
7982 BSTR libnam;
7984 /* Search on disk */
7985 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7986 ref_type->pImpTLInfo->wVersionMajor,
7987 ref_type->pImpTLInfo->wVersionMinor,
7988 This->pTypeLib->syskind,
7989 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7990 if (FAILED(result))
7991 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7993 result = LoadTypeLib(libnam, &pTLib);
7994 SysFreeString(libnam);
7997 if(SUCCEEDED(result)) {
7998 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7999 ITypeLib_AddRef(pTLib);
8003 if(SUCCEEDED(result)) {
8004 if(ref_type->index == TLB_REF_USE_GUID)
8005 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
8006 else
8007 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
8009 if (pTLib != NULL)
8010 ITypeLib_Release(pTLib);
8011 if (FAILED(result))
8013 WARN("(%p) failed hreftype %#lx.\n", iface, hRefType);
8014 return result;
8018 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
8019 ITypeInfo_Release(type_info);
8020 else *ppTInfo = type_info;
8022 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface, hRefType,
8023 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8024 return result;
8027 /* ITypeInfo::AddressOfMember
8029 * Retrieves the addresses of static functions or variables, such as those
8030 * defined in a DLL.
8032 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8033 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8035 HRESULT hr;
8036 BSTR dll, entry;
8037 WORD ordinal;
8038 HMODULE module;
8040 TRACE("%p, %lx, %#x, %p.\n", iface, memid, invKind, ppv);
8042 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8043 if (FAILED(hr))
8044 return hr;
8046 module = LoadLibraryW(dll);
8047 if (!module)
8049 ERR("couldn't load %s\n", debugstr_w(dll));
8050 SysFreeString(dll);
8051 SysFreeString(entry);
8052 return STG_E_FILENOTFOUND;
8054 /* FIXME: store library somewhere where we can free it */
8056 if (entry)
8058 LPSTR entryA;
8059 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8060 entryA = heap_alloc(len);
8061 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8063 *ppv = GetProcAddress(module, entryA);
8064 if (!*ppv)
8065 ERR("function not found %s\n", debugstr_a(entryA));
8067 heap_free(entryA);
8069 else
8071 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8072 if (!*ppv)
8073 ERR("function not found %d\n", ordinal);
8076 SysFreeString(dll);
8077 SysFreeString(entry);
8079 if (!*ppv)
8080 return TYPE_E_DLLFUNCTIONNOTFOUND;
8082 return S_OK;
8085 /* ITypeInfo::CreateInstance
8087 * Creates a new instance of a type that describes a component object class
8088 * (coclass).
8090 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8091 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8093 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8094 HRESULT hr;
8095 TYPEATTR *pTA;
8097 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8099 *ppvObj = NULL;
8101 if(pOuterUnk)
8103 WARN("Not able to aggregate\n");
8104 return CLASS_E_NOAGGREGATION;
8107 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8108 if(FAILED(hr)) return hr;
8110 if(pTA->typekind != TKIND_COCLASS)
8112 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8113 hr = E_INVALIDARG;
8114 goto end;
8117 hr = S_FALSE;
8118 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8120 IUnknown *pUnk;
8121 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8122 TRACE("GetActiveObject rets %#lx.\n", hr);
8123 if(hr == S_OK)
8125 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8126 IUnknown_Release(pUnk);
8130 if(hr != S_OK)
8131 hr = CoCreateInstance(&pTA->guid, NULL,
8132 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8133 riid, ppvObj);
8135 end:
8136 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8137 return hr;
8140 /* ITypeInfo::GetMops
8142 * Retrieves marshalling information.
8144 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, BSTR *pBstrMops)
8146 FIXME("%p, %ld stub!\n", iface, memid);
8147 *pBstrMops = NULL;
8148 return S_OK;
8151 /* ITypeInfo::GetContainingTypeLib
8153 * Retrieves the containing type library and the index of the type description
8154 * within that type library.
8156 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8157 ITypeLib * *ppTLib, UINT *pIndex)
8159 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8161 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8162 if (pIndex) {
8163 *pIndex=This->index;
8164 TRACE("returning pIndex=%d\n", *pIndex);
8167 if (ppTLib) {
8168 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8169 ITypeLib_AddRef(*ppTLib);
8170 TRACE("returning ppTLib=%p\n", *ppTLib);
8173 return S_OK;
8176 /* ITypeInfo::ReleaseTypeAttr
8178 * Releases a TYPEATTR previously returned by Get
8181 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8182 TYPEATTR* pTypeAttr)
8184 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8185 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8186 heap_free(pTypeAttr);
8189 /* ITypeInfo::ReleaseFuncDesc
8191 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8193 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8194 ITypeInfo2 *iface,
8195 FUNCDESC *pFuncDesc)
8197 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8198 SHORT i;
8200 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8202 for (i = 0; i < pFuncDesc->cParams; i++)
8203 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8204 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8206 SysFreeString((BSTR)pFuncDesc);
8209 /* ITypeInfo::ReleaseVarDesc
8211 * Releases a VARDESC previously returned by GetVarDesc.
8213 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8214 VARDESC *pVarDesc)
8216 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8217 TRACE("(%p)->(%p)\n", This, pVarDesc);
8219 TLB_FreeVarDesc(pVarDesc);
8222 /* ITypeInfo2::GetTypeKind
8224 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8227 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8228 TYPEKIND *pTypeKind)
8230 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8231 *pTypeKind = This->typeattr.typekind;
8232 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8233 return S_OK;
8236 /* ITypeInfo2::GetTypeFlags
8238 * Returns the type flags without any allocations. This returns a DWORD type
8239 * flag, which expands the type flags without growing the TYPEATTR (type
8240 * attribute).
8243 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8245 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8246 TRACE("%p, %p.\n", iface, pTypeFlags);
8247 *pTypeFlags=This->typeattr.wTypeFlags;
8248 return S_OK;
8251 /* ITypeInfo2::GetFuncIndexOfMemId
8252 * Binds to a specific member based on a known DISPID, where the member name
8253 * is not known (for example, when binding to a default member).
8256 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8257 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8259 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8260 UINT fdc;
8261 HRESULT result;
8263 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8264 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8265 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8266 break;
8268 if(fdc < This->typeattr.cFuncs) {
8269 *pFuncIndex = fdc;
8270 result = S_OK;
8271 } else
8272 result = TYPE_E_ELEMENTNOTFOUND;
8274 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface, memid, invKind, result);
8275 return result;
8278 /* TypeInfo2::GetVarIndexOfMemId
8280 * Binds to a specific member based on a known DISPID, where the member name
8281 * is not known (for example, when binding to a default member).
8284 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8285 MEMBERID memid, UINT *pVarIndex)
8287 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8288 TLBVarDesc *pVarInfo;
8290 TRACE("%p, %ld, %p.\n", iface, memid, pVarIndex);
8292 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8293 if(!pVarInfo)
8294 return TYPE_E_ELEMENTNOTFOUND;
8296 *pVarIndex = (pVarInfo - This->vardescs);
8298 return S_OK;
8301 /* ITypeInfo2::GetCustData
8303 * Gets the custom data
8305 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8306 ITypeInfo2 * iface,
8307 REFGUID guid,
8308 VARIANT *pVarVal)
8310 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8311 TLBCustData *pCData;
8313 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8315 if(!guid || !pVarVal)
8316 return E_INVALIDARG;
8318 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8320 VariantInit( pVarVal);
8321 if (pCData)
8322 VariantCopy( pVarVal, &pCData->data);
8323 else
8324 VariantClear( pVarVal );
8325 return S_OK;
8328 /* ITypeInfo2::GetFuncCustData
8330 * Gets the custom data
8332 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8333 ITypeInfo2 * iface,
8334 UINT index,
8335 REFGUID guid,
8336 VARIANT *pVarVal)
8338 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8339 const TLBFuncDesc *desc;
8340 TLBCustData *data;
8341 UINT hrefoffset;
8342 HRESULT hr;
8344 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8346 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8347 if (FAILED(hr))
8349 WARN("description for function %d not found\n", index);
8350 return hr;
8353 VariantInit(pVarVal);
8354 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8355 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8358 /* ITypeInfo2::GetParamCustData
8360 * Gets the custom data
8362 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8363 ITypeInfo2 * iface,
8364 UINT indexFunc,
8365 UINT indexParam,
8366 REFGUID guid,
8367 VARIANT *pVarVal)
8369 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8370 const TLBFuncDesc *pFDesc;
8371 TLBCustData *pCData;
8372 UINT hrefoffset;
8373 HRESULT hr;
8375 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8376 debugstr_guid(guid), pVarVal);
8378 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8379 if (FAILED(hr))
8380 return hr;
8382 if(indexParam >= pFDesc->funcdesc.cParams)
8383 return TYPE_E_ELEMENTNOTFOUND;
8385 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8386 if(!pCData)
8387 return TYPE_E_ELEMENTNOTFOUND;
8389 VariantInit(pVarVal);
8390 VariantCopy(pVarVal, &pCData->data);
8392 return S_OK;
8395 /* ITypeInfo2::GetVarCustData
8397 * Gets the custom data
8399 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8400 ITypeInfo2 * iface,
8401 UINT index,
8402 REFGUID guid,
8403 VARIANT *pVarVal)
8405 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8406 TLBCustData *pCData;
8407 TLBVarDesc *pVDesc = &This->vardescs[index];
8409 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8411 if(index >= This->typeattr.cVars)
8412 return TYPE_E_ELEMENTNOTFOUND;
8414 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8415 if(!pCData)
8416 return TYPE_E_ELEMENTNOTFOUND;
8418 VariantInit(pVarVal);
8419 VariantCopy(pVarVal, &pCData->data);
8421 return S_OK;
8424 /* ITypeInfo2::GetImplCustData
8426 * Gets the custom data
8428 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8429 ITypeInfo2 * iface,
8430 UINT index,
8431 REFGUID guid,
8432 VARIANT *pVarVal)
8434 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8435 TLBCustData *pCData;
8436 TLBImplType *pRDesc = &This->impltypes[index];
8438 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8440 if(index >= This->typeattr.cImplTypes)
8441 return TYPE_E_ELEMENTNOTFOUND;
8443 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8444 if(!pCData)
8445 return TYPE_E_ELEMENTNOTFOUND;
8447 VariantInit(pVarVal);
8448 VariantCopy(pVarVal, &pCData->data);
8450 return S_OK;
8453 /* ITypeInfo2::GetDocumentation2
8455 * Retrieves the documentation string, the complete Help file name and path,
8456 * the localization context to use, and the context ID for the library Help
8457 * topic in the Help file.
8460 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8461 ITypeInfo2 * iface,
8462 MEMBERID memid,
8463 LCID lcid,
8464 BSTR *pbstrHelpString,
8465 DWORD *pdwHelpStringContext,
8466 BSTR *pbstrHelpStringDll)
8468 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8469 const TLBFuncDesc *pFDesc;
8470 const TLBVarDesc *pVDesc;
8471 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8472 iface, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8473 pbstrHelpStringDll );
8474 /* the help string should be obtained from the helpstringdll,
8475 * using the _DLLGetDocumentation function, based on the supplied
8476 * lcid. Nice to do sometime...
8478 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8479 if(pbstrHelpString)
8480 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8481 if(pdwHelpStringContext)
8482 *pdwHelpStringContext=This->dwHelpStringContext;
8483 if(pbstrHelpStringDll)
8484 *pbstrHelpStringDll=
8485 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8486 return S_OK;
8487 }else {/* for a member */
8488 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8489 if(pFDesc){
8490 if(pbstrHelpString)
8491 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8492 if(pdwHelpStringContext)
8493 *pdwHelpStringContext=pFDesc->HelpStringContext;
8494 if(pbstrHelpStringDll)
8495 *pbstrHelpStringDll=
8496 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8497 return S_OK;
8499 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8500 if(pVDesc){
8501 if(pbstrHelpString)
8502 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8503 if(pdwHelpStringContext)
8504 *pdwHelpStringContext=pVDesc->HelpStringContext;
8505 if(pbstrHelpStringDll)
8506 *pbstrHelpStringDll=
8507 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8508 return S_OK;
8511 return TYPE_E_ELEMENTNOTFOUND;
8514 /* ITypeInfo2::GetAllCustData
8516 * Gets all custom data items for the Type info.
8519 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8520 ITypeInfo2 * iface,
8521 CUSTDATA *pCustData)
8523 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8525 TRACE("%p %p\n", This, pCustData);
8527 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8530 /* ITypeInfo2::GetAllFuncCustData
8532 * Gets all custom data items for the specified Function
8535 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8536 ITypeInfo2 * iface,
8537 UINT index,
8538 CUSTDATA *pCustData)
8540 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8541 const TLBFuncDesc *pFDesc;
8542 UINT hrefoffset;
8543 HRESULT hr;
8545 TRACE("%p %u %p\n", This, index, pCustData);
8547 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8548 if (FAILED(hr))
8549 return hr;
8551 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8554 /* ITypeInfo2::GetAllParamCustData
8556 * Gets all custom data items for the Functions
8559 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8560 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8562 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8563 const TLBFuncDesc *pFDesc;
8564 UINT hrefoffset;
8565 HRESULT hr;
8567 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8569 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8570 if (FAILED(hr))
8571 return hr;
8573 if(indexParam >= pFDesc->funcdesc.cParams)
8574 return TYPE_E_ELEMENTNOTFOUND;
8576 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8579 /* ITypeInfo2::GetAllVarCustData
8581 * Gets all custom data items for the specified Variable
8584 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8585 UINT index, CUSTDATA *pCustData)
8587 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8588 TLBVarDesc * pVDesc = &This->vardescs[index];
8590 TRACE("%p %u %p\n", This, index, pCustData);
8592 if(index >= This->typeattr.cVars)
8593 return TYPE_E_ELEMENTNOTFOUND;
8595 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8598 /* ITypeInfo2::GetAllImplCustData
8600 * Gets all custom data items for the specified implementation type
8603 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8604 ITypeInfo2 * iface,
8605 UINT index,
8606 CUSTDATA *pCustData)
8608 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8609 TLBImplType *pRDesc = &This->impltypes[index];
8611 TRACE("%p %u %p\n", This, index, pCustData);
8613 if(index >= This->typeattr.cImplTypes)
8614 return TYPE_E_ELEMENTNOTFOUND;
8616 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8619 static const ITypeInfo2Vtbl tinfvt =
8622 ITypeInfo_fnQueryInterface,
8623 ITypeInfo_fnAddRef,
8624 ITypeInfo_fnRelease,
8626 ITypeInfo_fnGetTypeAttr,
8627 ITypeInfo_fnGetTypeComp,
8628 ITypeInfo_fnGetFuncDesc,
8629 ITypeInfo_fnGetVarDesc,
8630 ITypeInfo_fnGetNames,
8631 ITypeInfo_fnGetRefTypeOfImplType,
8632 ITypeInfo_fnGetImplTypeFlags,
8633 ITypeInfo_fnGetIDsOfNames,
8634 ITypeInfo_fnInvoke,
8635 ITypeInfo_fnGetDocumentation,
8636 ITypeInfo_fnGetDllEntry,
8637 ITypeInfo_fnGetRefTypeInfo,
8638 ITypeInfo_fnAddressOfMember,
8639 ITypeInfo_fnCreateInstance,
8640 ITypeInfo_fnGetMops,
8641 ITypeInfo_fnGetContainingTypeLib,
8642 ITypeInfo_fnReleaseTypeAttr,
8643 ITypeInfo_fnReleaseFuncDesc,
8644 ITypeInfo_fnReleaseVarDesc,
8646 ITypeInfo2_fnGetTypeKind,
8647 ITypeInfo2_fnGetTypeFlags,
8648 ITypeInfo2_fnGetFuncIndexOfMemId,
8649 ITypeInfo2_fnGetVarIndexOfMemId,
8650 ITypeInfo2_fnGetCustData,
8651 ITypeInfo2_fnGetFuncCustData,
8652 ITypeInfo2_fnGetParamCustData,
8653 ITypeInfo2_fnGetVarCustData,
8654 ITypeInfo2_fnGetImplTypeCustData,
8655 ITypeInfo2_fnGetDocumentation2,
8656 ITypeInfo2_fnGetAllCustData,
8657 ITypeInfo2_fnGetAllFuncCustData,
8658 ITypeInfo2_fnGetAllParamCustData,
8659 ITypeInfo2_fnGetAllVarCustData,
8660 ITypeInfo2_fnGetAllImplTypeCustData,
8663 /******************************************************************************
8664 * CreateDispTypeInfo [OLEAUT32.31]
8666 * Build type information for an object so it can be called through an
8667 * IDispatch interface.
8669 * RETURNS
8670 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8671 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8673 * NOTES
8674 * This call allows an objects methods to be accessed through IDispatch, by
8675 * building an ITypeInfo object that IDispatch can use to call through.
8677 HRESULT WINAPI CreateDispTypeInfo(
8678 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8679 LCID lcid, /* [I] Locale Id */
8680 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8682 ITypeInfoImpl *pTIClass, *pTIIface;
8683 ITypeLibImpl *pTypeLibImpl;
8684 unsigned int param, func;
8685 TLBFuncDesc *pFuncDesc;
8686 TLBRefType *ref;
8688 TRACE("\n");
8689 pTypeLibImpl = TypeLibImpl_Constructor();
8690 if (!pTypeLibImpl) return E_FAIL;
8692 pTypeLibImpl->TypeInfoCount = 2;
8693 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8695 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8696 pTIIface->pTypeLib = pTypeLibImpl;
8697 pTIIface->index = 0;
8698 pTIIface->Name = NULL;
8699 pTIIface->dwHelpContext = -1;
8700 pTIIface->guid = NULL;
8701 pTIIface->typeattr.lcid = lcid;
8702 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8703 pTIIface->typeattr.wMajorVerNum = 0;
8704 pTIIface->typeattr.wMinorVerNum = 0;
8705 pTIIface->typeattr.cbAlignment = 2;
8706 pTIIface->typeattr.cbSizeInstance = -1;
8707 pTIIface->typeattr.cbSizeVft = -1;
8708 pTIIface->typeattr.cFuncs = 0;
8709 pTIIface->typeattr.cImplTypes = 0;
8710 pTIIface->typeattr.cVars = 0;
8711 pTIIface->typeattr.wTypeFlags = 0;
8712 pTIIface->hreftype = 0;
8714 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8715 pFuncDesc = pTIIface->funcdescs;
8716 for(func = 0; func < pidata->cMembers; func++) {
8717 METHODDATA *md = pidata->pmethdata + func;
8718 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8719 pFuncDesc->funcdesc.memid = md->dispid;
8720 pFuncDesc->funcdesc.lprgscode = NULL;
8721 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8722 pFuncDesc->funcdesc.invkind = md->wFlags;
8723 pFuncDesc->funcdesc.callconv = md->cc;
8724 pFuncDesc->funcdesc.cParams = md->cArgs;
8725 pFuncDesc->funcdesc.cParamsOpt = 0;
8726 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8727 pFuncDesc->funcdesc.cScodes = 0;
8728 pFuncDesc->funcdesc.wFuncFlags = 0;
8729 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8730 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8731 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8732 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8733 md->cArgs * sizeof(ELEMDESC));
8734 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8735 for(param = 0; param < md->cArgs; param++) {
8736 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8737 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8739 pFuncDesc->helpcontext = 0;
8740 pFuncDesc->HelpStringContext = 0;
8741 pFuncDesc->HelpString = NULL;
8742 pFuncDesc->Entry = NULL;
8743 list_init(&pFuncDesc->custdata_list);
8744 pTIIface->typeattr.cFuncs++;
8745 ++pFuncDesc;
8748 dump_TypeInfo(pTIIface);
8750 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8751 pTIClass->pTypeLib = pTypeLibImpl;
8752 pTIClass->index = 1;
8753 pTIClass->Name = NULL;
8754 pTIClass->dwHelpContext = -1;
8755 pTIClass->guid = NULL;
8756 pTIClass->typeattr.lcid = lcid;
8757 pTIClass->typeattr.typekind = TKIND_COCLASS;
8758 pTIClass->typeattr.wMajorVerNum = 0;
8759 pTIClass->typeattr.wMinorVerNum = 0;
8760 pTIClass->typeattr.cbAlignment = 2;
8761 pTIClass->typeattr.cbSizeInstance = -1;
8762 pTIClass->typeattr.cbSizeVft = -1;
8763 pTIClass->typeattr.cFuncs = 0;
8764 pTIClass->typeattr.cImplTypes = 1;
8765 pTIClass->typeattr.cVars = 0;
8766 pTIClass->typeattr.wTypeFlags = 0;
8767 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8769 pTIClass->impltypes = TLBImplType_Alloc(1);
8771 ref = heap_alloc_zero(sizeof(*ref));
8772 ref->pImpTLInfo = TLB_REF_INTERNAL;
8773 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8775 dump_TypeInfo(pTIClass);
8777 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8779 ITypeInfo_AddRef(*pptinfo);
8780 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8782 return S_OK;
8786 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8788 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8790 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8793 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8795 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8797 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8800 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8802 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8804 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8807 static HRESULT WINAPI ITypeComp_fnBind(
8808 ITypeComp * iface,
8809 OLECHAR * szName,
8810 ULONG lHash,
8811 WORD wFlags,
8812 ITypeInfo ** ppTInfo,
8813 DESCKIND * pDescKind,
8814 BINDPTR * pBindPtr)
8816 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8817 const TLBFuncDesc *pFDesc;
8818 const TLBVarDesc *pVDesc;
8819 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8820 UINT fdc;
8822 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8824 *pDescKind = DESCKIND_NONE;
8825 pBindPtr->lpfuncdesc = NULL;
8826 *ppTInfo = NULL;
8828 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8829 pFDesc = &This->funcdescs[fdc];
8830 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8831 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8832 break;
8833 else
8834 /* name found, but wrong flags */
8835 hr = TYPE_E_TYPEMISMATCH;
8839 if (fdc < This->typeattr.cFuncs)
8841 HRESULT hr = TLB_AllocAndInitFuncDesc(
8842 &pFDesc->funcdesc,
8843 &pBindPtr->lpfuncdesc,
8844 This->typeattr.typekind == TKIND_DISPATCH);
8845 if (FAILED(hr))
8846 return hr;
8847 *pDescKind = DESCKIND_FUNCDESC;
8848 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8849 ITypeInfo_AddRef(*ppTInfo);
8850 return S_OK;
8851 } else {
8852 pVDesc = TLB_get_vardesc_by_name(This, szName);
8853 if(pVDesc){
8854 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8855 if (FAILED(hr))
8856 return hr;
8857 *pDescKind = DESCKIND_VARDESC;
8858 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8859 ITypeInfo_AddRef(*ppTInfo);
8860 return S_OK;
8864 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8865 /* recursive search */
8866 ITypeInfo *pTInfo;
8867 ITypeComp *pTComp;
8868 HRESULT hr;
8869 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8870 if (SUCCEEDED(hr))
8872 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8873 ITypeInfo_Release(pTInfo);
8875 if (SUCCEEDED(hr))
8877 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8878 ITypeComp_Release(pTComp);
8879 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8880 This->typeattr.typekind == TKIND_DISPATCH)
8882 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8883 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8884 SysFreeString((BSTR)tmp);
8886 return hr;
8888 WARN("Could not search inherited interface!\n");
8890 if (hr == DISP_E_MEMBERNOTFOUND)
8891 hr = S_OK;
8892 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8893 return hr;
8896 static HRESULT WINAPI ITypeComp_fnBindType(
8897 ITypeComp * iface,
8898 OLECHAR * szName,
8899 ULONG lHash,
8900 ITypeInfo ** ppTInfo,
8901 ITypeComp ** ppTComp)
8903 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8905 /* strange behaviour (does nothing) but like the
8906 * original */
8908 if (!ppTInfo || !ppTComp)
8909 return E_POINTER;
8911 *ppTInfo = NULL;
8912 *ppTComp = NULL;
8914 return S_OK;
8917 static const ITypeCompVtbl tcompvt =
8920 ITypeComp_fnQueryInterface,
8921 ITypeComp_fnAddRef,
8922 ITypeComp_fnRelease,
8924 ITypeComp_fnBind,
8925 ITypeComp_fnBindType
8928 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8929 ICreateTypeLib2** ppctlib)
8931 ITypeLibImpl *This;
8932 HRESULT hres;
8934 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8936 if (!szFile) return E_INVALIDARG;
8938 This = TypeLibImpl_Constructor();
8939 if (!This)
8940 return E_OUTOFMEMORY;
8942 This->lcid = GetSystemDefaultLCID();
8943 This->syskind = syskind;
8944 This->ptr_size = get_ptr_size(syskind);
8946 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8947 if (!This->path) {
8948 ITypeLib2_Release(&This->ITypeLib2_iface);
8949 return E_OUTOFMEMORY;
8951 lstrcpyW(This->path, szFile);
8953 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8954 ITypeLib2_Release(&This->ITypeLib2_iface);
8955 return hres;
8958 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8959 REFIID riid, void **object)
8961 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8963 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8966 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8968 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8970 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8973 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8975 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8977 return ITypeLib2_Release(&This->ITypeLib2_iface);
8980 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8981 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8983 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8984 ITypeInfoImpl *info;
8985 HRESULT hres;
8987 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8989 if (!ctinfo || !name)
8990 return E_INVALIDARG;
8992 info = TLB_get_typeinfo_by_name(This, name);
8993 if (info)
8994 return TYPE_E_NAMECONFLICT;
8996 if (This->typeinfos)
8997 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8998 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8999 else
9000 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
9002 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
9004 info->pTypeLib = This;
9005 info->Name = TLB_append_str(&This->name_list, name);
9006 info->index = This->TypeInfoCount;
9007 info->typeattr.typekind = kind;
9008 info->typeattr.cbAlignment = 4;
9010 switch (info->typeattr.typekind) {
9011 case TKIND_ENUM:
9012 case TKIND_INTERFACE:
9013 case TKIND_DISPATCH:
9014 case TKIND_COCLASS:
9015 info->typeattr.cbSizeInstance = This->ptr_size;
9016 break;
9017 case TKIND_RECORD:
9018 case TKIND_UNION:
9019 info->typeattr.cbSizeInstance = 0;
9020 break;
9021 case TKIND_MODULE:
9022 info->typeattr.cbSizeInstance = 2;
9023 break;
9024 case TKIND_ALIAS:
9025 info->typeattr.cbSizeInstance = -0x75;
9026 break;
9027 default:
9028 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9029 info->typeattr.cbSizeInstance = 0xdeadbeef;
9030 break;
9033 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9034 &IID_ICreateTypeInfo, (void **)ctinfo);
9035 if (FAILED(hres)) {
9036 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9037 return hres;
9040 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9042 ++This->TypeInfoCount;
9044 return S_OK;
9047 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9048 LPOLESTR name)
9050 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9052 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9054 if (!name)
9055 return E_INVALIDARG;
9057 This->Name = TLB_append_str(&This->name_list, name);
9059 return S_OK;
9062 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9063 WORD majorVerNum, WORD minorVerNum)
9065 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9067 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9069 This->ver_major = majorVerNum;
9070 This->ver_minor = minorVerNum;
9072 return S_OK;
9075 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9076 REFGUID guid)
9078 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9080 TRACE("%p %s\n", This, debugstr_guid(guid));
9082 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9084 return S_OK;
9087 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9088 LPOLESTR doc)
9090 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9092 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9094 if (!doc)
9095 return E_INVALIDARG;
9097 This->DocString = TLB_append_str(&This->string_list, doc);
9099 return S_OK;
9102 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9103 LPOLESTR helpFileName)
9105 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9107 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9109 if (!helpFileName)
9110 return E_INVALIDARG;
9112 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9114 return S_OK;
9117 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9118 DWORD helpContext)
9120 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9122 TRACE("%p, %ld.\n", iface, helpContext);
9124 This->dwHelpContext = helpContext;
9126 return S_OK;
9129 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9130 LCID lcid)
9132 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9134 TRACE("%p, %#lx.\n", iface, lcid);
9136 This->set_lcid = lcid;
9138 return S_OK;
9141 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9142 UINT libFlags)
9144 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9146 TRACE("%p %x\n", This, libFlags);
9148 This->libflags = libFlags;
9150 return S_OK;
9153 typedef struct tagWMSFT_SegContents {
9154 DWORD len;
9155 void *data;
9156 } WMSFT_SegContents;
9158 typedef struct tagWMSFT_TLBFile {
9159 MSFT_Header header;
9160 WMSFT_SegContents typeinfo_seg;
9161 WMSFT_SegContents impfile_seg;
9162 WMSFT_SegContents impinfo_seg;
9163 WMSFT_SegContents ref_seg;
9164 WMSFT_SegContents guidhash_seg;
9165 WMSFT_SegContents guid_seg;
9166 WMSFT_SegContents namehash_seg;
9167 WMSFT_SegContents name_seg;
9168 WMSFT_SegContents string_seg;
9169 WMSFT_SegContents typdesc_seg;
9170 WMSFT_SegContents arraydesc_seg;
9171 WMSFT_SegContents custdata_seg;
9172 WMSFT_SegContents cdguids_seg;
9173 MSFT_SegDir segdir;
9174 WMSFT_SegContents aux_seg;
9175 } WMSFT_TLBFile;
9177 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9178 WMSFT_TLBFile *file)
9180 TLBString *str;
9181 UINT last_offs;
9182 char *data;
9184 file->string_seg.len = 0;
9185 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9186 int size;
9188 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9189 if (size == 0)
9190 return E_UNEXPECTED;
9192 size += sizeof(INT16);
9193 if (size % 4)
9194 size = (size + 4) & ~0x3;
9195 if (size < 8)
9196 size = 8;
9198 file->string_seg.len += size;
9200 /* temporarily use str->offset to store the length of the aligned,
9201 * converted string */
9202 str->offset = size;
9205 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9207 last_offs = 0;
9208 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9209 int size;
9211 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9212 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9213 if (size == 0) {
9214 heap_free(file->string_seg.data);
9215 return E_UNEXPECTED;
9218 *((INT16*)data) = size;
9220 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9222 size = str->offset;
9223 data += size;
9224 str->offset = last_offs;
9225 last_offs += size;
9228 return S_OK;
9231 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9232 WMSFT_TLBFile *file)
9234 TLBString *str;
9235 UINT last_offs;
9236 char *data;
9237 MSFT_NameIntro *last_intro = NULL;
9239 file->header.nametablecount = 0;
9240 file->header.nametablechars = 0;
9242 file->name_seg.len = 0;
9243 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9244 int size;
9246 size = lstrlenW(str->str);
9247 file->header.nametablechars += size;
9248 file->header.nametablecount++;
9250 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9251 if (size == 0)
9252 return E_UNEXPECTED;
9254 size += sizeof(MSFT_NameIntro);
9255 if (size % 4)
9256 size = (size + 4) & ~0x3;
9257 if (size < 8)
9258 size = 8;
9260 file->name_seg.len += size;
9262 /* temporarily use str->offset to store the length of the aligned,
9263 * converted string */
9264 str->offset = size;
9267 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9268 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9270 last_offs = 0;
9271 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9272 int size, hash;
9273 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9275 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9276 data + sizeof(MSFT_NameIntro),
9277 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9278 if (size == 0) {
9279 heap_free(file->name_seg.data);
9280 return E_UNEXPECTED;
9282 data[sizeof(MSFT_NameIntro) + size] = '\0';
9284 intro->hreftype = -1; /* TODO? */
9285 intro->namelen = size & 0xFF;
9286 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9287 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9288 intro->namelen |= hash << 16;
9289 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9290 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9292 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9293 str->offset - size - sizeof(MSFT_NameIntro));
9295 /* update str->offset to actual value to use in other
9296 * compilation functions that require positions within
9297 * the string table */
9298 last_intro = intro;
9299 size = str->offset;
9300 data += size;
9301 str->offset = last_offs;
9302 last_offs += size;
9305 if(last_intro)
9306 last_intro->hreftype = 0; /* last one is 0? */
9308 return S_OK;
9311 static inline int hash_guid(GUID *guid)
9313 int i, hash = 0;
9315 for (i = 0; i < 8; i ++)
9316 hash ^= ((const short *)guid)[i];
9318 return hash & 0x1f;
9321 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9323 TLBGuid *guid;
9324 MSFT_GuidEntry *entry;
9325 DWORD offs;
9326 int hash_key, *guidhashtab;
9328 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9329 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9331 entry = file->guid_seg.data;
9332 offs = 0;
9333 guidhashtab = file->guidhash_seg.data;
9334 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9335 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9336 entry->hreftype = guid->hreftype;
9338 hash_key = hash_guid(&guid->guid);
9339 entry->next_hash = guidhashtab[hash_key];
9340 guidhashtab[hash_key] = offs;
9342 guid->offset = offs;
9343 offs += sizeof(MSFT_GuidEntry);
9344 ++entry;
9347 return S_OK;
9350 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9352 VARIANT v = *value;
9353 VARTYPE arg_type = V_VT(value);
9354 int mask = 0;
9355 HRESULT hres;
9356 DWORD ret = file->custdata_seg.len;
9358 if(arg_type == VT_INT)
9359 arg_type = VT_I4;
9360 if(arg_type == VT_UINT)
9361 arg_type = VT_UI4;
9363 v = *value;
9364 if(V_VT(value) != arg_type) {
9365 hres = VariantChangeType(&v, value, 0, arg_type);
9366 if(FAILED(hres)){
9367 ERR("VariantChangeType failed: %#lx.\n", hres);
9368 return -1;
9372 /* Check if default value can be stored in-place */
9373 switch(arg_type){
9374 case VT_I4:
9375 case VT_UI4:
9376 mask = 0x3ffffff;
9377 if(V_UI4(&v) > 0x3ffffff)
9378 break;
9379 /* fall through */
9380 case VT_I1:
9381 case VT_UI1:
9382 case VT_BOOL:
9383 if(!mask)
9384 mask = 0xff;
9385 /* fall through */
9386 case VT_I2:
9387 case VT_UI2:
9388 if(!mask)
9389 mask = 0xffff;
9390 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9393 /* have to allocate space in custdata_seg */
9394 switch(arg_type) {
9395 case VT_I4:
9396 case VT_R4:
9397 case VT_UI4:
9398 case VT_INT:
9399 case VT_UINT:
9400 case VT_HRESULT:
9401 case VT_PTR: {
9402 /* Construct the data to be allocated */
9403 int *data;
9405 if(file->custdata_seg.data){
9406 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9407 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9408 file->custdata_seg.len += sizeof(int) * 2;
9409 }else{
9410 file->custdata_seg.len = sizeof(int) * 2;
9411 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9414 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9415 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9417 /* TODO: Check if the encoded data is already present in custdata_seg */
9419 return ret;
9422 case VT_BSTR: {
9423 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9424 char *data;
9426 if(file->custdata_seg.data){
9427 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9428 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9429 file->custdata_seg.len += len;
9430 }else{
9431 file->custdata_seg.len = len;
9432 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9435 *((unsigned short *)data) = V_VT(value);
9436 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9437 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9438 if(V_BSTR(&v)[i] <= 0x7f)
9439 data[i+6] = V_BSTR(&v)[i];
9440 else
9441 data[i+6] = '?';
9443 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9444 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9445 data[i] = 0x57;
9447 /* TODO: Check if the encoded data is already present in custdata_seg */
9449 return ret;
9451 default:
9452 FIXME("Argument type not yet handled\n");
9453 return -1;
9457 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9459 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9461 DWORD offs = file->arraydesc_seg.len;
9462 DWORD *encoded;
9463 USHORT i;
9465 /* TODO: we should check for duplicates, but that's harder because each
9466 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9467 * at the library-level) */
9469 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9470 if(!file->arraydesc_seg.data)
9471 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9472 else
9473 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9474 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9476 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9477 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9478 for(i = 0; i < desc->cDims; ++i){
9479 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9480 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9483 return offs;
9486 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9488 DWORD junk;
9489 INT16 junk2;
9490 DWORD offs = 0;
9491 DWORD encoded[2];
9492 VARTYPE vt, subtype;
9493 char *data;
9495 if(!desc)
9496 return -1;
9498 if(!out_mix)
9499 out_mix = &junk;
9500 if(!out_size)
9501 out_size = &junk2;
9503 vt = desc->vt & VT_TYPEMASK;
9505 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9506 DWORD mix;
9507 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9508 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9509 *out_mix = 0x7FFF;
9510 *out_size += 2 * sizeof(DWORD);
9511 }else if(vt == VT_CARRAY){
9512 encoded[0] = desc->vt | (0x7FFE << 16);
9513 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9514 *out_mix = 0x7FFE;
9515 }else if(vt == VT_USERDEFINED){
9516 encoded[0] = desc->vt | (0x7FFF << 16);
9517 encoded[1] = desc->u.hreftype;
9518 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9519 }else{
9520 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9522 switch(vt){
9523 case VT_INT:
9524 subtype = VT_I4;
9525 break;
9526 case VT_UINT:
9527 subtype = VT_UI4;
9528 break;
9529 case VT_VOID:
9530 subtype = VT_EMPTY;
9531 break;
9532 default:
9533 subtype = vt;
9534 break;
9537 *out_mix = subtype;
9538 return 0x80000000 | (subtype << 16) | desc->vt;
9541 data = file->typdesc_seg.data;
9542 while(offs < file->typdesc_seg.len){
9543 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9544 return offs;
9545 offs += sizeof(encoded);
9548 file->typdesc_seg.len += sizeof(encoded);
9549 if(!file->typdesc_seg.data)
9550 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9551 else
9552 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9554 memcpy(&data[offs], encoded, sizeof(encoded));
9556 return offs;
9559 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9561 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9562 DWORD ret = cdguids_seg->len, offs;
9563 MSFT_CDGuid *cdguid;
9564 TLBCustData *cd;
9566 if(list_empty(custdata_list))
9567 return -1;
9569 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9570 if(!cdguids_seg->data){
9571 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9572 }else {
9573 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9574 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9577 offs = ret + sizeof(MSFT_CDGuid);
9578 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9579 cdguid->GuidOffset = cd->guid->offset;
9580 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9581 cdguid->next = offs;
9582 offs += sizeof(MSFT_CDGuid);
9583 ++cdguid;
9586 --cdguid;
9587 cdguid->next = -1;
9589 return ret;
9592 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9593 WMSFT_TLBFile *file)
9595 WMSFT_SegContents *aux_seg = &file->aux_seg;
9596 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9597 MSFT_VarRecord *varrecord;
9598 MSFT_FuncRecord *funcrecord;
9599 MEMBERID *memid;
9600 DWORD *name, *offsets, offs;
9602 for(i = 0; i < info->typeattr.cFuncs; ++i){
9603 TLBFuncDesc *desc = &info->funcdescs[i];
9605 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9607 /* optional fields */
9608 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9609 if(!list_empty(&desc->custdata_list))
9610 recorded_size += 7 * sizeof(INT);
9611 else if(desc->HelpStringContext != 0)
9612 recorded_size += 6 * sizeof(INT);
9613 /* res9? resA? */
9614 else if(desc->Entry)
9615 recorded_size += 3 * sizeof(INT);
9616 else if(desc->HelpString)
9617 recorded_size += 2 * sizeof(INT);
9618 else if(desc->helpcontext)
9619 recorded_size += sizeof(INT);
9621 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9623 for(j = 0; j < desc->funcdesc.cParams; ++j){
9624 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9625 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9626 break;
9630 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9633 for(i = 0; i < info->typeattr.cVars; ++i){
9634 TLBVarDesc *desc = &info->vardescs[i];
9636 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9638 /* optional fields */
9639 if(desc->HelpStringContext != 0)
9640 recorded_size += 5 * sizeof(INT);
9641 else if(!list_empty(&desc->custdata_list))
9642 recorded_size += 4 * sizeof(INT);
9643 /* res9? */
9644 else if(desc->HelpString)
9645 recorded_size += 2 * sizeof(INT);
9646 else if(desc->HelpContext != 0)
9647 recorded_size += sizeof(INT);
9649 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9652 if(!recorded_size && !extra_size)
9653 return ret;
9655 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9657 aux_seg->len += recorded_size + extra_size;
9659 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9661 if(aux_seg->data)
9662 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9663 else
9664 aux_seg->data = heap_alloc(aux_seg->len);
9666 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9668 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9669 offs = 0;
9671 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9672 for(i = 0; i < info->typeattr.cFuncs; ++i){
9673 TLBFuncDesc *desc = &info->funcdescs[i];
9674 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9676 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9677 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9678 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9679 funcrecord->VtableOffset = desc->funcdesc.oVft;
9681 /* FKCCIC:
9682 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9683 * ^^^funckind
9684 * ^^^ ^invkind
9685 * ^has_cust_data
9686 * ^^^^callconv
9687 * ^has_param_defaults
9688 * ^oEntry_is_intresource
9690 funcrecord->FKCCIC =
9691 desc->funcdesc.funckind |
9692 (desc->funcdesc.invkind << 3) |
9693 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9694 (desc->funcdesc.callconv << 8);
9696 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9697 funcrecord->FKCCIC |= 0x2000;
9699 for(j = 0; j < desc->funcdesc.cParams; ++j){
9700 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9701 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9702 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9705 if(paramdefault_size > 0)
9706 funcrecord->FKCCIC |= 0x1000;
9708 funcrecord->nrargs = desc->funcdesc.cParams;
9709 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9711 /* optional fields */
9712 /* res9? resA? */
9713 if(!list_empty(&desc->custdata_list)){
9714 size += 7 * sizeof(INT);
9715 funcrecord->HelpContext = desc->helpcontext;
9716 if(desc->HelpString)
9717 funcrecord->oHelpString = desc->HelpString->offset;
9718 else
9719 funcrecord->oHelpString = -1;
9720 if(!desc->Entry)
9721 funcrecord->oEntry = -1;
9722 else if(IS_INTRESOURCE(desc->Entry))
9723 funcrecord->oEntry = LOWORD(desc->Entry);
9724 else
9725 funcrecord->oEntry = desc->Entry->offset;
9726 funcrecord->res9 = -1;
9727 funcrecord->resA = -1;
9728 funcrecord->HelpStringContext = desc->HelpStringContext;
9729 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9730 }else if(desc->HelpStringContext != 0){
9731 size += 6 * sizeof(INT);
9732 funcrecord->HelpContext = desc->helpcontext;
9733 if(desc->HelpString)
9734 funcrecord->oHelpString = desc->HelpString->offset;
9735 else
9736 funcrecord->oHelpString = -1;
9737 if(!desc->Entry)
9738 funcrecord->oEntry = -1;
9739 else if(IS_INTRESOURCE(desc->Entry))
9740 funcrecord->oEntry = LOWORD(desc->Entry);
9741 else
9742 funcrecord->oEntry = desc->Entry->offset;
9743 funcrecord->res9 = -1;
9744 funcrecord->resA = -1;
9745 funcrecord->HelpStringContext = desc->HelpStringContext;
9746 }else if(desc->Entry){
9747 size += 3 * sizeof(INT);
9748 funcrecord->HelpContext = desc->helpcontext;
9749 if(desc->HelpString)
9750 funcrecord->oHelpString = desc->HelpString->offset;
9751 else
9752 funcrecord->oHelpString = -1;
9753 if(!desc->Entry)
9754 funcrecord->oEntry = -1;
9755 else if(IS_INTRESOURCE(desc->Entry))
9756 funcrecord->oEntry = LOWORD(desc->Entry);
9757 else
9758 funcrecord->oEntry = desc->Entry->offset;
9759 }else if(desc->HelpString){
9760 size += 2 * sizeof(INT);
9761 funcrecord->HelpContext = desc->helpcontext;
9762 funcrecord->oHelpString = desc->HelpString->offset;
9763 }else if(desc->helpcontext){
9764 size += sizeof(INT);
9765 funcrecord->HelpContext = desc->helpcontext;
9768 paramdefault = (DWORD*)((char *)funcrecord + size);
9769 size += paramdefault_size;
9771 for(j = 0; j < desc->funcdesc.cParams; ++j){
9772 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9774 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9775 if(desc->pParamDesc[j].Name)
9776 info->oName = desc->pParamDesc[j].Name->offset;
9777 else
9778 info->oName = -1;
9779 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9781 if(paramdefault_size){
9782 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9783 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9784 else if(paramdefault_size)
9785 *paramdefault = -1;
9786 ++paramdefault;
9789 size += sizeof(MSFT_ParameterInfo);
9792 funcrecord->Info = size | (i << 16); /* is it just the index? */
9794 *offsets = offs;
9795 offs += size;
9796 ++offsets;
9798 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9801 varrecord = (MSFT_VarRecord*)funcrecord;
9802 for(i = 0; i < info->typeattr.cVars; ++i){
9803 TLBVarDesc *desc = &info->vardescs[i];
9804 DWORD size = 5 * sizeof(INT);
9806 varrecord->vardescsize = sizeof(desc->vardesc);
9807 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9808 varrecord->Flags = desc->vardesc.wVarFlags;
9809 varrecord->VarKind = desc->vardesc.varkind;
9811 if(desc->vardesc.varkind == VAR_CONST){
9812 varrecord->vardescsize += sizeof(VARIANT);
9813 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9814 }else
9815 varrecord->OffsValue = desc->vardesc.u.oInst;
9817 /* res9? */
9818 if(desc->HelpStringContext != 0){
9819 size += 5 * sizeof(INT);
9820 varrecord->HelpContext = desc->HelpContext;
9821 if(desc->HelpString)
9822 varrecord->HelpString = desc->HelpString->offset;
9823 else
9824 varrecord->HelpString = -1;
9825 varrecord->res9 = -1;
9826 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9827 varrecord->HelpStringContext = desc->HelpStringContext;
9828 }else if(!list_empty(&desc->custdata_list)){
9829 size += 4 * sizeof(INT);
9830 varrecord->HelpContext = desc->HelpContext;
9831 if(desc->HelpString)
9832 varrecord->HelpString = desc->HelpString->offset;
9833 else
9834 varrecord->HelpString = -1;
9835 varrecord->res9 = -1;
9836 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9837 }else if(desc->HelpString){
9838 size += 2 * sizeof(INT);
9839 varrecord->HelpContext = desc->HelpContext;
9840 if(desc->HelpString)
9841 varrecord->HelpString = desc->HelpString->offset;
9842 else
9843 varrecord->HelpString = -1;
9844 }else if(desc->HelpContext != 0){
9845 size += sizeof(INT);
9846 varrecord->HelpContext = desc->HelpContext;
9849 varrecord->Info = size | (i << 16);
9851 *offsets = offs;
9852 offs += size;
9853 ++offsets;
9855 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9858 memid = (MEMBERID*)varrecord;
9859 for(i = 0; i < info->typeattr.cFuncs; ++i){
9860 TLBFuncDesc *desc = &info->funcdescs[i];
9861 *memid = desc->funcdesc.memid;
9862 ++memid;
9864 for(i = 0; i < info->typeattr.cVars; ++i){
9865 TLBVarDesc *desc = &info->vardescs[i];
9866 *memid = desc->vardesc.memid;
9867 ++memid;
9870 name = (DWORD*)memid;
9871 for(i = 0; i < info->typeattr.cFuncs; ++i){
9872 TLBFuncDesc *desc = &info->funcdescs[i];
9873 if(desc->Name)
9874 *name = desc->Name->offset;
9875 else
9876 *name = -1;
9877 ++name;
9879 for(i = 0; i < info->typeattr.cVars; ++i){
9880 TLBVarDesc *desc = &info->vardescs[i];
9881 if(desc->Name)
9882 *name = desc->Name->offset;
9883 else
9884 *name = -1;
9885 ++name;
9888 return ret;
9891 typedef struct tagWMSFT_RefChunk {
9892 DWORD href;
9893 DWORD res04;
9894 DWORD res08;
9895 DWORD next;
9896 } WMSFT_RefChunk;
9898 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9900 DWORD offs = file->ref_seg.len, i;
9901 WMSFT_RefChunk *chunk;
9903 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9904 if(!file->ref_seg.data)
9905 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9906 else
9907 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9909 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9911 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9912 chunk->href = info->impltypes[i].hRef;
9913 chunk->res04 = info->impltypes[i].implflags;
9914 chunk->res08 = -1;
9915 if(i < info->typeattr.cImplTypes - 1)
9916 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9917 else
9918 chunk->next = -1;
9919 ++chunk;
9922 return offs;
9925 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9927 DWORD size;
9929 size = sizeof(MSFT_TypeInfoBase);
9931 if(data){
9932 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9933 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9934 base->typekind = TKIND_DISPATCH;
9935 else
9936 base->typekind = info->typeattr.typekind;
9937 base->typekind |= index << 16; /* TODO: There are some other flags here */
9938 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9939 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9940 base->res2 = 0;
9941 base->res3 = 0;
9942 base->res4 = 3;
9943 base->res5 = 0;
9944 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9945 base->res7 = 0;
9946 base->res8 = 0;
9947 base->res9 = 0;
9948 base->resA = 0;
9949 if(info->guid)
9950 base->posguid = info->guid->offset;
9951 else
9952 base->posguid = -1;
9953 base->flags = info->typeattr.wTypeFlags;
9954 if(info->Name) {
9955 base->NameOffset = info->Name->offset;
9957 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9958 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9959 }else {
9960 base->NameOffset = -1;
9962 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9963 if(info->DocString)
9964 base->docstringoffs = info->DocString->offset;
9965 else
9966 base->docstringoffs = -1;
9967 base->helpstringcontext = info->dwHelpStringContext;
9968 base->helpcontext = info->dwHelpContext;
9969 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9970 base->cImplTypes = info->typeattr.cImplTypes;
9971 base->cbSizeVft = info->typeattr.cbSizeVft;
9972 base->size = info->typeattr.cbSizeInstance;
9973 if(info->typeattr.typekind == TKIND_COCLASS){
9974 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9975 }else if(info->typeattr.typekind == TKIND_ALIAS){
9976 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9977 }else if(info->typeattr.typekind == TKIND_MODULE){
9978 if(info->DllName)
9979 base->datatype1 = info->DllName->offset;
9980 else
9981 base->datatype1 = -1;
9982 }else{
9983 if(info->typeattr.cImplTypes > 0)
9984 base->datatype1 = info->impltypes[0].hRef;
9985 else
9986 base->datatype1 = -1;
9988 base->datatype2 = index; /* FIXME: i think there's more here */
9989 base->res18 = 0;
9990 base->res19 = -1;
9993 return size;
9996 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9998 UINT i;
10000 file->typeinfo_seg.len = 0;
10001 for(i = 0; i < This->TypeInfoCount; ++i){
10002 ITypeInfoImpl *info = This->typeinfos[i];
10003 *junk = file->typeinfo_seg.len;
10004 ++junk;
10005 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
10008 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
10009 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
10011 file->aux_seg.len = 0;
10012 file->aux_seg.data = NULL;
10014 file->typeinfo_seg.len = 0;
10015 for(i = 0; i < This->TypeInfoCount; ++i){
10016 ITypeInfoImpl *info = This->typeinfos[i];
10017 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
10018 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
10022 typedef struct tagWMSFT_ImpFile {
10023 INT guid_offs;
10024 LCID lcid;
10025 DWORD version;
10026 } WMSFT_ImpFile;
10028 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
10030 TLBImpLib *implib;
10031 WMSFT_ImpFile *impfile;
10032 char *data;
10033 DWORD last_offs = 0;
10035 file->impfile_seg.len = 0;
10036 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10037 int size = 0;
10039 if(implib->name){
10040 WCHAR *path = wcsrchr(implib->name, '\\');
10041 if(path)
10042 ++path;
10043 else
10044 path = implib->name;
10045 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10046 if (size == 0)
10047 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10050 size += sizeof(INT16);
10051 if (size % 4)
10052 size = (size + 4) & ~0x3;
10053 if (size < 8)
10054 size = 8;
10056 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10059 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
10061 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10062 int strlen = 0, size;
10064 impfile = (WMSFT_ImpFile*)data;
10065 impfile->guid_offs = implib->guid->offset;
10066 impfile->lcid = implib->lcid;
10067 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10069 data += sizeof(WMSFT_ImpFile);
10071 if(implib->name){
10072 WCHAR *path= wcsrchr(implib->name, '\\');
10073 if(path)
10074 ++path;
10075 else
10076 path = implib->name;
10077 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10078 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10079 if (strlen == 0)
10080 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10083 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10085 size = strlen + sizeof(INT16);
10086 if (size % 4)
10087 size = (size + 4) & ~0x3;
10088 if (size < 8)
10089 size = 8;
10090 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10092 data += size;
10093 implib->offset = last_offs;
10094 last_offs += size + sizeof(WMSFT_ImpFile);
10098 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10100 MSFT_ImpInfo *info;
10101 TLBRefType *ref_type;
10102 UINT i = 0;
10104 WMSFT_compile_impfile(This, file);
10106 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10107 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10109 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10110 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10111 if(ref_type->index == TLB_REF_USE_GUID){
10112 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10113 info->oGuid = ref_type->guid->offset;
10114 }else
10115 info->oGuid = ref_type->index;
10116 info->oImpFile = ref_type->pImpTLInfo->offset;
10117 ++i;
10118 ++info;
10122 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10124 file->guidhash_seg.len = 0x80;
10125 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10126 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10129 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10131 file->namehash_seg.len = 0x200;
10132 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10133 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10136 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10138 if(contents && contents->len){
10139 segdir->offset = *running_offset;
10140 segdir->length = contents->len;
10141 *running_offset += segdir->length;
10142 }else{
10143 segdir->offset = -1;
10144 segdir->length = 0;
10147 /* TODO: do these ever change? */
10148 segdir->res08 = -1;
10149 segdir->res0c = 0xf;
10152 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10154 DWORD written;
10155 if(segment)
10156 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10159 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10160 DWORD file_len)
10162 DWORD i;
10163 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10165 for(i = 0; i < This->TypeInfoCount; ++i){
10166 base->memoffset += file_len;
10167 ++base;
10170 return S_OK;
10173 static void WMSFT_free_file(WMSFT_TLBFile *file)
10175 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10176 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10177 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10178 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10179 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10180 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10181 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10182 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10183 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10184 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10185 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10186 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10187 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10188 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10191 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10193 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10194 WMSFT_TLBFile file;
10195 DWORD written, junk_size, junk_offs, running_offset;
10196 BOOL br;
10197 HANDLE outfile;
10198 HRESULT hres;
10199 DWORD *junk;
10200 UINT i;
10202 TRACE("%p\n", This);
10204 for(i = 0; i < This->TypeInfoCount; ++i)
10205 if(This->typeinfos[i]->needs_layout)
10206 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10208 memset(&file, 0, sizeof(file));
10210 file.header.magic1 = 0x5446534D;
10211 file.header.magic2 = 0x00010002;
10212 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10213 file.header.lcid2 = This->set_lcid;
10214 file.header.varflags = 0x40 | This->syskind;
10215 if (This->HelpFile)
10216 file.header.varflags |= 0x10;
10217 if (This->HelpStringDll)
10218 file.header.varflags |= HELPDLLFLAG;
10219 file.header.version = (This->ver_minor << 16) | This->ver_major;
10220 file.header.flags = This->libflags;
10221 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10222 file.header.helpcontext = This->dwHelpContext;
10223 file.header.res44 = 0x20;
10224 file.header.res48 = 0x80;
10225 file.header.dispatchpos = This->dispatch_href;
10227 WMSFT_compile_namehash(This, &file);
10228 /* do name and string compilation to get offsets for other compilations */
10229 hres = WMSFT_compile_names(This, &file);
10230 if (FAILED(hres)){
10231 WMSFT_free_file(&file);
10232 return hres;
10235 hres = WMSFT_compile_strings(This, &file);
10236 if (FAILED(hres)){
10237 WMSFT_free_file(&file);
10238 return hres;
10241 WMSFT_compile_guidhash(This, &file);
10242 hres = WMSFT_compile_guids(This, &file);
10243 if (FAILED(hres)){
10244 WMSFT_free_file(&file);
10245 return hres;
10248 if(This->HelpFile)
10249 file.header.helpfile = This->HelpFile->offset;
10250 else
10251 file.header.helpfile = -1;
10253 if(This->DocString)
10254 file.header.helpstring = This->DocString->offset;
10255 else
10256 file.header.helpstring = -1;
10258 /* do some more segment compilation */
10259 file.header.nimpinfos = list_count(&This->ref_list);
10260 file.header.nrtypeinfos = This->TypeInfoCount;
10262 if(This->Name)
10263 file.header.NameOffset = This->Name->offset;
10264 else
10265 file.header.NameOffset = -1;
10267 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10269 if(This->guid)
10270 file.header.posguid = This->guid->offset;
10271 else
10272 file.header.posguid = -1;
10274 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10275 if(file.header.varflags & HELPDLLFLAG)
10276 junk_size += sizeof(DWORD);
10277 if(junk_size){
10278 junk = heap_alloc_zero(junk_size);
10279 if(file.header.varflags & HELPDLLFLAG){
10280 *junk = This->HelpStringDll->offset;
10281 junk_offs = 1;
10282 }else
10283 junk_offs = 0;
10284 }else{
10285 junk = NULL;
10286 junk_offs = 0;
10289 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10290 WMSFT_compile_impinfo(This, &file);
10292 running_offset = 0;
10294 TRACE("header at: 0x%lx\n", running_offset);
10295 running_offset += sizeof(file.header);
10297 TRACE("junk at: 0x%lx\n", running_offset);
10298 running_offset += junk_size;
10300 TRACE("segdir at: 0x%lx\n", running_offset);
10301 running_offset += sizeof(file.segdir);
10303 TRACE("typeinfo at: 0x%lx\n", running_offset);
10304 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10306 TRACE("guidhashtab at: 0x%lx\n", running_offset);
10307 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10309 TRACE("guidtab at: 0x%lx\n", running_offset);
10310 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10312 TRACE("reftab at: 0x%lx\n", running_offset);
10313 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10315 TRACE("impinfo at: 0x%lx\n", running_offset);
10316 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10318 TRACE("impfiles at: 0x%lx\n", running_offset);
10319 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10321 TRACE("namehashtab at: 0x%lx\n", running_offset);
10322 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10324 TRACE("nametab at: 0x%lx\n", running_offset);
10325 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10327 TRACE("stringtab at: 0x%lx\n", running_offset);
10328 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10330 TRACE("typdesc at: 0x%lx\n", running_offset);
10331 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10333 TRACE("arraydescriptions at: 0x%lx\n", running_offset);
10334 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10336 TRACE("custdata at: 0x%lx\n", running_offset);
10337 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10339 TRACE("cdguids at: 0x%lx\n", running_offset);
10340 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10342 TRACE("res0e at: 0x%lx\n", running_offset);
10343 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10345 TRACE("res0f at: 0x%lx\n", running_offset);
10346 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10348 TRACE("aux_seg at: 0x%lx\n", running_offset);
10350 WMSFT_fixup_typeinfos(This, &file, running_offset);
10352 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10353 FILE_ATTRIBUTE_NORMAL, 0);
10354 if (outfile == INVALID_HANDLE_VALUE){
10355 WMSFT_free_file(&file);
10356 heap_free(junk);
10357 return TYPE_E_IOERROR;
10360 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10361 if (!br) {
10362 WMSFT_free_file(&file);
10363 CloseHandle(outfile);
10364 heap_free(junk);
10365 return TYPE_E_IOERROR;
10368 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10369 heap_free(junk);
10370 if (!br) {
10371 WMSFT_free_file(&file);
10372 CloseHandle(outfile);
10373 return TYPE_E_IOERROR;
10376 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10377 if (!br) {
10378 WMSFT_free_file(&file);
10379 CloseHandle(outfile);
10380 return TYPE_E_IOERROR;
10383 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10384 WMSFT_write_segment(outfile, &file.guidhash_seg);
10385 WMSFT_write_segment(outfile, &file.guid_seg);
10386 WMSFT_write_segment(outfile, &file.ref_seg);
10387 WMSFT_write_segment(outfile, &file.impinfo_seg);
10388 WMSFT_write_segment(outfile, &file.impfile_seg);
10389 WMSFT_write_segment(outfile, &file.namehash_seg);
10390 WMSFT_write_segment(outfile, &file.name_seg);
10391 WMSFT_write_segment(outfile, &file.string_seg);
10392 WMSFT_write_segment(outfile, &file.typdesc_seg);
10393 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10394 WMSFT_write_segment(outfile, &file.custdata_seg);
10395 WMSFT_write_segment(outfile, &file.cdguids_seg);
10396 WMSFT_write_segment(outfile, &file.aux_seg);
10398 WMSFT_free_file(&file);
10400 CloseHandle(outfile);
10402 return S_OK;
10405 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10406 LPOLESTR name)
10408 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10409 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10410 return E_NOTIMPL;
10413 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10414 REFGUID guid, VARIANT *varVal)
10416 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10417 TLBGuid *tlbguid;
10419 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10421 if (!guid || !varVal)
10422 return E_INVALIDARG;
10424 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10426 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10429 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10430 ULONG helpStringContext)
10432 FIXME("%p, %lu - stub\n", iface, helpStringContext);
10433 return E_NOTIMPL;
10436 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10437 LPOLESTR filename)
10439 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10440 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10442 if (!filename)
10443 return E_INVALIDARG;
10445 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10447 return S_OK;
10450 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10451 ICreateTypeLib2_fnQueryInterface,
10452 ICreateTypeLib2_fnAddRef,
10453 ICreateTypeLib2_fnRelease,
10454 ICreateTypeLib2_fnCreateTypeInfo,
10455 ICreateTypeLib2_fnSetName,
10456 ICreateTypeLib2_fnSetVersion,
10457 ICreateTypeLib2_fnSetGuid,
10458 ICreateTypeLib2_fnSetDocString,
10459 ICreateTypeLib2_fnSetHelpFileName,
10460 ICreateTypeLib2_fnSetHelpContext,
10461 ICreateTypeLib2_fnSetLcid,
10462 ICreateTypeLib2_fnSetLibFlags,
10463 ICreateTypeLib2_fnSaveAllChanges,
10464 ICreateTypeLib2_fnDeleteTypeInfo,
10465 ICreateTypeLib2_fnSetCustData,
10466 ICreateTypeLib2_fnSetHelpStringContext,
10467 ICreateTypeLib2_fnSetHelpStringDll
10470 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10471 REFIID riid, void **object)
10473 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10475 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10478 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10480 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10482 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10485 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10487 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10489 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10492 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10493 REFGUID guid)
10495 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10497 TRACE("%p %s\n", This, debugstr_guid(guid));
10499 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10501 return S_OK;
10504 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10505 UINT typeFlags)
10507 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10508 WORD old_flags;
10509 HRESULT hres;
10511 TRACE("%p %x\n", This, typeFlags);
10513 if (typeFlags & TYPEFLAG_FDUAL) {
10514 ITypeLib *stdole;
10515 ITypeInfo *dispatch;
10516 HREFTYPE hreftype;
10517 HRESULT hres;
10519 hres = LoadTypeLib(L"stdole2.tlb", &stdole);
10520 if(FAILED(hres))
10521 return hres;
10523 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10524 ITypeLib_Release(stdole);
10525 if(FAILED(hres))
10526 return hres;
10528 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10529 ITypeInfo_Release(dispatch);
10530 if(FAILED(hres))
10531 return hres;
10534 old_flags = This->typeattr.wTypeFlags;
10535 This->typeattr.wTypeFlags = typeFlags;
10537 hres = ICreateTypeInfo2_LayOut(iface);
10538 if (FAILED(hres)) {
10539 This->typeattr.wTypeFlags = old_flags;
10540 return hres;
10543 return S_OK;
10546 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10547 LPOLESTR doc)
10549 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10551 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10553 if (!doc)
10554 return E_INVALIDARG;
10556 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10558 return S_OK;
10561 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10562 DWORD helpContext)
10564 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10566 TRACE("%p, %ld.\n", iface, helpContext);
10568 This->dwHelpContext = helpContext;
10570 return S_OK;
10573 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10574 WORD majorVerNum, WORD minorVerNum)
10576 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10578 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10580 This->typeattr.wMajorVerNum = majorVerNum;
10581 This->typeattr.wMinorVerNum = minorVerNum;
10583 return S_OK;
10586 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10587 ITypeInfo *typeInfo, HREFTYPE *refType)
10589 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10590 UINT index;
10591 ITypeLib *container;
10592 TLBRefType *ref_type;
10593 TLBImpLib *implib;
10594 TYPEATTR *typeattr;
10595 TLIBATTR *libattr;
10596 HRESULT hres;
10598 TRACE("%p %p %p\n", This, typeInfo, refType);
10600 if (!typeInfo || !refType)
10601 return E_INVALIDARG;
10603 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10604 if (FAILED(hres))
10605 return hres;
10607 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10608 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10610 ITypeLib_Release(container);
10612 *refType = target->hreftype;
10614 return S_OK;
10617 hres = ITypeLib_GetLibAttr(container, &libattr);
10618 if (FAILED(hres)) {
10619 ITypeLib_Release(container);
10620 return hres;
10623 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10624 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10625 implib->lcid == libattr->lcid &&
10626 implib->wVersionMajor == libattr->wMajorVerNum &&
10627 implib->wVersionMinor == libattr->wMinorVerNum)
10628 break;
10631 if(&implib->entry == &This->pTypeLib->implib_list){
10632 implib = heap_alloc_zero(sizeof(TLBImpLib));
10634 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10635 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10636 implib->name = SysAllocString(our_container->path);
10637 }else{
10638 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10639 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10640 if(FAILED(hres)){
10641 implib->name = NULL;
10642 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres);
10646 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10647 implib->lcid = libattr->lcid;
10648 implib->wVersionMajor = libattr->wMajorVerNum;
10649 implib->wVersionMinor = libattr->wMinorVerNum;
10651 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10654 ITypeLib_ReleaseTLibAttr(container, libattr);
10655 ITypeLib_Release(container);
10657 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10658 if (FAILED(hres))
10659 return hres;
10661 index = 0;
10662 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10663 if(ref_type->index == TLB_REF_USE_GUID &&
10664 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10665 ref_type->tkind == typeattr->typekind)
10666 break;
10667 ++index;
10670 if(&ref_type->entry == &This->pTypeLib->ref_list){
10671 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10673 ref_type->tkind = typeattr->typekind;
10674 ref_type->pImpTLInfo = implib;
10675 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10677 ref_type->index = TLB_REF_USE_GUID;
10679 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10681 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10684 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10686 *refType = ref_type->reference | 0x1;
10688 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10689 This->pTypeLib->dispatch_href = *refType;
10691 return S_OK;
10694 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10695 UINT index, FUNCDESC *funcDesc)
10697 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10698 TLBFuncDesc tmp_func_desc, *func_desc;
10699 int buf_size, i;
10700 char *buffer;
10701 HRESULT hres;
10703 TRACE("%p %u %p\n", This, index, funcDesc);
10705 if (!funcDesc || funcDesc->oVft & 3)
10706 return E_INVALIDARG;
10708 switch (This->typeattr.typekind) {
10709 case TKIND_MODULE:
10710 if (funcDesc->funckind != FUNC_STATIC)
10711 return TYPE_E_BADMODULEKIND;
10712 break;
10713 case TKIND_DISPATCH:
10714 if (funcDesc->funckind != FUNC_DISPATCH)
10715 return TYPE_E_BADMODULEKIND;
10716 break;
10717 default:
10718 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10719 return TYPE_E_BADMODULEKIND;
10722 if (index > This->typeattr.cFuncs)
10723 return TYPE_E_ELEMENTNOTFOUND;
10725 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10726 !funcDesc->cParams)
10727 return TYPE_E_INCONSISTENTPROPFUNCS;
10729 #ifdef _WIN64
10730 if(This->pTypeLib->syskind == SYS_WIN64 &&
10731 funcDesc->oVft % 8 != 0)
10732 return E_INVALIDARG;
10733 #endif
10735 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10736 TLBFuncDesc_Constructor(&tmp_func_desc);
10738 tmp_func_desc.funcdesc = *funcDesc;
10740 if (tmp_func_desc.funcdesc.oVft != 0)
10741 tmp_func_desc.funcdesc.oVft |= 1;
10743 if (funcDesc->cScodes && funcDesc->lprgscode) {
10744 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10745 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10746 } else {
10747 tmp_func_desc.funcdesc.lprgscode = NULL;
10748 tmp_func_desc.funcdesc.cScodes = 0;
10751 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10752 for (i = 0; i < funcDesc->cParams; ++i) {
10753 buf_size += sizeof(ELEMDESC);
10754 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10756 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10757 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10759 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10760 if (FAILED(hres)) {
10761 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10762 heap_free(tmp_func_desc.funcdesc.lprgscode);
10763 return hres;
10766 for (i = 0; i < funcDesc->cParams; ++i) {
10767 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10768 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10769 if (FAILED(hres)) {
10770 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10771 heap_free(tmp_func_desc.funcdesc.lprgscode);
10772 return hres;
10774 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10775 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10776 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10777 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10778 if (FAILED(hres)) {
10779 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10780 heap_free(tmp_func_desc.funcdesc.lprgscode);
10781 return hres;
10786 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10788 if (This->funcdescs) {
10789 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10790 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10792 if (index < This->typeattr.cFuncs) {
10793 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10794 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10795 func_desc = This->funcdescs + index;
10796 } else
10797 func_desc = This->funcdescs + This->typeattr.cFuncs;
10799 /* move custdata lists to the new memory location */
10800 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10801 if(index != i)
10802 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10804 } else
10805 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10807 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10808 list_init(&func_desc->custdata_list);
10810 ++This->typeattr.cFuncs;
10812 This->needs_layout = TRUE;
10814 return S_OK;
10817 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10818 UINT index, HREFTYPE refType)
10820 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10821 TLBImplType *impl_type;
10822 HRESULT hres;
10824 TRACE("%p, %u, %ld.\n", iface, index, refType);
10826 switch(This->typeattr.typekind){
10827 case TKIND_COCLASS: {
10828 if (index == -1) {
10829 FIXME("Unhandled index: -1\n");
10830 return E_NOTIMPL;
10833 if(index != This->typeattr.cImplTypes)
10834 return TYPE_E_ELEMENTNOTFOUND;
10836 break;
10838 case TKIND_INTERFACE:
10839 case TKIND_DISPATCH:
10840 if (index != 0 || This->typeattr.cImplTypes)
10841 return TYPE_E_ELEMENTNOTFOUND;
10842 break;
10843 default:
10844 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10845 return E_NOTIMPL;
10848 if (This->impltypes){
10849 UINT i;
10851 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10852 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10854 if (index < This->typeattr.cImplTypes) {
10855 memmove(This->impltypes + index + 1, This->impltypes + index,
10856 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10857 impl_type = This->impltypes + index;
10858 } else
10859 impl_type = This->impltypes + This->typeattr.cImplTypes;
10861 /* move custdata lists to the new memory location */
10862 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10863 if(index != i)
10864 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10866 } else
10867 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10869 memset(impl_type, 0, sizeof(TLBImplType));
10870 TLBImplType_Constructor(impl_type);
10871 impl_type->hRef = refType;
10873 ++This->typeattr.cImplTypes;
10875 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10876 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10878 hres = ICreateTypeInfo2_LayOut(iface);
10879 if (FAILED(hres))
10880 return hres;
10882 return S_OK;
10885 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10886 UINT index, INT implTypeFlags)
10888 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10889 TLBImplType *impl_type = &This->impltypes[index];
10891 TRACE("%p %u %x\n", This, index, implTypeFlags);
10893 if (This->typeattr.typekind != TKIND_COCLASS)
10894 return TYPE_E_BADMODULEKIND;
10896 if (index >= This->typeattr.cImplTypes)
10897 return TYPE_E_ELEMENTNOTFOUND;
10899 impl_type->implflags = implTypeFlags;
10901 return S_OK;
10904 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10905 WORD alignment)
10907 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10909 TRACE("%p %d\n", This, alignment);
10911 This->typeattr.cbAlignment = alignment;
10913 return S_OK;
10916 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10917 LPOLESTR schema)
10919 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10921 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10923 if (!schema)
10924 return E_INVALIDARG;
10926 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10928 This->typeattr.lpstrSchema = This->Schema->str;
10930 return S_OK;
10933 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10934 UINT index, VARDESC *varDesc)
10936 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10937 TLBVarDesc *var_desc;
10938 HRESULT hr;
10940 TRACE("%p %u %p\n", This, index, varDesc);
10942 if (This->vardescs){
10943 UINT i;
10945 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10946 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10948 if (index < This->typeattr.cVars) {
10949 memmove(This->vardescs + index + 1, This->vardescs + index,
10950 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10951 var_desc = This->vardescs + index;
10952 } else
10953 var_desc = This->vardescs + This->typeattr.cVars;
10955 /* move custdata lists to the new memory location */
10956 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10957 if(index != i)
10958 TLB_relink_custdata(&This->vardescs[i].custdata_list);
10960 } else
10961 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10963 TLBVarDesc_Constructor(var_desc);
10964 hr = TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10965 if (FAILED(hr))
10966 return hr;
10967 var_desc->vardesc = *var_desc->vardesc_create;
10969 ++This->typeattr.cVars;
10971 This->needs_layout = TRUE;
10973 return S_OK;
10976 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10977 UINT index, LPOLESTR *names, UINT numNames)
10979 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10980 TLBFuncDesc *func_desc = &This->funcdescs[index];
10981 int i;
10983 TRACE("%p %u %p %u\n", This, index, names, numNames);
10985 if (!names)
10986 return E_INVALIDARG;
10988 if (index >= This->typeattr.cFuncs || numNames == 0)
10989 return TYPE_E_ELEMENTNOTFOUND;
10991 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10992 if(numNames > func_desc->funcdesc.cParams)
10993 return TYPE_E_ELEMENTNOTFOUND;
10994 } else
10995 if(numNames > func_desc->funcdesc.cParams + 1)
10996 return TYPE_E_ELEMENTNOTFOUND;
10998 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10999 TLBFuncDesc *iter = &This->funcdescs[i];
11000 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
11001 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11002 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11003 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
11004 continue;
11005 return TYPE_E_AMBIGUOUSNAME;
11009 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
11011 for (i = 1; i < numNames; ++i) {
11012 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
11013 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
11016 return S_OK;
11019 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
11020 UINT index, LPOLESTR name)
11022 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11024 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
11026 if(!name)
11027 return E_INVALIDARG;
11029 if(index >= This->typeattr.cVars)
11030 return TYPE_E_ELEMENTNOTFOUND;
11032 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
11033 return S_OK;
11036 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
11037 TYPEDESC *tdescAlias)
11039 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11040 HRESULT hr;
11042 TRACE("%p %p\n", This, tdescAlias);
11044 if(!tdescAlias)
11045 return E_INVALIDARG;
11047 if(This->typeattr.typekind != TKIND_ALIAS)
11048 return TYPE_E_BADMODULEKIND;
11050 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11051 if(FAILED(hr))
11052 return hr;
11054 heap_free(This->tdescAlias);
11055 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11056 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11058 return S_OK;
11061 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11062 UINT index, LPOLESTR dllName, LPOLESTR procName)
11064 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11065 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11066 return E_NOTIMPL;
11069 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11070 UINT index, LPOLESTR docString)
11072 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11073 TLBFuncDesc *func_desc = &This->funcdescs[index];
11075 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11077 if(!docString)
11078 return E_INVALIDARG;
11080 if(index >= This->typeattr.cFuncs)
11081 return TYPE_E_ELEMENTNOTFOUND;
11083 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11085 return S_OK;
11088 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11089 UINT index, LPOLESTR docString)
11091 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11092 TLBVarDesc *var_desc = &This->vardescs[index];
11094 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11096 if(!docString)
11097 return E_INVALIDARG;
11099 if(index >= This->typeattr.cVars)
11100 return TYPE_E_ELEMENTNOTFOUND;
11102 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11104 return S_OK;
11107 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11108 UINT index, DWORD helpContext)
11110 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11111 TLBFuncDesc *func_desc = &This->funcdescs[index];
11113 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
11115 if(index >= This->typeattr.cFuncs)
11116 return TYPE_E_ELEMENTNOTFOUND;
11118 func_desc->helpcontext = helpContext;
11120 return S_OK;
11123 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11124 UINT index, DWORD helpContext)
11126 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11127 TLBVarDesc *var_desc = &This->vardescs[index];
11129 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
11131 if(index >= This->typeattr.cVars)
11132 return TYPE_E_ELEMENTNOTFOUND;
11134 var_desc->HelpContext = helpContext;
11136 return S_OK;
11139 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11140 UINT index, BSTR bstrMops)
11142 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11143 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11144 return E_NOTIMPL;
11147 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11148 IDLDESC *idlDesc)
11150 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11152 TRACE("%p %p\n", This, idlDesc);
11154 if (!idlDesc)
11155 return E_INVALIDARG;
11157 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11158 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11160 return S_OK;
11163 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11165 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11166 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11167 TLBFuncDesc *func_desc;
11168 UINT user_vft = 0, i, depth = 0;
11169 HRESULT hres = S_OK;
11171 TRACE("%p\n", This);
11173 This->needs_layout = FALSE;
11175 if (This->typeattr.typekind == TKIND_INTERFACE) {
11176 ITypeInfo *inh;
11177 TYPEATTR *attr;
11178 HREFTYPE inh_href;
11180 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11182 if (SUCCEEDED(hres)) {
11183 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11185 if (SUCCEEDED(hres)) {
11186 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11187 if (FAILED(hres)) {
11188 ITypeInfo_Release(inh);
11189 return hres;
11191 This->typeattr.cbSizeVft = attr->cbSizeVft;
11192 ITypeInfo_ReleaseTypeAttr(inh, attr);
11195 ++depth;
11196 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11197 if(SUCCEEDED(hres)){
11198 ITypeInfo *next;
11199 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11200 if(SUCCEEDED(hres)){
11201 ITypeInfo_Release(inh);
11202 inh = next;
11205 }while(SUCCEEDED(hres));
11206 hres = S_OK;
11208 ITypeInfo_Release(inh);
11209 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11210 This->typeattr.cbSizeVft = 0;
11211 hres = S_OK;
11212 } else
11213 return hres;
11214 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11215 This->typeattr.cbSizeVft = 0;
11216 hres = S_OK;
11217 } else
11218 return hres;
11219 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11220 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11221 else
11222 This->typeattr.cbSizeVft = 0;
11224 func_desc = This->funcdescs;
11225 i = 0;
11226 while (i < This->typeattr.cFuncs) {
11227 if (!(func_desc->funcdesc.oVft & 0x1))
11228 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11230 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11231 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11233 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11235 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11236 TLBFuncDesc *iter;
11237 UINT j = 0;
11238 BOOL reset = FALSE;
11240 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11242 iter = This->funcdescs;
11243 while (j < This->typeattr.cFuncs) {
11244 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11245 if (!reset) {
11246 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11247 reset = TRUE;
11248 } else
11249 ++func_desc->funcdesc.memid;
11250 iter = This->funcdescs;
11251 j = 0;
11252 } else {
11253 ++iter;
11254 ++j;
11259 ++func_desc;
11260 ++i;
11263 if (user_vft > This->typeattr.cbSizeVft)
11264 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11266 for(i = 0; i < This->typeattr.cVars; ++i){
11267 TLBVarDesc *var_desc = &This->vardescs[i];
11268 if(var_desc->vardesc.memid == MEMBERID_NIL){
11269 UINT j = 0;
11270 BOOL reset = FALSE;
11271 TLBVarDesc *iter;
11273 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11275 iter = This->vardescs;
11276 while (j < This->typeattr.cVars) {
11277 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11278 if (!reset) {
11279 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11280 reset = TRUE;
11281 } else
11282 ++var_desc->vardesc.memid;
11283 iter = This->vardescs;
11284 j = 0;
11285 } else {
11286 ++iter;
11287 ++j;
11293 return hres;
11296 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11297 UINT index)
11299 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11300 unsigned int i;
11302 TRACE("%p %u\n", This, index);
11304 if (index >= This->typeattr.cFuncs)
11305 return TYPE_E_ELEMENTNOTFOUND;
11307 typeinfo_release_funcdesc(&This->funcdescs[index]);
11309 --This->typeattr.cFuncs;
11310 if (index != This->typeattr.cFuncs)
11312 memmove(This->funcdescs + index, This->funcdescs + index + 1,
11313 sizeof(*This->funcdescs) * (This->typeattr.cFuncs - index));
11314 for (i = index; i < This->typeattr.cFuncs; ++i)
11315 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
11318 This->needs_layout = TRUE;
11320 return S_OK;
11323 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11324 MEMBERID memid, INVOKEKIND invKind)
11326 FIXME("%p, %#lx, %d - stub\n", iface, memid, invKind);
11327 return E_NOTIMPL;
11330 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11331 UINT index)
11333 FIXME("%p, %u - stub\n", iface, index);
11334 return E_NOTIMPL;
11337 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11338 MEMBERID memid)
11340 FIXME("%p, %#lx - stub\n", iface, memid);
11341 return E_NOTIMPL;
11344 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11345 UINT index)
11347 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11348 int i;
11350 TRACE("%p %u\n", This, index);
11352 if (index >= This->typeattr.cImplTypes)
11353 return TYPE_E_ELEMENTNOTFOUND;
11355 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11356 --This->typeattr.cImplTypes;
11358 if (index < This->typeattr.cImplTypes)
11360 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11361 sizeof(*This->impltypes));
11362 for (i = index; i < This->typeattr.cImplTypes; ++i)
11363 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11366 return S_OK;
11369 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11370 REFGUID guid, VARIANT *varVal)
11372 TLBGuid *tlbguid;
11374 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11376 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11378 if (!guid || !varVal)
11379 return E_INVALIDARG;
11381 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11383 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11386 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11387 UINT index, REFGUID guid, VARIANT *varVal)
11389 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11390 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11391 return E_NOTIMPL;
11394 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11395 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11397 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11398 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11399 return E_NOTIMPL;
11402 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11403 UINT index, REFGUID guid, VARIANT *varVal)
11405 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11406 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11407 return E_NOTIMPL;
11410 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11411 UINT index, REFGUID guid, VARIANT *varVal)
11413 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11414 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11415 return E_NOTIMPL;
11418 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11419 ULONG helpStringContext)
11421 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11423 TRACE("%p, %lu.\n", iface, helpStringContext);
11425 This->dwHelpStringContext = helpStringContext;
11427 return S_OK;
11430 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11431 UINT index, ULONG helpStringContext)
11433 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11434 return E_NOTIMPL;
11437 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11438 UINT index, ULONG helpStringContext)
11440 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11441 return E_NOTIMPL;
11444 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11446 FIXME("%p - stub\n", iface);
11447 return E_NOTIMPL;
11450 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11451 LPOLESTR name)
11453 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11455 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11457 if (!name)
11458 return E_INVALIDARG;
11460 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11462 return S_OK;
11465 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11466 ICreateTypeInfo2_fnQueryInterface,
11467 ICreateTypeInfo2_fnAddRef,
11468 ICreateTypeInfo2_fnRelease,
11469 ICreateTypeInfo2_fnSetGuid,
11470 ICreateTypeInfo2_fnSetTypeFlags,
11471 ICreateTypeInfo2_fnSetDocString,
11472 ICreateTypeInfo2_fnSetHelpContext,
11473 ICreateTypeInfo2_fnSetVersion,
11474 ICreateTypeInfo2_fnAddRefTypeInfo,
11475 ICreateTypeInfo2_fnAddFuncDesc,
11476 ICreateTypeInfo2_fnAddImplType,
11477 ICreateTypeInfo2_fnSetImplTypeFlags,
11478 ICreateTypeInfo2_fnSetAlignment,
11479 ICreateTypeInfo2_fnSetSchema,
11480 ICreateTypeInfo2_fnAddVarDesc,
11481 ICreateTypeInfo2_fnSetFuncAndParamNames,
11482 ICreateTypeInfo2_fnSetVarName,
11483 ICreateTypeInfo2_fnSetTypeDescAlias,
11484 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11485 ICreateTypeInfo2_fnSetFuncDocString,
11486 ICreateTypeInfo2_fnSetVarDocString,
11487 ICreateTypeInfo2_fnSetFuncHelpContext,
11488 ICreateTypeInfo2_fnSetVarHelpContext,
11489 ICreateTypeInfo2_fnSetMops,
11490 ICreateTypeInfo2_fnSetTypeIdldesc,
11491 ICreateTypeInfo2_fnLayOut,
11492 ICreateTypeInfo2_fnDeleteFuncDesc,
11493 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11494 ICreateTypeInfo2_fnDeleteVarDesc,
11495 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11496 ICreateTypeInfo2_fnDeleteImplType,
11497 ICreateTypeInfo2_fnSetCustData,
11498 ICreateTypeInfo2_fnSetFuncCustData,
11499 ICreateTypeInfo2_fnSetParamCustData,
11500 ICreateTypeInfo2_fnSetVarCustData,
11501 ICreateTypeInfo2_fnSetImplTypeCustData,
11502 ICreateTypeInfo2_fnSetHelpStringContext,
11503 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11504 ICreateTypeInfo2_fnSetVarHelpStringContext,
11505 ICreateTypeInfo2_fnInvalidate,
11506 ICreateTypeInfo2_fnSetName
11509 /******************************************************************************
11510 * ClearCustData (OLEAUT32.171)
11512 * Clear a custom data type's data.
11514 * PARAMS
11515 * lpCust [I] The custom data type instance
11517 * RETURNS
11518 * Nothing.
11520 void WINAPI ClearCustData(CUSTDATA *lpCust)
11522 if (lpCust && lpCust->cCustData)
11524 if (lpCust->prgCustData)
11526 DWORD i;
11528 for (i = 0; i < lpCust->cCustData; i++)
11529 VariantClear(&lpCust->prgCustData[i].varValue);
11531 CoTaskMemFree(lpCust->prgCustData);
11532 lpCust->prgCustData = NULL;
11534 lpCust->cCustData = 0;