Remove unused NONAMELESS defines.
[wine.git] / dlls / oleaut32 / typelib.c
blobdc354184d36800904a7816cf4e2939d0d4376792
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 #include "winerror.h"
58 #include "windef.h"
59 #include "winbase.h"
60 #include "winnls.h"
61 #include "winreg.h"
62 #include "winuser.h"
63 #include "winternl.h"
64 #include "lzexpand.h"
66 #include "objbase.h"
67 #include "typelib.h"
68 #include "wine/debug.h"
69 #include "variant.h"
70 #include "wine/asm.h"
71 #include "wine/heap.h"
72 #include "wine/list.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(ole);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib);
77 typedef struct
79 WORD offset;
80 WORD length;
81 WORD flags;
82 WORD id;
83 WORD handle;
84 WORD usage;
85 } NE_NAMEINFO;
87 typedef struct
89 WORD type_id; /* Type identifier */
90 WORD count; /* Number of resources of this type */
91 DWORD resloader; /* SetResourceHandler() */
93 * Name info array.
95 } NE_TYPEINFO;
97 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
98 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
99 static void TLB_FreeVarDesc(VARDESC*);
101 /****************************************************************************
102 * FromLExxx
104 * Takes p_iVal (which is in little endian) and returns it
105 * in the host machine's byte order.
107 #ifdef WORDS_BIGENDIAN
108 static WORD FromLEWord(WORD p_iVal)
110 return (((p_iVal & 0x00FF) << 8) |
111 ((p_iVal & 0xFF00) >> 8));
115 static DWORD FromLEDWord(DWORD p_iVal)
117 return (((p_iVal & 0x000000FF) << 24) |
118 ((p_iVal & 0x0000FF00) << 8) |
119 ((p_iVal & 0x00FF0000) >> 8) |
120 ((p_iVal & 0xFF000000) >> 24));
122 #else
123 #define FromLEWord(X) (X)
124 #define FromLEDWord(X) (X)
125 #endif
127 #define DISPATCH_HREF_OFFSET 0x01000000
128 #define DISPATCH_HREF_MASK 0xff000000
130 /****************************************************************************
131 * FromLExxx
133 * Fix byte order in any structure if necessary
135 #ifdef WORDS_BIGENDIAN
136 static void FromLEWords(void *p_Val, int p_iSize)
138 WORD *Val = p_Val;
140 p_iSize /= sizeof(WORD);
142 while (p_iSize) {
143 *Val = FromLEWord(*Val);
144 Val++;
145 p_iSize--;
150 static void FromLEDWords(void *p_Val, int p_iSize)
152 DWORD *Val = p_Val;
154 p_iSize /= sizeof(DWORD);
156 while (p_iSize) {
157 *Val = FromLEDWord(*Val);
158 Val++;
159 p_iSize--;
162 #else
163 #define FromLEWords(X,Y) /*nothing*/
164 #define FromLEDWords(X,Y) /*nothing*/
165 #endif
168 * Find a typelib key which matches a requested maj.min version.
170 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
172 WCHAR buffer[60];
173 char key_name[16];
174 DWORD len, i;
175 INT best_maj = -1, best_min = -1;
176 HKEY hkey;
178 lstrcpyW( buffer, L"Typelib\\" );
179 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
181 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
182 return FALSE;
184 len = sizeof(key_name);
185 i = 0;
186 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
188 INT v_maj, v_min;
190 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
192 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
194 if (*wMaj == 0xffff && *wMin == 0xffff)
196 if (v_maj > best_maj) best_maj = v_maj;
197 if (v_min > best_min) best_min = v_min;
199 else if (*wMaj == v_maj)
201 best_maj = v_maj;
203 if (*wMin == v_min)
205 best_min = v_min;
206 break; /* exact match */
208 if (*wMin != 0xffff && v_min >= *wMin && v_min > best_min) best_min = v_min;
211 len = sizeof(key_name);
213 RegCloseKey( hkey );
215 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
217 if (*wMaj == 0xffff && *wMin == 0xffff)
219 if (best_maj >= 0 && best_min >= 0)
221 *wMaj = best_maj;
222 *wMin = best_min;
223 return TRUE;
227 if (*wMaj == best_maj && best_min >= 0)
229 *wMin = best_min;
230 return TRUE;
232 return FALSE;
235 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
236 /* buffer must be at least 60 characters long */
237 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
239 lstrcpyW( buffer, L"Typelib\\" );
240 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
241 swprintf( buffer + lstrlenW(buffer), 20, L"\\%x.%x", wMaj, wMin );
242 return buffer;
245 /* get the path of an interface key, in the form "Interface\\<guid>" */
246 /* buffer must be at least 50 characters long */
247 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
249 lstrcpyW( buffer, L"Interface\\" );
250 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
251 return buffer;
254 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
255 /* buffer must be at least 16 characters long */
256 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
258 swprintf( buffer, 16, L"%lx\\", lcid );
259 switch(syskind)
261 case SYS_WIN16: lstrcatW( buffer, L"win16" ); break;
262 case SYS_WIN32: lstrcatW( buffer, L"win32" ); break;
263 case SYS_WIN64: lstrcatW( buffer, L"win64" ); break;
264 default:
265 TRACE("Typelib is for unsupported syskind %i\n", syskind);
266 return NULL;
268 return buffer;
271 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
273 struct tlibredirect_data
275 ULONG size;
276 DWORD res;
277 ULONG name_len;
278 ULONG name_offset;
279 LANGID langid;
280 WORD flags;
281 ULONG help_len;
282 ULONG help_offset;
283 WORD major_version;
284 WORD minor_version;
287 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
288 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
289 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
291 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
292 LCID myLCID = lcid;
293 HKEY hkey;
294 WCHAR buffer[60];
295 WCHAR Path[MAX_PATH];
296 LONG res;
298 TRACE_(typelib)("%s, %x.%x, %#lx, %p\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
300 if (redir)
302 ACTCTX_SECTION_KEYED_DATA data;
304 data.cbSize = sizeof(data);
305 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
307 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
308 WCHAR *nameW;
309 DWORD len;
311 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
312 return TYPE_E_LIBNOTREGISTERED;
314 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
315 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
316 if (!len) return TYPE_E_LIBNOTREGISTERED;
318 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
319 *path = SysAllocString( Path );
320 return S_OK;
324 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
325 get_typelib_key( guid, wMaj, wMin, buffer );
327 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
328 if (res == ERROR_FILE_NOT_FOUND)
330 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
331 return TYPE_E_LIBNOTREGISTERED;
333 else if (res != ERROR_SUCCESS)
335 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
336 return TYPE_E_REGISTRYACCESS;
339 while (hr != S_OK)
341 LONG dwPathLen = sizeof(Path);
343 get_lcid_subkey( myLCID, syskind, buffer );
345 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
347 if (!lcid)
348 break;
349 else if (myLCID == lcid)
351 /* try with sub-langid */
352 myLCID = SUBLANGID(lcid);
354 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
356 /* try with system langid */
357 myLCID = 0;
359 else
361 break;
364 else
366 *path = SysAllocString( Path );
367 hr = S_OK;
370 RegCloseKey( hkey );
371 TRACE_(typelib)("-- %#lx\n", hr);
372 return hr;
375 /****************************************************************************
376 * QueryPathOfRegTypeLib [OLEAUT32.164]
378 * Gets the path to a registered type library.
380 * PARAMS
381 * guid [I] referenced guid
382 * wMaj [I] major version
383 * wMin [I] minor version
384 * lcid [I] locale id
385 * path [O] path of typelib
387 * RETURNS
388 * Success: S_OK.
389 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
390 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
391 * opened.
393 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
395 BOOL redir = TRUE;
396 #ifdef _WIN64
397 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
398 if(SUCCEEDED(hres))
399 return hres;
400 redir = FALSE;
401 #endif
402 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
405 /******************************************************************************
406 * CreateTypeLib [OLEAUT32.160] creates a typelib
408 * RETURNS
409 * Success: S_OK
410 * Failure: Status
412 HRESULT WINAPI CreateTypeLib(
413 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
415 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
416 return E_FAIL;
419 /******************************************************************************
420 * LoadTypeLib [OLEAUT32.161]
422 * Loads a type library
424 * PARAMS
425 * szFile [I] Name of file to load from.
426 * pptLib [O] Pointer that receives ITypeLib object on success.
428 * RETURNS
429 * Success: S_OK
430 * Failure: Status
432 * SEE
433 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
435 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
437 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
438 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
441 /******************************************************************************
442 * LoadTypeLibEx [OLEAUT32.183]
444 * Loads and optionally registers a type library
446 * RETURNS
447 * Success: S_OK
448 * Failure: Status
450 HRESULT WINAPI LoadTypeLibEx(
451 LPCOLESTR szFile, /* [in] Name of file to load from */
452 REGKIND regkind, /* [in] Specify kind of registration */
453 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
455 WCHAR szPath[MAX_PATH+1];
456 HRESULT res;
458 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
460 if (!szFile || !pptLib)
461 return E_INVALIDARG;
463 *pptLib = NULL;
465 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
467 if (SUCCEEDED(res))
468 switch(regkind)
470 case REGKIND_DEFAULT:
471 /* don't register typelibs supplied with full path. Experimentation confirms the following */
472 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
473 (szFile[0] && (szFile[1] == ':'))) break;
474 /* else fall-through */
476 case REGKIND_REGISTER:
477 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
479 ITypeLib_Release(*pptLib);
480 *pptLib = 0;
482 break;
483 case REGKIND_NONE:
484 break;
487 TRACE(" returns %#lx\n",res);
488 return res;
491 /******************************************************************************
492 * LoadRegTypeLib [OLEAUT32.162]
494 * Loads a registered type library.
496 * PARAMS
497 * rguid [I] GUID of the registered type library.
498 * wVerMajor [I] major version.
499 * wVerMinor [I] minor version.
500 * lcid [I] locale ID.
501 * ppTLib [O] pointer that receives an ITypeLib object on success.
503 * RETURNS
504 * Success: S_OK.
505 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
506 * LoadTypeLib.
508 HRESULT WINAPI LoadRegTypeLib(
509 REFGUID rguid,
510 WORD wVerMajor,
511 WORD wVerMinor,
512 LCID lcid,
513 ITypeLib **ppTLib)
515 BSTR bstr=NULL;
516 HRESULT res;
518 *ppTLib = NULL;
520 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
522 if(SUCCEEDED(res))
524 res= LoadTypeLib(bstr, ppTLib);
525 SysFreeString(bstr);
527 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
529 TLIBATTR *attr;
531 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
532 if (res == S_OK)
534 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
535 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
537 if (mismatch)
539 ITypeLib_Release(*ppTLib);
540 *ppTLib = NULL;
541 res = TYPE_E_LIBNOTREGISTERED;
547 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
549 return res;
552 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
554 WCHAR keyName[60];
555 HKEY key, subKey;
557 get_interface_key( &tattr->guid, keyName );
558 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
559 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
561 const WCHAR *proxy_clsid;
563 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
564 proxy_clsid = L"{00020424-0000-0000-C000-000000000046}";
565 else
566 proxy_clsid = L"{00020420-0000-0000-C000-000000000046}";
568 if (name)
569 RegSetValueExW(key, NULL, 0, REG_SZ,
570 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR));
572 if (!RegCreateKeyExW(key, L"ProxyStubClsid", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
574 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
575 RegCloseKey(subKey);
578 if (!RegCreateKeyExW(key, L"ProxyStubClsid32", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
580 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
581 RegCloseKey(subKey);
584 if (RegCreateKeyExW(key, L"TypeLib", 0, NULL, 0,
585 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
587 WCHAR buffer[40];
589 StringFromGUID2(&libattr->guid, buffer, 40);
590 RegSetValueExW(subKey, NULL, 0, REG_SZ,
591 (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
592 swprintf(buffer, ARRAY_SIZE(buffer), L"%x.%x", libattr->wMajorVerNum, libattr->wMinorVerNum);
593 RegSetValueExW(subKey, L"Version", 0, REG_SZ, (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
594 RegCloseKey(subKey);
597 RegCloseKey(key);
601 /******************************************************************************
602 * RegisterTypeLib [OLEAUT32.163]
603 * Adds information about a type library to the System Registry
604 * NOTES
605 * Docs: ITypeLib FAR * ptlib
606 * Docs: OLECHAR FAR* szFullPath
607 * Docs: OLECHAR FAR* szHelpDir
609 * RETURNS
610 * Success: S_OK
611 * Failure: Status
613 HRESULT WINAPI RegisterTypeLib(ITypeLib *ptlib, const WCHAR *szFullPath, const WCHAR *szHelpDir)
615 HRESULT res;
616 TLIBATTR *attr;
617 WCHAR keyName[60];
618 WCHAR tmp[16];
619 HKEY key, subKey;
620 UINT types, tidx;
621 TYPEKIND kind;
622 DWORD disposition;
624 if (ptlib == NULL || szFullPath == NULL)
625 return E_INVALIDARG;
627 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
628 return E_FAIL;
630 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
632 res = S_OK;
633 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
634 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
636 LPOLESTR doc;
637 LPOLESTR libName;
639 /* Set the human-readable name of the typelib to
640 the typelib's doc, if it exists, else to the typelib's name. */
641 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, &libName, &doc, NULL, NULL)))
642 res = E_FAIL;
643 else if (doc || libName)
645 WCHAR *name = doc ? doc : libName;
647 if (RegSetValueExW(key, NULL, 0, REG_SZ,
648 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
649 res = E_FAIL;
651 SysFreeString(doc);
652 SysFreeString(libName);
655 /* Make up the name of the typelib path subkey */
656 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
658 /* Create the typelib path subkey */
659 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
660 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
662 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
663 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
664 res = E_FAIL;
666 RegCloseKey(subKey);
668 else
669 res = E_FAIL;
671 /* Create the flags subkey */
672 if (res == S_OK && RegCreateKeyExW(key, L"FLAGS", 0, NULL, 0,
673 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
675 WCHAR buf[20];
677 /* FIXME: is %u correct? */
678 swprintf(buf, ARRAY_SIZE(buf), L"%u", attr->wLibFlags);
679 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
680 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
681 res = E_FAIL;
683 RegCloseKey(subKey);
685 else
686 res = E_FAIL;
688 /* create the helpdir subkey */
689 if (res == S_OK && RegCreateKeyExW(key, L"HELPDIR", 0, NULL, 0,
690 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
692 BSTR freeHelpDir = NULL;
693 WCHAR *file_name;
695 /* if we created a new key, and helpDir was null, set the helpdir
696 to the directory which contains the typelib. However,
697 if we just opened an existing key, we leave the helpdir alone */
698 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
699 szHelpDir = freeHelpDir = SysAllocString(szFullPath);
700 file_name = wcsrchr(szHelpDir, '\\');
701 if (file_name && file_name[1]) {
702 /* possible remove a numeric \index (resource-id) */
703 WCHAR *end_ptr = file_name + 1;
704 while ('0' <= *end_ptr && *end_ptr <= '9') end_ptr++;
705 if (!*end_ptr)
707 *file_name = 0;
708 file_name = wcsrchr(szHelpDir, '\\');
711 if (file_name)
712 *file_name = 0;
715 /* if we have an szHelpDir, set it! */
716 if (szHelpDir != NULL) {
717 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
718 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
719 res = E_FAIL;
723 SysFreeString(freeHelpDir);
724 RegCloseKey(subKey);
725 } else {
726 res = E_FAIL;
729 RegCloseKey(key);
731 else
732 res = E_FAIL;
734 /* register OLE Automation-compatible interfaces for this typelib */
735 types = ITypeLib_GetTypeInfoCount(ptlib);
736 for (tidx=0; tidx<types; tidx++) {
737 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
738 LPOLESTR name = NULL;
739 ITypeInfo *tinfo = NULL;
741 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
743 switch (kind) {
744 case TKIND_INTERFACE:
745 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
746 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
747 break;
749 case TKIND_DISPATCH:
750 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
751 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
752 break;
754 default:
755 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
756 break;
759 if (tinfo) {
760 TYPEATTR *tattr = NULL;
761 ITypeInfo_GetTypeAttr(tinfo, &tattr);
763 if (tattr) {
764 TRACE_(typelib)("guid=%s, flags=%04x (",
765 debugstr_guid(&tattr->guid),
766 tattr->wTypeFlags);
768 if (TRACE_ON(typelib)) {
769 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
770 XX(FAPPOBJECT);
771 XX(FCANCREATE);
772 XX(FLICENSED);
773 XX(FPREDECLID);
774 XX(FHIDDEN);
775 XX(FCONTROL);
776 XX(FDUAL);
777 XX(FNONEXTENSIBLE);
778 XX(FOLEAUTOMATION);
779 XX(FRESTRICTED);
780 XX(FAGGREGATABLE);
781 XX(FREPLACEABLE);
782 XX(FDISPATCHABLE);
783 XX(FREVERSEBIND);
784 XX(FPROXY);
785 #undef XX
786 MESSAGE("\n");
789 /* Register all dispinterfaces (which includes dual interfaces) and
790 oleautomation interfaces */
791 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
792 kind == TKIND_DISPATCH)
794 BOOL is_wow64;
795 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
797 /* register interface<->typelib coupling */
798 TLB_register_interface(attr, name, tattr, 0);
800 /* register TLBs into the opposite registry view, too */
801 if(opposite == KEY_WOW64_32KEY ||
802 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
803 TLB_register_interface(attr, name, tattr, opposite);
806 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
809 ITypeInfo_Release(tinfo);
812 SysFreeString(name);
816 ITypeLib_ReleaseTLibAttr(ptlib, attr);
818 return res;
821 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
823 WCHAR subKeyName[50];
824 HKEY subKey;
826 /* the path to the type */
827 get_interface_key( guid, subKeyName );
829 /* Delete its bits */
830 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
831 return;
833 RegDeleteKeyW(subKey, L"ProxyStubClsid");
834 RegDeleteKeyW(subKey, L"ProxyStubClsid32");
835 RegDeleteKeyW(subKey, L"TypeLib");
836 RegCloseKey(subKey);
837 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
840 /******************************************************************************
841 * UnRegisterTypeLib [OLEAUT32.186]
842 * Removes information about a type library from the System Registry
843 * NOTES
845 * RETURNS
846 * Success: S_OK
847 * Failure: Status
849 HRESULT WINAPI UnRegisterTypeLib(
850 REFGUID libid, /* [in] Guid of the library */
851 WORD wVerMajor, /* [in] major version */
852 WORD wVerMinor, /* [in] minor version */
853 LCID lcid, /* [in] locale id */
854 SYSKIND syskind)
856 BSTR tlibPath = NULL;
857 DWORD tmpLength;
858 WCHAR keyName[60];
859 WCHAR subKeyName[50];
860 int result = S_OK;
861 DWORD i = 0;
862 BOOL deleteOtherStuff;
863 HKEY key = NULL;
864 TYPEATTR* typeAttr = NULL;
865 TYPEKIND kind;
866 ITypeInfo* typeInfo = NULL;
867 ITypeLib* typeLib = NULL;
868 int numTypes;
870 TRACE("(IID: %s)\n",debugstr_guid(libid));
872 /* Create the path to the key */
873 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
875 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
877 TRACE("Unsupported syskind %i\n", syskind);
878 result = E_INVALIDARG;
879 goto end;
882 /* get the path to the typelib on disk */
883 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
884 result = E_INVALIDARG;
885 goto end;
888 /* Try and open the key to the type library. */
889 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
890 result = E_INVALIDARG;
891 goto end;
894 /* Try and load the type library */
895 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
896 result = TYPE_E_INVALIDSTATE;
897 goto end;
900 /* remove any types registered with this typelib */
901 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
902 for (i=0; i<numTypes; i++) {
903 /* get the kind of type */
904 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
905 goto enddeleteloop;
908 /* skip non-interfaces, and get type info for the type */
909 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
910 goto enddeleteloop;
912 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
913 goto enddeleteloop;
915 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
916 goto enddeleteloop;
919 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
920 kind == TKIND_DISPATCH)
922 BOOL is_wow64;
923 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
925 TLB_unregister_interface(&typeAttr->guid, 0);
927 /* unregister TLBs into the opposite registry view, too */
928 if(opposite == KEY_WOW64_32KEY ||
929 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
930 TLB_unregister_interface(&typeAttr->guid, opposite);
934 enddeleteloop:
935 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
936 typeAttr = NULL;
937 if (typeInfo) ITypeInfo_Release(typeInfo);
938 typeInfo = NULL;
941 /* Now, delete the type library path subkey */
942 get_lcid_subkey( lcid, syskind, subKeyName );
943 RegDeleteKeyW(key, subKeyName);
944 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
945 RegDeleteKeyW(key, subKeyName);
947 /* check if there is anything besides the FLAGS/HELPDIR keys.
948 If there is, we don't delete them */
949 tmpLength = ARRAY_SIZE(subKeyName);
950 deleteOtherStuff = TRUE;
951 i = 0;
952 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
953 tmpLength = ARRAY_SIZE(subKeyName);
955 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
956 if (!wcscmp(subKeyName, L"FLAGS")) continue;
957 if (!wcscmp(subKeyName, L"HELPDIR")) continue;
958 deleteOtherStuff = FALSE;
959 break;
962 /* only delete the other parts of the key if we're absolutely sure */
963 if (deleteOtherStuff) {
964 RegDeleteKeyW(key, L"FLAGS");
965 RegDeleteKeyW(key, L"HELPDIR");
966 RegCloseKey(key);
967 key = NULL;
969 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
970 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
971 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
974 end:
975 SysFreeString(tlibPath);
976 if (typeLib) ITypeLib_Release(typeLib);
977 if (key) RegCloseKey(key);
978 return result;
981 /******************************************************************************
982 * RegisterTypeLibForUser [OLEAUT32.442]
983 * Adds information about a type library to the user registry
984 * NOTES
985 * Docs: ITypeLib FAR * ptlib
986 * Docs: OLECHAR FAR* szFullPath
987 * Docs: OLECHAR FAR* szHelpDir
989 * RETURNS
990 * Success: S_OK
991 * Failure: Status
993 HRESULT WINAPI RegisterTypeLibForUser(
994 ITypeLib * ptlib, /* [in] Pointer to the library*/
995 OLECHAR * szFullPath, /* [in] full Path of the library*/
996 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
997 may be NULL*/
999 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1000 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1001 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1004 /******************************************************************************
1005 * UnRegisterTypeLibForUser [OLEAUT32.443]
1006 * Removes information about a type library from the user registry
1008 * RETURNS
1009 * Success: S_OK
1010 * Failure: Status
1012 HRESULT WINAPI UnRegisterTypeLibForUser(
1013 REFGUID libid, /* [in] GUID of the library */
1014 WORD wVerMajor, /* [in] major version */
1015 WORD wVerMinor, /* [in] minor version */
1016 LCID lcid, /* [in] locale id */
1017 SYSKIND syskind)
1019 FIXME("%s, %u, %u, %#lx, %u unregistering the typelib system-wide\n",
1020 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1021 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1024 /*======================= ITypeLib implementation =======================*/
1026 typedef struct tagTLBGuid {
1027 GUID guid;
1028 INT hreftype;
1029 UINT offset;
1030 struct list entry;
1031 } TLBGuid;
1033 typedef struct tagTLBCustData
1035 TLBGuid *guid;
1036 VARIANT data;
1037 struct list entry;
1038 } TLBCustData;
1040 /* data structure for import typelibs */
1041 typedef struct tagTLBImpLib
1043 int offset; /* offset in the file (MSFT)
1044 offset in nametable (SLTG)
1045 just used to identify library while reading
1046 data from file */
1047 TLBGuid *guid; /* libid */
1048 BSTR name; /* name */
1050 LCID lcid; /* lcid of imported typelib */
1052 WORD wVersionMajor; /* major version number */
1053 WORD wVersionMinor; /* minor version number */
1055 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1056 NULL if not yet loaded */
1057 struct list entry;
1058 } TLBImpLib;
1060 typedef struct tagTLBString {
1061 BSTR str;
1062 UINT offset;
1063 struct list entry;
1064 } TLBString;
1066 /* internal ITypeLib data */
1067 typedef struct tagITypeLibImpl
1069 ITypeLib2 ITypeLib2_iface;
1070 ITypeComp ITypeComp_iface;
1071 ICreateTypeLib2 ICreateTypeLib2_iface;
1072 LONG ref;
1073 TLBGuid *guid;
1074 LCID lcid;
1075 SYSKIND syskind;
1076 int ptr_size;
1077 WORD ver_major;
1078 WORD ver_minor;
1079 WORD libflags;
1080 LCID set_lcid;
1082 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1083 * exported to the application as a UNICODE string.
1085 struct list string_list;
1086 struct list name_list;
1087 struct list guid_list;
1089 const TLBString *Name;
1090 const TLBString *DocString;
1091 const TLBString *HelpFile;
1092 const TLBString *HelpStringDll;
1093 DWORD dwHelpContext;
1094 int TypeInfoCount; /* nr of typeinfo's in librarry */
1095 struct tagITypeInfoImpl **typeinfos;
1096 struct list custdata_list;
1097 struct list implib_list;
1098 int ctTypeDesc; /* number of items in type desc array */
1099 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1100 library. Only used while reading MSFT
1101 typelibs */
1102 struct list ref_list; /* list of ref types in this typelib */
1103 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1106 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1107 struct list entry;
1108 WCHAR *path;
1109 INT index;
1110 } ITypeLibImpl;
1112 static const ITypeLib2Vtbl tlbvt;
1113 static const ITypeCompVtbl tlbtcvt;
1114 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1116 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1118 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1121 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1123 return impl_from_ITypeLib2((ITypeLib2*)iface);
1126 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1128 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1131 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1133 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1136 /* ITypeLib methods */
1137 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1138 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1140 /*======================= ITypeInfo implementation =======================*/
1142 /* data for referenced types */
1143 typedef struct tagTLBRefType
1145 INT index; /* Type index for internal ref or for external ref
1146 it the format is SLTG. -2 indicates to
1147 use guid */
1149 TYPEKIND tkind;
1150 TLBGuid *guid; /* guid of the referenced type */
1151 /* if index == TLB_REF_USE_GUID */
1153 HREFTYPE reference; /* The href of this ref */
1154 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1155 TLB_REF_INTERNAL for internal refs
1156 TLB_REF_NOT_FOUND for broken refs */
1158 struct list entry;
1159 } TLBRefType;
1161 #define TLB_REF_USE_GUID -2
1163 #define TLB_REF_INTERNAL (void*)-2
1164 #define TLB_REF_NOT_FOUND (void*)-1
1166 /* internal Parameter data */
1167 typedef struct tagTLBParDesc
1169 const TLBString *Name;
1170 struct list custdata_list;
1171 } TLBParDesc;
1173 /* internal Function data */
1174 typedef struct tagTLBFuncDesc
1176 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1177 const TLBString *Name; /* the name of this function */
1178 TLBParDesc *pParamDesc; /* array with param names and custom data */
1179 int helpcontext;
1180 int HelpStringContext;
1181 const TLBString *HelpString;
1182 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1183 struct list custdata_list;
1184 } TLBFuncDesc;
1186 /* internal Variable data */
1187 typedef struct tagTLBVarDesc
1189 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1190 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1191 const TLBString *Name; /* the name of this variable */
1192 int HelpContext;
1193 int HelpStringContext;
1194 const TLBString *HelpString;
1195 struct list custdata_list;
1196 } TLBVarDesc;
1198 /* internal implemented interface data */
1199 typedef struct tagTLBImplType
1201 HREFTYPE hRef; /* hRef of interface */
1202 int implflags; /* IMPLFLAG_*s */
1203 struct list custdata_list;
1204 } TLBImplType;
1206 /* internal TypeInfo data */
1207 typedef struct tagITypeInfoImpl
1209 ITypeInfo2 ITypeInfo2_iface;
1210 ITypeComp ITypeComp_iface;
1211 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1212 LONG ref;
1213 BOOL not_attached_to_typelib;
1214 BOOL needs_layout;
1216 TLBGuid *guid;
1217 TYPEATTR typeattr;
1218 TYPEDESC *tdescAlias;
1220 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1221 int index; /* index in this typelib; */
1222 HREFTYPE hreftype; /* hreftype for app object binding */
1223 /* type libs seem to store the doc strings in ascii
1224 * so why should we do it in unicode?
1226 const TLBString *Name;
1227 const TLBString *DocString;
1228 const TLBString *DllName;
1229 const TLBString *Schema;
1230 DWORD dwHelpContext;
1231 DWORD dwHelpStringContext;
1233 /* functions */
1234 TLBFuncDesc *funcdescs;
1236 /* variables */
1237 TLBVarDesc *vardescs;
1239 /* Implemented Interfaces */
1240 TLBImplType *impltypes;
1242 struct list *pcustdata_list;
1243 struct list custdata_list;
1244 } ITypeInfoImpl;
1246 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1248 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1251 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1253 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1256 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1258 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1261 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1263 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1266 static const ITypeInfo2Vtbl tinfvt;
1267 static const ITypeCompVtbl tcompvt;
1268 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1270 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1271 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1273 typedef struct tagTLBContext
1275 unsigned int oStart; /* start of TLB in file */
1276 unsigned int pos; /* current pos */
1277 unsigned int length; /* total length */
1278 void *mapping; /* memory mapping */
1279 MSFT_SegDir * pTblDir;
1280 ITypeLibImpl* pLibInfo;
1281 } TLBContext;
1284 static inline BSTR TLB_get_bstr(const TLBString *str)
1286 return str != NULL ? str->str : NULL;
1289 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1291 if(!str)
1292 return 1;
1293 return memcmp(left, str->str, len);
1296 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1298 return guid != NULL ? &guid->guid : NULL;
1301 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1303 return guid != NULL ? &guid->guid : &GUID_NULL;
1306 static int get_ptr_size(SYSKIND syskind)
1308 switch(syskind){
1309 case SYS_WIN64:
1310 return 8;
1311 case SYS_WIN32:
1312 case SYS_MAC:
1313 case SYS_WIN16:
1314 return 4;
1316 WARN("Unhandled syskind: 0x%x\n", syskind);
1317 return 4;
1321 debug
1323 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1324 if (pTD->vt & VT_RESERVED)
1325 szVarType += strlen(strcpy(szVarType, "reserved | "));
1326 if (pTD->vt & VT_BYREF)
1327 szVarType += strlen(strcpy(szVarType, "ref to "));
1328 if (pTD->vt & VT_ARRAY)
1329 szVarType += strlen(strcpy(szVarType, "array of "));
1330 if (pTD->vt & VT_VECTOR)
1331 szVarType += strlen(strcpy(szVarType, "vector of "));
1332 switch(pTD->vt & VT_TYPEMASK) {
1333 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1334 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1335 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1336 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1337 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1338 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1339 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1340 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1341 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1342 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1343 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1344 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1345 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1346 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1347 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1348 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1349 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1350 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1351 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1352 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1353 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx", pTD->hreftype); break;
1354 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1355 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1356 case VT_PTR: sprintf(szVarType, "ptr to ");
1357 dump_TypeDesc(pTD->lptdesc, szVarType + 7);
1358 break;
1359 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1360 dump_TypeDesc(pTD->lptdesc, szVarType + 13);
1361 break;
1362 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1363 pTD->lpadesc->cDims); /* FIXME print out sizes */
1364 dump_TypeDesc(&pTD->lpadesc->tdescElem, szVarType + strlen(szVarType));
1365 break;
1367 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1371 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1372 char buf[200];
1373 USHORT flags = edesc->paramdesc.wParamFlags;
1374 dump_TypeDesc(&edesc->tdesc,buf);
1375 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1376 MESSAGE("\t\tu.paramdesc.wParamFlags");
1377 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1378 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1379 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1380 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1381 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1382 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1383 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1384 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1385 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->paramdesc.pparamdescex);
1387 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1388 int i;
1389 MESSAGE("memid is %#lx\n", funcdesc->memid);
1390 for (i=0;i<funcdesc->cParams;i++) {
1391 MESSAGE("Param %d:\n",i);
1392 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1394 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1395 switch (funcdesc->funckind) {
1396 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1397 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1398 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1399 case FUNC_STATIC: MESSAGE("static");break;
1400 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1401 default: MESSAGE("unknown");break;
1403 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1404 switch (funcdesc->invkind) {
1405 case INVOKE_FUNC: MESSAGE("func");break;
1406 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1407 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1408 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1410 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1411 switch (funcdesc->callconv) {
1412 case CC_CDECL: MESSAGE("cdecl");break;
1413 case CC_PASCAL: MESSAGE("pascal");break;
1414 case CC_STDCALL: MESSAGE("stdcall");break;
1415 case CC_SYSCALL: MESSAGE("syscall");break;
1416 default:break;
1418 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1419 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1420 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1422 MESSAGE("\telemdescFunc (return value type):\n");
1423 dump_ELEMDESC(&funcdesc->elemdescFunc);
1426 static const char * const typekind_desc[] =
1428 "TKIND_ENUM",
1429 "TKIND_RECORD",
1430 "TKIND_MODULE",
1431 "TKIND_INTERFACE",
1432 "TKIND_DISPATCH",
1433 "TKIND_COCLASS",
1434 "TKIND_ALIAS",
1435 "TKIND_UNION",
1436 "TKIND_MAX"
1439 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1441 int i;
1442 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1443 for (i=0;i<pfd->funcdesc.cParams;i++)
1444 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1447 dump_FUNCDESC(&(pfd->funcdesc));
1449 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1450 if(pfd->Entry == NULL)
1451 MESSAGE("\tentry: (null)\n");
1452 else if(pfd->Entry == (void*)-1)
1453 MESSAGE("\tentry: invalid\n");
1454 else if(IS_INTRESOURCE(pfd->Entry))
1455 MESSAGE("\tentry: %p\n", pfd->Entry);
1456 else
1457 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1459 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1461 while (n)
1463 dump_TLBFuncDescOne(pfd);
1464 ++pfd;
1465 --n;
1468 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1470 while (n)
1472 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1473 ++pvd;
1474 --n;
1478 static void dump_TLBImpLib(const TLBImpLib *import)
1480 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1481 debugstr_w(import->name));
1482 TRACE_(typelib)("v%d.%d lcid %#lx offset=%x\n", import->wVersionMajor, import->wVersionMinor, import->lcid, import->offset);
1485 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1487 TLBRefType *ref;
1489 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1491 TRACE_(typelib)("href:%#lx\n", ref->reference);
1492 if(ref->index == -1)
1493 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1494 else
1495 TRACE_(typelib)("type no: %d\n", ref->index);
1497 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1499 TRACE_(typelib)("in lib\n");
1500 dump_TLBImpLib(ref->pImpTLInfo);
1505 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1507 if(!impl)
1508 return;
1509 while (n) {
1510 TRACE_(typelib)("implementing/inheriting interface hRef = %lx implflags %x\n",
1511 impl->hRef, impl->implflags);
1512 ++impl;
1513 --n;
1517 static void dump_DispParms(const DISPPARAMS * pdp)
1519 unsigned int index;
1521 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1523 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1525 TRACE("named args:\n");
1526 for (index = 0; index < pdp->cNamedArgs; index++)
1527 TRACE( "\t0x%lx\n", pdp->rgdispidNamedArgs[index] );
1530 if (pdp->cArgs && pdp->rgvarg)
1532 TRACE("args:\n");
1533 for (index = 0; index < pdp->cArgs; index++)
1534 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1538 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1540 TRACE("%p ref %lu\n", pty, pty->ref);
1541 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1542 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1543 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1544 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1545 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1546 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1547 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1548 if (TRACE_ON(ole))
1549 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1550 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1551 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1554 static void dump_VARDESC(const VARDESC *v)
1556 MESSAGE("memid %ld\n",v->memid);
1557 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1558 MESSAGE("oInst %ld\n", v->oInst);
1559 dump_ELEMDESC(&(v->elemdescVar));
1560 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1561 MESSAGE("varkind %d\n",v->varkind);
1564 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1566 /* VT_LPWSTR is largest type that, may appear in type description */
1567 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1568 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1569 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1570 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1571 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1572 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1573 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1574 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1577 static void TLB_abort(void)
1579 DebugBreak();
1582 /* returns the size required for a deep copy of a typedesc into a
1583 * flat buffer */
1584 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1586 SIZE_T size = 0;
1588 if (alloc_initial_space)
1589 size += sizeof(TYPEDESC);
1591 switch (tdesc->vt)
1593 case VT_PTR:
1594 case VT_SAFEARRAY:
1595 size += TLB_SizeTypeDesc(tdesc->lptdesc, TRUE);
1596 break;
1597 case VT_CARRAY:
1598 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->lpadesc->cDims]);
1599 size += TLB_SizeTypeDesc(&tdesc->lpadesc->tdescElem, FALSE);
1600 break;
1602 return size;
1605 /* deep copy a typedesc into a flat buffer */
1606 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1608 if (!dest)
1610 dest = buffer;
1611 buffer = (char *)buffer + sizeof(TYPEDESC);
1614 *dest = *src;
1616 switch (src->vt)
1618 case VT_PTR:
1619 case VT_SAFEARRAY:
1620 dest->lptdesc = buffer;
1621 buffer = TLB_CopyTypeDesc(NULL, src->lptdesc, buffer);
1622 break;
1623 case VT_CARRAY:
1624 dest->lpadesc = buffer;
1625 memcpy(dest->lpadesc, src->lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->lpadesc->cDims]));
1626 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->lpadesc->cDims]);
1627 buffer = TLB_CopyTypeDesc(&dest->lpadesc->tdescElem, &src->lpadesc->tdescElem, buffer);
1628 break;
1630 return buffer;
1633 /* free custom data allocated by MSFT_CustData */
1634 static inline void TLB_FreeCustData(struct list *custdata_list)
1636 TLBCustData *cd, *cdn;
1637 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1639 list_remove(&cd->entry);
1640 VariantClear(&cd->data);
1641 heap_free(cd);
1645 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1647 DWORD len;
1648 BSTR ret;
1650 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1651 ret = SysAllocStringLen(NULL, len - 1);
1652 if (!ret) return ret;
1653 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1654 return ret;
1657 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1659 int i;
1661 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1663 if (typeinfo->funcdescs[i].funcdesc.memid == memid)
1664 return &typeinfo->funcdescs[i];
1667 return NULL;
1670 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl *typeinfo, MEMBERID memid, INVOKEKIND invkind)
1672 int i;
1674 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1676 if (typeinfo->funcdescs[i].funcdesc.memid == memid && typeinfo->funcdescs[i].funcdesc.invkind == invkind)
1677 return &typeinfo->funcdescs[i];
1680 return NULL;
1683 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1685 int i;
1687 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1689 if (typeinfo->vardescs[i].vardesc.memid == memid)
1690 return &typeinfo->vardescs[i];
1693 return NULL;
1696 static inline TLBVarDesc *TLB_get_vardesc_by_name(ITypeInfoImpl *typeinfo, const OLECHAR *name)
1698 int i;
1700 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1702 if (!lstrcmpiW(TLB_get_bstr(typeinfo->vardescs[i].Name), name))
1703 return &typeinfo->vardescs[i];
1706 return NULL;
1709 static inline TLBCustData *TLB_get_custdata_by_guid(const struct list *custdata_list, REFGUID guid)
1711 TLBCustData *cust_data;
1712 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1713 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1714 return cust_data;
1715 return NULL;
1718 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeLibImpl *typelib, const OLECHAR *name)
1720 int i;
1722 for (i = 0; i < typelib->TypeInfoCount; ++i)
1724 if (!lstrcmpiW(TLB_get_bstr(typelib->typeinfos[i]->Name), name))
1725 return typelib->typeinfos[i];
1728 return NULL;
1731 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1733 list_init(&var_desc->custdata_list);
1736 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1738 TLBVarDesc *ret;
1740 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1741 if(!ret)
1742 return NULL;
1744 while(n){
1745 TLBVarDesc_Constructor(&ret[n-1]);
1746 --n;
1749 return ret;
1752 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1754 TLBParDesc *ret;
1756 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1757 if(!ret)
1758 return NULL;
1760 while(n){
1761 list_init(&ret[n-1].custdata_list);
1762 --n;
1765 return ret;
1768 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1770 list_init(&func_desc->custdata_list);
1773 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1775 TLBFuncDesc *ret;
1777 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1778 if(!ret)
1779 return NULL;
1781 while(n){
1782 TLBFuncDesc_Constructor(&ret[n-1]);
1783 --n;
1786 return ret;
1789 static void TLBImplType_Constructor(TLBImplType *impl)
1791 list_init(&impl->custdata_list);
1794 static TLBImplType *TLBImplType_Alloc(UINT n)
1796 TLBImplType *ret;
1798 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1799 if(!ret)
1800 return NULL;
1802 while(n){
1803 TLBImplType_Constructor(&ret[n-1]);
1804 --n;
1807 return ret;
1810 static TLBGuid *TLB_append_guid(struct list *guid_list,
1811 const GUID *new_guid, HREFTYPE hreftype)
1813 TLBGuid *guid;
1815 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1816 if (IsEqualGUID(&guid->guid, new_guid))
1817 return guid;
1820 guid = heap_alloc(sizeof(TLBGuid));
1821 if (!guid)
1822 return NULL;
1824 memcpy(&guid->guid, new_guid, sizeof(GUID));
1825 guid->hreftype = hreftype;
1827 list_add_tail(guid_list, &guid->entry);
1829 return guid;
1832 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1834 TLBCustData *cust_data;
1836 switch(V_VT(var)){
1837 case VT_I4:
1838 case VT_R4:
1839 case VT_UI4:
1840 case VT_INT:
1841 case VT_UINT:
1842 case VT_HRESULT:
1843 case VT_BSTR:
1844 break;
1845 default:
1846 return DISP_E_BADVARTYPE;
1849 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1851 if (!cust_data) {
1852 cust_data = heap_alloc(sizeof(TLBCustData));
1853 if (!cust_data)
1854 return E_OUTOFMEMORY;
1856 cust_data->guid = tlbguid;
1857 VariantInit(&cust_data->data);
1859 list_add_tail(custdata_list, &cust_data->entry);
1860 }else
1861 VariantClear(&cust_data->data);
1863 return VariantCopy(&cust_data->data, var);
1866 /* Used to update list pointers after list itself was moved. */
1867 static void TLB_relink_custdata(struct list *custdata_list)
1869 if (custdata_list->prev == custdata_list->next)
1870 list_init(custdata_list);
1871 else
1873 custdata_list->prev->next = custdata_list;
1874 custdata_list->next->prev = custdata_list;
1878 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1880 TLBString *str;
1882 if(!new_str)
1883 return NULL;
1885 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1886 if (wcscmp(str->str, new_str) == 0)
1887 return str;
1890 str = heap_alloc(sizeof(TLBString));
1891 if (!str)
1892 return NULL;
1894 str->str = SysAllocString(new_str);
1895 if (!str->str) {
1896 heap_free(str);
1897 return NULL;
1900 list_add_tail(string_list, &str->entry);
1902 return str;
1905 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1906 ULONG *size, WORD *align)
1908 ITypeInfo *other;
1909 TYPEATTR *attr;
1910 HRESULT hr;
1912 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1913 if(FAILED(hr))
1914 return hr;
1916 hr = ITypeInfo_GetTypeAttr(other, &attr);
1917 if(FAILED(hr)){
1918 ITypeInfo_Release(other);
1919 return hr;
1922 if(size)
1923 *size = attr->cbSizeInstance;
1924 if(align)
1925 *align = attr->cbAlignment;
1927 ITypeInfo_ReleaseTypeAttr(other, attr);
1928 ITypeInfo_Release(other);
1930 return S_OK;
1933 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1934 TYPEDESC *tdesc, ULONG *size, WORD *align)
1936 ULONG i, sub, ptr_size;
1937 HRESULT hr;
1939 ptr_size = get_ptr_size(sys);
1941 switch(tdesc->vt){
1942 case VT_VOID:
1943 *size = 0;
1944 break;
1945 case VT_I1:
1946 case VT_UI1:
1947 *size = 1;
1948 break;
1949 case VT_I2:
1950 case VT_BOOL:
1951 case VT_UI2:
1952 *size = 2;
1953 break;
1954 case VT_I4:
1955 case VT_R4:
1956 case VT_ERROR:
1957 case VT_UI4:
1958 case VT_INT:
1959 case VT_UINT:
1960 case VT_HRESULT:
1961 *size = 4;
1962 break;
1963 case VT_R8:
1964 case VT_I8:
1965 case VT_UI8:
1966 *size = 8;
1967 break;
1968 case VT_BSTR:
1969 case VT_DISPATCH:
1970 case VT_UNKNOWN:
1971 case VT_PTR:
1972 case VT_SAFEARRAY:
1973 case VT_LPSTR:
1974 case VT_LPWSTR:
1975 *size = ptr_size;
1976 break;
1977 case VT_DATE:
1978 *size = sizeof(DATE);
1979 break;
1980 case VT_VARIANT:
1981 *size = sizeof(VARIANT);
1982 #ifdef _WIN64
1983 if(sys == SYS_WIN32)
1984 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1985 #endif
1986 break;
1987 case VT_DECIMAL:
1988 *size = sizeof(DECIMAL);
1989 break;
1990 case VT_CY:
1991 *size = sizeof(CY);
1992 break;
1993 case VT_CARRAY:
1994 *size = 0;
1995 for(i = 0; i < tdesc->lpadesc->cDims; ++i)
1996 *size += tdesc->lpadesc->rgbounds[i].cElements;
1997 hr = TLB_size_instance(info, sys, &tdesc->lpadesc->tdescElem, &sub, align);
1998 if(FAILED(hr))
1999 return hr;
2000 *size *= sub;
2001 return S_OK;
2002 case VT_USERDEFINED:
2003 return TLB_get_size_from_hreftype(info, tdesc->hreftype, size, align);
2004 default:
2005 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2006 return E_FAIL;
2009 if(align){
2010 if(*size < 4)
2011 *align = *size;
2012 else
2013 *align = 4;
2016 return S_OK;
2019 /**********************************************************************
2021 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2024 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2026 if (where != DO_NOT_SEEK)
2028 where += pcx->oStart;
2029 if (where > pcx->length)
2031 /* FIXME */
2032 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
2033 TLB_abort();
2035 pcx->pos = where;
2039 /* read function */
2040 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2042 TRACE_(typelib)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2043 pcx->pos, count, pcx->oStart, pcx->length, where);
2045 MSFT_Seek(pcx, where);
2046 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2047 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2048 pcx->pos += count;
2049 return count;
2052 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2053 LONG where )
2055 DWORD ret;
2057 ret = MSFT_Read(buffer, count, pcx, where);
2058 FromLEDWords(buffer, ret);
2060 return ret;
2063 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2064 LONG where )
2066 DWORD ret;
2068 ret = MSFT_Read(buffer, count, pcx, where);
2069 FromLEWords(buffer, ret);
2071 return ret;
2074 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2076 TLBGuid *guid;
2077 MSFT_GuidEntry entry;
2078 int offs = 0;
2080 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2081 while (1) {
2082 if (offs >= pcx->pTblDir->pGuidTab.length)
2083 return S_OK;
2085 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2087 guid = heap_alloc(sizeof(TLBGuid));
2089 guid->offset = offs;
2090 guid->guid = entry.guid;
2091 guid->hreftype = entry.hreftype;
2093 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2095 offs += sizeof(MSFT_GuidEntry);
2099 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2101 TLBGuid *ret;
2103 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2104 if(ret->offset == offset){
2105 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2106 return ret;
2110 return NULL;
2113 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2115 MSFT_NameIntro niName;
2117 if (offset < 0)
2119 ERR_(typelib)("bad offset %d\n", offset);
2120 return -1;
2123 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2124 pcx->pTblDir->pNametab.offset+offset);
2126 return niName.hreftype;
2129 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2131 char *string;
2132 MSFT_NameIntro intro;
2133 INT16 len_piece;
2134 int offs = 0, lengthInChars;
2136 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2137 while (1) {
2138 TLBString *tlbstr;
2140 if (offs >= pcx->pTblDir->pNametab.length)
2141 return S_OK;
2143 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2144 intro.namelen &= 0xFF;
2145 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2146 if(len_piece % 4)
2147 len_piece = (len_piece + 4) & ~0x3;
2148 if(len_piece < 8)
2149 len_piece = 8;
2151 string = heap_alloc(len_piece + 1);
2152 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2153 string[intro.namelen] = '\0';
2155 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2156 string, -1, NULL, 0);
2157 if (!lengthInChars) {
2158 heap_free(string);
2159 return E_UNEXPECTED;
2162 tlbstr = heap_alloc(sizeof(TLBString));
2164 tlbstr->offset = offs;
2165 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2166 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2168 heap_free(string);
2170 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2172 offs += len_piece;
2176 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2178 TLBString *tlbstr;
2180 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2181 if (tlbstr->offset == offset) {
2182 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2183 return tlbstr;
2187 return NULL;
2190 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2192 TLBString *tlbstr;
2194 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2195 if (tlbstr->offset == offset) {
2196 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2197 return tlbstr;
2201 return NULL;
2205 * read a value and fill a VARIANT structure
2207 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2209 int size;
2211 TRACE_(typelib)("\n");
2213 if(offset <0) { /* data are packed in here */
2214 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2215 V_I4(pVar) = offset & 0x3ffffff;
2216 return;
2218 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2219 pcx->pTblDir->pCustData.offset + offset );
2220 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2221 switch (V_VT(pVar)){
2222 case VT_EMPTY: /* FIXME: is this right? */
2223 case VT_NULL: /* FIXME: is this right? */
2224 case VT_I2 : /* this should not happen */
2225 case VT_I4 :
2226 case VT_R4 :
2227 case VT_ERROR :
2228 case VT_BOOL :
2229 case VT_I1 :
2230 case VT_UI1 :
2231 case VT_UI2 :
2232 case VT_UI4 :
2233 case VT_INT :
2234 case VT_UINT :
2235 case VT_VOID : /* FIXME: is this right? */
2236 case VT_HRESULT :
2237 size=4; break;
2238 case VT_R8 :
2239 case VT_CY :
2240 case VT_DATE :
2241 case VT_I8 :
2242 case VT_UI8 :
2243 case VT_DECIMAL : /* FIXME: is this right? */
2244 case VT_FILETIME :
2245 size=8;break;
2246 /* pointer types with known behaviour */
2247 case VT_BSTR :{
2248 char * ptr;
2249 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2250 if(size == -1){
2251 V_BSTR(pVar) = NULL;
2252 }else{
2253 int len;
2254 ptr = heap_alloc_zero(size);
2255 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2256 len = MultiByteToWideChar(CP_ACP, 0, ptr, size, NULL, 0 );
2257 V_BSTR(pVar)=SysAllocStringLen(NULL,len);
2258 MultiByteToWideChar(CP_ACP, 0, ptr, size, V_BSTR(pVar), len );
2259 heap_free(ptr);
2262 size=-4; break;
2263 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2264 case VT_DISPATCH :
2265 case VT_VARIANT :
2266 case VT_UNKNOWN :
2267 case VT_PTR :
2268 case VT_SAFEARRAY :
2269 case VT_CARRAY :
2270 case VT_USERDEFINED :
2271 case VT_LPSTR :
2272 case VT_LPWSTR :
2273 case VT_BLOB :
2274 case VT_STREAM :
2275 case VT_STORAGE :
2276 case VT_STREAMED_OBJECT :
2277 case VT_STORED_OBJECT :
2278 case VT_BLOB_OBJECT :
2279 case VT_CF :
2280 case VT_CLSID :
2281 default:
2282 size=0;
2283 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2284 V_VT(pVar));
2287 if(size>0) /* (big|small) endian correct? */
2288 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2289 return;
2292 * create a linked list with custom data
2294 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2296 MSFT_CDGuid entry;
2297 TLBCustData* pNew;
2298 int count=0;
2300 TRACE_(typelib)("\n");
2302 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2304 while(offset >=0){
2305 count++;
2306 pNew=heap_alloc_zero(sizeof(TLBCustData));
2307 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2308 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2309 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2310 list_add_head(custdata_list, &pNew->entry);
2311 offset = entry.next;
2313 return count;
2316 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2318 if(type <0)
2319 pTd->vt=type & VT_TYPEMASK;
2320 else
2321 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2323 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2326 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2328 return (invkind == INVOKE_PROPERTYGET ||
2329 invkind == INVOKE_PROPERTYPUT ||
2330 invkind == INVOKE_PROPERTYPUTREF);
2333 static void
2334 MSFT_DoFuncs(TLBContext* pcx,
2335 ITypeInfoImpl* pTI,
2336 int cFuncs,
2337 int cVars,
2338 int offset,
2339 TLBFuncDesc** pptfd)
2342 * member information is stored in a data structure at offset
2343 * indicated by the memoffset field of the typeinfo structure
2344 * There are several distinctive parts.
2345 * The first part starts with a field that holds the total length
2346 * of this (first) part excluding this field. Then follow the records,
2347 * for each member there is one record.
2349 * The first entry is always the length of the record (including this
2350 * length word).
2351 * The rest of the record depends on the type of the member. If there is
2352 * a field indicating the member type (function, variable, interface, etc)
2353 * I have not found it yet. At this time we depend on the information
2354 * in the type info and the usual order how things are stored.
2356 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2357 * for each member;
2359 * Third is an equal sized array with file offsets to the name entry
2360 * of each member.
2362 * The fourth and last (?) part is an array with offsets to the records
2363 * in the first part of this file segment.
2366 int infolen, nameoffset, reclength, i;
2367 int recoffset = offset + sizeof(INT);
2369 char *recbuf = heap_alloc(0xffff);
2370 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2371 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2373 TRACE_(typelib)("\n");
2375 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2377 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2378 ptfd = *pptfd;
2379 for ( i = 0; i < cFuncs ; i++ )
2381 int optional;
2383 /* name, eventually add to a hash table */
2384 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2385 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2387 /* read the function information record */
2388 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2390 reclength &= 0xffff;
2392 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2394 /* size without argument data */
2395 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2396 if (pFuncRec->FKCCIC & 0x1000)
2397 optional -= pFuncRec->nrargs * sizeof(INT);
2399 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2400 ptfd->helpcontext = pFuncRec->HelpContext;
2402 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2403 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2405 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2407 if (pFuncRec->FKCCIC & 0x2000 )
2409 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2410 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2411 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2413 else
2414 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2416 else
2417 ptfd->Entry = (TLBString*)-1;
2419 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2420 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2422 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2423 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2425 /* fill the FuncDesc Structure */
2426 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2427 offset + infolen + ( i + 1) * sizeof(INT));
2429 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2430 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2431 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2432 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2433 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2434 if (ptfd->funcdesc.funckind == FUNC_DISPATCH)
2435 ptfd->funcdesc.oVft = 0;
2436 else
2437 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2438 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2440 /* nameoffset is sometimes -1 on the second half of a propget/propput
2441 * pair of functions */
2442 if ((nameoffset == -1) && (i > 0) &&
2443 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2444 TLB_is_propgetput(ptfd->funcdesc.invkind))
2445 ptfd->Name = ptfd_prev->Name;
2446 else
2447 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2449 MSFT_GetTdesc(pcx,
2450 pFuncRec->DataType,
2451 &ptfd->funcdesc.elemdescFunc.tdesc);
2453 /* do the parameters/arguments */
2454 if(pFuncRec->nrargs)
2456 int j = 0;
2457 MSFT_ParameterInfo paraminfo;
2459 ptfd->funcdesc.lprgelemdescParam =
2460 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2462 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2464 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2465 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2467 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2469 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2471 MSFT_GetTdesc(pcx,
2472 paraminfo.DataType,
2473 &elemdesc->tdesc);
2475 elemdesc->paramdesc.wParamFlags = paraminfo.Flags;
2477 /* name */
2478 if (paraminfo.oName != -1)
2479 ptfd->pParamDesc[j].Name =
2480 MSFT_ReadName( pcx, paraminfo.oName );
2481 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2483 /* default value */
2484 if ( (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2485 (pFuncRec->FKCCIC & 0x1000) )
2487 INT* pInt = (INT *)((char *)pFuncRec +
2488 reclength -
2489 (pFuncRec->nrargs * 4) * sizeof(INT) );
2491 PARAMDESC* pParamDesc = &elemdesc->paramdesc;
2493 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2494 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2496 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2497 pInt[j], pcx);
2499 else
2500 elemdesc->paramdesc.pparamdescex = NULL;
2502 /* custom info */
2503 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2504 j*sizeof(pFuncRec->oArgCustData[0])) &&
2505 pFuncRec->FKCCIC & 0x80 )
2507 MSFT_CustData(pcx,
2508 pFuncRec->oArgCustData[j],
2509 &ptfd->pParamDesc[j].custdata_list);
2512 /* SEEK value = jump to offset,
2513 * from there jump to the end of record,
2514 * go back by (j-1) arguments
2516 MSFT_ReadLEDWords( &paraminfo ,
2517 sizeof(MSFT_ParameterInfo), pcx,
2518 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2519 * sizeof(MSFT_ParameterInfo)));
2523 /* scode is not used: archaic win16 stuff FIXME: right? */
2524 ptfd->funcdesc.cScodes = 0 ;
2525 ptfd->funcdesc.lprgscode = NULL ;
2527 ptfd_prev = ptfd;
2528 ++ptfd;
2529 recoffset += reclength;
2531 heap_free(recbuf);
2534 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2535 int cVars, int offset, TLBVarDesc ** pptvd)
2537 int infolen, nameoffset, reclength;
2538 char recbuf[256];
2539 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2540 TLBVarDesc *ptvd;
2541 int i;
2542 int recoffset;
2544 TRACE_(typelib)("\n");
2546 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2547 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2548 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2549 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2550 recoffset += offset+sizeof(INT);
2551 for(i=0;i<cVars;i++, ++ptvd){
2552 /* name, eventually add to a hash table */
2553 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2554 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2555 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2556 /* read the variable information record */
2557 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2558 reclength &= 0xff;
2559 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2561 /* optional data */
2562 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2563 ptvd->HelpContext = pVarRec->HelpContext;
2565 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2566 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2568 if (reclength > FIELD_OFFSET(MSFT_VarRecord, oCustData))
2569 MSFT_CustData(pcx, pVarRec->oCustData, &ptvd->custdata_list);
2571 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2572 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2574 /* fill the VarDesc Structure */
2575 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2576 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2577 ptvd->vardesc.varkind = pVarRec->VarKind;
2578 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2579 MSFT_GetTdesc(pcx, pVarRec->DataType,
2580 &ptvd->vardesc.elemdescVar.tdesc);
2581 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2582 if(pVarRec->VarKind == VAR_CONST ){
2583 ptvd->vardesc.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2584 MSFT_ReadValue(ptvd->vardesc.lpvarValue,
2585 pVarRec->OffsValue, pcx);
2586 } else
2587 ptvd->vardesc.oInst=pVarRec->OffsValue;
2588 recoffset += reclength;
2592 /* process Implemented Interfaces of a com class */
2593 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2594 int offset)
2596 int i;
2597 MSFT_RefRecord refrec;
2598 TLBImplType *pImpl;
2600 TRACE_(typelib)("\n");
2602 pTI->impltypes = TLBImplType_Alloc(count);
2603 pImpl = pTI->impltypes;
2604 for(i=0;i<count;i++){
2605 if(offset<0) break; /* paranoia */
2606 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2607 pImpl->hRef = refrec.reftype;
2608 pImpl->implflags=refrec.flags;
2609 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2610 offset=refrec.onext;
2611 ++pImpl;
2615 #ifdef _WIN64
2616 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2617 * and some structures, and fix the alignment */
2618 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2620 if(info->typeattr.typekind == TKIND_ALIAS){
2621 switch(info->tdescAlias->vt){
2622 case VT_BSTR:
2623 case VT_DISPATCH:
2624 case VT_UNKNOWN:
2625 case VT_PTR:
2626 case VT_SAFEARRAY:
2627 case VT_LPSTR:
2628 case VT_LPWSTR:
2629 info->typeattr.cbSizeInstance = sizeof(void*);
2630 info->typeattr.cbAlignment = sizeof(void*);
2631 break;
2632 case VT_CARRAY:
2633 case VT_USERDEFINED:
2634 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2635 break;
2636 case VT_VARIANT:
2637 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2638 info->typeattr.cbAlignment = 8;
2639 default:
2640 if(info->typeattr.cbSizeInstance < sizeof(void*))
2641 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2642 else
2643 info->typeattr.cbAlignment = sizeof(void*);
2644 break;
2646 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2647 info->typeattr.typekind == TKIND_DISPATCH ||
2648 info->typeattr.typekind == TKIND_COCLASS){
2649 info->typeattr.cbSizeInstance = sizeof(void*);
2650 info->typeattr.cbAlignment = sizeof(void*);
2653 #endif
2656 * process a typeinfo record
2658 static ITypeInfoImpl * MSFT_DoTypeInfo(
2659 TLBContext *pcx,
2660 int count,
2661 ITypeLibImpl * pLibInfo)
2663 MSFT_TypeInfoBase tiBase;
2664 ITypeInfoImpl *ptiRet;
2666 TRACE_(typelib)("count=%u\n", count);
2668 ptiRet = ITypeInfoImpl_Constructor();
2669 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2670 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2672 /* this is where we are coming from */
2673 ptiRet->pTypeLib = pLibInfo;
2674 ptiRet->index=count;
2676 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2677 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2678 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2679 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2680 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2681 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2682 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2683 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2684 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2685 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2686 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2687 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2688 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2689 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2690 TYPEDESC tmp;
2691 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2692 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2693 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2696 /* FIXME: */
2697 /* IDLDESC idldescType; *//* never saw this one != zero */
2699 /* name, eventually add to a hash table */
2700 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2701 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2702 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2703 /* help info */
2704 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2705 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2706 ptiRet->dwHelpContext=tiBase.helpcontext;
2708 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2709 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2711 /* note: InfoType's Help file and HelpStringDll come from the containing
2712 * library. Further HelpString and Docstring appear to be the same thing :(
2714 /* functions */
2715 if(ptiRet->typeattr.cFuncs >0 )
2716 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2717 ptiRet->typeattr.cVars,
2718 tiBase.memoffset, &ptiRet->funcdescs);
2719 /* variables */
2720 if(ptiRet->typeattr.cVars >0 )
2721 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2722 ptiRet->typeattr.cVars,
2723 tiBase.memoffset, &ptiRet->vardescs);
2724 if(ptiRet->typeattr.cImplTypes >0 ) {
2725 switch(ptiRet->typeattr.typekind)
2727 case TKIND_COCLASS:
2728 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2729 tiBase.datatype1);
2730 break;
2731 case TKIND_DISPATCH:
2732 /* This is not -1 when the interface is a non-base dual interface or
2733 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2734 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2735 not this interface.
2738 if (tiBase.datatype1 != -1)
2740 ptiRet->impltypes = TLBImplType_Alloc(1);
2741 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2743 break;
2744 default:
2745 ptiRet->impltypes = TLBImplType_Alloc(1);
2746 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2747 break;
2750 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2752 TRACE_(typelib)("%s guid: %s kind:%s\n",
2753 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2754 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2755 typekind_desc[ptiRet->typeattr.typekind]);
2756 if (TRACE_ON(typelib))
2757 dump_TypeInfo(ptiRet);
2759 return ptiRet;
2762 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2764 char *string;
2765 INT16 len_str, len_piece;
2766 int offs = 0, lengthInChars;
2768 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2769 while (1) {
2770 TLBString *tlbstr;
2772 if (offs >= pcx->pTblDir->pStringtab.length)
2773 return S_OK;
2775 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2776 len_piece = len_str + sizeof(INT16);
2777 if(len_piece % 4)
2778 len_piece = (len_piece + 4) & ~0x3;
2779 if(len_piece < 8)
2780 len_piece = 8;
2782 string = heap_alloc(len_piece + 1);
2783 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2784 string[len_str] = '\0';
2786 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2787 string, -1, NULL, 0);
2788 if (!lengthInChars) {
2789 heap_free(string);
2790 return E_UNEXPECTED;
2793 tlbstr = heap_alloc(sizeof(TLBString));
2795 tlbstr->offset = offs;
2796 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2797 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2799 heap_free(string);
2801 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2803 offs += len_piece;
2807 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2809 TLBRefType *ref;
2810 int offs = 0;
2812 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2813 while (offs < pcx->pTblDir->pImpInfo.length) {
2814 MSFT_ImpInfo impinfo;
2815 TLBImpLib *pImpLib;
2817 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2819 ref = heap_alloc_zero(sizeof(TLBRefType));
2820 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2822 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2823 if(pImpLib->offset==impinfo.oImpFile)
2824 break;
2826 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2827 ref->reference = offs;
2828 ref->pImpTLInfo = pImpLib;
2829 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2830 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2831 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2832 ref->index = TLB_REF_USE_GUID;
2833 } else
2834 ref->index = impinfo.oGuid;
2835 }else{
2836 ERR("Cannot find a reference\n");
2837 ref->reference = -1;
2838 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2841 offs += sizeof(impinfo);
2844 return S_OK;
2847 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2848 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2849 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2850 * tradeoff here.
2852 static struct list tlb_cache = LIST_INIT(tlb_cache);
2853 static CRITICAL_SECTION cache_section;
2854 static CRITICAL_SECTION_DEBUG cache_section_debug =
2856 0, 0, &cache_section,
2857 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2858 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2860 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2863 typedef struct TLB_PEFile
2865 IUnknown IUnknown_iface;
2866 LONG refs;
2867 HMODULE dll;
2868 HRSRC typelib_resource;
2869 HGLOBAL typelib_global;
2870 LPVOID typelib_base;
2871 } TLB_PEFile;
2873 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2875 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2878 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2880 if (IsEqualIID(riid, &IID_IUnknown))
2882 *ppv = iface;
2883 IUnknown_AddRef(iface);
2884 return S_OK;
2886 *ppv = NULL;
2887 return E_NOINTERFACE;
2890 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2892 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2893 return InterlockedIncrement(&This->refs);
2896 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2898 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2899 ULONG refs = InterlockedDecrement(&This->refs);
2900 if (!refs)
2902 if (This->typelib_global)
2903 FreeResource(This->typelib_global);
2904 if (This->dll)
2905 FreeLibrary(This->dll);
2906 heap_free(This);
2908 return refs;
2911 static const IUnknownVtbl TLB_PEFile_Vtable =
2913 TLB_PEFile_QueryInterface,
2914 TLB_PEFile_AddRef,
2915 TLB_PEFile_Release
2918 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2920 TLB_PEFile *This;
2921 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2923 This = heap_alloc(sizeof(TLB_PEFile));
2924 if (!This)
2925 return E_OUTOFMEMORY;
2927 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2928 This->refs = 1;
2929 This->dll = NULL;
2930 This->typelib_resource = NULL;
2931 This->typelib_global = NULL;
2932 This->typelib_base = NULL;
2934 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2935 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2937 if (This->dll)
2939 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), L"TYPELIB");
2940 if (This->typelib_resource)
2942 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2943 if (This->typelib_global)
2945 This->typelib_base = LockResource(This->typelib_global);
2947 if (This->typelib_base)
2949 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2950 *ppBase = This->typelib_base;
2951 *ppFile = &This->IUnknown_iface;
2952 return S_OK;
2957 TRACE("No TYPELIB resource found\n");
2958 hr = E_FAIL;
2961 TLB_PEFile_Release(&This->IUnknown_iface);
2962 return hr;
2965 typedef struct TLB_NEFile
2967 IUnknown IUnknown_iface;
2968 LONG refs;
2969 LPVOID typelib_base;
2970 } TLB_NEFile;
2972 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2974 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2977 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2979 if (IsEqualIID(riid, &IID_IUnknown))
2981 *ppv = iface;
2982 IUnknown_AddRef(iface);
2983 return S_OK;
2985 *ppv = NULL;
2986 return E_NOINTERFACE;
2989 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2991 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2992 return InterlockedIncrement(&This->refs);
2995 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2997 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2998 ULONG refs = InterlockedDecrement(&This->refs);
2999 if (!refs)
3001 heap_free(This->typelib_base);
3002 heap_free(This);
3004 return refs;
3007 static const IUnknownVtbl TLB_NEFile_Vtable =
3009 TLB_NEFile_QueryInterface,
3010 TLB_NEFile_AddRef,
3011 TLB_NEFile_Release
3014 /***********************************************************************
3015 * read_xx_header [internal]
3017 static int read_xx_header( HFILE lzfd )
3019 IMAGE_DOS_HEADER mzh;
3020 char magic[3];
3022 LZSeek( lzfd, 0, SEEK_SET );
3023 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3024 return 0;
3025 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3026 return 0;
3028 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3029 if ( 2 != LZRead( lzfd, magic, 2 ) )
3030 return 0;
3032 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3034 if ( magic[0] == 'N' && magic[1] == 'E' )
3035 return IMAGE_OS2_SIGNATURE;
3036 if ( magic[0] == 'P' && magic[1] == 'E' )
3037 return IMAGE_NT_SIGNATURE;
3039 magic[2] = '\0';
3040 WARN("Can't handle %s files.\n", magic );
3041 return 0;
3045 /***********************************************************************
3046 * find_ne_resource [internal]
3048 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3049 DWORD *resLen, DWORD *resOff )
3051 IMAGE_OS2_HEADER nehd;
3052 NE_TYPEINFO *typeInfo;
3053 NE_NAMEINFO *nameInfo;
3054 DWORD nehdoffset;
3055 LPBYTE resTab;
3056 DWORD resTabSize;
3057 int count;
3059 /* Read in NE header */
3060 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3061 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3063 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3064 if ( !resTabSize )
3066 TRACE("No resources in NE dll\n" );
3067 return FALSE;
3070 /* Read in resource table */
3071 resTab = heap_alloc( resTabSize );
3072 if ( !resTab ) return FALSE;
3074 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3075 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3077 heap_free( resTab );
3078 return FALSE;
3081 /* Find resource */
3082 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3084 if (!IS_INTRESOURCE(typeid)) /* named type */
3086 BYTE len = strlen( typeid );
3087 while (typeInfo->type_id)
3089 if (!(typeInfo->type_id & 0x8000))
3091 BYTE *p = resTab + typeInfo->type_id;
3092 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3094 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3095 typeInfo->count * sizeof(NE_NAMEINFO));
3098 else /* numeric type id */
3100 WORD id = LOWORD(typeid) | 0x8000;
3101 while (typeInfo->type_id)
3103 if (typeInfo->type_id == id) goto found_type;
3104 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3105 typeInfo->count * sizeof(NE_NAMEINFO));
3108 TRACE("No typeid entry found for %p\n", typeid );
3109 heap_free( resTab );
3110 return FALSE;
3112 found_type:
3113 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3115 if (!IS_INTRESOURCE(resid)) /* named resource */
3117 BYTE len = strlen( resid );
3118 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3120 BYTE *p = resTab + nameInfo->id;
3121 if (nameInfo->id & 0x8000) continue;
3122 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3125 else /* numeric resource id */
3127 WORD id = LOWORD(resid) | 0x8000;
3128 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3129 if (nameInfo->id == id) goto found_name;
3131 TRACE("No resid entry found for %p\n", typeid );
3132 heap_free( resTab );
3133 return FALSE;
3135 found_name:
3136 /* Return resource data */
3137 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3138 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3140 heap_free( resTab );
3141 return TRUE;
3144 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3146 HFILE lzfd = -1;
3147 OFSTRUCT ofs;
3148 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3149 TLB_NEFile *This;
3151 This = heap_alloc(sizeof(TLB_NEFile));
3152 if (!This) return E_OUTOFMEMORY;
3154 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3155 This->refs = 1;
3156 This->typelib_base = NULL;
3158 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3159 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3161 DWORD reslen, offset;
3162 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3164 This->typelib_base = heap_alloc(reslen);
3165 if( !This->typelib_base )
3166 hr = E_OUTOFMEMORY;
3167 else
3169 LZSeek( lzfd, offset, SEEK_SET );
3170 reslen = LZRead( lzfd, This->typelib_base, reslen );
3171 LZClose( lzfd );
3172 *ppBase = This->typelib_base;
3173 *pdwTLBLength = reslen;
3174 *ppFile = &This->IUnknown_iface;
3175 return S_OK;
3180 if( lzfd >= 0) LZClose( lzfd );
3181 TLB_NEFile_Release(&This->IUnknown_iface);
3182 return hr;
3185 typedef struct TLB_Mapping
3187 IUnknown IUnknown_iface;
3188 LONG refs;
3189 HANDLE file;
3190 HANDLE mapping;
3191 LPVOID typelib_base;
3192 } TLB_Mapping;
3194 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3196 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3199 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3201 if (IsEqualIID(riid, &IID_IUnknown))
3203 *ppv = iface;
3204 IUnknown_AddRef(iface);
3205 return S_OK;
3207 *ppv = NULL;
3208 return E_NOINTERFACE;
3211 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3213 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3214 return InterlockedIncrement(&This->refs);
3217 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3219 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3220 ULONG refs = InterlockedDecrement(&This->refs);
3221 if (!refs)
3223 if (This->typelib_base)
3224 UnmapViewOfFile(This->typelib_base);
3225 if (This->mapping)
3226 CloseHandle(This->mapping);
3227 if (This->file != INVALID_HANDLE_VALUE)
3228 CloseHandle(This->file);
3229 heap_free(This);
3231 return refs;
3234 static const IUnknownVtbl TLB_Mapping_Vtable =
3236 TLB_Mapping_QueryInterface,
3237 TLB_Mapping_AddRef,
3238 TLB_Mapping_Release
3241 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3243 TLB_Mapping *This;
3245 This = heap_alloc(sizeof(TLB_Mapping));
3246 if (!This)
3247 return E_OUTOFMEMORY;
3249 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3250 This->refs = 1;
3251 This->file = INVALID_HANDLE_VALUE;
3252 This->mapping = NULL;
3253 This->typelib_base = NULL;
3255 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3256 if (INVALID_HANDLE_VALUE != This->file)
3258 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3259 if (This->mapping)
3261 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3262 if(This->typelib_base)
3264 /* retrieve file size */
3265 *pdwTLBLength = GetFileSize(This->file, NULL);
3266 *ppBase = This->typelib_base;
3267 *ppFile = &This->IUnknown_iface;
3268 return S_OK;
3273 IUnknown_Release(&This->IUnknown_iface);
3274 return TYPE_E_CANTLOADLIBRARY;
3277 /****************************************************************************
3278 * TLB_ReadTypeLib
3280 * find the type of the typelib file and map the typelib resource into
3281 * the memory
3284 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3285 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3287 ITypeLibImpl *entry;
3288 HRESULT ret;
3289 INT index = 1;
3290 LPWSTR index_str, file = (LPWSTR)pszFileName;
3291 LPVOID pBase = NULL;
3292 DWORD dwTLBLength = 0;
3293 IUnknown *pFile = NULL;
3294 HANDLE h;
3296 *ppTypeLib = NULL;
3298 index_str = wcsrchr(pszFileName, '\\');
3299 if(index_str && *++index_str != '\0')
3301 LPWSTR end_ptr;
3302 LONG idx = wcstol(index_str, &end_ptr, 10);
3303 if(*end_ptr == '\0')
3305 int str_len = index_str - pszFileName - 1;
3306 index = idx;
3307 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3308 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3309 file[str_len] = 0;
3313 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3315 if(wcschr(file, '\\'))
3317 lstrcpyW(pszPath, file);
3319 else
3321 int len = GetSystemDirectoryW(pszPath, cchPath);
3322 pszPath[len] = '\\';
3323 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3327 if(file != pszFileName) heap_free(file);
3329 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3330 if(h != INVALID_HANDLE_VALUE){
3331 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3332 CloseHandle(h);
3335 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3337 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3338 EnterCriticalSection(&cache_section);
3339 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3341 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3343 TRACE("cache hit\n");
3344 *ppTypeLib = &entry->ITypeLib2_iface;
3345 ITypeLib2_AddRef(*ppTypeLib);
3346 LeaveCriticalSection(&cache_section);
3347 return S_OK;
3350 LeaveCriticalSection(&cache_section);
3352 /* now actually load and parse the typelib */
3354 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3355 if (ret == TYPE_E_CANTLOADLIBRARY)
3356 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3357 if (ret == TYPE_E_CANTLOADLIBRARY)
3358 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3359 if (SUCCEEDED(ret))
3361 if (dwTLBLength >= 4)
3363 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3364 if (dwSignature == MSFT_SIGNATURE)
3365 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3366 else if (dwSignature == SLTG_SIGNATURE)
3367 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3368 else
3370 FIXME("Header type magic %#lx not supported.\n", dwSignature);
3371 ret = TYPE_E_CANTLOADLIBRARY;
3374 else
3375 ret = TYPE_E_CANTLOADLIBRARY;
3376 IUnknown_Release(pFile);
3379 if(*ppTypeLib) {
3380 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3382 TRACE("adding to cache\n");
3383 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3384 lstrcpyW(impl->path, pszPath);
3385 /* We should really canonicalise the path here. */
3386 impl->index = index;
3388 /* FIXME: check if it has added already in the meantime */
3389 EnterCriticalSection(&cache_section);
3390 list_add_head(&tlb_cache, &impl->entry);
3391 LeaveCriticalSection(&cache_section);
3392 ret = S_OK;
3394 else
3396 if(ret != E_FAIL)
3397 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
3399 ret = TYPE_E_CANTLOADLIBRARY;
3403 return ret;
3406 /*================== ITypeLib(2) Methods ===================================*/
3408 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3410 ITypeLibImpl* pTypeLibImpl;
3412 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3413 if (!pTypeLibImpl) return NULL;
3415 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3416 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3417 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3418 pTypeLibImpl->ref = 1;
3420 list_init(&pTypeLibImpl->implib_list);
3421 list_init(&pTypeLibImpl->custdata_list);
3422 list_init(&pTypeLibImpl->name_list);
3423 list_init(&pTypeLibImpl->string_list);
3424 list_init(&pTypeLibImpl->guid_list);
3425 list_init(&pTypeLibImpl->ref_list);
3426 pTypeLibImpl->dispatch_href = -1;
3428 return pTypeLibImpl;
3431 /****************************************************************************
3432 * ITypeLib2_Constructor_MSFT
3434 * loading an MSFT typelib from an in-memory image
3436 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3438 TLBContext cx;
3439 LONG lPSegDir;
3440 MSFT_Header tlbHeader;
3441 MSFT_SegDir tlbSegDir;
3442 ITypeLibImpl * pTypeLibImpl;
3443 int i;
3445 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3447 pTypeLibImpl = TypeLibImpl_Constructor();
3448 if (!pTypeLibImpl) return NULL;
3450 /* get pointer to beginning of typelib data */
3451 cx.pos = 0;
3452 cx.oStart=0;
3453 cx.mapping = pLib;
3454 cx.pLibInfo = pTypeLibImpl;
3455 cx.length = dwTLBLength;
3457 /* read header */
3458 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3459 TRACE_(typelib)("header:\n");
3460 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3461 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3462 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3463 return NULL;
3465 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3467 /* there is a small amount of information here until the next important
3468 * part:
3469 * the segment directory . Try to calculate the amount of data */
3470 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3472 /* now read the segment directory */
3473 TRACE("read segment directory (at %ld)\n",lPSegDir);
3474 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3475 cx.pTblDir = &tlbSegDir;
3477 /* just check two entries */
3478 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3480 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir);
3481 heap_free(pTypeLibImpl);
3482 return NULL;
3485 MSFT_ReadAllNames(&cx);
3486 MSFT_ReadAllStrings(&cx);
3487 MSFT_ReadAllGuids(&cx);
3489 /* now fill our internal data */
3490 /* TLIBATTR fields */
3491 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3493 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3494 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3495 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3496 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3497 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3499 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3500 pTypeLibImpl->lcid = tlbHeader.lcid;
3502 /* name, eventually add to a hash table */
3503 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3505 /* help info */
3506 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3507 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3509 if( tlbHeader.varflags & HELPDLLFLAG)
3511 int offset;
3512 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3513 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3516 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3518 /* custom data */
3519 if(tlbHeader.CustomDataOffset >= 0)
3521 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3524 /* fill in type descriptions */
3525 if(tlbSegDir.pTypdescTab.length > 0)
3527 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3528 INT16 td[4];
3529 pTypeLibImpl->ctTypeDesc = cTD;
3530 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3531 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3532 for(i=0; i<cTD; )
3534 /* FIXME: add several sanity checks here */
3535 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3536 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3538 /* FIXME: check safearray */
3539 if(td[3] < 0)
3540 pTypeLibImpl->pTypeDesc[i].lptdesc = &std_typedesc[td[2]];
3541 else
3542 pTypeLibImpl->pTypeDesc[i].lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3544 else if(td[0] == VT_CARRAY)
3546 /* array descr table here */
3547 pTypeLibImpl->pTypeDesc[i].lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3549 else if(td[0] == VT_USERDEFINED)
3551 pTypeLibImpl->pTypeDesc[i].hreftype = MAKELONG(td[2],td[3]);
3553 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3556 /* second time around to fill the array subscript info */
3557 for(i=0;i<cTD;i++)
3559 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3560 if(tlbSegDir.pArrayDescriptions.offset>0)
3562 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].lpadesc);
3563 pTypeLibImpl->pTypeDesc[i].lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3565 if(td[1]<0)
3566 pTypeLibImpl->pTypeDesc[i].lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3567 else
3568 pTypeLibImpl->pTypeDesc[i].lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3570 pTypeLibImpl->pTypeDesc[i].lpadesc->cDims = td[2];
3572 for(j = 0; j<td[2]; j++)
3574 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].lpadesc->rgbounds[j].cElements,
3575 sizeof(INT), &cx, DO_NOT_SEEK);
3576 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].lpadesc->rgbounds[j].lLbound,
3577 sizeof(INT), &cx, DO_NOT_SEEK);
3580 else
3582 pTypeLibImpl->pTypeDesc[i].lpadesc = NULL;
3583 ERR("didn't find array description data\n");
3588 /* imported type libs */
3589 if(tlbSegDir.pImpFiles.offset>0)
3591 TLBImpLib *pImpLib;
3592 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3593 UINT16 size;
3595 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3597 char *name;
3599 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3600 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3601 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3603 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3604 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3605 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3606 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3608 size >>= 2;
3609 name = heap_alloc_zero(size+1);
3610 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3611 pImpLib->name = TLB_MultiByteToBSTR(name);
3612 heap_free(name);
3614 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3615 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3617 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3621 MSFT_ReadAllRefs(&cx);
3623 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3625 /* type infos */
3626 if(tlbHeader.nrtypeinfos >= 0 )
3628 ITypeInfoImpl **ppTI;
3630 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3632 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3634 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3636 ++ppTI;
3637 (pTypeLibImpl->TypeInfoCount)++;
3641 #ifdef _WIN64
3642 if(pTypeLibImpl->syskind == SYS_WIN32){
3643 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3644 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3646 #endif
3648 TRACE("(%p)\n", pTypeLibImpl);
3649 return &pTypeLibImpl->ITypeLib2_iface;
3653 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3655 char b[3];
3656 int i;
3657 short s;
3659 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3660 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3661 return FALSE;
3664 guid->Data4[0] = s >> 8;
3665 guid->Data4[1] = s & 0xff;
3667 b[2] = '\0';
3668 for(i = 0; i < 6; i++) {
3669 memcpy(b, str + 24 + 2 * i, 2);
3670 guid->Data4[i + 2] = strtol(b, NULL, 16);
3672 return TRUE;
3675 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3677 WORD bytelen;
3678 DWORD len;
3679 BSTR tmp_str;
3681 *pStr = NULL;
3682 bytelen = *(const WORD*)ptr;
3683 if(bytelen == 0xffff) return 2;
3685 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3686 tmp_str = SysAllocStringLen(NULL, len);
3687 if (tmp_str) {
3688 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3689 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3690 SysFreeString(tmp_str);
3692 return bytelen + 2;
3695 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3697 WORD bytelen;
3699 *str = NULL;
3700 bytelen = *(const WORD*)ptr;
3701 if(bytelen == 0xffff) return 2;
3702 *str = heap_alloc(bytelen + 1);
3703 memcpy(*str, ptr + 2, bytelen);
3704 (*str)[bytelen] = '\0';
3705 return bytelen + 2;
3708 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3710 BSTR tmp_str;
3711 TLBString *tlbstr;
3713 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3714 if (tlbstr->offset == offset)
3715 return tlbstr;
3718 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3719 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3720 SysFreeString(tmp_str);
3722 return tlbstr;
3725 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3727 char *ptr = pLibBlk;
3728 WORD w;
3730 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3731 FIXME("libblk magic = %04x\n", w);
3732 return 0;
3735 ptr += 6;
3736 if((w = *(WORD*)ptr) != 0xffff) {
3737 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3738 ptr += w;
3740 ptr += 2;
3742 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3744 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3746 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3747 ptr += 4;
3749 pTypeLibImpl->syskind = *(WORD*)ptr;
3750 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3751 ptr += 2;
3753 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3754 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3755 else
3756 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3757 ptr += 2;
3759 ptr += 4; /* skip res12 */
3761 pTypeLibImpl->libflags = *(WORD*)ptr;
3762 ptr += 2;
3764 pTypeLibImpl->ver_major = *(WORD*)ptr;
3765 ptr += 2;
3767 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3768 ptr += 2;
3770 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3771 ptr += sizeof(GUID);
3773 return ptr - (char*)pLibBlk;
3776 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3777 typedef struct
3779 unsigned int num;
3780 HREFTYPE refs[1];
3781 } sltg_ref_lookup_t;
3783 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3784 HREFTYPE *typelib_ref)
3786 if(table && typeinfo_ref < table->num)
3788 *typelib_ref = table->refs[typeinfo_ref];
3789 return S_OK;
3792 ERR_(typelib)("Unable to find reference\n");
3793 *typelib_ref = -1;
3794 return E_FAIL;
3797 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3799 BOOL done = FALSE;
3801 while(!done) {
3802 if((*pType & 0xe00) == 0xe00) {
3803 pTD->vt = VT_PTR;
3804 pTD->lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3805 pTD = pTD->lptdesc;
3807 switch(*pType & 0x3f) {
3808 case VT_PTR:
3809 pTD->vt = VT_PTR;
3810 pTD->lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3811 pTD = pTD->lptdesc;
3812 break;
3814 case VT_USERDEFINED:
3815 pTD->vt = VT_USERDEFINED;
3816 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->hreftype);
3817 done = TRUE;
3818 break;
3820 case VT_CARRAY:
3822 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3823 array */
3825 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3827 pTD->vt = VT_CARRAY;
3828 pTD->lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3829 pTD->lpadesc->cDims = pSA->cDims;
3830 memcpy(pTD->lpadesc->rgbounds, pSA->rgsabound,
3831 pSA->cDims * sizeof(SAFEARRAYBOUND));
3833 pTD = &pTD->lpadesc->tdescElem;
3834 break;
3837 case VT_SAFEARRAY:
3839 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3840 useful? */
3842 pType++;
3843 pTD->vt = VT_SAFEARRAY;
3844 pTD->lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3845 pTD = pTD->lptdesc;
3846 break;
3848 default:
3849 pTD->vt = *pType & 0x3f;
3850 done = TRUE;
3851 break;
3853 pType++;
3855 return pType;
3858 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3859 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3861 /* Handle [in/out] first */
3862 if((*pType & 0xc000) == 0xc000)
3863 pElem->paramdesc.wParamFlags = PARAMFLAG_NONE;
3864 else if(*pType & 0x8000)
3865 pElem->paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3866 else if(*pType & 0x4000)
3867 pElem->paramdesc.wParamFlags = PARAMFLAG_FOUT;
3868 else
3869 pElem->paramdesc.wParamFlags = PARAMFLAG_FIN;
3871 if(*pType & 0x2000)
3872 pElem->paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3874 if(*pType & 0x80)
3875 pElem->paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3877 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3881 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3882 char *pNameTable)
3884 unsigned int ref;
3885 char *name;
3886 TLBRefType *ref_type;
3887 sltg_ref_lookup_t *table;
3888 HREFTYPE typelib_ref;
3890 if(pRef->magic != SLTG_REF_MAGIC) {
3891 FIXME("Ref magic = %x\n", pRef->magic);
3892 return NULL;
3894 name = ( (char*)pRef->names + pRef->number);
3896 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3897 table->num = pRef->number >> 3;
3899 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3901 /* We don't want the first href to be 0 */
3902 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3904 for(ref = 0; ref < pRef->number >> 3; ref++) {
3905 char *refname;
3906 unsigned int lib_offs, type_num;
3908 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3910 name += SLTG_ReadStringA(name, &refname);
3911 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3912 FIXME_(typelib)("Can't sscanf ref\n");
3913 if(lib_offs != 0xffff) {
3914 TLBImpLib *import;
3916 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3917 if(import->offset == lib_offs)
3918 break;
3920 if(&import->entry == &pTL->implib_list) {
3921 char fname[MAX_PATH+1];
3922 int len;
3923 GUID tmpguid;
3925 import = heap_alloc_zero(sizeof(*import));
3926 import->offset = lib_offs;
3927 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3928 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3929 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
3930 &import->wVersionMajor,
3931 &import->wVersionMinor,
3932 &import->lcid, fname) != 4) {
3933 FIXME_(typelib)("can't sscanf ref %s\n",
3934 pNameTable + lib_offs + 40);
3936 len = strlen(fname);
3937 if(fname[len-1] != '#')
3938 FIXME("fname = %s\n", fname);
3939 fname[len-1] = '\0';
3940 import->name = TLB_MultiByteToBSTR(fname);
3941 list_add_tail(&pTL->implib_list, &import->entry);
3943 ref_type->pImpTLInfo = import;
3945 /* Store a reference to IDispatch */
3946 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3947 pTL->dispatch_href = typelib_ref;
3949 } else { /* internal ref */
3950 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3952 ref_type->reference = typelib_ref;
3953 ref_type->index = type_num;
3955 heap_free(refname);
3956 list_add_tail(&pTL->ref_list, &ref_type->entry);
3958 table->refs[ref] = typelib_ref;
3959 typelib_ref += 4;
3961 if((BYTE)*name != SLTG_REF_MAGIC)
3962 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3963 dump_TLBRefType(pTL);
3964 return table;
3967 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3968 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3970 SLTG_ImplInfo *info;
3971 TLBImplType *pImplType;
3972 /* I don't really get this structure, usually it's 0x16 bytes
3973 long, but iuser.tlb contains some that are 0x18 bytes long.
3974 That's ok because we can use the next ptr to jump to the next
3975 one. But how do we know the length of the last one? The WORD
3976 at offs 0x8 might be the clue. For now I'm just assuming that
3977 the last one is the regular 0x16 bytes. */
3979 info = (SLTG_ImplInfo*)pBlk;
3980 while(1){
3981 pTI->typeattr.cImplTypes++;
3982 if(info->next == 0xffff)
3983 break;
3984 info = (SLTG_ImplInfo*)(pBlk + info->next);
3987 info = (SLTG_ImplInfo*)pBlk;
3988 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3989 pImplType = pTI->impltypes;
3990 while(1) {
3991 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3992 pImplType->implflags = info->impltypeflags;
3993 ++pImplType;
3995 if(info->next == 0xffff)
3996 break;
3997 if(OneOnly)
3998 FIXME_(typelib)("Interface inheriting more than one interface\n");
3999 info = (SLTG_ImplInfo*)(pBlk + info->next);
4001 info++; /* see comment at top of function */
4002 return (char*)info;
4005 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4006 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4008 TLBVarDesc *pVarDesc;
4009 const TLBString *prevName = NULL;
4010 SLTG_Variable *pItem;
4011 unsigned short i;
4012 WORD *pType;
4014 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4016 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4017 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4019 pVarDesc->vardesc.memid = pItem->memid;
4021 if (pItem->magic != SLTG_VAR_MAGIC &&
4022 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4023 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4024 return;
4027 if (pItem->name == 0xfffe)
4028 pVarDesc->Name = prevName;
4029 else
4030 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4032 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4033 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4034 TRACE_(typelib)("memid = %#lx\n", pItem->memid);
4036 if(pItem->flags & 0x02)
4037 pType = &pItem->type;
4038 else
4039 pType = (WORD*)(pBlk + pItem->type);
4041 if (pItem->flags & ~0xda)
4042 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4044 SLTG_DoElem(pType, pBlk,
4045 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4047 if (TRACE_ON(typelib)) {
4048 char buf[300];
4049 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4050 TRACE_(typelib)("elemdescVar: %s\n", buf);
4053 if (pItem->flags & 0x40) {
4054 TRACE_(typelib)("VAR_DISPATCH\n");
4055 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4057 else if (pItem->flags & 0x10) {
4058 TRACE_(typelib)("VAR_CONST\n");
4059 pVarDesc->vardesc.varkind = VAR_CONST;
4060 pVarDesc->vardesc.lpvarValue = heap_alloc(sizeof(VARIANT));
4061 V_VT(pVarDesc->vardesc.lpvarValue) = VT_INT;
4062 if (pItem->flags & 0x08)
4063 V_INT(pVarDesc->vardesc.lpvarValue) = pItem->byte_offs;
4064 else {
4065 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4067 case VT_LPSTR:
4068 case VT_LPWSTR:
4069 case VT_BSTR:
4071 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4072 BSTR str;
4073 TRACE_(typelib)("len = %u\n", len);
4074 if (len == 0xffff) {
4075 str = NULL;
4076 } else {
4077 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4078 str = SysAllocStringLen(NULL, alloc_len);
4079 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4081 V_VT(pVarDesc->vardesc.lpvarValue) = VT_BSTR;
4082 V_BSTR(pVarDesc->vardesc.lpvarValue) = str;
4083 break;
4085 case VT_I2:
4086 case VT_UI2:
4087 case VT_I4:
4088 case VT_UI4:
4089 case VT_INT:
4090 case VT_UINT:
4091 V_INT(pVarDesc->vardesc.lpvarValue) =
4092 *(INT*)(pBlk + pItem->byte_offs);
4093 break;
4094 default:
4095 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4099 else {
4100 TRACE_(typelib)("VAR_PERINSTANCE\n");
4101 pVarDesc->vardesc.oInst = pItem->byte_offs;
4102 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4105 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4106 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4108 if (pItem->flags & 0x80)
4109 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4111 prevName = pVarDesc->Name;
4113 pTI->typeattr.cVars = cVars;
4116 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4117 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4119 SLTG_Function *pFunc;
4120 unsigned short i;
4121 TLBFuncDesc *pFuncDesc;
4123 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4125 pFuncDesc = pTI->funcdescs;
4126 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4127 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4129 int param;
4130 WORD *pType, *pArg;
4132 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4133 case SLTG_FUNCTION_MAGIC:
4134 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4135 break;
4136 case SLTG_DISPATCH_FUNCTION_MAGIC:
4137 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4138 break;
4139 case SLTG_STATIC_FUNCTION_MAGIC:
4140 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4141 break;
4142 default:
4143 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4144 continue;
4146 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4148 pFuncDesc->funcdesc.memid = pFunc->dispid;
4149 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4150 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4151 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4152 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4153 if (pFuncDesc->funcdesc.funckind == FUNC_DISPATCH)
4154 pFuncDesc->funcdesc.oVft = 0;
4155 else
4156 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4158 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4159 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4161 if(pFunc->retnextopt & 0x80)
4162 pType = &pFunc->rettype;
4163 else
4164 pType = (WORD*)(pBlk + pFunc->rettype);
4166 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4168 pFuncDesc->funcdesc.lprgelemdescParam =
4169 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4170 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4172 pArg = (WORD*)(pBlk + pFunc->arg_off);
4174 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4175 char *paramName = pNameTable + *pArg;
4176 BOOL HaveOffs;
4177 /* If arg type follows then paramName points to the 2nd
4178 letter of the name, else the next WORD is an offset to
4179 the arg type and paramName points to the first letter.
4180 So let's take one char off paramName and see if we're
4181 pointing at an alphanumeric char. However if *pArg is
4182 0xffff or 0xfffe then the param has no name, the former
4183 meaning that the next WORD is the type, the latter
4184 meaning that the next WORD is an offset to the type. */
4186 HaveOffs = FALSE;
4187 if(*pArg == 0xffff)
4188 paramName = NULL;
4189 else if(*pArg == 0xfffe) {
4190 paramName = NULL;
4191 HaveOffs = TRUE;
4193 else if(paramName[-1] && !isalnum(paramName[-1]))
4194 HaveOffs = TRUE;
4196 pArg++;
4198 if(HaveOffs) { /* the next word is an offset to type */
4199 pType = (WORD*)(pBlk + *pArg);
4200 SLTG_DoElem(pType, pBlk,
4201 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4202 pArg++;
4203 } else {
4204 if(paramName)
4205 paramName--;
4206 pArg = SLTG_DoElem(pArg, pBlk,
4207 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4210 /* Are we an optional param ? */
4211 if(pFuncDesc->funcdesc.cParams - param <=
4212 pFuncDesc->funcdesc.cParamsOpt)
4213 pFuncDesc->funcdesc.lprgelemdescParam[param].paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4215 if(paramName) {
4216 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4217 paramName - pNameTable, pTI->pTypeLib);
4218 } else {
4219 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4223 pTI->typeattr.cFuncs = cFuncs;
4226 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4227 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4228 SLTG_TypeInfoTail *pTITail)
4230 char *pFirstItem;
4231 sltg_ref_lookup_t *ref_lookup = NULL;
4233 if(pTIHeader->href_table != 0xffffffff) {
4234 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4235 pNameTable);
4238 pFirstItem = pBlk;
4240 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4241 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4243 heap_free(ref_lookup);
4247 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4248 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4249 const SLTG_TypeInfoTail *pTITail)
4251 char *pFirstItem;
4252 sltg_ref_lookup_t *ref_lookup = NULL;
4254 if(pTIHeader->href_table != 0xffffffff) {
4255 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4256 pNameTable);
4259 pFirstItem = pBlk;
4261 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4262 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4265 if (pTITail->funcs_off != 0xffff)
4266 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4268 heap_free(ref_lookup);
4270 if (TRACE_ON(typelib))
4271 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4274 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4275 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4276 const SLTG_TypeInfoTail *pTITail)
4278 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4281 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4282 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4283 const SLTG_TypeInfoTail *pTITail)
4285 WORD *pType;
4286 sltg_ref_lookup_t *ref_lookup = NULL;
4288 if (pTITail->simple_alias) {
4289 /* if simple alias, no more processing required */
4290 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4291 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4292 return;
4295 if(pTIHeader->href_table != 0xffffffff) {
4296 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4297 pNameTable);
4300 /* otherwise it is an offset to a type */
4301 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4303 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4304 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4306 heap_free(ref_lookup);
4309 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4310 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4311 const SLTG_TypeInfoTail *pTITail)
4313 sltg_ref_lookup_t *ref_lookup = NULL;
4314 if (pTIHeader->href_table != 0xffffffff)
4315 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4316 pNameTable);
4318 if (pTITail->vars_off != 0xffff)
4319 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4321 if (pTITail->funcs_off != 0xffff)
4322 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4324 if (pTITail->impls_off != 0xffff)
4325 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4327 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4328 * of dispinterface functions including the IDispatch ones, so
4329 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4330 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4332 heap_free(ref_lookup);
4333 if (TRACE_ON(typelib))
4334 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4337 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4338 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4339 const SLTG_TypeInfoTail *pTITail)
4341 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4344 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4345 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4346 const SLTG_TypeInfoTail *pTITail)
4348 sltg_ref_lookup_t *ref_lookup = NULL;
4349 if (pTIHeader->href_table != 0xffffffff)
4350 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4351 pNameTable);
4353 if (pTITail->vars_off != 0xffff)
4354 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4356 if (pTITail->funcs_off != 0xffff)
4357 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4358 heap_free(ref_lookup);
4359 if (TRACE_ON(typelib))
4360 dump_TypeInfo(pTI);
4363 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4364 manageable copy of it into this */
4365 typedef struct {
4366 WORD small_no;
4367 char *index_name;
4368 char *other_name;
4369 WORD res1a;
4370 WORD name_offs;
4371 WORD more_bytes;
4372 char *extra;
4373 WORD res20;
4374 DWORD helpcontext;
4375 WORD res26;
4376 GUID uuid;
4377 } SLTG_InternalOtherTypeInfo;
4379 /****************************************************************************
4380 * ITypeLib2_Constructor_SLTG
4382 * loading a SLTG typelib from an in-memory image
4384 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4386 ITypeLibImpl *pTypeLibImpl;
4387 SLTG_Header *pHeader;
4388 SLTG_BlkEntry *pBlkEntry;
4389 SLTG_Magic *pMagic;
4390 SLTG_Index *pIndex;
4391 SLTG_Pad9 *pPad9;
4392 LPVOID pBlk, pFirstBlk;
4393 SLTG_LibBlk *pLibBlk;
4394 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4395 char *pAfterOTIBlks = NULL;
4396 char *pNameTable, *ptr;
4397 int i;
4398 DWORD len, order;
4399 ITypeInfoImpl **ppTypeInfoImpl;
4401 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
4404 pTypeLibImpl = TypeLibImpl_Constructor();
4405 if (!pTypeLibImpl) return NULL;
4407 pHeader = pLib;
4409 TRACE_(typelib)("header:\n");
4410 TRACE_(typelib)("\tmagic %#lx, file blocks = %d\n", pHeader->SLTG_magic,
4411 pHeader->nrOfFileBlks );
4412 if (pHeader->SLTG_magic != SLTG_SIGNATURE)
4414 FIXME_(typelib)("Header type magic %#lx not supported.\n", pHeader->SLTG_magic);
4415 return NULL;
4418 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4419 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4421 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4422 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4424 /* Next we have a magic block */
4425 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4427 /* Let's see if we're still in sync */
4428 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4429 sizeof(SLTG_COMPOBJ_MAGIC))) {
4430 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4431 return NULL;
4433 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4434 sizeof(SLTG_DIR_MAGIC))) {
4435 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4436 return NULL;
4439 pIndex = (SLTG_Index*)(pMagic+1);
4441 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4443 pFirstBlk = pPad9 + 1;
4445 /* We'll set up a ptr to the main library block, which is the last one. */
4447 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4448 pBlkEntry[order].next != 0;
4449 order = pBlkEntry[order].next - 1) {
4450 pBlk = (char*)pBlk + pBlkEntry[order].len;
4452 pLibBlk = pBlk;
4454 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4456 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4457 interspersed */
4459 len += 0x40;
4461 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4463 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4466 ptr = (char*)pLibBlk + len;
4468 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4469 WORD w, extra;
4470 len = 0;
4472 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4474 w = *(WORD*)(ptr + 2);
4475 if(w != 0xffff) {
4476 len += w;
4477 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4478 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4479 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4481 w = *(WORD*)(ptr + 4 + len);
4482 if(w != 0xffff) {
4483 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4484 len += w;
4485 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4486 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4487 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4489 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4490 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4491 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4492 if(extra) {
4493 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4494 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4495 len += extra;
4497 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4498 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4499 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4500 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4501 len += sizeof(SLTG_OtherTypeInfo);
4502 ptr += len;
4505 pAfterOTIBlks = ptr;
4507 /* Skip this WORD and get the next DWORD */
4508 len = *(DWORD*)(pAfterOTIBlks + 2);
4510 /* Now add this to pLibBLk look at what we're pointing at and
4511 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4512 dust and we should be pointing at the beginning of the name
4513 table */
4515 pNameTable = (char*)pLibBlk + len;
4517 switch(*(WORD*)pNameTable) {
4518 case 0xffff:
4519 break;
4520 case 0x0200:
4521 pNameTable += 0x20;
4522 break;
4523 default:
4524 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4525 break;
4528 pNameTable += 0x216;
4530 pNameTable += 2;
4532 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4534 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4537 /* Hopefully we now have enough ptrs set up to actually read in
4538 some TypeInfos. It's not clear which order to do them in, so
4539 I'll just follow the links along the BlkEntry chain and read
4540 them in the order in which they are in the file */
4542 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4543 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4545 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4546 pBlkEntry[order].next != 0;
4547 order = pBlkEntry[order].next - 1, i++) {
4549 SLTG_TypeInfoHeader *pTIHeader;
4550 SLTG_TypeInfoTail *pTITail;
4551 SLTG_MemberHeader *pMemHeader;
4553 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4554 FIXME_(typelib)("Index strings don't match\n");
4555 heap_free(pOtherTypeInfoBlks);
4556 return NULL;
4559 pTIHeader = pBlk;
4560 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4561 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4562 heap_free(pOtherTypeInfoBlks);
4563 return NULL;
4565 TRACE_(typelib)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4566 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4567 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4569 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4570 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4571 (*ppTypeInfoImpl)->index = i;
4572 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4573 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4574 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4575 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4576 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4577 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4578 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4579 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4581 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4582 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4584 if((pTIHeader->typeflags1 & 7) != 2)
4585 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4586 if(pTIHeader->typeflags3 != 2)
4587 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4589 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4590 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4591 typekind_desc[pTIHeader->typekind],
4592 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4593 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4595 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4597 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4599 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4600 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4601 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4603 switch(pTIHeader->typekind) {
4604 case TKIND_ENUM:
4605 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4606 pTIHeader, pTITail);
4607 break;
4609 case TKIND_RECORD:
4610 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4611 pTIHeader, pTITail);
4612 break;
4614 case TKIND_INTERFACE:
4615 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4616 pTIHeader, pTITail);
4617 break;
4619 case TKIND_COCLASS:
4620 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4621 pTIHeader, pTITail);
4622 break;
4624 case TKIND_ALIAS:
4625 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4626 pTIHeader, pTITail);
4627 break;
4629 case TKIND_DISPATCH:
4630 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4631 pTIHeader, pTITail);
4632 break;
4634 case TKIND_MODULE:
4635 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4636 pTIHeader, pTITail);
4637 break;
4639 default:
4640 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4641 break;
4645 /* could get cFuncs, cVars and cImplTypes from here
4646 but we've already set those */
4647 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4648 X(06);
4649 X(16);
4650 X(18);
4651 X(1a);
4652 X(1e);
4653 X(24);
4654 X(26);
4655 X(2a);
4656 X(2c);
4657 X(2e);
4658 X(30);
4659 X(32);
4660 X(34);
4661 #undef X
4662 ++ppTypeInfoImpl;
4663 pBlk = (char*)pBlk + pBlkEntry[order].len;
4666 if(i != pTypeLibImpl->TypeInfoCount) {
4667 FIXME("Somehow processed %d TypeInfos\n", i);
4668 heap_free(pOtherTypeInfoBlks);
4669 return NULL;
4672 heap_free(pOtherTypeInfoBlks);
4673 return &pTypeLibImpl->ITypeLib2_iface;
4676 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4678 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4680 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4682 if(IsEqualIID(riid, &IID_IUnknown) ||
4683 IsEqualIID(riid,&IID_ITypeLib)||
4684 IsEqualIID(riid,&IID_ITypeLib2))
4686 *ppv = &This->ITypeLib2_iface;
4688 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4689 IsEqualIID(riid, &IID_ICreateTypeLib2))
4691 *ppv = &This->ICreateTypeLib2_iface;
4693 else
4695 *ppv = NULL;
4696 TRACE("-- Interface: E_NOINTERFACE\n");
4697 return E_NOINTERFACE;
4700 IUnknown_AddRef((IUnknown*)*ppv);
4701 return S_OK;
4704 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4706 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4707 ULONG ref = InterlockedIncrement(&This->ref);
4709 TRACE("%p, refcount %lu.\n", iface, ref);
4711 return ref;
4714 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4716 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4717 ULONG ref = InterlockedDecrement(&This->ref);
4719 TRACE("%p, refcount %lu.\n", iface, ref);
4721 if (!ref)
4723 TLBImpLib *pImpLib, *pImpLibNext;
4724 TLBRefType *ref_type, *ref_type_next;
4725 TLBString *tlbstr, *tlbstr_next;
4726 TLBGuid *tlbguid, *tlbguid_next;
4727 int i;
4729 /* remove cache entry */
4730 if(This->path)
4732 TRACE("removing from cache list\n");
4733 EnterCriticalSection(&cache_section);
4734 if(This->entry.next)
4735 list_remove(&This->entry);
4736 LeaveCriticalSection(&cache_section);
4737 heap_free(This->path);
4739 TRACE(" destroying ITypeLib(%p)\n",This);
4741 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4742 list_remove(&tlbstr->entry);
4743 SysFreeString(tlbstr->str);
4744 heap_free(tlbstr);
4747 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4748 list_remove(&tlbstr->entry);
4749 SysFreeString(tlbstr->str);
4750 heap_free(tlbstr);
4753 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4754 list_remove(&tlbguid->entry);
4755 heap_free(tlbguid);
4758 TLB_FreeCustData(&This->custdata_list);
4760 for (i = 0; i < This->ctTypeDesc; i++)
4761 if (This->pTypeDesc[i].vt == VT_CARRAY)
4762 heap_free(This->pTypeDesc[i].lpadesc);
4764 heap_free(This->pTypeDesc);
4766 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4768 if (pImpLib->pImpTypeLib)
4769 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4770 SysFreeString(pImpLib->name);
4772 list_remove(&pImpLib->entry);
4773 heap_free(pImpLib);
4776 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4778 list_remove(&ref_type->entry);
4779 heap_free(ref_type);
4782 for (i = 0; i < This->TypeInfoCount; ++i){
4783 heap_free(This->typeinfos[i]->tdescAlias);
4784 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4786 heap_free(This->typeinfos);
4787 heap_free(This);
4788 return 0;
4791 return ref;
4794 /* ITypeLib::GetTypeInfoCount
4796 * Returns the number of type descriptions in the type library
4798 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4800 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4801 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4802 return This->TypeInfoCount;
4805 /* ITypeLib::GetTypeInfo
4807 * retrieves the specified type description in the library.
4809 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4810 ITypeLib2 *iface,
4811 UINT index,
4812 ITypeInfo **ppTInfo)
4814 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4816 TRACE("%p %u %p\n", This, index, ppTInfo);
4818 if(!ppTInfo)
4819 return E_INVALIDARG;
4821 if(index >= This->TypeInfoCount)
4822 return TYPE_E_ELEMENTNOTFOUND;
4824 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4825 ITypeInfo_AddRef(*ppTInfo);
4827 return S_OK;
4831 /* ITypeLibs::GetTypeInfoType
4833 * Retrieves the type of a type description.
4835 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4836 ITypeLib2 *iface,
4837 UINT index,
4838 TYPEKIND *pTKind)
4840 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4842 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4844 if(!pTKind)
4845 return E_INVALIDARG;
4847 if(index >= This->TypeInfoCount)
4848 return TYPE_E_ELEMENTNOTFOUND;
4850 *pTKind = This->typeinfos[index]->typeattr.typekind;
4852 return S_OK;
4855 /* ITypeLib::GetTypeInfoOfGuid
4857 * Retrieves the type description that corresponds to the specified GUID.
4860 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4861 ITypeLib2 *iface,
4862 REFGUID guid,
4863 ITypeInfo **ppTInfo)
4865 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4866 int i;
4868 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4870 for(i = 0; i < This->TypeInfoCount; ++i){
4871 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4872 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4873 ITypeInfo_AddRef(*ppTInfo);
4874 return S_OK;
4878 return TYPE_E_ELEMENTNOTFOUND;
4881 /* ITypeLib::GetLibAttr
4883 * Retrieves the structure that contains the library's attributes.
4886 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4887 ITypeLib2 *iface,
4888 LPTLIBATTR *attr)
4890 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4892 TRACE("(%p, %p)\n", This, attr);
4894 if (!attr) return E_INVALIDARG;
4896 *attr = heap_alloc(sizeof(**attr));
4897 if (!*attr) return E_OUTOFMEMORY;
4899 (*attr)->guid = *TLB_get_guid_null(This->guid);
4900 (*attr)->lcid = This->set_lcid;
4901 (*attr)->syskind = This->syskind;
4902 (*attr)->wMajorVerNum = This->ver_major;
4903 (*attr)->wMinorVerNum = This->ver_minor;
4904 (*attr)->wLibFlags = This->libflags;
4906 return S_OK;
4909 /* ITypeLib::GetTypeComp
4911 * Enables a client compiler to bind to a library's types, variables,
4912 * constants, and global functions.
4915 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4916 ITypeLib2 *iface,
4917 ITypeComp **ppTComp)
4919 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4921 TRACE("(%p)->(%p)\n",This,ppTComp);
4922 *ppTComp = &This->ITypeComp_iface;
4923 ITypeComp_AddRef(*ppTComp);
4925 return S_OK;
4928 /* ITypeLib::GetDocumentation
4930 * Retrieves the library's documentation string, the complete Help file name
4931 * and path, and the context identifier for the library Help topic in the Help
4932 * file.
4934 * On a successful return all non-null BSTR pointers will have been set,
4935 * possibly to NULL.
4937 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4938 ITypeLib2 *iface,
4939 INT index,
4940 BSTR *pBstrName,
4941 BSTR *pBstrDocString,
4942 DWORD *pdwHelpContext,
4943 BSTR *pBstrHelpFile)
4945 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4946 HRESULT result = E_INVALIDARG;
4947 ITypeInfo *pTInfo;
4949 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4950 This, index,
4951 pBstrName, pBstrDocString,
4952 pdwHelpContext, pBstrHelpFile);
4954 if(index<0)
4956 /* documentation for the typelib */
4957 if(pBstrName)
4959 if (This->Name)
4961 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4962 goto memerr1;
4964 else
4965 *pBstrName = NULL;
4967 if(pBstrDocString)
4969 if (This->DocString)
4971 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4972 goto memerr2;
4974 else
4975 *pBstrDocString = NULL;
4977 if(pdwHelpContext)
4979 *pdwHelpContext = This->dwHelpContext;
4981 if(pBstrHelpFile)
4983 if (This->HelpFile)
4985 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4986 goto memerr3;
4988 else
4989 *pBstrHelpFile = NULL;
4992 result = S_OK;
4994 else
4996 /* for a typeinfo */
4997 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4999 if(SUCCEEDED(result))
5001 result = ITypeInfo_GetDocumentation(pTInfo,
5002 MEMBERID_NIL,
5003 pBstrName,
5004 pBstrDocString,
5005 pdwHelpContext, pBstrHelpFile);
5007 ITypeInfo_Release(pTInfo);
5010 return result;
5011 memerr3:
5012 if (pBstrDocString) SysFreeString (*pBstrDocString);
5013 memerr2:
5014 if (pBstrName) SysFreeString (*pBstrName);
5015 memerr1:
5016 return STG_E_INSUFFICIENTMEMORY;
5019 /* ITypeLib::IsName
5021 * Indicates whether a passed-in string contains the name of a type or member
5022 * described in the library.
5025 static HRESULT WINAPI ITypeLib2_fnIsName(
5026 ITypeLib2 *iface,
5027 LPOLESTR szNameBuf,
5028 ULONG lHashVal,
5029 BOOL *pfName)
5031 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5032 int tic;
5033 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5035 TRACE("%p, %s, %#lx, %p.\n", iface, debugstr_w(szNameBuf), lHashVal, pfName);
5037 *pfName=TRUE;
5038 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5039 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5040 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5041 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5042 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5043 int pc;
5044 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5045 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5046 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5047 goto ITypeLib2_fnIsName_exit;
5050 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5051 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5052 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5056 *pfName=FALSE;
5058 ITypeLib2_fnIsName_exit:
5059 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5060 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5062 return S_OK;
5065 /* ITypeLib::FindName
5067 * Finds occurrences of a type description in a type library. This may be used
5068 * to quickly verify that a name exists in a type library.
5071 static HRESULT WINAPI ITypeLib2_fnFindName(
5072 ITypeLib2 *iface,
5073 LPOLESTR name,
5074 ULONG hash,
5075 ITypeInfo **ppTInfo,
5076 MEMBERID *memid,
5077 UINT16 *found)
5079 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5080 int tic;
5081 UINT count = 0;
5082 UINT len;
5084 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface, debugstr_w(name), hash, ppTInfo, memid, found);
5086 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5087 return E_INVALIDARG;
5089 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5090 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5091 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5092 TLBVarDesc *var;
5093 UINT fdc;
5095 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5096 memid[count] = MEMBERID_NIL;
5097 goto ITypeLib2_fnFindName_exit;
5100 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5101 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5103 if(!TLB_str_memcmp(name, func->Name, len)) {
5104 memid[count] = func->funcdesc.memid;
5105 goto ITypeLib2_fnFindName_exit;
5109 var = TLB_get_vardesc_by_name(pTInfo, name);
5110 if (var) {
5111 memid[count] = var->vardesc.memid;
5112 goto ITypeLib2_fnFindName_exit;
5115 continue;
5116 ITypeLib2_fnFindName_exit:
5117 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5118 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5119 count++;
5121 TRACE("found %d typeinfos\n", count);
5123 *found = count;
5125 return S_OK;
5128 /* ITypeLib::ReleaseTLibAttr
5130 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5133 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5134 ITypeLib2 *iface,
5135 TLIBATTR *pTLibAttr)
5137 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5138 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5139 heap_free(pTLibAttr);
5142 /* ITypeLib2::GetCustData
5144 * gets the custom data
5146 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5147 ITypeLib2 * iface,
5148 REFGUID guid,
5149 VARIANT *pVarVal)
5151 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5152 TLBCustData *pCData;
5154 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5156 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5157 if(!pCData)
5158 return TYPE_E_ELEMENTNOTFOUND;
5160 VariantInit(pVarVal);
5161 VariantCopy(pVarVal, &pCData->data);
5163 return S_OK;
5166 /* ITypeLib2::GetLibStatistics
5168 * Returns statistics about a type library that are required for efficient
5169 * sizing of hash tables.
5172 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5173 ITypeLib2 * iface,
5174 ULONG *pcUniqueNames,
5175 ULONG *pcchUniqueNames)
5177 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5179 FIXME("(%p): stub!\n", This);
5181 if(pcUniqueNames) *pcUniqueNames=1;
5182 if(pcchUniqueNames) *pcchUniqueNames=1;
5183 return S_OK;
5186 /* ITypeLib2::GetDocumentation2
5188 * Retrieves the library's documentation string, the complete Help file name
5189 * and path, the localization context to use, and the context ID for the
5190 * library Help topic in the Help file.
5193 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5194 ITypeLib2 * iface,
5195 INT index,
5196 LCID lcid,
5197 BSTR *pbstrHelpString,
5198 DWORD *pdwHelpStringContext,
5199 BSTR *pbstrHelpStringDll)
5201 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5202 HRESULT result;
5203 ITypeInfo *pTInfo;
5205 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface, index, lcid);
5207 /* the help string should be obtained from the helpstringdll,
5208 * using the _DLLGetDocumentation function, based on the supplied
5209 * lcid. Nice to do sometime...
5211 if(index<0)
5213 /* documentation for the typelib */
5214 if(pbstrHelpString)
5215 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5216 if(pdwHelpStringContext)
5217 *pdwHelpStringContext=This->dwHelpContext;
5218 if(pbstrHelpStringDll)
5219 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5221 result = S_OK;
5223 else
5225 /* for a typeinfo */
5226 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5228 if(SUCCEEDED(result))
5230 ITypeInfo2 * pTInfo2;
5231 result = ITypeInfo_QueryInterface(pTInfo,
5232 &IID_ITypeInfo2,
5233 (LPVOID*) &pTInfo2);
5235 if(SUCCEEDED(result))
5237 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5238 MEMBERID_NIL,
5239 lcid,
5240 pbstrHelpString,
5241 pdwHelpStringContext,
5242 pbstrHelpStringDll);
5244 ITypeInfo2_Release(pTInfo2);
5247 ITypeInfo_Release(pTInfo);
5250 return result;
5253 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5255 TLBCustData *pCData;
5256 unsigned int ct;
5257 CUSTDATAITEM *cdi;
5258 HRESULT hr = S_OK;
5260 ct = list_count(custdata_list);
5262 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5263 if(!pCustData->prgCustData)
5264 return E_OUTOFMEMORY;
5266 pCustData->cCustData = ct;
5268 cdi = pCustData->prgCustData;
5269 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5270 cdi->guid = *TLB_get_guid_null(pCData->guid);
5271 VariantInit(&cdi->varValue);
5272 hr = VariantCopy(&cdi->varValue, &pCData->data);
5273 if(FAILED(hr)) break;
5274 ++cdi;
5277 return hr;
5281 /* ITypeLib2::GetAllCustData
5283 * Gets all custom data items for the library.
5286 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5287 ITypeLib2 * iface,
5288 CUSTDATA *pCustData)
5290 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5291 TRACE("(%p)->(%p)\n", This, pCustData);
5292 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5295 static const ITypeLib2Vtbl tlbvt = {
5296 ITypeLib2_fnQueryInterface,
5297 ITypeLib2_fnAddRef,
5298 ITypeLib2_fnRelease,
5299 ITypeLib2_fnGetTypeInfoCount,
5300 ITypeLib2_fnGetTypeInfo,
5301 ITypeLib2_fnGetTypeInfoType,
5302 ITypeLib2_fnGetTypeInfoOfGuid,
5303 ITypeLib2_fnGetLibAttr,
5304 ITypeLib2_fnGetTypeComp,
5305 ITypeLib2_fnGetDocumentation,
5306 ITypeLib2_fnIsName,
5307 ITypeLib2_fnFindName,
5308 ITypeLib2_fnReleaseTLibAttr,
5310 ITypeLib2_fnGetCustData,
5311 ITypeLib2_fnGetLibStatistics,
5312 ITypeLib2_fnGetDocumentation2,
5313 ITypeLib2_fnGetAllCustData
5317 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5319 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5321 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5324 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5326 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5328 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5331 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5333 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5335 return ITypeLib2_Release(&This->ITypeLib2_iface);
5338 static HRESULT WINAPI ITypeLibComp_fnBind(
5339 ITypeComp * iface,
5340 OLECHAR * szName,
5341 ULONG lHash,
5342 WORD wFlags,
5343 ITypeInfo ** ppTInfo,
5344 DESCKIND * pDescKind,
5345 BINDPTR * pBindPtr)
5347 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5348 BOOL typemismatch = FALSE;
5349 int i;
5351 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5353 *pDescKind = DESCKIND_NONE;
5354 pBindPtr->lptcomp = NULL;
5355 *ppTInfo = NULL;
5357 for(i = 0; i < This->TypeInfoCount; ++i){
5358 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5359 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5361 /* FIXME: check wFlags here? */
5362 /* FIXME: we should use a hash table to look this info up using lHash
5363 * instead of an O(n) search */
5364 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5365 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5367 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5369 *pDescKind = DESCKIND_TYPECOMP;
5370 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5371 ITypeComp_AddRef(pBindPtr->lptcomp);
5372 TRACE("module or enum: %s\n", debugstr_w(szName));
5373 return S_OK;
5377 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5378 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5380 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5381 HRESULT hr;
5383 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5384 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5386 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5387 return S_OK;
5389 else if (hr == TYPE_E_TYPEMISMATCH)
5390 typemismatch = TRUE;
5393 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5394 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5396 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5397 HRESULT hr;
5398 ITypeInfo *subtypeinfo;
5399 BINDPTR subbindptr;
5400 DESCKIND subdesckind;
5402 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5403 &subtypeinfo, &subdesckind, &subbindptr);
5404 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5406 TYPEDESC tdesc_appobject;
5407 const VARDESC vardesc_appobject =
5409 -2, /* memid */
5410 NULL, /* lpstrSchema */
5412 0 /* oInst */
5415 /* ELEMDESC */
5417 /* TYPEDESC */
5419 &tdesc_appobject
5421 VT_PTR
5424 0, /* wVarFlags */
5425 VAR_STATIC /* varkind */
5428 tdesc_appobject.hreftype = pTypeInfo->hreftype;
5429 tdesc_appobject.vt = VT_USERDEFINED;
5431 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5433 /* cleanup things filled in by Bind call so we can put our
5434 * application object data in there instead */
5435 switch (subdesckind)
5437 case DESCKIND_FUNCDESC:
5438 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5439 break;
5440 case DESCKIND_VARDESC:
5441 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5442 break;
5443 default:
5444 break;
5446 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5448 if (pTypeInfo->hreftype == -1)
5449 FIXME("no hreftype for interface %p\n", pTypeInfo);
5451 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5452 if (FAILED(hr))
5453 return hr;
5455 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5456 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5457 ITypeInfo_AddRef(*ppTInfo);
5458 return S_OK;
5460 else if (hr == TYPE_E_TYPEMISMATCH)
5461 typemismatch = TRUE;
5465 if (typemismatch)
5467 TRACE("type mismatch %s\n", debugstr_w(szName));
5468 return TYPE_E_TYPEMISMATCH;
5470 else
5472 TRACE("name not found %s\n", debugstr_w(szName));
5473 return S_OK;
5477 static HRESULT WINAPI ITypeLibComp_fnBindType(
5478 ITypeComp * iface,
5479 OLECHAR * szName,
5480 ULONG lHash,
5481 ITypeInfo ** ppTInfo,
5482 ITypeComp ** ppTComp)
5484 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5485 ITypeInfoImpl *info;
5487 TRACE("%p, %s, %#lx, %p, %p.\n", iface, debugstr_w(szName), lHash, ppTInfo, ppTComp);
5489 if(!szName || !ppTInfo || !ppTComp)
5490 return E_INVALIDARG;
5492 info = TLB_get_typeinfo_by_name(This, szName);
5493 if(!info){
5494 *ppTInfo = NULL;
5495 *ppTComp = NULL;
5496 return S_OK;
5499 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5500 ITypeInfo_AddRef(*ppTInfo);
5501 *ppTComp = &info->ITypeComp_iface;
5502 ITypeComp_AddRef(*ppTComp);
5504 return S_OK;
5507 static const ITypeCompVtbl tlbtcvt =
5510 ITypeLibComp_fnQueryInterface,
5511 ITypeLibComp_fnAddRef,
5512 ITypeLibComp_fnRelease,
5514 ITypeLibComp_fnBind,
5515 ITypeLibComp_fnBindType
5518 /*================== ITypeInfo(2) Methods ===================================*/
5519 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5521 ITypeInfoImpl *pTypeInfoImpl;
5523 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5524 if (pTypeInfoImpl)
5526 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5527 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5528 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5529 pTypeInfoImpl->ref = 0;
5530 pTypeInfoImpl->hreftype = -1;
5531 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5532 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5533 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5534 list_init(pTypeInfoImpl->pcustdata_list);
5536 TRACE("(%p)\n", pTypeInfoImpl);
5537 return pTypeInfoImpl;
5540 /* ITypeInfo::QueryInterface
5542 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5543 ITypeInfo2 *iface,
5544 REFIID riid,
5545 VOID **ppvObject)
5547 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5549 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5551 *ppvObject=NULL;
5552 if(IsEqualIID(riid, &IID_IUnknown) ||
5553 IsEqualIID(riid,&IID_ITypeInfo)||
5554 IsEqualIID(riid,&IID_ITypeInfo2))
5555 *ppvObject = &This->ITypeInfo2_iface;
5556 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5557 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5558 *ppvObject = &This->ICreateTypeInfo2_iface;
5559 else if(IsEqualIID(riid, &IID_ITypeComp))
5560 *ppvObject = &This->ITypeComp_iface;
5562 if(*ppvObject){
5563 IUnknown_AddRef((IUnknown*)*ppvObject);
5564 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5565 return S_OK;
5567 TRACE("-- Interface: E_NOINTERFACE\n");
5568 return E_NOINTERFACE;
5571 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5573 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5574 ULONG ref = InterlockedIncrement(&This->ref);
5576 TRACE("%p, refcount %lu.\n", iface, ref);
5578 if (ref == 1 /* incremented from 0 */)
5579 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5581 return ref;
5584 static void typeinfo_release_funcdesc(TLBFuncDesc *func)
5586 unsigned int i;
5588 for (i = 0; i < func->funcdesc.cParams; ++i)
5590 ELEMDESC *elemdesc = &func->funcdesc.lprgelemdescParam[i];
5591 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5592 VariantClear(&elemdesc->paramdesc.pparamdescex->varDefaultValue);
5593 TLB_FreeCustData(&func->pParamDesc[i].custdata_list);
5595 heap_free(func->funcdesc.lprgelemdescParam);
5596 heap_free(func->pParamDesc);
5597 TLB_FreeCustData(&func->custdata_list);
5600 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5602 UINT i;
5604 TRACE("destroying ITypeInfo(%p)\n",This);
5606 for (i = 0; i < This->typeattr.cFuncs; ++i)
5608 typeinfo_release_funcdesc(&This->funcdescs[i]);
5610 heap_free(This->funcdescs);
5612 for(i = 0; i < This->typeattr.cVars; ++i)
5614 TLBVarDesc *pVInfo = &This->vardescs[i];
5615 if (pVInfo->vardesc_create) {
5616 TLB_FreeVarDesc(pVInfo->vardesc_create);
5617 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5618 VariantClear(pVInfo->vardesc.lpvarValue);
5619 heap_free(pVInfo->vardesc.lpvarValue);
5621 TLB_FreeCustData(&pVInfo->custdata_list);
5623 heap_free(This->vardescs);
5625 if(This->impltypes){
5626 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5627 TLBImplType *pImpl = &This->impltypes[i];
5628 TLB_FreeCustData(&pImpl->custdata_list);
5630 heap_free(This->impltypes);
5633 TLB_FreeCustData(&This->custdata_list);
5635 heap_free(This);
5638 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5640 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5641 ULONG ref = InterlockedDecrement(&This->ref);
5643 TRACE("%p, refcount %lu.\n", iface, ref);
5645 if (!ref)
5647 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5648 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5649 if (not_attached_to_typelib)
5650 heap_free(This);
5651 /* otherwise This will be freed when typelib is freed */
5654 return ref;
5657 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5658 LPTYPEATTR *ppTypeAttr)
5660 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5661 SIZE_T size;
5663 TRACE("(%p)\n",This);
5665 size = sizeof(**ppTypeAttr);
5666 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5667 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5669 *ppTypeAttr = heap_alloc(size);
5670 if (!*ppTypeAttr)
5671 return E_OUTOFMEMORY;
5673 **ppTypeAttr = This->typeattr;
5674 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5676 if (This->tdescAlias)
5677 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5679 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5680 /* This should include all the inherited funcs */
5681 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5682 /* This is always the size of IDispatch's vtbl */
5683 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5684 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5686 return S_OK;
5689 /* ITypeInfo::GetTypeComp
5691 * Retrieves the ITypeComp interface for the type description, which enables a
5692 * client compiler to bind to the type description's members.
5695 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5696 ITypeComp * *ppTComp)
5698 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5700 TRACE("(%p)->(%p)\n", This, ppTComp);
5702 *ppTComp = &This->ITypeComp_iface;
5703 ITypeComp_AddRef(*ppTComp);
5704 return S_OK;
5707 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5709 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5710 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5711 size += sizeof(*elemdesc->paramdesc.pparamdescex);
5712 return size;
5715 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5717 *dest = *src;
5718 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5719 if (src->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5721 const PARAMDESCEX *pparamdescex_src = src->paramdesc.pparamdescex;
5722 PARAMDESCEX *pparamdescex_dest = dest->paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5723 *buffer += sizeof(PARAMDESCEX);
5724 *pparamdescex_dest = *pparamdescex_src;
5725 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5726 VariantInit(&pparamdescex_dest->varDefaultValue);
5727 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5728 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5730 else
5731 dest->paramdesc.pparamdescex = NULL;
5732 return S_OK;
5735 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5737 if (V_VT(var) == VT_INT)
5738 return VariantChangeType(var, var, 0, VT_I4);
5739 else if (V_VT(var) == VT_UINT)
5740 return VariantChangeType(var, var, 0, VT_UI4);
5742 return S_OK;
5745 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5747 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5748 VariantClear(&elemdesc->paramdesc.pparamdescex->varDefaultValue);
5751 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5753 FUNCDESC *dest;
5754 char *buffer;
5755 SIZE_T size = sizeof(*src);
5756 SHORT i;
5757 HRESULT hr;
5759 size += sizeof(*src->lprgscode) * src->cScodes;
5760 size += TLB_SizeElemDesc(&src->elemdescFunc);
5761 for (i = 0; i < src->cParams; i++)
5763 size += sizeof(ELEMDESC);
5764 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5767 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5768 if (!dest) return E_OUTOFMEMORY;
5770 *dest = *src;
5771 if (dispinterface) /* overwrite funckind */
5772 dest->funckind = FUNC_DISPATCH;
5773 buffer = (char *)(dest + 1);
5775 dest->oVft = dest->oVft & 0xFFFC;
5777 if (dest->cScodes) {
5778 dest->lprgscode = (SCODE *)buffer;
5779 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5780 buffer += sizeof(*src->lprgscode) * src->cScodes;
5781 } else
5782 dest->lprgscode = NULL;
5784 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5785 if (FAILED(hr))
5787 SysFreeString((BSTR)dest);
5788 return hr;
5791 if (dest->cParams) {
5792 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5793 buffer += sizeof(ELEMDESC) * src->cParams;
5794 for (i = 0; i < src->cParams; i++)
5796 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5797 if (FAILED(hr))
5798 break;
5800 if (FAILED(hr))
5802 /* undo the above actions */
5803 for (i = i - 1; i >= 0; i--)
5804 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5805 TLB_FreeElemDesc(&dest->elemdescFunc);
5806 SysFreeString((BSTR)dest);
5807 return hr;
5809 } else
5810 dest->lprgelemdescParam = NULL;
5812 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5813 * This accounts for several arguments that are separate in the signature of
5814 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5815 if (dispinterface && (src->funckind != FUNC_DISPATCH))
5817 /* functions that have a [retval] parameter return this value into pVarResult.
5818 * [retval] is always the last parameter (if present) */
5819 if (dest->cParams &&
5820 (dest->lprgelemdescParam[dest->cParams - 1].paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5822 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5823 if (elemdesc->tdesc.vt != VT_PTR)
5825 ERR("elemdesc should have started with VT_PTR instead of:\n");
5826 if (ERR_ON(ole))
5827 dump_ELEMDESC(elemdesc);
5828 return E_UNEXPECTED;
5831 /* the type pointed to by this [retval] becomes elemdescFunc,
5832 * i.e. the function signature's return type.
5833 * We are using a flat buffer so there is no danger of leaking memory */
5834 dest->elemdescFunc.tdesc = *elemdesc->tdesc.lptdesc;
5836 /* remove the last parameter */
5837 dest->cParams--;
5839 else if (dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5840 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5841 * not pVarResult. So the function signature should show no return value. */
5842 dest->elemdescFunc.tdesc.vt = VT_VOID;
5844 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5845 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5846 if (dest->cParams && (dest->lprgelemdescParam[dest->cParams - 1].paramdesc.wParamFlags & PARAMFLAG_FLCID))
5847 dest->cParams--;
5850 *dest_ptr = dest;
5851 return S_OK;
5854 static void TLB_FreeVarDesc(VARDESC *var_desc)
5856 TLB_FreeElemDesc(&var_desc->elemdescVar);
5857 if (var_desc->varkind == VAR_CONST)
5858 VariantClear(var_desc->lpvarValue);
5859 SysFreeString((BSTR)var_desc);
5862 /* internal function to make the inherited interfaces' methods appear
5863 * part of the interface */
5864 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5865 UINT index, const TLBFuncDesc **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5867 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5868 HRESULT hr;
5869 UINT implemented_funcs = 0;
5871 if (funcs)
5872 *funcs = 0;
5873 else
5874 *hrefoffset = DISPATCH_HREF_OFFSET;
5876 if(This->impltypes)
5878 ITypeInfo *pSubTypeInfo;
5879 UINT sub_funcs;
5881 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5882 if (FAILED(hr))
5883 return hr;
5885 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5886 index,
5887 ppFuncDesc,
5888 &sub_funcs, hrefoffset);
5889 implemented_funcs += sub_funcs;
5890 ITypeInfo_Release(pSubTypeInfo);
5891 if (SUCCEEDED(hr))
5892 return hr;
5893 *hrefoffset += DISPATCH_HREF_OFFSET;
5896 if (funcs)
5897 *funcs = implemented_funcs + This->typeattr.cFuncs;
5898 else
5899 *hrefoffset = 0;
5901 if (index < implemented_funcs)
5902 return E_INVALIDARG;
5903 index -= implemented_funcs;
5905 if (index >= This->typeattr.cFuncs)
5906 return TYPE_E_ELEMENTNOTFOUND;
5908 *ppFuncDesc = &This->funcdescs[index];
5909 return S_OK;
5912 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5914 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5916 if (This->typeattr.typekind == TKIND_DISPATCH)
5917 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5919 if (index >= This->typeattr.cFuncs)
5920 return TYPE_E_ELEMENTNOTFOUND;
5922 *func_desc = &This->funcdescs[index];
5923 return S_OK;
5926 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5928 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5929 while (TRUE)
5931 switch (pTypeDesc->vt)
5933 case VT_USERDEFINED:
5934 pTypeDesc->hreftype += hrefoffset;
5935 return;
5936 case VT_PTR:
5937 case VT_SAFEARRAY:
5938 pTypeDesc = pTypeDesc->lptdesc;
5939 break;
5940 case VT_CARRAY:
5941 pTypeDesc = &pTypeDesc->lpadesc->tdescElem;
5942 break;
5943 default:
5944 return;
5949 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5951 SHORT i;
5952 for (i = 0; i < pFuncDesc->cParams; i++)
5953 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5954 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5957 /* ITypeInfo::GetFuncDesc
5959 * Retrieves the FUNCDESC structure that contains information about a
5960 * specified function.
5963 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5964 LPFUNCDESC *ppFuncDesc)
5966 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5967 const TLBFuncDesc *internal_funcdesc;
5968 HRESULT hr;
5969 UINT hrefoffset = 0;
5971 TRACE("(%p) index %d\n", This, index);
5973 if (!ppFuncDesc)
5974 return E_INVALIDARG;
5976 if (This->needs_layout)
5977 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5979 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5980 &internal_funcdesc, &hrefoffset);
5981 if (FAILED(hr))
5983 WARN("description for function %d not found\n", index);
5984 return hr;
5987 hr = TLB_AllocAndInitFuncDesc(
5988 &internal_funcdesc->funcdesc,
5989 ppFuncDesc,
5990 This->typeattr.typekind == TKIND_DISPATCH);
5992 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
5993 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5995 TRACE("-- %#lx.\n", hr);
5996 return hr;
5999 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6001 VARDESC *dest;
6002 char *buffer;
6003 SIZE_T size = sizeof(*src);
6004 HRESULT hr;
6006 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6007 if (src->varkind == VAR_CONST)
6008 size += sizeof(VARIANT);
6009 size += TLB_SizeElemDesc(&src->elemdescVar);
6011 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6012 if (!dest) return E_OUTOFMEMORY;
6014 *dest = *src;
6015 buffer = (char *)(dest + 1);
6016 if (src->lpstrSchema)
6018 int len;
6019 dest->lpstrSchema = (LPOLESTR)buffer;
6020 len = lstrlenW(src->lpstrSchema);
6021 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6022 buffer += (len + 1) * sizeof(WCHAR);
6025 if (src->varkind == VAR_CONST)
6027 HRESULT hr;
6029 dest->lpvarValue = (VARIANT *)buffer;
6030 *dest->lpvarValue = *src->lpvarValue;
6031 buffer += sizeof(VARIANT);
6032 VariantInit(dest->lpvarValue);
6033 hr = VariantCopy(dest->lpvarValue, src->lpvarValue);
6034 if (FAILED(hr))
6036 SysFreeString((BSTR)dest);
6037 return hr;
6040 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6041 if (FAILED(hr))
6043 if (src->varkind == VAR_CONST)
6044 VariantClear(dest->lpvarValue);
6045 SysFreeString((BSTR)dest);
6046 return hr;
6048 *dest_ptr = dest;
6049 return S_OK;
6052 /* ITypeInfo::GetVarDesc
6054 * Retrieves a VARDESC structure that describes the specified variable.
6057 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6058 LPVARDESC *ppVarDesc)
6060 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6061 const TLBVarDesc *pVDesc = &This->vardescs[index];
6063 TRACE("(%p) index %d\n", This, index);
6065 if(index >= This->typeattr.cVars)
6066 return TYPE_E_ELEMENTNOTFOUND;
6068 if (This->needs_layout)
6069 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6071 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6074 /* internal function to make the inherited interfaces' methods appear
6075 * part of the interface, remembering if the top-level was dispinterface */
6076 static HRESULT typeinfo_getnames( ITypeInfo *iface, MEMBERID memid, BSTR *names,
6077 UINT max_names, UINT *num_names, BOOL dispinterface)
6079 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6080 const TLBFuncDesc *func_desc;
6081 const TLBVarDesc *var_desc;
6082 int i;
6084 *num_names = 0;
6086 func_desc = TLB_get_funcdesc_by_memberid(This, memid);
6087 if (func_desc)
6089 UINT params = func_desc->funcdesc.cParams;
6090 if (!max_names || !func_desc->Name)
6091 return S_OK;
6093 *names = SysAllocString(TLB_get_bstr(func_desc->Name));
6094 ++(*num_names);
6096 if (dispinterface && (func_desc->funcdesc.funckind != FUNC_DISPATCH))
6098 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6099 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
6100 --params; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6101 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].paramdesc.wParamFlags & PARAMFLAG_FLCID))
6102 --params; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6105 for (i = 0; i < params; i++)
6107 if (*num_names >= max_names || !func_desc->pParamDesc[i].Name)
6108 return S_OK;
6109 names[*num_names] = SysAllocString(TLB_get_bstr(func_desc->pParamDesc[i].Name));
6110 ++(*num_names);
6112 return S_OK;
6115 var_desc = TLB_get_vardesc_by_memberid(This, memid);
6116 if (var_desc)
6118 *names = SysAllocString(TLB_get_bstr(var_desc->Name));
6119 *num_names = 1;
6121 else
6123 if (This->impltypes &&
6124 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH))
6126 /* recursive search */
6127 ITypeInfo *parent;
6128 HRESULT result;
6129 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &parent);
6130 if (SUCCEEDED(result))
6132 result = typeinfo_getnames(parent, memid, names, max_names, num_names, dispinterface);
6133 ITypeInfo_Release(parent);
6134 return result;
6136 WARN("Could not search inherited interface!\n");
6138 else
6140 WARN("no names found\n");
6142 *num_names = 0;
6143 return TYPE_E_ELEMENTNOTFOUND;
6145 return S_OK;
6148 /* ITypeInfo_GetNames
6150 * Retrieves the variable with the specified member ID (or the name of the
6151 * property or method and its parameters) that correspond to the specified
6152 * function ID.
6154 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6155 BSTR *names, UINT max_names, UINT *num_names)
6157 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6159 TRACE("%p, %#lx, %p, %d, %p\n", iface, memid, names, max_names, num_names);
6161 if (!names) return E_INVALIDARG;
6163 return typeinfo_getnames((ITypeInfo *)iface, memid, names, max_names, num_names,
6164 This->typeattr.typekind == TKIND_DISPATCH);
6167 /* ITypeInfo::GetRefTypeOfImplType
6169 * If a type description describes a COM class, it retrieves the type
6170 * description of the implemented interface types. For an interface,
6171 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6172 * if any exist.
6175 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6176 ITypeInfo2 *iface,
6177 UINT index,
6178 HREFTYPE *pRefType)
6180 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6181 HRESULT hr = S_OK;
6183 TRACE("(%p) index %d\n", This, index);
6184 if (TRACE_ON(ole)) dump_TypeInfo(This);
6186 if(index==(UINT)-1)
6188 /* only valid on dual interfaces;
6189 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6192 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6194 *pRefType = -2;
6196 else
6198 hr = TYPE_E_ELEMENTNOTFOUND;
6201 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6203 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6204 *pRefType = This->pTypeLib->dispatch_href;
6206 else
6208 if(index >= This->typeattr.cImplTypes)
6209 hr = TYPE_E_ELEMENTNOTFOUND;
6210 else{
6211 *pRefType = This->impltypes[index].hRef;
6212 if (This->typeattr.typekind == TKIND_INTERFACE)
6213 *pRefType |= 0x2;
6217 if(TRACE_ON(ole))
6219 if(SUCCEEDED(hr))
6220 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType );
6221 else
6222 TRACE("FAILURE -- hresult %#lx.\n", hr);
6225 return hr;
6228 /* ITypeInfo::GetImplTypeFlags
6230 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6231 * or base interface in a type description.
6233 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6234 UINT index, INT *pImplTypeFlags)
6236 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6238 TRACE("(%p) index %d\n", This, index);
6240 if(!pImplTypeFlags)
6241 return E_INVALIDARG;
6243 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6244 *pImplTypeFlags = 0;
6245 return S_OK;
6248 if(index >= This->typeattr.cImplTypes)
6249 return TYPE_E_ELEMENTNOTFOUND;
6251 *pImplTypeFlags = This->impltypes[index].implflags;
6253 return S_OK;
6256 /* GetIDsOfNames
6257 * Maps between member names and member IDs, and parameter names and
6258 * parameter IDs.
6260 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6261 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6263 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6264 const TLBVarDesc *pVDesc;
6265 HRESULT ret=S_OK;
6266 UINT i, fdc;
6268 TRACE("%p, %s, %d.\n", iface, debugstr_w(*rgszNames), cNames);
6270 /* init out parameters in case of failure */
6271 for (i = 0; i < cNames; i++)
6272 pMemId[i] = MEMBERID_NIL;
6274 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6275 int j;
6276 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6277 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6278 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6279 for(i=1; i < cNames; i++){
6280 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6281 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6282 break;
6283 if( j<pFDesc->funcdesc.cParams)
6284 pMemId[i]=j;
6285 else
6286 ret=DISP_E_UNKNOWNNAME;
6288 TRACE("-- %#lx.\n", ret);
6289 return ret;
6292 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6293 if(pVDesc){
6294 if(cNames)
6295 *pMemId = pVDesc->vardesc.memid;
6296 return ret;
6298 /* not found, see if it can be found in an inherited interface */
6299 if(This->impltypes) {
6300 /* recursive search */
6301 ITypeInfo *pTInfo;
6302 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6303 if(SUCCEEDED(ret)){
6304 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6305 ITypeInfo_Release(pTInfo);
6306 return ret;
6308 WARN("Could not search inherited interface!\n");
6309 } else
6310 WARN("no names found\n");
6311 return DISP_E_UNKNOWNNAME;
6315 #ifdef __i386__
6317 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6318 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6319 __ASM_GLOBAL_FUNC( call_method,
6320 "pushl %ebp\n\t"
6321 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6322 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6323 "movl %esp,%ebp\n\t"
6324 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6325 "pushl %esi\n\t"
6326 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6327 "pushl %edi\n\t"
6328 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6329 "movl 12(%ebp),%edx\n\t"
6330 "movl %esp,%edi\n\t"
6331 "shll $2,%edx\n\t"
6332 "jz 1f\n\t"
6333 "subl %edx,%edi\n\t"
6334 "andl $~15,%edi\n\t"
6335 "movl %edi,%esp\n\t"
6336 "movl 12(%ebp),%ecx\n\t"
6337 "movl 16(%ebp),%esi\n\t"
6338 "cld\n\t"
6339 "rep; movsl\n"
6340 "1:\tcall *8(%ebp)\n\t"
6341 "subl %esp,%edi\n\t"
6342 "movl 20(%ebp),%ecx\n\t"
6343 "movl %edi,(%ecx)\n\t"
6344 "leal -8(%ebp),%esp\n\t"
6345 "popl %edi\n\t"
6346 __ASM_CFI(".cfi_same_value %edi\n\t")
6347 "popl %esi\n\t"
6348 __ASM_CFI(".cfi_same_value %esi\n\t")
6349 "popl %ebp\n\t"
6350 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6351 __ASM_CFI(".cfi_same_value %ebp\n\t")
6352 "ret" )
6353 __ASM_GLOBAL_FUNC( call_double_method,
6354 "jmp " __ASM_NAME("call_method") )
6356 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6357 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6359 int argspos = 0, stack_offset;
6360 void *func;
6361 UINT i;
6362 DWORD *args;
6364 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6365 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6366 pvargResult, V_VT(pvargResult));
6368 if (cc != CC_STDCALL && cc != CC_CDECL)
6370 FIXME("unsupported calling convention %d\n",cc);
6371 return E_INVALIDARG;
6374 /* maximum size for an argument is sizeof(VARIANT) */
6375 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6377 if (pvInstance)
6379 const FARPROC *vtable = *(FARPROC **)pvInstance;
6380 func = vtable[oVft/sizeof(void *)];
6381 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6383 else func = (void *)oVft;
6385 switch (vtReturn)
6387 case VT_DECIMAL:
6388 case VT_VARIANT:
6389 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6390 break;
6391 case VT_HRESULT:
6392 WARN("invalid return type %u\n", vtReturn);
6393 heap_free( args );
6394 return E_INVALIDARG;
6395 default:
6396 break;
6399 for (i = 0; i < cActuals; i++)
6401 VARIANT *arg = prgpvarg[i];
6403 switch (prgvt[i])
6405 case VT_EMPTY:
6406 break;
6407 case VT_I8:
6408 case VT_UI8:
6409 case VT_R8:
6410 case VT_DATE:
6411 case VT_CY:
6412 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6413 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6414 break;
6415 case VT_DECIMAL:
6416 case VT_VARIANT:
6417 memcpy( &args[argspos], arg, sizeof(*arg) );
6418 argspos += sizeof(*arg) / sizeof(DWORD);
6419 break;
6420 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6421 args[argspos++] = V_BOOL(arg);
6422 break;
6423 default:
6424 args[argspos++] = V_UI4(arg);
6425 break;
6427 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6430 switch (vtReturn)
6432 case VT_EMPTY:
6433 case VT_DECIMAL:
6434 case VT_VARIANT:
6435 call_method( func, argspos, args, &stack_offset );
6436 break;
6437 case VT_R4:
6438 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6439 break;
6440 case VT_R8:
6441 case VT_DATE:
6442 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6443 break;
6444 case VT_I8:
6445 case VT_UI8:
6446 case VT_CY:
6447 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6448 break;
6449 default:
6450 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6451 break;
6453 heap_free( args );
6454 if (stack_offset && cc == CC_STDCALL)
6456 WARN( "stack pointer off by %d\n", stack_offset );
6457 return DISP_E_BADCALLEE;
6459 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6460 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6461 return S_OK;
6464 #elif defined(__x86_64__)
6466 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6467 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6468 __ASM_GLOBAL_FUNC( call_method,
6469 "pushq %rbp\n\t"
6470 __ASM_SEH(".seh_pushreg %rbp\n\t")
6471 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6472 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6473 "movq %rsp,%rbp\n\t"
6474 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6475 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6476 "pushq %rsi\n\t"
6477 __ASM_SEH(".seh_pushreg %rsi\n\t")
6478 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6479 "pushq %rdi\n\t"
6480 __ASM_SEH(".seh_pushreg %rdi\n\t")
6481 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6482 __ASM_SEH(".seh_endprologue\n\t")
6483 "movq %rcx,%rax\n\t"
6484 "movq $4,%rcx\n\t"
6485 "cmp %rcx,%rdx\n\t"
6486 "cmovgq %rdx,%rcx\n\t"
6487 "leaq 0(,%rcx,8),%rdx\n\t"
6488 "subq %rdx,%rsp\n\t"
6489 "andq $~15,%rsp\n\t"
6490 "movq %rsp,%rdi\n\t"
6491 "movq %r8,%rsi\n\t"
6492 "rep; movsq\n\t"
6493 "movq 0(%rsp),%rcx\n\t"
6494 "movq 8(%rsp),%rdx\n\t"
6495 "movq 16(%rsp),%r8\n\t"
6496 "movq 24(%rsp),%r9\n\t"
6497 "movq 0(%rsp),%xmm0\n\t"
6498 "movq 8(%rsp),%xmm1\n\t"
6499 "movq 16(%rsp),%xmm2\n\t"
6500 "movq 24(%rsp),%xmm3\n\t"
6501 "callq *%rax\n\t"
6502 "leaq -16(%rbp),%rsp\n\t"
6503 "popq %rdi\n\t"
6504 __ASM_CFI(".cfi_same_value %rdi\n\t")
6505 "popq %rsi\n\t"
6506 __ASM_CFI(".cfi_same_value %rsi\n\t")
6507 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6508 "popq %rbp\n\t"
6509 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6510 __ASM_CFI(".cfi_same_value %rbp\n\t")
6511 "ret")
6512 __ASM_GLOBAL_FUNC( call_double_method,
6513 "jmp " __ASM_NAME("call_method") )
6515 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6516 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6518 int argspos = 0;
6519 UINT i;
6520 DWORD_PTR *args;
6521 void *func;
6523 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6524 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6525 pvargResult, V_VT(pvargResult));
6527 if (cc != CC_STDCALL && cc != CC_CDECL)
6529 FIXME("unsupported calling convention %d\n",cc);
6530 return E_INVALIDARG;
6533 /* maximum size for an argument is sizeof(DWORD_PTR) */
6534 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6536 if (pvInstance)
6538 const FARPROC *vtable = *(FARPROC **)pvInstance;
6539 func = vtable[oVft/sizeof(void *)];
6540 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6542 else func = (void *)oVft;
6544 switch (vtReturn)
6546 case VT_DECIMAL:
6547 case VT_VARIANT:
6548 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6549 break;
6550 case VT_HRESULT:
6551 WARN("invalid return type %u\n", vtReturn);
6552 heap_free( args );
6553 return E_INVALIDARG;
6554 default:
6555 break;
6558 for (i = 0; i < cActuals; i++)
6560 VARIANT *arg = prgpvarg[i];
6562 switch (prgvt[i])
6564 case VT_DECIMAL:
6565 case VT_VARIANT:
6566 args[argspos++] = (ULONG_PTR)arg;
6567 break;
6568 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6569 args[argspos++] = V_BOOL(arg);
6570 break;
6571 default:
6572 args[argspos++] = V_UI8(arg);
6573 break;
6575 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6578 switch (vtReturn)
6580 case VT_R4:
6581 V_R4(pvargResult) = call_double_method( func, argspos, args );
6582 break;
6583 case VT_R8:
6584 case VT_DATE:
6585 V_R8(pvargResult) = call_double_method( func, argspos, args );
6586 break;
6587 case VT_DECIMAL:
6588 case VT_VARIANT:
6589 call_method( func, argspos, args );
6590 break;
6591 default:
6592 V_UI8(pvargResult) = call_method( func, argspos, args );
6593 break;
6595 heap_free( args );
6596 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6597 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6598 return S_OK;
6601 #elif defined(__arm__)
6603 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6604 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6605 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6606 __ASM_GLOBAL_FUNC( call_method,
6607 /* r0 = *func
6608 * r1 = nb_stk_args
6609 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6610 * 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)
6613 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6614 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6616 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6617 "beq 1f\n\t" /* Skip allocation if no stack args */
6618 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6619 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6620 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6621 "subs r1, r1, #4\n\t" /* Decrement count */
6622 "bgt 2b\n\t" /* Loop till done */
6624 "1:\n\t"
6625 #ifndef __SOFTFP__
6626 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6627 #endif
6628 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6629 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6631 "blx ip\n\t" /* Call the target function */
6633 "mov sp, fp\n\t" /* Clean the stack using fp */
6634 "pop {fp, pc}\n\t" /* Restore fp and return */
6636 __ASM_GLOBAL_FUNC( call_float_method,
6637 "b " __ASM_NAME("call_method") )
6638 __ASM_GLOBAL_FUNC( call_double_method,
6639 "b " __ASM_NAME("call_method") )
6641 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6642 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6644 int argspos;
6645 void *func;
6646 UINT i;
6647 DWORD *args;
6648 struct {
6649 #ifndef __SOFTFP__
6650 union {
6651 float s[16];
6652 double d[8];
6653 } sd;
6654 #endif
6655 DWORD r[4];
6656 } regs;
6657 int rcount; /* 32-bit register index count */
6658 #ifndef __SOFTFP__
6659 int scount = 0; /* single-precision float register index count */
6660 int dcount = 0; /* double-precision float register index count */
6661 #endif
6663 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6664 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6666 if (cc != CC_STDCALL && cc != CC_CDECL)
6668 FIXME("unsupported calling convention %d\n",cc);
6669 return E_INVALIDARG;
6672 argspos = 0;
6673 rcount = 0;
6675 if (pvInstance)
6677 const FARPROC *vtable = *(FARPROC **)pvInstance;
6678 func = vtable[oVft/sizeof(void *)];
6679 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6681 else func = (void *)oVft;
6683 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6684 /* first as it will need to be in the 'r' registers: */
6685 switch (vtReturn)
6687 case VT_DECIMAL:
6688 case VT_VARIANT:
6689 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6690 break;
6691 case VT_HRESULT:
6692 WARN("invalid return type %u\n", vtReturn);
6693 return E_INVALIDARG;
6694 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6695 break;
6698 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6699 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6701 for (i = 0; i < cActuals; i++)
6703 VARIANT *arg = prgpvarg[i];
6704 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6705 int ntemp; /* Used for counting words split between registers and stack */
6707 switch (prgvt[i])
6709 case VT_EMPTY:
6710 break;
6711 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6712 case VT_DATE:
6713 #ifndef __SOFTFP__
6714 dcount = max( (scount + 1) / 2, dcount );
6715 if (dcount < 8)
6717 regs.sd.d[dcount++] = V_R8(arg);
6719 else
6721 argspos += (argspos % 2); /* align argspos to 8-bytes */
6722 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6723 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6725 break;
6726 #endif
6727 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6728 case VT_UI8:
6729 case VT_CY:
6730 if (rcount < 3)
6732 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6733 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6734 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6736 else
6738 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6739 argspos += (argspos % 2); /* align argspos to 8-bytes */
6740 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6741 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6743 break;
6744 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6745 case VT_VARIANT:
6746 /* 8-byte align 'r' and/or stack: */
6747 if (rcount < 3)
6748 rcount += (rcount % 2);
6749 else
6751 rcount = 4;
6752 argspos += (argspos % 2);
6754 ntemp = sizeof(*arg) / sizeof(DWORD);
6755 while (ntemp > 0)
6757 if (rcount < 4)
6758 regs.r[rcount++] = *pdwarg++;
6759 else
6760 args[argspos++] = *pdwarg++;
6761 --ntemp;
6763 break;
6764 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6765 if (rcount < 4)
6766 regs.r[rcount++] = V_BOOL(arg);
6767 else
6768 args[argspos++] = V_BOOL(arg);
6769 break;
6770 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6771 #ifndef __SOFTFP__
6772 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6773 if (scount < 16)
6774 regs.sd.s[scount++] = V_R4(arg);
6775 else
6776 args[argspos++] = V_UI4(arg);
6777 break;
6778 #endif
6779 default:
6780 if (rcount < 4)
6781 regs.r[rcount++] = V_UI4(arg);
6782 else
6783 args[argspos++] = V_UI4(arg);
6784 break;
6786 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6789 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6791 switch (vtReturn)
6793 case VT_EMPTY: /* EMPTY = no return value */
6794 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6795 case VT_VARIANT:
6796 call_method( func, argspos, args, (DWORD*)&regs );
6797 break;
6798 case VT_R4:
6799 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6800 break;
6801 case VT_R8:
6802 case VT_DATE:
6803 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6804 break;
6805 case VT_I8:
6806 case VT_UI8:
6807 case VT_CY:
6808 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6809 break;
6810 default:
6811 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6812 break;
6814 heap_free( args );
6815 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6816 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6817 return S_OK;
6820 #elif defined(__aarch64__)
6822 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6823 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6824 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6825 __ASM_GLOBAL_FUNC( call_method,
6826 "stp x29, x30, [sp, #-16]!\n\t"
6827 "mov x29, sp\n\t"
6828 "sub sp, sp, x1, lsl #3\n\t"
6829 "cbz x1, 2f\n"
6830 "1:\tsub x1, x1, #1\n\t"
6831 "ldr x4, [x2, x1, lsl #3]\n\t"
6832 "str x4, [sp, x1, lsl #3]\n\t"
6833 "cbnz x1, 1b\n"
6834 "2:\tmov x16, x0\n\t"
6835 "mov x9, x3\n\t"
6836 "ldp d0, d1, [x9]\n\t"
6837 "ldp d2, d3, [x9, #0x10]\n\t"
6838 "ldp d4, d5, [x9, #0x20]\n\t"
6839 "ldp d6, d7, [x9, #0x30]\n\t"
6840 "ldp x0, x1, [x9, #0x40]\n\t"
6841 "ldp x2, x3, [x9, #0x50]\n\t"
6842 "ldp x4, x5, [x9, #0x60]\n\t"
6843 "ldp x6, x7, [x9, #0x70]\n\t"
6844 "ldr x8, [x9, #0x80]\n\t"
6845 "blr x16\n\t"
6846 "mov sp, x29\n\t"
6847 "ldp x29, x30, [sp], #16\n\t"
6848 "ret" )
6849 __ASM_GLOBAL_FUNC( call_float_method,
6850 "b " __ASM_NAME("call_method") )
6851 __ASM_GLOBAL_FUNC( call_double_method,
6852 "b " __ASM_NAME("call_method") )
6854 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6855 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6857 int argspos;
6858 void *func;
6859 UINT i;
6860 DWORD_PTR *args;
6861 struct
6863 union
6865 float f;
6866 double d;
6867 } fp[8];
6868 DWORD_PTR x[9];
6869 } regs;
6870 int rcount; /* 64-bit register index count */
6871 int fpcount = 0; /* float register index count */
6873 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6874 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6876 if (cc != CC_STDCALL && cc != CC_CDECL)
6878 FIXME("unsupported calling convention %d\n",cc);
6879 return E_INVALIDARG;
6882 argspos = 0;
6883 rcount = 0;
6885 if (instance)
6887 const FARPROC *vtable = *(FARPROC **)instance;
6888 func = vtable[offset/sizeof(void *)];
6889 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6891 else func = (void *)offset;
6893 /* maximum size for an argument is 16 */
6894 args = heap_alloc( 16 * count );
6896 for (i = 0; i < count; i++)
6898 VARIANT *arg = vargs[i];
6900 switch (types[i])
6902 case VT_R4:
6903 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6904 else *(float *)&args[argspos++] = V_R4(arg);
6905 break;
6906 case VT_R8:
6907 case VT_DATE:
6908 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6909 else *(double *)&args[argspos++] = V_R8(arg);
6910 break;
6911 case VT_DECIMAL:
6912 if (rcount < 7)
6914 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6915 rcount += 2;
6917 else
6919 memcpy( &args[argspos], arg, sizeof(*arg) );
6920 argspos += 2;
6922 break;
6923 case VT_VARIANT:
6924 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6925 else args[argspos++] = (DWORD_PTR)arg;
6926 break;
6927 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6928 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6929 else args[argspos++] = V_BOOL(arg);
6930 break;
6931 default:
6932 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6933 else args[argspos++] = V_UI8(arg);
6934 break;
6936 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6939 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6941 switch (ret_type)
6943 case VT_HRESULT:
6944 heap_free( args );
6945 return E_INVALIDARG;
6946 case VT_DECIMAL:
6947 case VT_VARIANT:
6948 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6949 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6950 break;
6951 case VT_R4:
6952 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6953 break;
6954 case VT_R8:
6955 case VT_DATE:
6956 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6957 break;
6958 default:
6959 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6960 break;
6962 heap_free( args );
6963 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6964 TRACE("retval: %s\n", debugstr_variant(result));
6965 return S_OK;
6968 #else /* __aarch64__ */
6970 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6971 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6973 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6974 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6975 return E_NOTIMPL;
6978 #endif
6980 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6982 HRESULT hr = S_OK;
6983 ITypeInfo *tinfo2 = NULL;
6984 TYPEATTR *tattr = NULL;
6986 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->hreftype, &tinfo2);
6987 if (hr)
6989 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc->hreftype, hr);
6990 return hr;
6992 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6993 if (hr)
6995 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr);
6996 ITypeInfo_Release(tinfo2);
6997 return hr;
7000 switch (tattr->typekind)
7002 case TKIND_ENUM:
7003 *vt |= VT_I4;
7004 break;
7006 case TKIND_ALIAS:
7007 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7008 break;
7010 case TKIND_INTERFACE:
7011 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7012 *vt |= VT_DISPATCH;
7013 else
7014 *vt |= VT_UNKNOWN;
7015 break;
7017 case TKIND_DISPATCH:
7018 *vt |= VT_DISPATCH;
7019 break;
7021 case TKIND_COCLASS:
7022 *vt |= VT_DISPATCH;
7023 break;
7025 case TKIND_RECORD:
7026 FIXME("TKIND_RECORD unhandled.\n");
7027 hr = E_NOTIMPL;
7028 break;
7030 case TKIND_UNION:
7031 FIXME("TKIND_UNION unhandled.\n");
7032 hr = E_NOTIMPL;
7033 break;
7035 default:
7036 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7037 hr = E_NOTIMPL;
7038 break;
7040 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7041 ITypeInfo_Release(tinfo2);
7042 return hr;
7045 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7047 HRESULT hr = S_OK;
7049 /* enforce only one level of pointer indirection */
7050 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7052 tdesc = tdesc->lptdesc;
7054 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7055 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7056 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7057 if ((tdesc->vt == VT_USERDEFINED) ||
7058 ((tdesc->vt == VT_PTR) && (tdesc->lptdesc->vt == VT_USERDEFINED)))
7060 VARTYPE vt_userdefined = 0;
7061 const TYPEDESC *tdesc_userdefined = tdesc;
7062 if (tdesc->vt == VT_PTR)
7064 vt_userdefined = VT_BYREF;
7065 tdesc_userdefined = tdesc->lptdesc;
7067 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7068 if ((hr == S_OK) &&
7069 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7070 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7072 *vt |= vt_userdefined;
7073 return S_OK;
7076 *vt = VT_BYREF;
7079 switch (tdesc->vt)
7081 case VT_HRESULT:
7082 *vt |= VT_ERROR;
7083 break;
7084 case VT_USERDEFINED:
7085 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7086 break;
7087 case VT_VOID:
7088 case VT_CARRAY:
7089 case VT_PTR:
7090 case VT_LPSTR:
7091 case VT_LPWSTR:
7092 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7093 hr = DISP_E_BADVARTYPE;
7094 break;
7095 case VT_SAFEARRAY:
7096 *vt |= VT_ARRAY;
7097 hr = typedescvt_to_variantvt(tinfo, tdesc->lptdesc, vt);
7098 break;
7099 case VT_INT:
7100 *vt |= VT_I4;
7101 break;
7102 case VT_UINT:
7103 *vt |= VT_UI4;
7104 break;
7105 default:
7106 *vt |= tdesc->vt;
7107 break;
7109 return hr;
7112 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7114 ITypeInfo *tinfo2;
7115 TYPEATTR *tattr;
7116 HRESULT hres;
7117 int flags, i;
7119 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7120 if(FAILED(hres))
7121 return hres;
7123 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7124 if(FAILED(hres)) {
7125 ITypeInfo_Release(tinfo2);
7126 return hres;
7129 switch(tattr->typekind) {
7130 case TKIND_ALIAS:
7131 hres = get_iface_guid(tinfo2, tattr->tdescAlias.hreftype, guid);
7132 break;
7134 case TKIND_INTERFACE:
7135 case TKIND_DISPATCH:
7136 *guid = tattr->guid;
7137 break;
7139 case TKIND_COCLASS:
7140 for (i = 0; i < tattr->cImplTypes; i++)
7142 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7143 if (flags & IMPLTYPEFLAG_FDEFAULT)
7144 break;
7147 if (i == tattr->cImplTypes)
7148 i = 0;
7150 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7151 if (SUCCEEDED(hres))
7152 hres = get_iface_guid(tinfo2, href, guid);
7153 break;
7155 default:
7156 ERR("Unexpected typekind %d\n", tattr->typekind);
7157 hres = E_UNEXPECTED;
7160 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7161 ITypeInfo_Release(tinfo2);
7162 return hres;
7165 static inline BOOL func_restricted( const FUNCDESC *desc )
7167 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7170 #define INVBUF_ELEMENT_SIZE \
7171 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7172 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7173 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7174 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7175 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7176 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7177 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7178 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7180 static HRESULT WINAPI ITypeInfo_fnInvoke(
7181 ITypeInfo2 *iface,
7182 VOID *pIUnk,
7183 MEMBERID memid,
7184 UINT16 wFlags,
7185 DISPPARAMS *pDispParams,
7186 VARIANT *pVarResult,
7187 EXCEPINFO *pExcepInfo,
7188 UINT *pArgErr)
7190 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7191 int i, j;
7192 unsigned int var_index;
7193 TYPEKIND type_kind;
7194 HRESULT hres;
7195 const TLBFuncDesc *pFuncInfo;
7196 UINT fdc;
7198 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface, pIUnk, memid, wFlags, pDispParams,
7199 pVarResult, pExcepInfo, pArgErr);
7201 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7202 return DISP_E_MEMBERNOTFOUND;
7204 if (!pDispParams)
7206 ERR("NULL pDispParams not allowed\n");
7207 return E_INVALIDARG;
7210 dump_DispParms(pDispParams);
7212 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7214 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7215 pDispParams->cNamedArgs, pDispParams->cArgs);
7216 return E_INVALIDARG;
7219 /* we do this instead of using GetFuncDesc since it will return a fake
7220 * FUNCDESC for dispinterfaces and we want the real function description */
7221 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7222 pFuncInfo = &This->funcdescs[fdc];
7223 if ((memid == pFuncInfo->funcdesc.memid) &&
7224 (wFlags & pFuncInfo->funcdesc.invkind) &&
7225 !func_restricted( &pFuncInfo->funcdesc ))
7226 break;
7229 if (fdc < This->typeattr.cFuncs) {
7230 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7232 if (TRACE_ON(ole))
7234 TRACE("invoking:\n");
7235 dump_TLBFuncDescOne(pFuncInfo);
7238 switch (func_desc->funckind) {
7239 case FUNC_PUREVIRTUAL:
7240 case FUNC_VIRTUAL: {
7241 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7242 VARIANT varresult;
7243 VARIANT retval = {{{0}}}; /* pointer for storing byref retvals in */
7244 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7245 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7246 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7247 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7248 UINT cNamedArgs = pDispParams->cNamedArgs;
7249 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7250 UINT vargs_converted=0;
7251 SAFEARRAY *a;
7253 hres = S_OK;
7255 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7257 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7259 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7260 hres = DISP_E_PARAMNOTFOUND;
7261 goto func_fail;
7265 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7267 ERR("functions with the vararg attribute do not support named arguments\n");
7268 hres = DISP_E_NONAMEDARGS;
7269 goto func_fail;
7272 for (i = 0; i < func_desc->cParams; i++)
7274 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7275 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7276 if (FAILED(hres))
7277 goto func_fail;
7280 TRACE("changing args\n");
7281 for (i = 0; i < func_desc->cParams; i++)
7283 USHORT wParamFlags = func_desc->lprgelemdescParam[i].paramdesc.wParamFlags;
7284 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7285 VARIANTARG *src_arg;
7287 if (wParamFlags & PARAMFLAG_FLCID)
7289 prgpvarg[i] = &rgvarg[i];
7290 V_VT(prgpvarg[i]) = VT_I4;
7291 V_I4(prgpvarg[i]) = This->pTypeLib->lcid;
7292 continue;
7295 src_arg = NULL;
7297 for (j = 0; j < cNamedArgs; j++)
7299 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7301 src_arg = &pDispParams->rgvarg[j];
7302 break;
7306 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7308 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7309 vargs_converted++;
7312 if (wParamFlags & PARAMFLAG_FRETVAL)
7314 /* under most conditions the caller is not allowed to
7315 * pass in a dispparam arg in the index of what would be
7316 * the retval parameter. however, there is an exception
7317 * where the extra parameter is used in an extra
7318 * IDispatch::Invoke below */
7319 if ((i < pDispParams->cArgs) &&
7320 ((func_desc->cParams != 1) || !pVarResult ||
7321 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7323 hres = DISP_E_BADPARAMCOUNT;
7324 break;
7327 /* note: this check is placed so that if the caller passes
7328 * in a VARIANTARG for the retval we just ignore it, like
7329 * native does */
7330 if (i == func_desc->cParams - 1)
7332 prgpvarg[i] = &rgvarg[i];
7333 V_BYREF(prgpvarg[i]) = &retval;
7334 V_VT(prgpvarg[i]) = rgvt[i];
7336 else
7338 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7339 hres = E_UNEXPECTED;
7340 break;
7343 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7344 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7346 TRACE("%s\n", debugstr_variant(src_arg));
7348 if(rgvt[i]!=V_VT(src_arg))
7350 if (rgvt[i] == VT_VARIANT)
7351 hres = VariantCopy(&rgvarg[i], src_arg);
7352 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7354 if (rgvt[i] == V_VT(src_arg))
7355 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7356 else
7358 if (wParamFlags & PARAMFLAG_FIN)
7359 hres = VariantCopy(&missing_arg[i], src_arg);
7360 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7362 V_VT(&rgvarg[i]) = rgvt[i];
7364 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7366 SAFEARRAYBOUND bound;
7367 VARIANT *v;
7369 bound.lLbound = 0;
7370 bound.cElements = pDispParams->cArgs-i;
7371 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7373 ERR("SafeArrayCreate failed\n");
7374 break;
7376 hres = SafeArrayAccessData(a, (LPVOID)&v);
7377 if (hres != S_OK)
7379 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7380 SafeArrayDestroy(a);
7381 break;
7383 for (j = 0; j < bound.cElements; j++)
7384 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7385 hres = SafeArrayUnaccessData(a);
7386 if (hres != S_OK)
7388 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7389 SafeArrayDestroy(a);
7390 break;
7392 if (rgvt[i] & VT_BYREF)
7393 V_BYREF(&rgvarg[i]) = &a;
7394 else
7395 V_ARRAY(&rgvarg[i]) = a;
7396 V_VT(&rgvarg[i]) = rgvt[i];
7398 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7400 if (wParamFlags & PARAMFLAG_FIN)
7401 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7402 else
7403 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7404 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7405 V_VT(&rgvarg[i]) = rgvt[i];
7407 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7409 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7410 V_VT(&rgvarg[i]) = rgvt[i];
7412 else
7414 /* FIXME: this doesn't work for VT_BYREF arguments if
7415 * they are not the same type as in the paramdesc */
7416 V_VT(&rgvarg[i]) = V_VT(src_arg);
7417 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7418 V_VT(&rgvarg[i]) = rgvt[i];
7421 if (FAILED(hres))
7423 ERR("failed to convert param %d to %s from %s\n", i,
7424 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7425 break;
7427 prgpvarg[i] = &rgvarg[i];
7429 else
7431 prgpvarg[i] = src_arg;
7434 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->lptdesc->vt == VT_USERDEFINED))
7435 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7436 && V_UNKNOWN(prgpvarg[i])) {
7437 IUnknown *userdefined_iface;
7438 GUID guid;
7440 if (tdesc->vt == VT_PTR)
7441 tdesc = tdesc->lptdesc;
7443 hres = get_iface_guid((ITypeInfo*)iface, tdesc->hreftype, &guid);
7444 if(FAILED(hres))
7445 break;
7447 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7448 if(FAILED(hres)) {
7449 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7450 break;
7453 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7454 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7457 else if (wParamFlags & PARAMFLAG_FOPT)
7459 VARIANTARG *arg;
7460 arg = prgpvarg[i] = &rgvarg[i];
7461 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7463 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].paramdesc.pparamdescex->varDefaultValue);
7464 if (FAILED(hres))
7465 break;
7467 else
7469 /* if the function wants a pointer to a variant then
7470 * set that up, otherwise just pass the VT_ERROR in
7471 * the argument by value */
7472 if (rgvt[i] & VT_BYREF)
7474 V_VT(&missing_arg[i]) = VT_ERROR;
7475 V_ERROR(&missing_arg[i]) = DISP_E_PARAMNOTFOUND;
7477 V_VT(arg) = VT_VARIANT | VT_BYREF;
7478 V_VARIANTREF(arg) = &missing_arg[i];
7480 else
7482 V_VT(arg) = VT_ERROR;
7483 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
7487 else
7489 hres = DISP_E_BADPARAMCOUNT;
7490 break;
7493 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7495 /* VT_VOID is a special case for return types, so it is not
7496 * handled in the general function */
7497 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7498 V_VT(&varresult) = VT_EMPTY;
7499 else
7501 V_VT(&varresult) = 0;
7502 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7503 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7506 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7507 V_VT(&varresult), func_desc->cParams, rgvt,
7508 prgpvarg, &varresult);
7510 vargs_converted = 0;
7512 for (i = 0; i < func_desc->cParams; i++)
7514 USHORT wParamFlags = func_desc->lprgelemdescParam[i].paramdesc.wParamFlags;
7516 if (wParamFlags & PARAMFLAG_FLCID)
7517 continue;
7518 else if (wParamFlags & PARAMFLAG_FRETVAL)
7520 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7522 if (pVarResult)
7524 VariantInit(pVarResult);
7525 /* deref return value */
7526 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7529 VARIANT_ClearInd(prgpvarg[i]);
7531 else if (vargs_converted < pDispParams->cArgs)
7533 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7534 if (wParamFlags & PARAMFLAG_FOUT)
7536 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7538 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7540 if (FAILED(hres))
7542 ERR("failed to convert param %d to vt %d\n", i,
7543 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7544 break;
7548 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7549 func_desc->cParamsOpt < 0 &&
7550 i == func_desc->cParams-1)
7552 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7553 LONG ubound;
7554 VARIANT *v;
7555 hres = SafeArrayGetUBound(a, 1, &ubound);
7556 if (hres != S_OK)
7558 ERR("SafeArrayGetUBound failed with %#lx.\n", hres);
7559 break;
7561 hres = SafeArrayAccessData(a, (LPVOID)&v);
7562 if (hres != S_OK)
7564 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7565 break;
7567 for (j = 0; j <= ubound; j++)
7568 VariantClear(&v[j]);
7569 hres = SafeArrayUnaccessData(a);
7570 if (hres != S_OK)
7572 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7573 break;
7576 VariantClear(&rgvarg[i]);
7577 vargs_converted++;
7579 else if (wParamFlags & PARAMFLAG_FOPT)
7581 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7582 VariantClear(&rgvarg[i]);
7585 VariantClear(&missing_arg[i]);
7588 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7590 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult));
7591 hres = DISP_E_EXCEPTION;
7592 if (pExcepInfo)
7594 IErrorInfo *pErrorInfo;
7595 pExcepInfo->scode = V_ERROR(&varresult);
7596 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7598 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7599 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7600 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7601 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7603 IErrorInfo_Release(pErrorInfo);
7607 if (V_VT(&varresult) != VT_ERROR)
7609 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7611 if (pVarResult)
7613 VariantClear(pVarResult);
7614 *pVarResult = varresult;
7616 else
7617 VariantClear(&varresult);
7620 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7621 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7622 (func_desc->lprgelemdescParam[0].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7623 (pDispParams->cArgs != 0))
7625 if (V_VT(pVarResult) == VT_DISPATCH)
7627 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7628 /* Note: not VariantClear; we still need the dispatch
7629 * pointer to be valid */
7630 VariantInit(pVarResult);
7631 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7632 GetSystemDefaultLCID(), wFlags,
7633 pDispParams, pVarResult, pExcepInfo, pArgErr);
7634 IDispatch_Release(pDispatch);
7636 else
7638 VariantClear(pVarResult);
7639 hres = DISP_E_NOTACOLLECTION;
7643 func_fail:
7644 heap_free(buffer);
7645 break;
7647 case FUNC_DISPATCH: {
7648 IDispatch *disp;
7650 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7651 if (SUCCEEDED(hres)) {
7652 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7653 hres = IDispatch_Invoke(
7654 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7655 pVarResult,pExcepInfo,pArgErr
7657 if (FAILED(hres))
7658 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres);
7659 IDispatch_Release(disp);
7660 } else
7661 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7662 break;
7664 default:
7665 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7666 hres = E_FAIL;
7667 break;
7670 TRACE("-- %#lx\n", hres);
7671 return hres;
7673 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7674 VARDESC *var_desc;
7676 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7677 if(FAILED(hres)) return hres;
7679 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7680 dump_VARDESC(var_desc);
7681 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7682 return E_NOTIMPL;
7685 /* not found, look for it in inherited interfaces */
7686 ITypeInfo2_GetTypeKind(iface, &type_kind);
7687 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7688 if(This->impltypes) {
7689 /* recursive search */
7690 ITypeInfo *pTInfo;
7691 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7692 if(SUCCEEDED(hres)){
7693 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7694 ITypeInfo_Release(pTInfo);
7695 return hres;
7697 WARN("Could not search inherited interface!\n");
7700 WARN("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
7701 return DISP_E_MEMBERNOTFOUND;
7704 /* ITypeInfo::GetDocumentation
7706 * Retrieves the documentation string, the complete Help file name and path,
7707 * and the context ID for the Help topic for a specified type description.
7709 * (Can be tested by the Visual Basic Editor in Word for instance.)
7711 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7712 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7713 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7715 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7716 const TLBFuncDesc *pFDesc;
7717 const TLBVarDesc *pVDesc;
7718 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7719 iface, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7720 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7721 if(pBstrName)
7722 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7723 if(pBstrDocString)
7724 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7725 if(pdwHelpContext)
7726 *pdwHelpContext=This->dwHelpContext;
7727 if(pBstrHelpFile)
7728 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7729 return S_OK;
7730 }else {/* for a member */
7731 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7732 if(pFDesc){
7733 if(pBstrName)
7734 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7735 if(pBstrDocString)
7736 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7737 if(pdwHelpContext)
7738 *pdwHelpContext=pFDesc->helpcontext;
7739 if(pBstrHelpFile)
7740 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7741 return S_OK;
7743 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7744 if(pVDesc){
7745 if(pBstrName)
7746 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7747 if(pBstrDocString)
7748 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7749 if(pdwHelpContext)
7750 *pdwHelpContext=pVDesc->HelpContext;
7751 if(pBstrHelpFile)
7752 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7753 return S_OK;
7757 if(This->impltypes &&
7758 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7759 /* recursive search */
7760 ITypeInfo *pTInfo;
7761 HRESULT result;
7762 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7763 if(SUCCEEDED(result)) {
7764 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7765 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7766 ITypeInfo_Release(pTInfo);
7767 return result;
7769 WARN("Could not search inherited interface!\n");
7772 WARN("member %ld not found\n", memid);
7773 return TYPE_E_ELEMENTNOTFOUND;
7776 /* ITypeInfo::GetDllEntry
7778 * Retrieves a description or specification of an entry point for a function
7779 * in a DLL.
7781 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7782 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7783 WORD *pwOrdinal)
7785 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7786 const TLBFuncDesc *pFDesc;
7788 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7790 if (pBstrDllName) *pBstrDllName = NULL;
7791 if (pBstrName) *pBstrName = NULL;
7792 if (pwOrdinal) *pwOrdinal = 0;
7794 if (This->typeattr.typekind != TKIND_MODULE)
7795 return TYPE_E_BADMODULEKIND;
7797 pFDesc = TLB_get_funcdesc_by_memberid_invkind(This, memid, invKind);
7798 if (!pFDesc) return TYPE_E_ELEMENTNOTFOUND;
7800 dump_TypeInfo(This);
7801 if (TRACE_ON(ole)) dump_TLBFuncDescOne(pFDesc);
7803 if (pBstrDllName) *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7805 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1))
7807 if (pBstrName) *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7808 if (pwOrdinal) *pwOrdinal = -1;
7810 else
7812 if (pBstrName) *pBstrName = NULL;
7813 if (pwOrdinal) *pwOrdinal = LOWORD(pFDesc->Entry);
7815 return S_OK;
7818 /* internal function to make the inherited interfaces' methods appear
7819 * part of the interface */
7820 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7821 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7823 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7824 HRESULT hr;
7826 TRACE("%p, %#lx.\n", iface, *hRefType);
7828 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7830 ITypeInfo *pSubTypeInfo;
7832 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7833 if (FAILED(hr))
7834 return hr;
7836 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7837 hRefType, ppTInfo);
7838 ITypeInfo_Release(pSubTypeInfo);
7839 if (SUCCEEDED(hr))
7840 return hr;
7842 *hRefType -= DISPATCH_HREF_OFFSET;
7844 if (!(*hRefType & DISPATCH_HREF_MASK))
7845 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7846 else
7847 return E_FAIL;
7850 /* ITypeInfo::GetRefTypeInfo
7852 * If a type description references other type descriptions, it retrieves
7853 * the referenced type descriptions.
7855 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7856 ITypeInfo2 *iface,
7857 HREFTYPE hRefType,
7858 ITypeInfo **ppTInfo)
7860 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7861 ITypeInfo *type_info = NULL;
7862 HRESULT result = E_FAIL;
7863 TLBRefType *ref_type;
7864 UINT i;
7866 if(!ppTInfo)
7867 return E_INVALIDARG;
7869 if ((INT)hRefType < 0) {
7870 ITypeInfoImpl *pTypeInfoImpl;
7872 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7873 !(This->typeattr.typekind == TKIND_INTERFACE ||
7874 This->typeattr.typekind == TKIND_DISPATCH))
7875 return TYPE_E_ELEMENTNOTFOUND;
7877 /* when we meet a DUAL typeinfo, we must create the alternate
7878 * version of it.
7880 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7882 *pTypeInfoImpl = *This;
7883 pTypeInfoImpl->ref = 0;
7884 list_init(&pTypeInfoImpl->custdata_list);
7886 if (This->typeattr.typekind == TKIND_INTERFACE)
7887 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7888 else
7889 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7891 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7892 /* the AddRef implicitly adds a reference to the parent typelib, which
7893 * stops the copied data from being destroyed until the new typeinfo's
7894 * refcount goes to zero, but we need to signal to the new instance to
7895 * not free its data structures when it is destroyed */
7896 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7897 ITypeInfo_AddRef(*ppTInfo);
7899 TRACE("got dual interface %p\n", *ppTInfo);
7900 return S_OK;
7903 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7904 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7906 if(!(hRefType & 0x1))
7908 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7910 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7912 result = S_OK;
7913 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7914 ITypeInfo_AddRef(type_info);
7915 break;
7920 if (!type_info)
7922 ITypeLib *pTLib = NULL;
7924 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7926 if(ref_type->reference == (hRefType & (~0x3)))
7927 break;
7929 if(&ref_type->entry == &This->pTypeLib->ref_list)
7931 FIXME("Can't find pRefType for ref %lx\n", hRefType);
7932 return E_FAIL;
7935 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7936 UINT Index;
7937 TRACE("internal reference\n");
7938 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7939 } else {
7940 if(ref_type->pImpTLInfo->pImpTypeLib) {
7941 TRACE("typeinfo in imported typelib that is already loaded\n");
7942 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7943 ITypeLib_AddRef(pTLib);
7944 result = S_OK;
7945 } else {
7946 /* Search in cached typelibs */
7947 ITypeLibImpl *entry;
7949 EnterCriticalSection(&cache_section);
7950 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
7952 if (entry->guid
7953 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
7954 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
7955 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
7956 && entry->set_lcid == ref_type->pImpTLInfo->lcid
7957 && entry->syskind == This->pTypeLib->syskind)
7959 TRACE("got cached %p\n", entry);
7960 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
7961 ITypeLib_AddRef(pTLib);
7962 result = S_OK;
7963 break;
7966 LeaveCriticalSection(&cache_section);
7968 if (!pTLib)
7970 BSTR libnam;
7972 /* Search on disk */
7973 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7974 ref_type->pImpTLInfo->wVersionMajor,
7975 ref_type->pImpTLInfo->wVersionMinor,
7976 This->pTypeLib->syskind,
7977 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7978 if (FAILED(result))
7979 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7981 result = LoadTypeLib(libnam, &pTLib);
7982 SysFreeString(libnam);
7985 if(SUCCEEDED(result)) {
7986 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7987 ITypeLib_AddRef(pTLib);
7991 if(SUCCEEDED(result)) {
7992 if(ref_type->index == TLB_REF_USE_GUID)
7993 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
7994 else
7995 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
7997 if (pTLib != NULL)
7998 ITypeLib_Release(pTLib);
7999 if (FAILED(result))
8001 WARN("(%p) failed hreftype %#lx.\n", iface, hRefType);
8002 return result;
8006 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
8007 ITypeInfo_Release(type_info);
8008 else *ppTInfo = type_info;
8010 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface, hRefType,
8011 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8012 return result;
8015 /* ITypeInfo::AddressOfMember
8017 * Retrieves the addresses of static functions or variables, such as those
8018 * defined in a DLL.
8020 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8021 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8023 HRESULT hr;
8024 BSTR dll, entry;
8025 WORD ordinal;
8026 HMODULE module;
8028 TRACE("%p, %lx, %#x, %p.\n", iface, memid, invKind, ppv);
8030 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8031 if (FAILED(hr))
8032 return hr;
8034 module = LoadLibraryW(dll);
8035 if (!module)
8037 ERR("couldn't load %s\n", debugstr_w(dll));
8038 SysFreeString(dll);
8039 SysFreeString(entry);
8040 return STG_E_FILENOTFOUND;
8042 /* FIXME: store library somewhere where we can free it */
8044 if (entry)
8046 LPSTR entryA;
8047 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8048 entryA = heap_alloc(len);
8049 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8051 *ppv = GetProcAddress(module, entryA);
8052 if (!*ppv)
8053 ERR("function not found %s\n", debugstr_a(entryA));
8055 heap_free(entryA);
8057 else
8059 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8060 if (!*ppv)
8061 ERR("function not found %d\n", ordinal);
8064 SysFreeString(dll);
8065 SysFreeString(entry);
8067 if (!*ppv)
8068 return TYPE_E_DLLFUNCTIONNOTFOUND;
8070 return S_OK;
8073 /* ITypeInfo::CreateInstance
8075 * Creates a new instance of a type that describes a component object class
8076 * (coclass).
8078 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8079 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8081 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8082 HRESULT hr;
8083 TYPEATTR *pTA;
8085 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8087 *ppvObj = NULL;
8089 if(pOuterUnk)
8091 WARN("Not able to aggregate\n");
8092 return CLASS_E_NOAGGREGATION;
8095 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8096 if(FAILED(hr)) return hr;
8098 if(pTA->typekind != TKIND_COCLASS)
8100 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8101 hr = E_INVALIDARG;
8102 goto end;
8105 hr = S_FALSE;
8106 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8108 IUnknown *pUnk;
8109 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8110 TRACE("GetActiveObject rets %#lx.\n", hr);
8111 if(hr == S_OK)
8113 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8114 IUnknown_Release(pUnk);
8118 if(hr != S_OK)
8119 hr = CoCreateInstance(&pTA->guid, NULL,
8120 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8121 riid, ppvObj);
8123 end:
8124 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8125 return hr;
8128 /* ITypeInfo::GetMops
8130 * Retrieves marshalling information.
8132 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, BSTR *pBstrMops)
8134 FIXME("%p, %ld stub!\n", iface, memid);
8135 *pBstrMops = NULL;
8136 return S_OK;
8139 /* ITypeInfo::GetContainingTypeLib
8141 * Retrieves the containing type library and the index of the type description
8142 * within that type library.
8144 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8145 ITypeLib * *ppTLib, UINT *pIndex)
8147 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8149 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8150 if (pIndex) {
8151 *pIndex=This->index;
8152 TRACE("returning pIndex=%d\n", *pIndex);
8155 if (ppTLib) {
8156 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8157 ITypeLib_AddRef(*ppTLib);
8158 TRACE("returning ppTLib=%p\n", *ppTLib);
8161 return S_OK;
8164 /* ITypeInfo::ReleaseTypeAttr
8166 * Releases a TYPEATTR previously returned by Get
8169 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8170 TYPEATTR* pTypeAttr)
8172 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8173 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8174 heap_free(pTypeAttr);
8177 /* ITypeInfo::ReleaseFuncDesc
8179 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8181 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8182 ITypeInfo2 *iface,
8183 FUNCDESC *pFuncDesc)
8185 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8186 SHORT i;
8188 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8190 for (i = 0; i < pFuncDesc->cParams; i++)
8191 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8192 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8194 SysFreeString((BSTR)pFuncDesc);
8197 /* ITypeInfo::ReleaseVarDesc
8199 * Releases a VARDESC previously returned by GetVarDesc.
8201 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8202 VARDESC *pVarDesc)
8204 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8205 TRACE("(%p)->(%p)\n", This, pVarDesc);
8207 TLB_FreeVarDesc(pVarDesc);
8210 /* ITypeInfo2::GetTypeKind
8212 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8215 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8216 TYPEKIND *pTypeKind)
8218 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8219 *pTypeKind = This->typeattr.typekind;
8220 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8221 return S_OK;
8224 /* ITypeInfo2::GetTypeFlags
8226 * Returns the type flags without any allocations. This returns a DWORD type
8227 * flag, which expands the type flags without growing the TYPEATTR (type
8228 * attribute).
8231 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8233 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8234 TRACE("%p, %p.\n", iface, pTypeFlags);
8235 *pTypeFlags=This->typeattr.wTypeFlags;
8236 return S_OK;
8239 /* ITypeInfo2::GetFuncIndexOfMemId
8240 * Binds to a specific member based on a known DISPID, where the member name
8241 * is not known (for example, when binding to a default member).
8244 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8245 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8247 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8248 UINT fdc;
8249 HRESULT result;
8251 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8252 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8253 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8254 break;
8256 if(fdc < This->typeattr.cFuncs) {
8257 *pFuncIndex = fdc;
8258 result = S_OK;
8259 } else
8260 result = TYPE_E_ELEMENTNOTFOUND;
8262 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface, memid, invKind, result);
8263 return result;
8266 /* TypeInfo2::GetVarIndexOfMemId
8268 * Binds to a specific member based on a known DISPID, where the member name
8269 * is not known (for example, when binding to a default member).
8272 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8273 MEMBERID memid, UINT *pVarIndex)
8275 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8276 TLBVarDesc *pVarInfo;
8278 TRACE("%p, %ld, %p.\n", iface, memid, pVarIndex);
8280 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8281 if(!pVarInfo)
8282 return TYPE_E_ELEMENTNOTFOUND;
8284 *pVarIndex = (pVarInfo - This->vardescs);
8286 return S_OK;
8289 /* ITypeInfo2::GetCustData
8291 * Gets the custom data
8293 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8294 ITypeInfo2 * iface,
8295 REFGUID guid,
8296 VARIANT *pVarVal)
8298 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8299 TLBCustData *pCData;
8301 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8303 if(!guid || !pVarVal)
8304 return E_INVALIDARG;
8306 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8308 VariantInit( pVarVal);
8309 if (pCData)
8310 VariantCopy( pVarVal, &pCData->data);
8311 else
8312 VariantClear( pVarVal );
8313 return S_OK;
8316 /* ITypeInfo2::GetFuncCustData
8318 * Gets the custom data
8320 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8321 ITypeInfo2 * iface,
8322 UINT index,
8323 REFGUID guid,
8324 VARIANT *pVarVal)
8326 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8327 const TLBFuncDesc *desc;
8328 TLBCustData *data;
8329 UINT hrefoffset;
8330 HRESULT hr;
8332 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8334 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8335 if (FAILED(hr))
8337 WARN("description for function %d not found\n", index);
8338 return hr;
8341 VariantInit(pVarVal);
8342 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8343 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8346 /* ITypeInfo2::GetParamCustData
8348 * Gets the custom data
8350 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8351 ITypeInfo2 * iface,
8352 UINT indexFunc,
8353 UINT indexParam,
8354 REFGUID guid,
8355 VARIANT *pVarVal)
8357 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8358 const TLBFuncDesc *pFDesc;
8359 TLBCustData *pCData;
8360 UINT hrefoffset;
8361 HRESULT hr;
8363 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8364 debugstr_guid(guid), pVarVal);
8366 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8367 if (FAILED(hr))
8368 return hr;
8370 if(indexParam >= pFDesc->funcdesc.cParams)
8371 return TYPE_E_ELEMENTNOTFOUND;
8373 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8374 if(!pCData)
8375 return TYPE_E_ELEMENTNOTFOUND;
8377 VariantInit(pVarVal);
8378 VariantCopy(pVarVal, &pCData->data);
8380 return S_OK;
8383 /* ITypeInfo2::GetVarCustData
8385 * Gets the custom data
8387 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8388 ITypeInfo2 * iface,
8389 UINT index,
8390 REFGUID guid,
8391 VARIANT *pVarVal)
8393 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8394 TLBCustData *pCData;
8395 TLBVarDesc *pVDesc = &This->vardescs[index];
8397 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8399 if(index >= This->typeattr.cVars)
8400 return TYPE_E_ELEMENTNOTFOUND;
8402 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8403 if(!pCData)
8404 return TYPE_E_ELEMENTNOTFOUND;
8406 VariantInit(pVarVal);
8407 VariantCopy(pVarVal, &pCData->data);
8409 return S_OK;
8412 /* ITypeInfo2::GetImplCustData
8414 * Gets the custom data
8416 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8417 ITypeInfo2 * iface,
8418 UINT index,
8419 REFGUID guid,
8420 VARIANT *pVarVal)
8422 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8423 TLBCustData *pCData;
8424 TLBImplType *pRDesc = &This->impltypes[index];
8426 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8428 if(index >= This->typeattr.cImplTypes)
8429 return TYPE_E_ELEMENTNOTFOUND;
8431 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8432 if(!pCData)
8433 return TYPE_E_ELEMENTNOTFOUND;
8435 VariantInit(pVarVal);
8436 VariantCopy(pVarVal, &pCData->data);
8438 return S_OK;
8441 /* ITypeInfo2::GetDocumentation2
8443 * Retrieves the documentation string, the complete Help file name and path,
8444 * the localization context to use, and the context ID for the library Help
8445 * topic in the Help file.
8448 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8449 ITypeInfo2 * iface,
8450 MEMBERID memid,
8451 LCID lcid,
8452 BSTR *pbstrHelpString,
8453 DWORD *pdwHelpStringContext,
8454 BSTR *pbstrHelpStringDll)
8456 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8457 const TLBFuncDesc *pFDesc;
8458 const TLBVarDesc *pVDesc;
8459 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8460 iface, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8461 pbstrHelpStringDll );
8462 /* the help string should be obtained from the helpstringdll,
8463 * using the _DLLGetDocumentation function, based on the supplied
8464 * lcid. Nice to do sometime...
8466 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8467 if(pbstrHelpString)
8468 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8469 if(pdwHelpStringContext)
8470 *pdwHelpStringContext=This->dwHelpStringContext;
8471 if(pbstrHelpStringDll)
8472 *pbstrHelpStringDll=
8473 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8474 return S_OK;
8475 }else {/* for a member */
8476 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8477 if(pFDesc){
8478 if(pbstrHelpString)
8479 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8480 if(pdwHelpStringContext)
8481 *pdwHelpStringContext=pFDesc->HelpStringContext;
8482 if(pbstrHelpStringDll)
8483 *pbstrHelpStringDll=
8484 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8485 return S_OK;
8487 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8488 if(pVDesc){
8489 if(pbstrHelpString)
8490 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8491 if(pdwHelpStringContext)
8492 *pdwHelpStringContext=pVDesc->HelpStringContext;
8493 if(pbstrHelpStringDll)
8494 *pbstrHelpStringDll=
8495 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8496 return S_OK;
8499 return TYPE_E_ELEMENTNOTFOUND;
8502 /* ITypeInfo2::GetAllCustData
8504 * Gets all custom data items for the Type info.
8507 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8508 ITypeInfo2 * iface,
8509 CUSTDATA *pCustData)
8511 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8513 TRACE("%p %p\n", This, pCustData);
8515 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8518 /* ITypeInfo2::GetAllFuncCustData
8520 * Gets all custom data items for the specified Function
8523 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8524 ITypeInfo2 * iface,
8525 UINT index,
8526 CUSTDATA *pCustData)
8528 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8529 const TLBFuncDesc *pFDesc;
8530 UINT hrefoffset;
8531 HRESULT hr;
8533 TRACE("%p %u %p\n", This, index, pCustData);
8535 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8536 if (FAILED(hr))
8537 return hr;
8539 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8542 /* ITypeInfo2::GetAllParamCustData
8544 * Gets all custom data items for the Functions
8547 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8548 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8550 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8551 const TLBFuncDesc *pFDesc;
8552 UINT hrefoffset;
8553 HRESULT hr;
8555 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8557 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8558 if (FAILED(hr))
8559 return hr;
8561 if(indexParam >= pFDesc->funcdesc.cParams)
8562 return TYPE_E_ELEMENTNOTFOUND;
8564 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8567 /* ITypeInfo2::GetAllVarCustData
8569 * Gets all custom data items for the specified Variable
8572 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8573 UINT index, CUSTDATA *pCustData)
8575 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8576 TLBVarDesc * pVDesc = &This->vardescs[index];
8578 TRACE("%p %u %p\n", This, index, pCustData);
8580 if(index >= This->typeattr.cVars)
8581 return TYPE_E_ELEMENTNOTFOUND;
8583 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8586 /* ITypeInfo2::GetAllImplCustData
8588 * Gets all custom data items for the specified implementation type
8591 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8592 ITypeInfo2 * iface,
8593 UINT index,
8594 CUSTDATA *pCustData)
8596 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8597 TLBImplType *pRDesc = &This->impltypes[index];
8599 TRACE("%p %u %p\n", This, index, pCustData);
8601 if(index >= This->typeattr.cImplTypes)
8602 return TYPE_E_ELEMENTNOTFOUND;
8604 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8607 static const ITypeInfo2Vtbl tinfvt =
8610 ITypeInfo_fnQueryInterface,
8611 ITypeInfo_fnAddRef,
8612 ITypeInfo_fnRelease,
8614 ITypeInfo_fnGetTypeAttr,
8615 ITypeInfo_fnGetTypeComp,
8616 ITypeInfo_fnGetFuncDesc,
8617 ITypeInfo_fnGetVarDesc,
8618 ITypeInfo_fnGetNames,
8619 ITypeInfo_fnGetRefTypeOfImplType,
8620 ITypeInfo_fnGetImplTypeFlags,
8621 ITypeInfo_fnGetIDsOfNames,
8622 ITypeInfo_fnInvoke,
8623 ITypeInfo_fnGetDocumentation,
8624 ITypeInfo_fnGetDllEntry,
8625 ITypeInfo_fnGetRefTypeInfo,
8626 ITypeInfo_fnAddressOfMember,
8627 ITypeInfo_fnCreateInstance,
8628 ITypeInfo_fnGetMops,
8629 ITypeInfo_fnGetContainingTypeLib,
8630 ITypeInfo_fnReleaseTypeAttr,
8631 ITypeInfo_fnReleaseFuncDesc,
8632 ITypeInfo_fnReleaseVarDesc,
8634 ITypeInfo2_fnGetTypeKind,
8635 ITypeInfo2_fnGetTypeFlags,
8636 ITypeInfo2_fnGetFuncIndexOfMemId,
8637 ITypeInfo2_fnGetVarIndexOfMemId,
8638 ITypeInfo2_fnGetCustData,
8639 ITypeInfo2_fnGetFuncCustData,
8640 ITypeInfo2_fnGetParamCustData,
8641 ITypeInfo2_fnGetVarCustData,
8642 ITypeInfo2_fnGetImplTypeCustData,
8643 ITypeInfo2_fnGetDocumentation2,
8644 ITypeInfo2_fnGetAllCustData,
8645 ITypeInfo2_fnGetAllFuncCustData,
8646 ITypeInfo2_fnGetAllParamCustData,
8647 ITypeInfo2_fnGetAllVarCustData,
8648 ITypeInfo2_fnGetAllImplTypeCustData,
8651 /******************************************************************************
8652 * CreateDispTypeInfo [OLEAUT32.31]
8654 * Build type information for an object so it can be called through an
8655 * IDispatch interface.
8657 * RETURNS
8658 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8659 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8661 * NOTES
8662 * This call allows an objects methods to be accessed through IDispatch, by
8663 * building an ITypeInfo object that IDispatch can use to call through.
8665 HRESULT WINAPI CreateDispTypeInfo(
8666 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8667 LCID lcid, /* [I] Locale Id */
8668 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8670 ITypeInfoImpl *pTIClass, *pTIIface;
8671 ITypeLibImpl *pTypeLibImpl;
8672 unsigned int param, func;
8673 TLBFuncDesc *pFuncDesc;
8674 TLBRefType *ref;
8676 TRACE("\n");
8677 pTypeLibImpl = TypeLibImpl_Constructor();
8678 if (!pTypeLibImpl) return E_FAIL;
8680 pTypeLibImpl->TypeInfoCount = 2;
8681 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8683 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8684 pTIIface->pTypeLib = pTypeLibImpl;
8685 pTIIface->index = 0;
8686 pTIIface->Name = NULL;
8687 pTIIface->dwHelpContext = -1;
8688 pTIIface->guid = NULL;
8689 pTIIface->typeattr.lcid = lcid;
8690 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8691 pTIIface->typeattr.wMajorVerNum = 0;
8692 pTIIface->typeattr.wMinorVerNum = 0;
8693 pTIIface->typeattr.cbAlignment = 2;
8694 pTIIface->typeattr.cbSizeInstance = -1;
8695 pTIIface->typeattr.cbSizeVft = -1;
8696 pTIIface->typeattr.cFuncs = 0;
8697 pTIIface->typeattr.cImplTypes = 0;
8698 pTIIface->typeattr.cVars = 0;
8699 pTIIface->typeattr.wTypeFlags = 0;
8700 pTIIface->hreftype = 0;
8702 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8703 pFuncDesc = pTIIface->funcdescs;
8704 for(func = 0; func < pidata->cMembers; func++) {
8705 METHODDATA *md = pidata->pmethdata + func;
8706 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8707 pFuncDesc->funcdesc.memid = md->dispid;
8708 pFuncDesc->funcdesc.lprgscode = NULL;
8709 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8710 pFuncDesc->funcdesc.invkind = md->wFlags;
8711 pFuncDesc->funcdesc.callconv = md->cc;
8712 pFuncDesc->funcdesc.cParams = md->cArgs;
8713 pFuncDesc->funcdesc.cParamsOpt = 0;
8714 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8715 pFuncDesc->funcdesc.cScodes = 0;
8716 pFuncDesc->funcdesc.wFuncFlags = 0;
8717 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8718 pFuncDesc->funcdesc.elemdescFunc.paramdesc.wParamFlags = PARAMFLAG_NONE;
8719 pFuncDesc->funcdesc.elemdescFunc.paramdesc.pparamdescex = NULL;
8720 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8721 md->cArgs * sizeof(ELEMDESC));
8722 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8723 for(param = 0; param < md->cArgs; param++) {
8724 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8725 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8727 pFuncDesc->helpcontext = 0;
8728 pFuncDesc->HelpStringContext = 0;
8729 pFuncDesc->HelpString = NULL;
8730 pFuncDesc->Entry = NULL;
8731 list_init(&pFuncDesc->custdata_list);
8732 pTIIface->typeattr.cFuncs++;
8733 ++pFuncDesc;
8736 dump_TypeInfo(pTIIface);
8738 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8739 pTIClass->pTypeLib = pTypeLibImpl;
8740 pTIClass->index = 1;
8741 pTIClass->Name = NULL;
8742 pTIClass->dwHelpContext = -1;
8743 pTIClass->guid = NULL;
8744 pTIClass->typeattr.lcid = lcid;
8745 pTIClass->typeattr.typekind = TKIND_COCLASS;
8746 pTIClass->typeattr.wMajorVerNum = 0;
8747 pTIClass->typeattr.wMinorVerNum = 0;
8748 pTIClass->typeattr.cbAlignment = 2;
8749 pTIClass->typeattr.cbSizeInstance = -1;
8750 pTIClass->typeattr.cbSizeVft = -1;
8751 pTIClass->typeattr.cFuncs = 0;
8752 pTIClass->typeattr.cImplTypes = 1;
8753 pTIClass->typeattr.cVars = 0;
8754 pTIClass->typeattr.wTypeFlags = 0;
8755 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8757 pTIClass->impltypes = TLBImplType_Alloc(1);
8759 ref = heap_alloc_zero(sizeof(*ref));
8760 ref->pImpTLInfo = TLB_REF_INTERNAL;
8761 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8763 dump_TypeInfo(pTIClass);
8765 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8767 ITypeInfo_AddRef(*pptinfo);
8768 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8770 return S_OK;
8774 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8776 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8778 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8781 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8783 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8785 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8788 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8790 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8792 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8795 static HRESULT WINAPI ITypeComp_fnBind(
8796 ITypeComp * iface,
8797 OLECHAR * szName,
8798 ULONG lHash,
8799 WORD wFlags,
8800 ITypeInfo ** ppTInfo,
8801 DESCKIND * pDescKind,
8802 BINDPTR * pBindPtr)
8804 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8805 const TLBFuncDesc *pFDesc;
8806 const TLBVarDesc *pVDesc;
8807 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8808 UINT fdc;
8810 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8812 *pDescKind = DESCKIND_NONE;
8813 pBindPtr->lpfuncdesc = NULL;
8814 *ppTInfo = NULL;
8816 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8817 pFDesc = &This->funcdescs[fdc];
8818 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8819 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8820 break;
8821 else
8822 /* name found, but wrong flags */
8823 hr = TYPE_E_TYPEMISMATCH;
8827 if (fdc < This->typeattr.cFuncs)
8829 HRESULT hr = TLB_AllocAndInitFuncDesc(
8830 &pFDesc->funcdesc,
8831 &pBindPtr->lpfuncdesc,
8832 This->typeattr.typekind == TKIND_DISPATCH);
8833 if (FAILED(hr))
8834 return hr;
8835 *pDescKind = DESCKIND_FUNCDESC;
8836 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8837 ITypeInfo_AddRef(*ppTInfo);
8838 return S_OK;
8839 } else {
8840 pVDesc = TLB_get_vardesc_by_name(This, szName);
8841 if(pVDesc){
8842 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8843 if (FAILED(hr))
8844 return hr;
8845 *pDescKind = DESCKIND_VARDESC;
8846 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8847 ITypeInfo_AddRef(*ppTInfo);
8848 return S_OK;
8852 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8853 /* recursive search */
8854 ITypeInfo *pTInfo;
8855 ITypeComp *pTComp;
8856 HRESULT hr;
8857 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8858 if (SUCCEEDED(hr))
8860 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8861 ITypeInfo_Release(pTInfo);
8863 if (SUCCEEDED(hr))
8865 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8866 ITypeComp_Release(pTComp);
8867 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8868 This->typeattr.typekind == TKIND_DISPATCH)
8870 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8871 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8872 SysFreeString((BSTR)tmp);
8874 return hr;
8876 WARN("Could not search inherited interface!\n");
8878 if (hr == DISP_E_MEMBERNOTFOUND)
8879 hr = S_OK;
8880 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8881 return hr;
8884 static HRESULT WINAPI ITypeComp_fnBindType(
8885 ITypeComp * iface,
8886 OLECHAR * szName,
8887 ULONG lHash,
8888 ITypeInfo ** ppTInfo,
8889 ITypeComp ** ppTComp)
8891 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8893 /* strange behaviour (does nothing) but like the
8894 * original */
8896 if (!ppTInfo || !ppTComp)
8897 return E_POINTER;
8899 *ppTInfo = NULL;
8900 *ppTComp = NULL;
8902 return S_OK;
8905 static const ITypeCompVtbl tcompvt =
8908 ITypeComp_fnQueryInterface,
8909 ITypeComp_fnAddRef,
8910 ITypeComp_fnRelease,
8912 ITypeComp_fnBind,
8913 ITypeComp_fnBindType
8916 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8917 ICreateTypeLib2** ppctlib)
8919 ITypeLibImpl *This;
8920 HRESULT hres;
8922 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8924 if (!szFile) return E_INVALIDARG;
8926 This = TypeLibImpl_Constructor();
8927 if (!This)
8928 return E_OUTOFMEMORY;
8930 This->lcid = GetSystemDefaultLCID();
8931 This->syskind = syskind;
8932 This->ptr_size = get_ptr_size(syskind);
8934 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8935 if (!This->path) {
8936 ITypeLib2_Release(&This->ITypeLib2_iface);
8937 return E_OUTOFMEMORY;
8939 lstrcpyW(This->path, szFile);
8941 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8942 ITypeLib2_Release(&This->ITypeLib2_iface);
8943 return hres;
8946 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8947 REFIID riid, void **object)
8949 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8951 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8954 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8956 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8958 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8961 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8963 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8965 return ITypeLib2_Release(&This->ITypeLib2_iface);
8968 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8969 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8971 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8972 ITypeInfoImpl *info;
8973 HRESULT hres;
8975 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8977 if (!ctinfo || !name)
8978 return E_INVALIDARG;
8980 info = TLB_get_typeinfo_by_name(This, name);
8981 if (info)
8982 return TYPE_E_NAMECONFLICT;
8984 if (This->typeinfos)
8985 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8986 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8987 else
8988 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8990 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8992 info->pTypeLib = This;
8993 info->Name = TLB_append_str(&This->name_list, name);
8994 info->index = This->TypeInfoCount;
8995 info->typeattr.typekind = kind;
8996 info->typeattr.cbAlignment = 4;
8998 switch (info->typeattr.typekind) {
8999 case TKIND_ENUM:
9000 case TKIND_INTERFACE:
9001 case TKIND_DISPATCH:
9002 case TKIND_COCLASS:
9003 info->typeattr.cbSizeInstance = This->ptr_size;
9004 break;
9005 case TKIND_RECORD:
9006 case TKIND_UNION:
9007 info->typeattr.cbSizeInstance = 0;
9008 break;
9009 case TKIND_MODULE:
9010 info->typeattr.cbSizeInstance = 2;
9011 break;
9012 case TKIND_ALIAS:
9013 info->typeattr.cbSizeInstance = -0x75;
9014 break;
9015 default:
9016 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9017 info->typeattr.cbSizeInstance = 0xdeadbeef;
9018 break;
9021 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9022 &IID_ICreateTypeInfo, (void **)ctinfo);
9023 if (FAILED(hres)) {
9024 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9025 return hres;
9028 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9030 ++This->TypeInfoCount;
9032 return S_OK;
9035 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9036 LPOLESTR name)
9038 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9040 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9042 if (!name)
9043 return E_INVALIDARG;
9045 This->Name = TLB_append_str(&This->name_list, name);
9047 return S_OK;
9050 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9051 WORD majorVerNum, WORD minorVerNum)
9053 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9055 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9057 This->ver_major = majorVerNum;
9058 This->ver_minor = minorVerNum;
9060 return S_OK;
9063 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9064 REFGUID guid)
9066 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9068 TRACE("%p %s\n", This, debugstr_guid(guid));
9070 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9072 return S_OK;
9075 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9076 LPOLESTR doc)
9078 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9080 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9082 if (!doc)
9083 return E_INVALIDARG;
9085 This->DocString = TLB_append_str(&This->string_list, doc);
9087 return S_OK;
9090 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9091 LPOLESTR helpFileName)
9093 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9095 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9097 if (!helpFileName)
9098 return E_INVALIDARG;
9100 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9102 return S_OK;
9105 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9106 DWORD helpContext)
9108 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9110 TRACE("%p, %ld.\n", iface, helpContext);
9112 This->dwHelpContext = helpContext;
9114 return S_OK;
9117 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9118 LCID lcid)
9120 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9122 TRACE("%p, %#lx.\n", iface, lcid);
9124 This->set_lcid = lcid;
9126 return S_OK;
9129 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9130 UINT libFlags)
9132 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9134 TRACE("%p %x\n", This, libFlags);
9136 This->libflags = libFlags;
9138 return S_OK;
9141 typedef struct tagWMSFT_SegContents {
9142 DWORD len;
9143 void *data;
9144 } WMSFT_SegContents;
9146 typedef struct tagWMSFT_TLBFile {
9147 MSFT_Header header;
9148 WMSFT_SegContents typeinfo_seg;
9149 WMSFT_SegContents impfile_seg;
9150 WMSFT_SegContents impinfo_seg;
9151 WMSFT_SegContents ref_seg;
9152 WMSFT_SegContents guidhash_seg;
9153 WMSFT_SegContents guid_seg;
9154 WMSFT_SegContents namehash_seg;
9155 WMSFT_SegContents name_seg;
9156 WMSFT_SegContents string_seg;
9157 WMSFT_SegContents typdesc_seg;
9158 WMSFT_SegContents arraydesc_seg;
9159 WMSFT_SegContents custdata_seg;
9160 WMSFT_SegContents cdguids_seg;
9161 MSFT_SegDir segdir;
9162 WMSFT_SegContents aux_seg;
9163 } WMSFT_TLBFile;
9165 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9166 WMSFT_TLBFile *file)
9168 TLBString *str;
9169 UINT last_offs;
9170 char *data;
9172 file->string_seg.len = 0;
9173 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9174 int size;
9176 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9177 if (size == 0)
9178 return E_UNEXPECTED;
9180 size += sizeof(INT16);
9181 if (size % 4)
9182 size = (size + 4) & ~0x3;
9183 if (size < 8)
9184 size = 8;
9186 file->string_seg.len += size;
9188 /* temporarily use str->offset to store the length of the aligned,
9189 * converted string */
9190 str->offset = size;
9193 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9195 last_offs = 0;
9196 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9197 int size;
9199 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9200 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9201 if (size == 0) {
9202 heap_free(file->string_seg.data);
9203 return E_UNEXPECTED;
9206 *((INT16*)data) = size;
9208 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9210 size = str->offset;
9211 data += size;
9212 str->offset = last_offs;
9213 last_offs += size;
9216 return S_OK;
9219 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9220 WMSFT_TLBFile *file)
9222 TLBString *str;
9223 UINT last_offs;
9224 char *data;
9225 MSFT_NameIntro *last_intro = NULL;
9227 file->header.nametablecount = 0;
9228 file->header.nametablechars = 0;
9230 file->name_seg.len = 0;
9231 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9232 int size;
9234 size = lstrlenW(str->str);
9235 file->header.nametablechars += size;
9236 file->header.nametablecount++;
9238 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9239 if (size == 0)
9240 return E_UNEXPECTED;
9242 size += sizeof(MSFT_NameIntro);
9243 if (size % 4)
9244 size = (size + 4) & ~0x3;
9245 if (size < 8)
9246 size = 8;
9248 file->name_seg.len += size;
9250 /* temporarily use str->offset to store the length of the aligned,
9251 * converted string */
9252 str->offset = size;
9255 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9256 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9258 last_offs = 0;
9259 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9260 int size, hash;
9261 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9263 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9264 data + sizeof(MSFT_NameIntro),
9265 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9266 if (size == 0) {
9267 heap_free(file->name_seg.data);
9268 return E_UNEXPECTED;
9270 data[sizeof(MSFT_NameIntro) + size] = '\0';
9272 intro->hreftype = -1; /* TODO? */
9273 intro->namelen = size & 0xFF;
9274 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9275 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9276 intro->namelen |= hash << 16;
9277 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9278 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9280 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9281 str->offset - size - sizeof(MSFT_NameIntro));
9283 /* update str->offset to actual value to use in other
9284 * compilation functions that require positions within
9285 * the string table */
9286 last_intro = intro;
9287 size = str->offset;
9288 data += size;
9289 str->offset = last_offs;
9290 last_offs += size;
9293 if(last_intro)
9294 last_intro->hreftype = 0; /* last one is 0? */
9296 return S_OK;
9299 static inline int hash_guid(GUID *guid)
9301 int i, hash = 0;
9303 for (i = 0; i < 8; i ++)
9304 hash ^= ((const short *)guid)[i];
9306 return hash & 0x1f;
9309 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9311 TLBGuid *guid;
9312 MSFT_GuidEntry *entry;
9313 DWORD offs;
9314 int hash_key, *guidhashtab;
9316 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9317 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9319 entry = file->guid_seg.data;
9320 offs = 0;
9321 guidhashtab = file->guidhash_seg.data;
9322 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9323 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9324 entry->hreftype = guid->hreftype;
9326 hash_key = hash_guid(&guid->guid);
9327 entry->next_hash = guidhashtab[hash_key];
9328 guidhashtab[hash_key] = offs;
9330 guid->offset = offs;
9331 offs += sizeof(MSFT_GuidEntry);
9332 ++entry;
9335 return S_OK;
9338 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9340 VARIANT v = *value;
9341 VARTYPE arg_type = V_VT(value);
9342 int mask = 0;
9343 HRESULT hres;
9344 DWORD ret = file->custdata_seg.len;
9346 if(arg_type == VT_INT)
9347 arg_type = VT_I4;
9348 if(arg_type == VT_UINT)
9349 arg_type = VT_UI4;
9351 v = *value;
9352 if(V_VT(value) != arg_type) {
9353 hres = VariantChangeType(&v, value, 0, arg_type);
9354 if(FAILED(hres)){
9355 ERR("VariantChangeType failed: %#lx.\n", hres);
9356 return -1;
9360 /* Check if default value can be stored in-place */
9361 switch(arg_type){
9362 case VT_I4:
9363 case VT_UI4:
9364 mask = 0x3ffffff;
9365 if(V_UI4(&v) > 0x3ffffff)
9366 break;
9367 /* fall through */
9368 case VT_I1:
9369 case VT_UI1:
9370 case VT_BOOL:
9371 if(!mask)
9372 mask = 0xff;
9373 /* fall through */
9374 case VT_I2:
9375 case VT_UI2:
9376 if(!mask)
9377 mask = 0xffff;
9378 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9381 /* have to allocate space in custdata_seg */
9382 switch(arg_type) {
9383 case VT_I4:
9384 case VT_R4:
9385 case VT_UI4:
9386 case VT_INT:
9387 case VT_UINT:
9388 case VT_HRESULT:
9389 case VT_PTR: {
9390 /* Construct the data to be allocated */
9391 int *data;
9393 if(file->custdata_seg.data){
9394 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9395 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9396 file->custdata_seg.len += sizeof(int) * 2;
9397 }else{
9398 file->custdata_seg.len = sizeof(int) * 2;
9399 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9402 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9403 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9405 /* TODO: Check if the encoded data is already present in custdata_seg */
9407 return ret;
9410 case VT_BSTR: {
9411 int mb_len = WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), NULL, 0, NULL, NULL );
9412 int i, len = (6 + mb_len + 3) & ~0x3;
9413 char *data;
9415 if(file->custdata_seg.data){
9416 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9417 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9418 file->custdata_seg.len += len;
9419 }else{
9420 file->custdata_seg.len = len;
9421 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9424 *((unsigned short *)data) = V_VT(value);
9425 *((unsigned int *)(data+2)) = mb_len;
9426 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], mb_len, NULL, NULL);
9427 for (i = 6 + mb_len; i < len; i++)
9428 data[i] = 0x57;
9430 /* TODO: Check if the encoded data is already present in custdata_seg */
9432 return ret;
9434 default:
9435 FIXME("Argument type not yet handled\n");
9436 return -1;
9440 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9442 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9444 DWORD offs = file->arraydesc_seg.len;
9445 DWORD *encoded;
9446 USHORT i;
9448 /* TODO: we should check for duplicates, but that's harder because each
9449 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9450 * at the library-level) */
9452 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9453 if(!file->arraydesc_seg.data)
9454 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9455 else
9456 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9457 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9459 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9460 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9461 for(i = 0; i < desc->cDims; ++i){
9462 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9463 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9466 return offs;
9469 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9471 DWORD junk;
9472 INT16 junk2;
9473 DWORD offs = 0;
9474 DWORD encoded[2];
9475 VARTYPE vt, subtype;
9476 char *data;
9478 if(!desc)
9479 return -1;
9481 if(!out_mix)
9482 out_mix = &junk;
9483 if(!out_size)
9484 out_size = &junk2;
9486 vt = desc->vt & VT_TYPEMASK;
9488 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9489 DWORD mix;
9490 encoded[1] = WMSFT_append_typedesc(desc->lptdesc, file, &mix, out_size);
9491 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9492 *out_mix = 0x7FFF;
9493 *out_size += 2 * sizeof(DWORD);
9494 }else if(vt == VT_CARRAY){
9495 encoded[0] = desc->vt | (0x7FFE << 16);
9496 encoded[1] = WMSFT_append_arraydesc(desc->lpadesc, file);
9497 *out_mix = 0x7FFE;
9498 }else if(vt == VT_USERDEFINED){
9499 encoded[0] = desc->vt | (0x7FFF << 16);
9500 encoded[1] = desc->hreftype;
9501 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9502 }else{
9503 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9505 switch(vt){
9506 case VT_INT:
9507 subtype = VT_I4;
9508 break;
9509 case VT_UINT:
9510 subtype = VT_UI4;
9511 break;
9512 case VT_VOID:
9513 subtype = VT_EMPTY;
9514 break;
9515 default:
9516 subtype = vt;
9517 break;
9520 *out_mix = subtype;
9521 return 0x80000000 | (subtype << 16) | desc->vt;
9524 data = file->typdesc_seg.data;
9525 while(offs < file->typdesc_seg.len){
9526 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9527 return offs;
9528 offs += sizeof(encoded);
9531 file->typdesc_seg.len += sizeof(encoded);
9532 if(!file->typdesc_seg.data)
9533 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9534 else
9535 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9537 memcpy(&data[offs], encoded, sizeof(encoded));
9539 return offs;
9542 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9544 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9545 DWORD ret = cdguids_seg->len, offs;
9546 MSFT_CDGuid *cdguid;
9547 TLBCustData *cd;
9549 if(list_empty(custdata_list))
9550 return -1;
9552 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9553 if(!cdguids_seg->data){
9554 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9555 }else {
9556 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9557 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9560 offs = ret + sizeof(MSFT_CDGuid);
9561 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9562 cdguid->GuidOffset = cd->guid->offset;
9563 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9564 cdguid->next = offs;
9565 offs += sizeof(MSFT_CDGuid);
9566 ++cdguid;
9569 --cdguid;
9570 cdguid->next = -1;
9572 return ret;
9575 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9576 WMSFT_TLBFile *file)
9578 WMSFT_SegContents *aux_seg = &file->aux_seg;
9579 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9580 MSFT_VarRecord *varrecord;
9581 MSFT_FuncRecord *funcrecord;
9582 MEMBERID *memid;
9583 DWORD *name, *offsets, offs;
9585 for(i = 0; i < info->typeattr.cFuncs; ++i){
9586 TLBFuncDesc *desc = &info->funcdescs[i];
9588 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9590 /* optional fields */
9591 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9592 if(!list_empty(&desc->custdata_list))
9593 recorded_size += 7 * sizeof(INT);
9594 else if(desc->HelpStringContext != 0)
9595 recorded_size += 6 * sizeof(INT);
9596 /* res9? resA? */
9597 else if(desc->Entry)
9598 recorded_size += 3 * sizeof(INT);
9599 else if(desc->HelpString)
9600 recorded_size += 2 * sizeof(INT);
9601 else if(desc->helpcontext)
9602 recorded_size += sizeof(INT);
9604 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9606 for(j = 0; j < desc->funcdesc.cParams; ++j){
9607 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9608 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9609 break;
9613 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9616 for(i = 0; i < info->typeattr.cVars; ++i){
9617 TLBVarDesc *desc = &info->vardescs[i];
9619 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9621 /* optional fields */
9622 if(desc->HelpStringContext != 0)
9623 recorded_size += 5 * sizeof(INT);
9624 else if(!list_empty(&desc->custdata_list))
9625 recorded_size += 4 * sizeof(INT);
9626 /* res9? */
9627 else if(desc->HelpString)
9628 recorded_size += 2 * sizeof(INT);
9629 else if(desc->HelpContext != 0)
9630 recorded_size += sizeof(INT);
9632 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9635 if(!recorded_size && !extra_size)
9636 return ret;
9638 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9640 aux_seg->len += recorded_size + extra_size;
9642 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9644 if(aux_seg->data)
9645 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9646 else
9647 aux_seg->data = heap_alloc(aux_seg->len);
9649 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9651 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9652 offs = 0;
9654 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9655 for(i = 0; i < info->typeattr.cFuncs; ++i){
9656 TLBFuncDesc *desc = &info->funcdescs[i];
9657 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9659 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9660 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9661 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9662 funcrecord->VtableOffset = desc->funcdesc.oVft;
9664 /* FKCCIC:
9665 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9666 * ^^^funckind
9667 * ^^^ ^invkind
9668 * ^has_cust_data
9669 * ^^^^callconv
9670 * ^has_param_defaults
9671 * ^oEntry_is_intresource
9673 funcrecord->FKCCIC =
9674 desc->funcdesc.funckind |
9675 (desc->funcdesc.invkind << 3) |
9676 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9677 (desc->funcdesc.callconv << 8);
9679 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9680 funcrecord->FKCCIC |= 0x2000;
9682 for(j = 0; j < desc->funcdesc.cParams; ++j){
9683 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9684 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9685 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9688 if(paramdefault_size > 0)
9689 funcrecord->FKCCIC |= 0x1000;
9691 funcrecord->nrargs = desc->funcdesc.cParams;
9692 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9694 /* optional fields */
9695 /* res9? resA? */
9696 if(!list_empty(&desc->custdata_list)){
9697 size += 7 * sizeof(INT);
9698 funcrecord->HelpContext = desc->helpcontext;
9699 if(desc->HelpString)
9700 funcrecord->oHelpString = desc->HelpString->offset;
9701 else
9702 funcrecord->oHelpString = -1;
9703 if(!desc->Entry)
9704 funcrecord->oEntry = -1;
9705 else if(IS_INTRESOURCE(desc->Entry))
9706 funcrecord->oEntry = LOWORD(desc->Entry);
9707 else
9708 funcrecord->oEntry = desc->Entry->offset;
9709 funcrecord->res9 = -1;
9710 funcrecord->resA = -1;
9711 funcrecord->HelpStringContext = desc->HelpStringContext;
9712 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9713 }else if(desc->HelpStringContext != 0){
9714 size += 6 * 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 }else if(desc->Entry){
9730 size += 3 * sizeof(INT);
9731 funcrecord->HelpContext = desc->helpcontext;
9732 if(desc->HelpString)
9733 funcrecord->oHelpString = desc->HelpString->offset;
9734 else
9735 funcrecord->oHelpString = -1;
9736 if(!desc->Entry)
9737 funcrecord->oEntry = -1;
9738 else if(IS_INTRESOURCE(desc->Entry))
9739 funcrecord->oEntry = LOWORD(desc->Entry);
9740 else
9741 funcrecord->oEntry = desc->Entry->offset;
9742 }else if(desc->HelpString){
9743 size += 2 * sizeof(INT);
9744 funcrecord->HelpContext = desc->helpcontext;
9745 funcrecord->oHelpString = desc->HelpString->offset;
9746 }else if(desc->helpcontext){
9747 size += sizeof(INT);
9748 funcrecord->HelpContext = desc->helpcontext;
9751 paramdefault = (DWORD*)((char *)funcrecord + size);
9752 size += paramdefault_size;
9754 for(j = 0; j < desc->funcdesc.cParams; ++j){
9755 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9757 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9758 if(desc->pParamDesc[j].Name)
9759 info->oName = desc->pParamDesc[j].Name->offset;
9760 else
9761 info->oName = -1;
9762 info->Flags = desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags;
9764 if(paramdefault_size){
9765 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9766 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].paramdesc.pparamdescex->varDefaultValue, file);
9767 else if(paramdefault_size)
9768 *paramdefault = -1;
9769 ++paramdefault;
9772 size += sizeof(MSFT_ParameterInfo);
9775 funcrecord->Info = size | (i << 16); /* is it just the index? */
9777 *offsets = offs;
9778 offs += size;
9779 ++offsets;
9781 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9784 varrecord = (MSFT_VarRecord*)funcrecord;
9785 for(i = 0; i < info->typeattr.cVars; ++i){
9786 TLBVarDesc *desc = &info->vardescs[i];
9787 DWORD size = 5 * sizeof(INT);
9789 varrecord->vardescsize = sizeof(desc->vardesc);
9790 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9791 varrecord->Flags = desc->vardesc.wVarFlags;
9792 varrecord->VarKind = desc->vardesc.varkind;
9794 if(desc->vardesc.varkind == VAR_CONST){
9795 varrecord->vardescsize += sizeof(VARIANT);
9796 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.lpvarValue, file);
9797 }else
9798 varrecord->OffsValue = desc->vardesc.oInst;
9800 /* res9? */
9801 if(desc->HelpStringContext != 0){
9802 size += 5 * sizeof(INT);
9803 varrecord->HelpContext = desc->HelpContext;
9804 if(desc->HelpString)
9805 varrecord->HelpString = desc->HelpString->offset;
9806 else
9807 varrecord->HelpString = -1;
9808 varrecord->res9 = -1;
9809 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9810 varrecord->HelpStringContext = desc->HelpStringContext;
9811 }else if(!list_empty(&desc->custdata_list)){
9812 size += 4 * sizeof(INT);
9813 varrecord->HelpContext = desc->HelpContext;
9814 if(desc->HelpString)
9815 varrecord->HelpString = desc->HelpString->offset;
9816 else
9817 varrecord->HelpString = -1;
9818 varrecord->res9 = -1;
9819 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9820 }else if(desc->HelpString){
9821 size += 2 * sizeof(INT);
9822 varrecord->HelpContext = desc->HelpContext;
9823 if(desc->HelpString)
9824 varrecord->HelpString = desc->HelpString->offset;
9825 else
9826 varrecord->HelpString = -1;
9827 }else if(desc->HelpContext != 0){
9828 size += sizeof(INT);
9829 varrecord->HelpContext = desc->HelpContext;
9832 varrecord->Info = size | (i << 16);
9834 *offsets = offs;
9835 offs += size;
9836 ++offsets;
9838 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9841 memid = (MEMBERID*)varrecord;
9842 for(i = 0; i < info->typeattr.cFuncs; ++i){
9843 TLBFuncDesc *desc = &info->funcdescs[i];
9844 *memid = desc->funcdesc.memid;
9845 ++memid;
9847 for(i = 0; i < info->typeattr.cVars; ++i){
9848 TLBVarDesc *desc = &info->vardescs[i];
9849 *memid = desc->vardesc.memid;
9850 ++memid;
9853 name = (DWORD*)memid;
9854 for(i = 0; i < info->typeattr.cFuncs; ++i){
9855 TLBFuncDesc *desc = &info->funcdescs[i];
9856 if(desc->Name)
9857 *name = desc->Name->offset;
9858 else
9859 *name = -1;
9860 ++name;
9862 for(i = 0; i < info->typeattr.cVars; ++i){
9863 TLBVarDesc *desc = &info->vardescs[i];
9864 if(desc->Name)
9865 *name = desc->Name->offset;
9866 else
9867 *name = -1;
9868 ++name;
9871 return ret;
9874 typedef struct tagWMSFT_RefChunk {
9875 DWORD href;
9876 DWORD res04;
9877 DWORD res08;
9878 DWORD next;
9879 } WMSFT_RefChunk;
9881 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9883 DWORD offs = file->ref_seg.len, i;
9884 WMSFT_RefChunk *chunk;
9886 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9887 if(!file->ref_seg.data)
9888 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9889 else
9890 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9892 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9894 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9895 chunk->href = info->impltypes[i].hRef;
9896 chunk->res04 = info->impltypes[i].implflags;
9897 chunk->res08 = -1;
9898 if(i < info->typeattr.cImplTypes - 1)
9899 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9900 else
9901 chunk->next = -1;
9902 ++chunk;
9905 return offs;
9908 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9910 DWORD size;
9912 size = sizeof(MSFT_TypeInfoBase);
9914 if(data){
9915 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9916 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9917 base->typekind = TKIND_DISPATCH;
9918 else
9919 base->typekind = info->typeattr.typekind;
9920 base->typekind |= index << 16; /* TODO: There are some other flags here */
9921 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9922 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9923 base->res2 = 0;
9924 base->res3 = 0;
9925 base->res4 = 3;
9926 base->res5 = 0;
9927 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9928 base->res7 = 0;
9929 base->res8 = 0;
9930 base->res9 = 0;
9931 base->resA = 0;
9932 if(info->guid)
9933 base->posguid = info->guid->offset;
9934 else
9935 base->posguid = -1;
9936 base->flags = info->typeattr.wTypeFlags;
9937 if(info->Name) {
9938 base->NameOffset = info->Name->offset;
9940 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9941 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9942 }else {
9943 base->NameOffset = -1;
9945 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9946 if(info->DocString)
9947 base->docstringoffs = info->DocString->offset;
9948 else
9949 base->docstringoffs = -1;
9950 base->helpstringcontext = info->dwHelpStringContext;
9951 base->helpcontext = info->dwHelpContext;
9952 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9953 base->cImplTypes = info->typeattr.cImplTypes;
9954 base->cbSizeVft = info->typeattr.cbSizeVft;
9955 base->size = info->typeattr.cbSizeInstance;
9956 if(info->typeattr.typekind == TKIND_COCLASS){
9957 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9958 }else if(info->typeattr.typekind == TKIND_ALIAS){
9959 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9960 }else if(info->typeattr.typekind == TKIND_MODULE){
9961 if(info->DllName)
9962 base->datatype1 = info->DllName->offset;
9963 else
9964 base->datatype1 = -1;
9965 }else{
9966 if(info->typeattr.cImplTypes > 0)
9967 base->datatype1 = info->impltypes[0].hRef;
9968 else
9969 base->datatype1 = -1;
9971 base->datatype2 = index; /* FIXME: i think there's more here */
9972 base->res18 = 0;
9973 base->res19 = -1;
9976 return size;
9979 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9981 UINT i;
9983 file->typeinfo_seg.len = 0;
9984 for(i = 0; i < This->TypeInfoCount; ++i){
9985 ITypeInfoImpl *info = This->typeinfos[i];
9986 *junk = file->typeinfo_seg.len;
9987 ++junk;
9988 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9991 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9992 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9994 file->aux_seg.len = 0;
9995 file->aux_seg.data = NULL;
9997 file->typeinfo_seg.len = 0;
9998 for(i = 0; i < This->TypeInfoCount; ++i){
9999 ITypeInfoImpl *info = This->typeinfos[i];
10000 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
10001 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
10005 typedef struct tagWMSFT_ImpFile {
10006 INT guid_offs;
10007 LCID lcid;
10008 DWORD version;
10009 } WMSFT_ImpFile;
10011 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
10013 TLBImpLib *implib;
10014 WMSFT_ImpFile *impfile;
10015 char *data;
10016 DWORD last_offs = 0;
10018 file->impfile_seg.len = 0;
10019 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10020 int size = 0;
10022 if(implib->name){
10023 WCHAR *path = wcsrchr(implib->name, '\\');
10024 if(path)
10025 ++path;
10026 else
10027 path = implib->name;
10028 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10029 if (size == 0)
10030 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10033 size += sizeof(INT16);
10034 if (size % 4)
10035 size = (size + 4) & ~0x3;
10036 if (size < 8)
10037 size = 8;
10039 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10042 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
10044 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10045 int strlen = 0, size;
10047 impfile = (WMSFT_ImpFile*)data;
10048 impfile->guid_offs = implib->guid->offset;
10049 impfile->lcid = implib->lcid;
10050 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10052 data += sizeof(WMSFT_ImpFile);
10054 if(implib->name){
10055 WCHAR *path= wcsrchr(implib->name, '\\');
10056 if(path)
10057 ++path;
10058 else
10059 path = implib->name;
10060 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10061 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10062 if (strlen == 0)
10063 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10066 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10068 size = strlen + sizeof(INT16);
10069 if (size % 4)
10070 size = (size + 4) & ~0x3;
10071 if (size < 8)
10072 size = 8;
10073 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10075 data += size;
10076 implib->offset = last_offs;
10077 last_offs += size + sizeof(WMSFT_ImpFile);
10081 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10083 MSFT_ImpInfo *info;
10084 TLBRefType *ref_type;
10085 UINT i = 0;
10087 WMSFT_compile_impfile(This, file);
10089 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10090 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10092 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10093 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10094 if(ref_type->index == TLB_REF_USE_GUID){
10095 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10096 info->oGuid = ref_type->guid->offset;
10097 }else
10098 info->oGuid = ref_type->index;
10099 info->oImpFile = ref_type->pImpTLInfo->offset;
10100 ++i;
10101 ++info;
10105 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10107 file->guidhash_seg.len = 0x80;
10108 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10109 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10112 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10114 file->namehash_seg.len = 0x200;
10115 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10116 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10119 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10121 if(contents && contents->len){
10122 segdir->offset = *running_offset;
10123 segdir->length = contents->len;
10124 *running_offset += segdir->length;
10125 }else{
10126 segdir->offset = -1;
10127 segdir->length = 0;
10130 /* TODO: do these ever change? */
10131 segdir->res08 = -1;
10132 segdir->res0c = 0xf;
10135 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10137 DWORD written;
10138 if(segment)
10139 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10142 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10143 DWORD file_len)
10145 DWORD i;
10146 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10148 for(i = 0; i < This->TypeInfoCount; ++i){
10149 base->memoffset += file_len;
10150 ++base;
10153 return S_OK;
10156 static void WMSFT_free_file(WMSFT_TLBFile *file)
10158 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10159 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10160 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10161 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10162 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10163 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10164 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10165 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10166 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10167 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10168 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10169 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10170 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10171 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10174 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10176 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10177 WMSFT_TLBFile file;
10178 DWORD written, junk_size, junk_offs, running_offset;
10179 BOOL br;
10180 HANDLE outfile;
10181 HRESULT hres;
10182 DWORD *junk;
10183 UINT i;
10185 TRACE("%p\n", This);
10187 for(i = 0; i < This->TypeInfoCount; ++i)
10188 if(This->typeinfos[i]->needs_layout)
10189 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10191 memset(&file, 0, sizeof(file));
10193 file.header.magic1 = 0x5446534D;
10194 file.header.magic2 = 0x00010002;
10195 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10196 file.header.lcid2 = This->set_lcid;
10197 file.header.varflags = 0x40 | This->syskind;
10198 if (This->HelpFile)
10199 file.header.varflags |= 0x10;
10200 if (This->HelpStringDll)
10201 file.header.varflags |= HELPDLLFLAG;
10202 file.header.version = (This->ver_minor << 16) | This->ver_major;
10203 file.header.flags = This->libflags;
10204 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10205 file.header.helpcontext = This->dwHelpContext;
10206 file.header.res44 = 0x20;
10207 file.header.res48 = 0x80;
10208 file.header.dispatchpos = This->dispatch_href;
10210 WMSFT_compile_namehash(This, &file);
10211 /* do name and string compilation to get offsets for other compilations */
10212 hres = WMSFT_compile_names(This, &file);
10213 if (FAILED(hres)){
10214 WMSFT_free_file(&file);
10215 return hres;
10218 hres = WMSFT_compile_strings(This, &file);
10219 if (FAILED(hres)){
10220 WMSFT_free_file(&file);
10221 return hres;
10224 WMSFT_compile_guidhash(This, &file);
10225 hres = WMSFT_compile_guids(This, &file);
10226 if (FAILED(hres)){
10227 WMSFT_free_file(&file);
10228 return hres;
10231 if(This->HelpFile)
10232 file.header.helpfile = This->HelpFile->offset;
10233 else
10234 file.header.helpfile = -1;
10236 if(This->DocString)
10237 file.header.helpstring = This->DocString->offset;
10238 else
10239 file.header.helpstring = -1;
10241 /* do some more segment compilation */
10242 file.header.nimpinfos = list_count(&This->ref_list);
10243 file.header.nrtypeinfos = This->TypeInfoCount;
10245 if(This->Name)
10246 file.header.NameOffset = This->Name->offset;
10247 else
10248 file.header.NameOffset = -1;
10250 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10252 if(This->guid)
10253 file.header.posguid = This->guid->offset;
10254 else
10255 file.header.posguid = -1;
10257 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10258 if(file.header.varflags & HELPDLLFLAG)
10259 junk_size += sizeof(DWORD);
10260 if(junk_size){
10261 junk = heap_alloc_zero(junk_size);
10262 if(file.header.varflags & HELPDLLFLAG){
10263 *junk = This->HelpStringDll->offset;
10264 junk_offs = 1;
10265 }else
10266 junk_offs = 0;
10267 }else{
10268 junk = NULL;
10269 junk_offs = 0;
10272 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10273 WMSFT_compile_impinfo(This, &file);
10275 running_offset = 0;
10277 TRACE("header at: 0x%lx\n", running_offset);
10278 running_offset += sizeof(file.header);
10280 TRACE("junk at: 0x%lx\n", running_offset);
10281 running_offset += junk_size;
10283 TRACE("segdir at: 0x%lx\n", running_offset);
10284 running_offset += sizeof(file.segdir);
10286 TRACE("typeinfo at: 0x%lx\n", running_offset);
10287 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10289 TRACE("guidhashtab at: 0x%lx\n", running_offset);
10290 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10292 TRACE("guidtab at: 0x%lx\n", running_offset);
10293 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10295 TRACE("reftab at: 0x%lx\n", running_offset);
10296 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10298 TRACE("impinfo at: 0x%lx\n", running_offset);
10299 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10301 TRACE("impfiles at: 0x%lx\n", running_offset);
10302 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10304 TRACE("namehashtab at: 0x%lx\n", running_offset);
10305 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10307 TRACE("nametab at: 0x%lx\n", running_offset);
10308 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10310 TRACE("stringtab at: 0x%lx\n", running_offset);
10311 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10313 TRACE("typdesc at: 0x%lx\n", running_offset);
10314 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10316 TRACE("arraydescriptions at: 0x%lx\n", running_offset);
10317 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10319 TRACE("custdata at: 0x%lx\n", running_offset);
10320 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10322 TRACE("cdguids at: 0x%lx\n", running_offset);
10323 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10325 TRACE("res0e at: 0x%lx\n", running_offset);
10326 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10328 TRACE("res0f at: 0x%lx\n", running_offset);
10329 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10331 TRACE("aux_seg at: 0x%lx\n", running_offset);
10333 WMSFT_fixup_typeinfos(This, &file, running_offset);
10335 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10336 FILE_ATTRIBUTE_NORMAL, 0);
10337 if (outfile == INVALID_HANDLE_VALUE){
10338 WMSFT_free_file(&file);
10339 heap_free(junk);
10340 return TYPE_E_IOERROR;
10343 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10344 if (!br) {
10345 WMSFT_free_file(&file);
10346 CloseHandle(outfile);
10347 heap_free(junk);
10348 return TYPE_E_IOERROR;
10351 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10352 heap_free(junk);
10353 if (!br) {
10354 WMSFT_free_file(&file);
10355 CloseHandle(outfile);
10356 return TYPE_E_IOERROR;
10359 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10360 if (!br) {
10361 WMSFT_free_file(&file);
10362 CloseHandle(outfile);
10363 return TYPE_E_IOERROR;
10366 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10367 WMSFT_write_segment(outfile, &file.guidhash_seg);
10368 WMSFT_write_segment(outfile, &file.guid_seg);
10369 WMSFT_write_segment(outfile, &file.ref_seg);
10370 WMSFT_write_segment(outfile, &file.impinfo_seg);
10371 WMSFT_write_segment(outfile, &file.impfile_seg);
10372 WMSFT_write_segment(outfile, &file.namehash_seg);
10373 WMSFT_write_segment(outfile, &file.name_seg);
10374 WMSFT_write_segment(outfile, &file.string_seg);
10375 WMSFT_write_segment(outfile, &file.typdesc_seg);
10376 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10377 WMSFT_write_segment(outfile, &file.custdata_seg);
10378 WMSFT_write_segment(outfile, &file.cdguids_seg);
10379 WMSFT_write_segment(outfile, &file.aux_seg);
10381 WMSFT_free_file(&file);
10383 CloseHandle(outfile);
10385 return S_OK;
10388 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10389 LPOLESTR name)
10391 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10392 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10393 return E_NOTIMPL;
10396 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10397 REFGUID guid, VARIANT *varVal)
10399 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10400 TLBGuid *tlbguid;
10402 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10404 if (!guid || !varVal)
10405 return E_INVALIDARG;
10407 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10409 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10412 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10413 ULONG helpStringContext)
10415 FIXME("%p, %lu - stub\n", iface, helpStringContext);
10416 return E_NOTIMPL;
10419 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10420 LPOLESTR filename)
10422 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10423 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10425 if (!filename)
10426 return E_INVALIDARG;
10428 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10430 return S_OK;
10433 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10434 ICreateTypeLib2_fnQueryInterface,
10435 ICreateTypeLib2_fnAddRef,
10436 ICreateTypeLib2_fnRelease,
10437 ICreateTypeLib2_fnCreateTypeInfo,
10438 ICreateTypeLib2_fnSetName,
10439 ICreateTypeLib2_fnSetVersion,
10440 ICreateTypeLib2_fnSetGuid,
10441 ICreateTypeLib2_fnSetDocString,
10442 ICreateTypeLib2_fnSetHelpFileName,
10443 ICreateTypeLib2_fnSetHelpContext,
10444 ICreateTypeLib2_fnSetLcid,
10445 ICreateTypeLib2_fnSetLibFlags,
10446 ICreateTypeLib2_fnSaveAllChanges,
10447 ICreateTypeLib2_fnDeleteTypeInfo,
10448 ICreateTypeLib2_fnSetCustData,
10449 ICreateTypeLib2_fnSetHelpStringContext,
10450 ICreateTypeLib2_fnSetHelpStringDll
10453 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10454 REFIID riid, void **object)
10456 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10458 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10461 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10463 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10465 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10468 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10470 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10472 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10475 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10476 REFGUID guid)
10478 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10480 TRACE("%p %s\n", This, debugstr_guid(guid));
10482 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10484 return S_OK;
10487 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10488 UINT typeFlags)
10490 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10491 WORD old_flags;
10492 HRESULT hres;
10494 TRACE("%p %x\n", This, typeFlags);
10496 if (typeFlags & TYPEFLAG_FDUAL) {
10497 ITypeLib *stdole;
10498 ITypeInfo *dispatch;
10499 HREFTYPE hreftype;
10500 HRESULT hres;
10502 hres = LoadTypeLib(L"stdole2.tlb", &stdole);
10503 if(FAILED(hres))
10504 return hres;
10506 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10507 ITypeLib_Release(stdole);
10508 if(FAILED(hres))
10509 return hres;
10511 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10512 ITypeInfo_Release(dispatch);
10513 if(FAILED(hres))
10514 return hres;
10517 old_flags = This->typeattr.wTypeFlags;
10518 This->typeattr.wTypeFlags = typeFlags;
10520 hres = ICreateTypeInfo2_LayOut(iface);
10521 if (FAILED(hres)) {
10522 This->typeattr.wTypeFlags = old_flags;
10523 return hres;
10526 return S_OK;
10529 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10530 LPOLESTR doc)
10532 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10534 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10536 if (!doc)
10537 return E_INVALIDARG;
10539 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10541 return S_OK;
10544 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10545 DWORD helpContext)
10547 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10549 TRACE("%p, %ld.\n", iface, helpContext);
10551 This->dwHelpContext = helpContext;
10553 return S_OK;
10556 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10557 WORD majorVerNum, WORD minorVerNum)
10559 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10561 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10563 This->typeattr.wMajorVerNum = majorVerNum;
10564 This->typeattr.wMinorVerNum = minorVerNum;
10566 return S_OK;
10569 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10570 ITypeInfo *typeInfo, HREFTYPE *refType)
10572 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10573 UINT index;
10574 ITypeLib *container;
10575 TLBRefType *ref_type;
10576 TLBImpLib *implib;
10577 TYPEATTR *typeattr;
10578 TLIBATTR *libattr;
10579 HRESULT hres;
10581 TRACE("%p %p %p\n", This, typeInfo, refType);
10583 if (!typeInfo || !refType)
10584 return E_INVALIDARG;
10586 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10587 if (FAILED(hres))
10588 return hres;
10590 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10591 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10593 ITypeLib_Release(container);
10595 *refType = target->hreftype;
10597 return S_OK;
10600 hres = ITypeLib_GetLibAttr(container, &libattr);
10601 if (FAILED(hres)) {
10602 ITypeLib_Release(container);
10603 return hres;
10606 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10607 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10608 implib->lcid == libattr->lcid &&
10609 implib->wVersionMajor == libattr->wMajorVerNum &&
10610 implib->wVersionMinor == libattr->wMinorVerNum)
10611 break;
10614 if(&implib->entry == &This->pTypeLib->implib_list){
10615 implib = heap_alloc_zero(sizeof(TLBImpLib));
10617 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10618 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10619 implib->name = SysAllocString(our_container->path);
10620 }else{
10621 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10622 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10623 if(FAILED(hres)){
10624 implib->name = NULL;
10625 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres);
10629 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10630 implib->lcid = libattr->lcid;
10631 implib->wVersionMajor = libattr->wMajorVerNum;
10632 implib->wVersionMinor = libattr->wMinorVerNum;
10634 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10637 ITypeLib_ReleaseTLibAttr(container, libattr);
10638 ITypeLib_Release(container);
10640 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10641 if (FAILED(hres))
10642 return hres;
10644 index = 0;
10645 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10646 if(ref_type->index == TLB_REF_USE_GUID &&
10647 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10648 ref_type->tkind == typeattr->typekind)
10649 break;
10650 ++index;
10653 if(&ref_type->entry == &This->pTypeLib->ref_list){
10654 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10656 ref_type->tkind = typeattr->typekind;
10657 ref_type->pImpTLInfo = implib;
10658 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10660 ref_type->index = TLB_REF_USE_GUID;
10662 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10664 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10667 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10669 *refType = ref_type->reference | 0x1;
10671 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10672 This->pTypeLib->dispatch_href = *refType;
10674 return S_OK;
10677 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10678 UINT index, FUNCDESC *funcDesc)
10680 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10681 TLBFuncDesc tmp_func_desc, *func_desc;
10682 int buf_size, i;
10683 char *buffer;
10684 HRESULT hres;
10686 TRACE("%p %u %p\n", This, index, funcDesc);
10688 if (!funcDesc || funcDesc->oVft & 3)
10689 return E_INVALIDARG;
10691 switch (This->typeattr.typekind) {
10692 case TKIND_MODULE:
10693 if (funcDesc->funckind != FUNC_STATIC)
10694 return TYPE_E_BADMODULEKIND;
10695 break;
10696 case TKIND_DISPATCH:
10697 if (funcDesc->funckind != FUNC_DISPATCH)
10698 return TYPE_E_BADMODULEKIND;
10699 break;
10700 default:
10701 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10702 return TYPE_E_BADMODULEKIND;
10705 if (index > This->typeattr.cFuncs)
10706 return TYPE_E_ELEMENTNOTFOUND;
10708 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10709 !funcDesc->cParams)
10710 return TYPE_E_INCONSISTENTPROPFUNCS;
10712 #ifdef _WIN64
10713 if(This->pTypeLib->syskind == SYS_WIN64 &&
10714 funcDesc->oVft % 8 != 0)
10715 return E_INVALIDARG;
10716 #endif
10718 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10719 TLBFuncDesc_Constructor(&tmp_func_desc);
10721 tmp_func_desc.funcdesc = *funcDesc;
10723 if (tmp_func_desc.funcdesc.oVft != 0)
10724 tmp_func_desc.funcdesc.oVft |= 1;
10726 if (funcDesc->cScodes && funcDesc->lprgscode) {
10727 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10728 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10729 } else {
10730 tmp_func_desc.funcdesc.lprgscode = NULL;
10731 tmp_func_desc.funcdesc.cScodes = 0;
10734 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10735 for (i = 0; i < funcDesc->cParams; ++i) {
10736 buf_size += sizeof(ELEMDESC);
10737 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10739 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10740 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10742 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10743 if (FAILED(hres)) {
10744 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10745 heap_free(tmp_func_desc.funcdesc.lprgscode);
10746 return hres;
10749 for (i = 0; i < funcDesc->cParams; ++i) {
10750 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10751 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10752 if (FAILED(hres)) {
10753 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10754 heap_free(tmp_func_desc.funcdesc.lprgscode);
10755 return hres;
10757 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10758 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10759 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10760 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].paramdesc.pparamdescex->varDefaultValue);
10761 if (FAILED(hres)) {
10762 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10763 heap_free(tmp_func_desc.funcdesc.lprgscode);
10764 return hres;
10769 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10771 if (This->funcdescs) {
10772 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10773 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10775 if (index < This->typeattr.cFuncs) {
10776 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10777 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10778 func_desc = This->funcdescs + index;
10779 } else
10780 func_desc = This->funcdescs + This->typeattr.cFuncs;
10782 /* move custdata lists to the new memory location */
10783 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10784 if(index != i)
10785 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10787 } else
10788 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10790 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10791 list_init(&func_desc->custdata_list);
10793 ++This->typeattr.cFuncs;
10795 This->needs_layout = TRUE;
10797 return S_OK;
10800 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10801 UINT index, HREFTYPE refType)
10803 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10804 TLBImplType *impl_type;
10805 HRESULT hres;
10807 TRACE("%p, %u, %ld.\n", iface, index, refType);
10809 switch(This->typeattr.typekind){
10810 case TKIND_COCLASS: {
10811 if (index == -1) {
10812 FIXME("Unhandled index: -1\n");
10813 return E_NOTIMPL;
10816 if(index != This->typeattr.cImplTypes)
10817 return TYPE_E_ELEMENTNOTFOUND;
10819 break;
10821 case TKIND_INTERFACE:
10822 case TKIND_DISPATCH:
10823 if (index != 0 || This->typeattr.cImplTypes)
10824 return TYPE_E_ELEMENTNOTFOUND;
10825 break;
10826 default:
10827 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10828 return E_NOTIMPL;
10831 if (This->impltypes){
10832 UINT i;
10834 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10835 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10837 if (index < This->typeattr.cImplTypes) {
10838 memmove(This->impltypes + index + 1, This->impltypes + index,
10839 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10840 impl_type = This->impltypes + index;
10841 } else
10842 impl_type = This->impltypes + This->typeattr.cImplTypes;
10844 /* move custdata lists to the new memory location */
10845 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10846 if(index != i)
10847 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10849 } else
10850 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10852 memset(impl_type, 0, sizeof(TLBImplType));
10853 TLBImplType_Constructor(impl_type);
10854 impl_type->hRef = refType;
10856 ++This->typeattr.cImplTypes;
10858 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10859 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10861 hres = ICreateTypeInfo2_LayOut(iface);
10862 if (FAILED(hres))
10863 return hres;
10865 return S_OK;
10868 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10869 UINT index, INT implTypeFlags)
10871 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10872 TLBImplType *impl_type = &This->impltypes[index];
10874 TRACE("%p %u %x\n", This, index, implTypeFlags);
10876 if (This->typeattr.typekind != TKIND_COCLASS)
10877 return TYPE_E_BADMODULEKIND;
10879 if (index >= This->typeattr.cImplTypes)
10880 return TYPE_E_ELEMENTNOTFOUND;
10882 impl_type->implflags = implTypeFlags;
10884 return S_OK;
10887 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10888 WORD alignment)
10890 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10892 TRACE("%p %d\n", This, alignment);
10894 This->typeattr.cbAlignment = alignment;
10896 return S_OK;
10899 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10900 LPOLESTR schema)
10902 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10904 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10906 if (!schema)
10907 return E_INVALIDARG;
10909 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10911 This->typeattr.lpstrSchema = This->Schema->str;
10913 return S_OK;
10916 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10917 UINT index, VARDESC *varDesc)
10919 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10920 TLBVarDesc *var_desc;
10921 HRESULT hr;
10923 TRACE("%p %u %p\n", This, index, varDesc);
10925 if (This->vardescs){
10926 UINT i;
10928 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10929 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10931 if (index < This->typeattr.cVars) {
10932 memmove(This->vardescs + index + 1, This->vardescs + index,
10933 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10934 var_desc = This->vardescs + index;
10935 } else
10936 var_desc = This->vardescs + This->typeattr.cVars;
10938 /* move custdata lists to the new memory location */
10939 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10940 if(index != i)
10941 TLB_relink_custdata(&This->vardescs[i].custdata_list);
10943 } else
10944 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10946 TLBVarDesc_Constructor(var_desc);
10947 hr = TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10948 if (FAILED(hr))
10949 return hr;
10950 var_desc->vardesc = *var_desc->vardesc_create;
10952 ++This->typeattr.cVars;
10954 This->needs_layout = TRUE;
10956 return S_OK;
10959 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10960 UINT index, LPOLESTR *names, UINT numNames)
10962 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10963 TLBFuncDesc *func_desc = &This->funcdescs[index];
10964 int i;
10966 TRACE("%p %u %p %u\n", This, index, names, numNames);
10968 if (!names)
10969 return E_INVALIDARG;
10971 if (index >= This->typeattr.cFuncs || numNames == 0)
10972 return TYPE_E_ELEMENTNOTFOUND;
10974 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10975 if(numNames > func_desc->funcdesc.cParams)
10976 return TYPE_E_ELEMENTNOTFOUND;
10977 } else
10978 if(numNames > func_desc->funcdesc.cParams + 1)
10979 return TYPE_E_ELEMENTNOTFOUND;
10981 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10982 TLBFuncDesc *iter = &This->funcdescs[i];
10983 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
10984 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10985 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10986 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10987 continue;
10988 return TYPE_E_AMBIGUOUSNAME;
10992 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10994 for (i = 1; i < numNames; ++i) {
10995 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10996 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10999 return S_OK;
11002 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
11003 UINT index, LPOLESTR name)
11005 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11007 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
11009 if(!name)
11010 return E_INVALIDARG;
11012 if(index >= This->typeattr.cVars)
11013 return TYPE_E_ELEMENTNOTFOUND;
11015 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
11016 return S_OK;
11019 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
11020 TYPEDESC *tdescAlias)
11022 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11023 HRESULT hr;
11025 TRACE("%p %p\n", This, tdescAlias);
11027 if(!tdescAlias)
11028 return E_INVALIDARG;
11030 if(This->typeattr.typekind != TKIND_ALIAS)
11031 return TYPE_E_BADMODULEKIND;
11033 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11034 if(FAILED(hr))
11035 return hr;
11037 heap_free(This->tdescAlias);
11038 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11039 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11041 return S_OK;
11044 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11045 UINT index, LPOLESTR dllName, LPOLESTR procName)
11047 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11048 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11049 return E_NOTIMPL;
11052 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11053 UINT index, LPOLESTR docString)
11055 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11056 TLBFuncDesc *func_desc = &This->funcdescs[index];
11058 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11060 if(!docString)
11061 return E_INVALIDARG;
11063 if(index >= This->typeattr.cFuncs)
11064 return TYPE_E_ELEMENTNOTFOUND;
11066 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11068 return S_OK;
11071 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11072 UINT index, LPOLESTR docString)
11074 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11075 TLBVarDesc *var_desc = &This->vardescs[index];
11077 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11079 if(!docString)
11080 return E_INVALIDARG;
11082 if(index >= This->typeattr.cVars)
11083 return TYPE_E_ELEMENTNOTFOUND;
11085 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11087 return S_OK;
11090 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11091 UINT index, DWORD helpContext)
11093 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11094 TLBFuncDesc *func_desc = &This->funcdescs[index];
11096 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
11098 if(index >= This->typeattr.cFuncs)
11099 return TYPE_E_ELEMENTNOTFOUND;
11101 func_desc->helpcontext = helpContext;
11103 return S_OK;
11106 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11107 UINT index, DWORD helpContext)
11109 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11110 TLBVarDesc *var_desc = &This->vardescs[index];
11112 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
11114 if(index >= This->typeattr.cVars)
11115 return TYPE_E_ELEMENTNOTFOUND;
11117 var_desc->HelpContext = helpContext;
11119 return S_OK;
11122 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11123 UINT index, BSTR bstrMops)
11125 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11126 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11127 return E_NOTIMPL;
11130 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11131 IDLDESC *idlDesc)
11133 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11135 TRACE("%p %p\n", This, idlDesc);
11137 if (!idlDesc)
11138 return E_INVALIDARG;
11140 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11141 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11143 return S_OK;
11146 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11148 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11149 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11150 TLBFuncDesc *func_desc;
11151 UINT user_vft = 0, i, depth = 0;
11152 HRESULT hres = S_OK;
11154 TRACE("%p\n", This);
11156 This->needs_layout = FALSE;
11158 if (This->typeattr.typekind == TKIND_INTERFACE) {
11159 ITypeInfo *inh;
11160 TYPEATTR *attr;
11161 HREFTYPE inh_href;
11163 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11165 if (SUCCEEDED(hres)) {
11166 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11168 if (SUCCEEDED(hres)) {
11169 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11170 if (FAILED(hres)) {
11171 ITypeInfo_Release(inh);
11172 return hres;
11174 This->typeattr.cbSizeVft = attr->cbSizeVft;
11175 ITypeInfo_ReleaseTypeAttr(inh, attr);
11178 ++depth;
11179 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11180 if(SUCCEEDED(hres)){
11181 ITypeInfo *next;
11182 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11183 if(SUCCEEDED(hres)){
11184 ITypeInfo_Release(inh);
11185 inh = next;
11188 }while(SUCCEEDED(hres));
11189 hres = S_OK;
11191 ITypeInfo_Release(inh);
11192 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11193 This->typeattr.cbSizeVft = 0;
11194 hres = S_OK;
11195 } else
11196 return hres;
11197 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11198 This->typeattr.cbSizeVft = 0;
11199 hres = S_OK;
11200 } else
11201 return hres;
11202 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11203 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11204 else
11205 This->typeattr.cbSizeVft = 0;
11207 func_desc = This->funcdescs;
11208 i = 0;
11209 while (i < This->typeattr.cFuncs) {
11210 if (!(func_desc->funcdesc.oVft & 0x1))
11211 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11213 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11214 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11216 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11218 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11219 TLBFuncDesc *iter;
11220 UINT j = 0;
11221 BOOL reset = FALSE;
11223 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11225 iter = This->funcdescs;
11226 while (j < This->typeattr.cFuncs) {
11227 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11228 if (!reset) {
11229 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11230 reset = TRUE;
11231 } else
11232 ++func_desc->funcdesc.memid;
11233 iter = This->funcdescs;
11234 j = 0;
11235 } else {
11236 ++iter;
11237 ++j;
11242 ++func_desc;
11243 ++i;
11246 if (user_vft > This->typeattr.cbSizeVft)
11247 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11249 for(i = 0; i < This->typeattr.cVars; ++i){
11250 TLBVarDesc *var_desc = &This->vardescs[i];
11251 if(var_desc->vardesc.memid == MEMBERID_NIL){
11252 UINT j = 0;
11253 BOOL reset = FALSE;
11254 TLBVarDesc *iter;
11256 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11258 iter = This->vardescs;
11259 while (j < This->typeattr.cVars) {
11260 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11261 if (!reset) {
11262 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11263 reset = TRUE;
11264 } else
11265 ++var_desc->vardesc.memid;
11266 iter = This->vardescs;
11267 j = 0;
11268 } else {
11269 ++iter;
11270 ++j;
11276 return hres;
11279 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11280 UINT index)
11282 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11283 unsigned int i;
11285 TRACE("%p %u\n", This, index);
11287 if (index >= This->typeattr.cFuncs)
11288 return TYPE_E_ELEMENTNOTFOUND;
11290 typeinfo_release_funcdesc(&This->funcdescs[index]);
11292 --This->typeattr.cFuncs;
11293 if (index != This->typeattr.cFuncs)
11295 memmove(This->funcdescs + index, This->funcdescs + index + 1,
11296 sizeof(*This->funcdescs) * (This->typeattr.cFuncs - index));
11297 for (i = index; i < This->typeattr.cFuncs; ++i)
11298 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
11301 This->needs_layout = TRUE;
11303 return S_OK;
11306 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11307 MEMBERID memid, INVOKEKIND invKind)
11309 FIXME("%p, %#lx, %d - stub\n", iface, memid, invKind);
11310 return E_NOTIMPL;
11313 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11314 UINT index)
11316 FIXME("%p, %u - stub\n", iface, index);
11317 return E_NOTIMPL;
11320 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11321 MEMBERID memid)
11323 FIXME("%p, %#lx - stub\n", iface, memid);
11324 return E_NOTIMPL;
11327 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11328 UINT index)
11330 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11331 int i;
11333 TRACE("%p %u\n", This, index);
11335 if (index >= This->typeattr.cImplTypes)
11336 return TYPE_E_ELEMENTNOTFOUND;
11338 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11339 --This->typeattr.cImplTypes;
11341 if (index < This->typeattr.cImplTypes)
11343 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11344 sizeof(*This->impltypes));
11345 for (i = index; i < This->typeattr.cImplTypes; ++i)
11346 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11349 return S_OK;
11352 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11353 REFGUID guid, VARIANT *varVal)
11355 TLBGuid *tlbguid;
11357 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11359 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11361 if (!guid || !varVal)
11362 return E_INVALIDARG;
11364 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11366 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11369 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11370 UINT index, REFGUID guid, VARIANT *varVal)
11372 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11373 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11374 return E_NOTIMPL;
11377 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11378 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11380 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11381 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11382 return E_NOTIMPL;
11385 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11386 UINT index, REFGUID guid, VARIANT *varVal)
11388 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11389 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11390 return E_NOTIMPL;
11393 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11394 UINT index, REFGUID guid, VARIANT *varVal)
11396 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11397 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11398 return E_NOTIMPL;
11401 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11402 ULONG helpStringContext)
11404 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11406 TRACE("%p, %lu.\n", iface, helpStringContext);
11408 This->dwHelpStringContext = helpStringContext;
11410 return S_OK;
11413 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11414 UINT index, ULONG helpStringContext)
11416 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11417 return E_NOTIMPL;
11420 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11421 UINT index, ULONG helpStringContext)
11423 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11424 return E_NOTIMPL;
11427 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11429 FIXME("%p - stub\n", iface);
11430 return E_NOTIMPL;
11433 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11434 LPOLESTR name)
11436 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11438 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11440 if (!name)
11441 return E_INVALIDARG;
11443 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11445 return S_OK;
11448 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11449 ICreateTypeInfo2_fnQueryInterface,
11450 ICreateTypeInfo2_fnAddRef,
11451 ICreateTypeInfo2_fnRelease,
11452 ICreateTypeInfo2_fnSetGuid,
11453 ICreateTypeInfo2_fnSetTypeFlags,
11454 ICreateTypeInfo2_fnSetDocString,
11455 ICreateTypeInfo2_fnSetHelpContext,
11456 ICreateTypeInfo2_fnSetVersion,
11457 ICreateTypeInfo2_fnAddRefTypeInfo,
11458 ICreateTypeInfo2_fnAddFuncDesc,
11459 ICreateTypeInfo2_fnAddImplType,
11460 ICreateTypeInfo2_fnSetImplTypeFlags,
11461 ICreateTypeInfo2_fnSetAlignment,
11462 ICreateTypeInfo2_fnSetSchema,
11463 ICreateTypeInfo2_fnAddVarDesc,
11464 ICreateTypeInfo2_fnSetFuncAndParamNames,
11465 ICreateTypeInfo2_fnSetVarName,
11466 ICreateTypeInfo2_fnSetTypeDescAlias,
11467 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11468 ICreateTypeInfo2_fnSetFuncDocString,
11469 ICreateTypeInfo2_fnSetVarDocString,
11470 ICreateTypeInfo2_fnSetFuncHelpContext,
11471 ICreateTypeInfo2_fnSetVarHelpContext,
11472 ICreateTypeInfo2_fnSetMops,
11473 ICreateTypeInfo2_fnSetTypeIdldesc,
11474 ICreateTypeInfo2_fnLayOut,
11475 ICreateTypeInfo2_fnDeleteFuncDesc,
11476 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11477 ICreateTypeInfo2_fnDeleteVarDesc,
11478 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11479 ICreateTypeInfo2_fnDeleteImplType,
11480 ICreateTypeInfo2_fnSetCustData,
11481 ICreateTypeInfo2_fnSetFuncCustData,
11482 ICreateTypeInfo2_fnSetParamCustData,
11483 ICreateTypeInfo2_fnSetVarCustData,
11484 ICreateTypeInfo2_fnSetImplTypeCustData,
11485 ICreateTypeInfo2_fnSetHelpStringContext,
11486 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11487 ICreateTypeInfo2_fnSetVarHelpStringContext,
11488 ICreateTypeInfo2_fnInvalidate,
11489 ICreateTypeInfo2_fnSetName
11492 /******************************************************************************
11493 * ClearCustData (OLEAUT32.171)
11495 * Clear a custom data type's data.
11497 * PARAMS
11498 * lpCust [I] The custom data type instance
11500 * RETURNS
11501 * Nothing.
11503 void WINAPI ClearCustData(CUSTDATA *lpCust)
11505 if (lpCust && lpCust->cCustData)
11507 if (lpCust->prgCustData)
11509 DWORD i;
11511 for (i = 0; i < lpCust->cCustData; i++)
11512 VariantClear(&lpCust->prgCustData[i].varValue);
11514 CoTaskMemFree(lpCust->prgCustData);
11515 lpCust->prgCustData = NULL;
11517 lpCust->cCustData = 0;