gdi32: Fix leak in GdiDeleteSpoolFileHandle.
[wine.git] / dlls / oleaut32 / typelib.c
blobfa512184182d7ee8f231b30e40ed79193ce401ad
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/list.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(ole);
74 WINE_DECLARE_DEBUG_CHANNEL(typelib);
76 typedef struct
78 WORD offset;
79 WORD length;
80 WORD flags;
81 WORD id;
82 WORD handle;
83 WORD usage;
84 } NE_NAMEINFO;
86 typedef struct
88 WORD type_id; /* Type identifier */
89 WORD count; /* Number of resources of this type */
90 DWORD resloader; /* SetResourceHandler() */
92 * Name info array.
94 } NE_TYPEINFO;
96 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
97 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
98 static void TLB_FreeVarDesc(VARDESC*);
100 /****************************************************************************
101 * FromLExxx
103 * Takes p_iVal (which is in little endian) and returns it
104 * in the host machine's byte order.
106 #ifdef WORDS_BIGENDIAN
107 static WORD FromLEWord(WORD p_iVal)
109 return (((p_iVal & 0x00FF) << 8) |
110 ((p_iVal & 0xFF00) >> 8));
114 static DWORD FromLEDWord(DWORD p_iVal)
116 return (((p_iVal & 0x000000FF) << 24) |
117 ((p_iVal & 0x0000FF00) << 8) |
118 ((p_iVal & 0x00FF0000) >> 8) |
119 ((p_iVal & 0xFF000000) >> 24));
121 #else
122 #define FromLEWord(X) (X)
123 #define FromLEDWord(X) (X)
124 #endif
126 #define DISPATCH_HREF_OFFSET 0x01000000
127 #define DISPATCH_HREF_MASK 0xff000000
129 /****************************************************************************
130 * FromLExxx
132 * Fix byte order in any structure if necessary
134 #ifdef WORDS_BIGENDIAN
135 static void FromLEWords(void *p_Val, int p_iSize)
137 WORD *Val = p_Val;
139 p_iSize /= sizeof(WORD);
141 while (p_iSize) {
142 *Val = FromLEWord(*Val);
143 Val++;
144 p_iSize--;
149 static void FromLEDWords(void *p_Val, int p_iSize)
151 DWORD *Val = p_Val;
153 p_iSize /= sizeof(DWORD);
155 while (p_iSize) {
156 *Val = FromLEDWord(*Val);
157 Val++;
158 p_iSize--;
161 #else
162 #define FromLEWords(X,Y) /*nothing*/
163 #define FromLEDWords(X,Y) /*nothing*/
164 #endif
167 * Find a typelib key which matches a requested maj.min version.
169 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
171 WCHAR buffer[60];
172 char key_name[16];
173 DWORD len, i;
174 INT best_maj = -1, best_min = -1;
175 HKEY hkey;
177 lstrcpyW( buffer, L"Typelib\\" );
178 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
180 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
181 return FALSE;
183 len = sizeof(key_name);
184 i = 0;
185 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
187 INT v_maj, v_min;
189 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
191 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
193 if (*wMaj == 0xffff && *wMin == 0xffff)
195 if (v_maj > best_maj) best_maj = v_maj;
196 if (v_min > best_min) best_min = v_min;
198 else if (*wMaj == v_maj)
200 best_maj = v_maj;
202 if (*wMin == v_min)
204 best_min = v_min;
205 break; /* exact match */
207 if (*wMin != 0xffff && v_min >= *wMin && v_min > best_min) best_min = v_min;
210 len = sizeof(key_name);
212 RegCloseKey( hkey );
214 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
216 if (*wMaj == 0xffff && *wMin == 0xffff)
218 if (best_maj >= 0 && best_min >= 0)
220 *wMaj = best_maj;
221 *wMin = best_min;
222 return TRUE;
226 if (*wMaj == best_maj && best_min >= 0)
228 *wMin = best_min;
229 return TRUE;
231 return FALSE;
234 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
235 /* buffer must be at least 60 characters long */
236 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
238 lstrcpyW( buffer, L"Typelib\\" );
239 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
240 swprintf( buffer + lstrlenW(buffer), 20, L"\\%x.%x", wMaj, wMin );
241 return buffer;
244 /* get the path of an interface key, in the form "Interface\\<guid>" */
245 /* buffer must be at least 50 characters long */
246 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
248 lstrcpyW( buffer, L"Interface\\" );
249 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
250 return buffer;
253 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
254 /* buffer must be at least 16 characters long */
255 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
257 swprintf( buffer, 16, L"%lx\\", lcid );
258 switch(syskind)
260 case SYS_WIN16: lstrcatW( buffer, L"win16" ); break;
261 case SYS_WIN32: lstrcatW( buffer, L"win32" ); break;
262 case SYS_WIN64: lstrcatW( buffer, L"win64" ); break;
263 default:
264 TRACE("Typelib is for unsupported syskind %i\n", syskind);
265 return NULL;
267 return buffer;
270 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
272 struct tlibredirect_data
274 ULONG size;
275 DWORD res;
276 ULONG name_len;
277 ULONG name_offset;
278 LANGID langid;
279 WORD flags;
280 ULONG help_len;
281 ULONG help_offset;
282 WORD major_version;
283 WORD minor_version;
286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
288 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
290 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
291 LCID myLCID = lcid;
292 HKEY hkey;
293 WCHAR buffer[60];
294 WCHAR Path[MAX_PATH];
295 LONG res;
297 TRACE_(typelib)("%s, %x.%x, %#lx, %p\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
299 if (redir)
301 ACTCTX_SECTION_KEYED_DATA data;
303 data.cbSize = sizeof(data);
304 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
306 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
307 WCHAR *nameW;
308 DWORD len;
310 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
311 return TYPE_E_LIBNOTREGISTERED;
313 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
314 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
315 if (!len) return TYPE_E_LIBNOTREGISTERED;
317 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
318 *path = SysAllocString( Path );
319 return S_OK;
323 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
324 get_typelib_key( guid, wMaj, wMin, buffer );
326 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
327 if (res == ERROR_FILE_NOT_FOUND)
329 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
330 return TYPE_E_LIBNOTREGISTERED;
332 else if (res != ERROR_SUCCESS)
334 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
335 return TYPE_E_REGISTRYACCESS;
338 while (hr != S_OK)
340 LONG dwPathLen = sizeof(Path);
342 get_lcid_subkey( myLCID, syskind, buffer );
344 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
346 if (!lcid)
347 break;
348 else if (myLCID == lcid)
350 /* try with sub-langid */
351 myLCID = SUBLANGID(lcid);
353 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
355 /* try with system langid */
356 myLCID = 0;
358 else
360 break;
363 else
365 *path = SysAllocString( Path );
366 hr = S_OK;
369 RegCloseKey( hkey );
370 TRACE_(typelib)("-- %#lx\n", hr);
371 return hr;
374 /****************************************************************************
375 * QueryPathOfRegTypeLib [OLEAUT32.164]
377 * Gets the path to a registered type library.
379 * PARAMS
380 * guid [I] referenced guid
381 * wMaj [I] major version
382 * wMin [I] minor version
383 * lcid [I] locale id
384 * path [O] path of typelib
386 * RETURNS
387 * Success: S_OK.
388 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
389 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
390 * opened.
392 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
394 BOOL redir = TRUE;
395 #ifdef _WIN64
396 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
397 if(SUCCEEDED(hres))
398 return hres;
399 redir = FALSE;
400 #endif
401 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
404 /******************************************************************************
405 * CreateTypeLib [OLEAUT32.160] creates a typelib
407 * RETURNS
408 * Success: S_OK
409 * Failure: Status
411 HRESULT WINAPI CreateTypeLib(
412 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
414 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
415 return E_FAIL;
418 /******************************************************************************
419 * LoadTypeLib [OLEAUT32.161]
421 * Loads a type library
423 * PARAMS
424 * szFile [I] Name of file to load from.
425 * pptLib [O] Pointer that receives ITypeLib object on success.
427 * RETURNS
428 * Success: S_OK
429 * Failure: Status
431 * SEE
432 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
434 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
436 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
437 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
440 /******************************************************************************
441 * LoadTypeLibEx [OLEAUT32.183]
443 * Loads and optionally registers a type library
445 * RETURNS
446 * Success: S_OK
447 * Failure: Status
449 HRESULT WINAPI LoadTypeLibEx(
450 LPCOLESTR szFile, /* [in] Name of file to load from */
451 REGKIND regkind, /* [in] Specify kind of registration */
452 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
454 WCHAR szPath[MAX_PATH+1];
455 HRESULT res;
457 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
459 if (!szFile || !pptLib)
460 return E_INVALIDARG;
462 *pptLib = NULL;
464 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
466 if (SUCCEEDED(res))
467 switch(regkind)
469 case REGKIND_DEFAULT:
470 /* don't register typelibs supplied with full path. Experimentation confirms the following */
471 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
472 (szFile[0] && (szFile[1] == ':'))) break;
473 /* else fall-through */
475 case REGKIND_REGISTER:
476 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
478 ITypeLib_Release(*pptLib);
479 *pptLib = 0;
481 break;
482 case REGKIND_NONE:
483 break;
486 TRACE(" returns %#lx\n",res);
487 return res;
490 /******************************************************************************
491 * LoadRegTypeLib [OLEAUT32.162]
493 * Loads a registered type library.
495 * PARAMS
496 * rguid [I] GUID of the registered type library.
497 * wVerMajor [I] major version.
498 * wVerMinor [I] minor version.
499 * lcid [I] locale ID.
500 * ppTLib [O] pointer that receives an ITypeLib object on success.
502 * RETURNS
503 * Success: S_OK.
504 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
505 * LoadTypeLib.
507 HRESULT WINAPI LoadRegTypeLib(
508 REFGUID rguid,
509 WORD wVerMajor,
510 WORD wVerMinor,
511 LCID lcid,
512 ITypeLib **ppTLib)
514 BSTR bstr=NULL;
515 HRESULT res;
517 *ppTLib = NULL;
519 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
521 if(SUCCEEDED(res))
523 res= LoadTypeLib(bstr, ppTLib);
524 SysFreeString(bstr);
526 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
528 TLIBATTR *attr;
530 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
531 if (res == S_OK)
533 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
534 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
536 if (mismatch)
538 ITypeLib_Release(*ppTLib);
539 *ppTLib = NULL;
540 res = TYPE_E_LIBNOTREGISTERED;
546 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
548 return res;
551 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
553 WCHAR keyName[60];
554 HKEY key, subKey;
556 get_interface_key( &tattr->guid, keyName );
557 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
558 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
560 const WCHAR *proxy_clsid;
562 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
563 proxy_clsid = L"{00020424-0000-0000-C000-000000000046}";
564 else
565 proxy_clsid = L"{00020420-0000-0000-C000-000000000046}";
567 if (name)
568 RegSetValueExW(key, NULL, 0, REG_SZ,
569 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR));
571 if (!RegCreateKeyExW(key, L"ProxyStubClsid", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
573 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
574 RegCloseKey(subKey);
577 if (!RegCreateKeyExW(key, L"ProxyStubClsid32", 0, NULL, 0, KEY_WRITE | flag, NULL, &subKey, NULL))
579 RegSetValueExW(subKey, NULL, 0, REG_SZ, (const BYTE *)proxy_clsid, (lstrlenW(proxy_clsid) + 1) * sizeof(WCHAR));
580 RegCloseKey(subKey);
583 if (RegCreateKeyExW(key, L"TypeLib", 0, NULL, 0,
584 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
586 WCHAR buffer[40];
588 StringFromGUID2(&libattr->guid, buffer, 40);
589 RegSetValueExW(subKey, NULL, 0, REG_SZ,
590 (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
591 swprintf(buffer, ARRAY_SIZE(buffer), L"%x.%x", libattr->wMajorVerNum, libattr->wMinorVerNum);
592 RegSetValueExW(subKey, L"Version", 0, REG_SZ, (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
593 RegCloseKey(subKey);
596 RegCloseKey(key);
600 /******************************************************************************
601 * RegisterTypeLib [OLEAUT32.163]
602 * Adds information about a type library to the System Registry
603 * NOTES
604 * Docs: ITypeLib FAR * ptlib
605 * Docs: OLECHAR FAR* szFullPath
606 * Docs: OLECHAR FAR* szHelpDir
608 * RETURNS
609 * Success: S_OK
610 * Failure: Status
612 HRESULT WINAPI RegisterTypeLib(ITypeLib *ptlib, const WCHAR *szFullPath, const WCHAR *szHelpDir)
614 HRESULT res;
615 TLIBATTR *attr;
616 WCHAR keyName[60];
617 WCHAR tmp[16];
618 HKEY key, subKey;
619 UINT types, tidx;
620 TYPEKIND kind;
621 DWORD disposition;
623 if (ptlib == NULL || szFullPath == NULL)
624 return E_INVALIDARG;
626 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
627 return E_FAIL;
629 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
631 res = S_OK;
632 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
633 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
635 LPOLESTR doc;
636 LPOLESTR libName;
638 /* Set the human-readable name of the typelib to
639 the typelib's doc, if it exists, else to the typelib's name. */
640 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, &libName, &doc, NULL, NULL)))
641 res = E_FAIL;
642 else if (doc || libName)
644 WCHAR *name = doc ? doc : libName;
646 if (RegSetValueExW(key, NULL, 0, REG_SZ,
647 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
648 res = E_FAIL;
650 SysFreeString(doc);
651 SysFreeString(libName);
654 /* Make up the name of the typelib path subkey */
655 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
657 /* Create the typelib path subkey */
658 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
659 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
661 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
662 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
663 res = E_FAIL;
665 RegCloseKey(subKey);
667 else
668 res = E_FAIL;
670 /* Create the flags subkey */
671 if (res == S_OK && RegCreateKeyExW(key, L"FLAGS", 0, NULL, 0,
672 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
674 WCHAR buf[20];
676 /* FIXME: is %u correct? */
677 swprintf(buf, ARRAY_SIZE(buf), L"%u", attr->wLibFlags);
678 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
679 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
680 res = E_FAIL;
682 RegCloseKey(subKey);
684 else
685 res = E_FAIL;
687 /* create the helpdir subkey */
688 if (res == S_OK && RegCreateKeyExW(key, L"HELPDIR", 0, NULL, 0,
689 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
691 BSTR freeHelpDir = NULL;
692 WCHAR *file_name;
694 /* if we created a new key, and helpDir was null, set the helpdir
695 to the directory which contains the typelib. However,
696 if we just opened an existing key, we leave the helpdir alone */
697 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
698 szHelpDir = freeHelpDir = SysAllocString(szFullPath);
699 file_name = wcsrchr(szHelpDir, '\\');
700 if (file_name && file_name[1]) {
701 /* possible remove a numeric \index (resource-id) */
702 WCHAR *end_ptr = file_name + 1;
703 while ('0' <= *end_ptr && *end_ptr <= '9') end_ptr++;
704 if (!*end_ptr)
706 *file_name = 0;
707 file_name = wcsrchr(szHelpDir, '\\');
710 if (file_name)
711 *file_name = 0;
714 /* if we have an szHelpDir, set it! */
715 if (szHelpDir != NULL) {
716 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
717 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
718 res = E_FAIL;
722 SysFreeString(freeHelpDir);
723 RegCloseKey(subKey);
724 } else {
725 res = E_FAIL;
728 RegCloseKey(key);
730 else
731 res = E_FAIL;
733 /* register OLE Automation-compatible interfaces for this typelib */
734 types = ITypeLib_GetTypeInfoCount(ptlib);
735 for (tidx=0; tidx<types; tidx++) {
736 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
737 LPOLESTR name = NULL;
738 ITypeInfo *tinfo = NULL;
740 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
742 switch (kind) {
743 case TKIND_INTERFACE:
744 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
745 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
746 break;
748 case TKIND_DISPATCH:
749 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
750 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
751 break;
753 default:
754 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
755 break;
758 if (tinfo) {
759 TYPEATTR *tattr = NULL;
760 ITypeInfo_GetTypeAttr(tinfo, &tattr);
762 if (tattr) {
763 TRACE_(typelib)("guid=%s, flags=%04x (",
764 debugstr_guid(&tattr->guid),
765 tattr->wTypeFlags);
767 if (TRACE_ON(typelib)) {
768 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
769 XX(FAPPOBJECT);
770 XX(FCANCREATE);
771 XX(FLICENSED);
772 XX(FPREDECLID);
773 XX(FHIDDEN);
774 XX(FCONTROL);
775 XX(FDUAL);
776 XX(FNONEXTENSIBLE);
777 XX(FOLEAUTOMATION);
778 XX(FRESTRICTED);
779 XX(FAGGREGATABLE);
780 XX(FREPLACEABLE);
781 XX(FDISPATCHABLE);
782 XX(FREVERSEBIND);
783 XX(FPROXY);
784 #undef XX
785 MESSAGE("\n");
788 /* Register all dispinterfaces (which includes dual interfaces) and
789 oleautomation interfaces */
790 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
791 kind == TKIND_DISPATCH)
793 BOOL is_wow64;
794 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
796 /* register interface<->typelib coupling */
797 TLB_register_interface(attr, name, tattr, 0);
799 /* register TLBs into the opposite registry view, too */
800 if(opposite == KEY_WOW64_32KEY ||
801 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
802 TLB_register_interface(attr, name, tattr, opposite);
805 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
808 ITypeInfo_Release(tinfo);
811 SysFreeString(name);
815 ITypeLib_ReleaseTLibAttr(ptlib, attr);
817 return res;
820 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
822 WCHAR subKeyName[50];
823 HKEY subKey;
825 /* the path to the type */
826 get_interface_key( guid, subKeyName );
828 /* Delete its bits */
829 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
830 return;
832 RegDeleteKeyW(subKey, L"ProxyStubClsid");
833 RegDeleteKeyW(subKey, L"ProxyStubClsid32");
834 RegDeleteKeyW(subKey, L"TypeLib");
835 RegCloseKey(subKey);
836 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
839 /******************************************************************************
840 * UnRegisterTypeLib [OLEAUT32.186]
841 * Removes information about a type library from the System Registry
842 * NOTES
844 * RETURNS
845 * Success: S_OK
846 * Failure: Status
848 HRESULT WINAPI UnRegisterTypeLib(
849 REFGUID libid, /* [in] Guid of the library */
850 WORD wVerMajor, /* [in] major version */
851 WORD wVerMinor, /* [in] minor version */
852 LCID lcid, /* [in] locale id */
853 SYSKIND syskind)
855 BSTR tlibPath = NULL;
856 DWORD tmpLength;
857 WCHAR keyName[60];
858 WCHAR subKeyName[50];
859 int result = S_OK;
860 DWORD i = 0;
861 BOOL deleteOtherStuff;
862 HKEY key = NULL;
863 TYPEATTR* typeAttr = NULL;
864 TYPEKIND kind;
865 ITypeInfo* typeInfo = NULL;
866 ITypeLib* typeLib = NULL;
867 int numTypes;
869 TRACE("(IID: %s)\n",debugstr_guid(libid));
871 /* Create the path to the key */
872 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
874 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
876 TRACE("Unsupported syskind %i\n", syskind);
877 result = E_INVALIDARG;
878 goto end;
881 /* get the path to the typelib on disk */
882 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
883 result = E_INVALIDARG;
884 goto end;
887 /* Try and open the key to the type library. */
888 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
889 result = E_INVALIDARG;
890 goto end;
893 /* Try and load the type library */
894 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
895 result = TYPE_E_INVALIDSTATE;
896 goto end;
899 /* remove any types registered with this typelib */
900 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
901 for (i=0; i<numTypes; i++) {
902 /* get the kind of type */
903 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
904 goto enddeleteloop;
907 /* skip non-interfaces, and get type info for the type */
908 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
909 goto enddeleteloop;
911 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
912 goto enddeleteloop;
914 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
915 goto enddeleteloop;
918 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
919 kind == TKIND_DISPATCH)
921 BOOL is_wow64;
922 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
924 TLB_unregister_interface(&typeAttr->guid, 0);
926 /* unregister TLBs into the opposite registry view, too */
927 if(opposite == KEY_WOW64_32KEY ||
928 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
929 TLB_unregister_interface(&typeAttr->guid, opposite);
933 enddeleteloop:
934 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
935 typeAttr = NULL;
936 if (typeInfo) ITypeInfo_Release(typeInfo);
937 typeInfo = NULL;
940 /* Now, delete the type library path subkey */
941 get_lcid_subkey( lcid, syskind, subKeyName );
942 RegDeleteKeyW(key, subKeyName);
943 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
944 RegDeleteKeyW(key, subKeyName);
946 /* check if there is anything besides the FLAGS/HELPDIR keys.
947 If there is, we don't delete them */
948 tmpLength = ARRAY_SIZE(subKeyName);
949 deleteOtherStuff = TRUE;
950 i = 0;
951 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
952 tmpLength = ARRAY_SIZE(subKeyName);
954 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
955 if (!wcscmp(subKeyName, L"FLAGS")) continue;
956 if (!wcscmp(subKeyName, L"HELPDIR")) continue;
957 deleteOtherStuff = FALSE;
958 break;
961 /* only delete the other parts of the key if we're absolutely sure */
962 if (deleteOtherStuff) {
963 RegDeleteKeyW(key, L"FLAGS");
964 RegDeleteKeyW(key, L"HELPDIR");
965 RegCloseKey(key);
966 key = NULL;
968 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
969 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
970 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
973 end:
974 SysFreeString(tlibPath);
975 if (typeLib) ITypeLib_Release(typeLib);
976 if (key) RegCloseKey(key);
977 return result;
980 /******************************************************************************
981 * RegisterTypeLibForUser [OLEAUT32.442]
982 * Adds information about a type library to the user registry
983 * NOTES
984 * Docs: ITypeLib FAR * ptlib
985 * Docs: OLECHAR FAR* szFullPath
986 * Docs: OLECHAR FAR* szHelpDir
988 * RETURNS
989 * Success: S_OK
990 * Failure: Status
992 HRESULT WINAPI RegisterTypeLibForUser(
993 ITypeLib * ptlib, /* [in] Pointer to the library*/
994 OLECHAR * szFullPath, /* [in] full Path of the library*/
995 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
996 may be NULL*/
998 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
999 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1000 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1003 /******************************************************************************
1004 * UnRegisterTypeLibForUser [OLEAUT32.443]
1005 * Removes information about a type library from the user registry
1007 * RETURNS
1008 * Success: S_OK
1009 * Failure: Status
1011 HRESULT WINAPI UnRegisterTypeLibForUser(
1012 REFGUID libid, /* [in] GUID of the library */
1013 WORD wVerMajor, /* [in] major version */
1014 WORD wVerMinor, /* [in] minor version */
1015 LCID lcid, /* [in] locale id */
1016 SYSKIND syskind)
1018 FIXME("%s, %u, %u, %#lx, %u unregistering the typelib system-wide\n",
1019 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1020 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1023 /*======================= ITypeLib implementation =======================*/
1025 typedef struct tagTLBGuid {
1026 GUID guid;
1027 INT hreftype;
1028 UINT offset;
1029 struct list entry;
1030 } TLBGuid;
1032 typedef struct tagTLBCustData
1034 TLBGuid *guid;
1035 VARIANT data;
1036 struct list entry;
1037 } TLBCustData;
1039 /* data structure for import typelibs */
1040 typedef struct tagTLBImpLib
1042 int offset; /* offset in the file (MSFT)
1043 offset in nametable (SLTG)
1044 just used to identify library while reading
1045 data from file */
1046 TLBGuid *guid; /* libid */
1047 BSTR name; /* name */
1049 LCID lcid; /* lcid of imported typelib */
1051 WORD wVersionMajor; /* major version number */
1052 WORD wVersionMinor; /* minor version number */
1054 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1055 NULL if not yet loaded */
1056 struct list entry;
1057 } TLBImpLib;
1059 typedef struct tagTLBString {
1060 BSTR str;
1061 UINT offset;
1062 struct list entry;
1063 } TLBString;
1065 /* internal ITypeLib data */
1066 typedef struct tagITypeLibImpl
1068 ITypeLib2 ITypeLib2_iface;
1069 ITypeComp ITypeComp_iface;
1070 ICreateTypeLib2 ICreateTypeLib2_iface;
1071 LONG ref;
1072 TLBGuid *guid;
1073 LCID lcid;
1074 SYSKIND syskind;
1075 int ptr_size;
1076 WORD ver_major;
1077 WORD ver_minor;
1078 WORD libflags;
1079 LCID set_lcid;
1081 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1082 * exported to the application as a UNICODE string.
1084 struct list string_list;
1085 struct list name_list;
1086 struct list guid_list;
1088 const TLBString *Name;
1089 const TLBString *DocString;
1090 const TLBString *HelpFile;
1091 const TLBString *HelpStringDll;
1092 DWORD dwHelpContext;
1093 int TypeInfoCount; /* nr of typeinfo's in librarry */
1094 struct tagITypeInfoImpl **typeinfos;
1095 struct list custdata_list;
1096 struct list implib_list;
1097 int ctTypeDesc; /* number of items in type desc array */
1098 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1099 library. Only used while reading MSFT
1100 typelibs */
1101 struct list ref_list; /* list of ref types in this typelib */
1102 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1105 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1106 struct list entry;
1107 WCHAR *path;
1108 INT index;
1109 } ITypeLibImpl;
1111 static const ITypeLib2Vtbl tlbvt;
1112 static const ITypeCompVtbl tlbtcvt;
1113 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1115 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1117 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1120 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1122 return impl_from_ITypeLib2((ITypeLib2*)iface);
1125 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1127 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1130 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1132 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1135 /* ITypeLib methods */
1136 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1137 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1139 /*======================= ITypeInfo implementation =======================*/
1141 /* data for referenced types */
1142 typedef struct tagTLBRefType
1144 INT index; /* Type index for internal ref or for external ref
1145 it the format is SLTG. -2 indicates to
1146 use guid */
1148 TYPEKIND tkind;
1149 TLBGuid *guid; /* guid of the referenced type */
1150 /* if index == TLB_REF_USE_GUID */
1152 HREFTYPE reference; /* The href of this ref */
1153 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1154 TLB_REF_INTERNAL for internal refs
1155 TLB_REF_NOT_FOUND for broken refs */
1157 struct list entry;
1158 } TLBRefType;
1160 #define TLB_REF_USE_GUID -2
1162 #define TLB_REF_INTERNAL (void*)-2
1163 #define TLB_REF_NOT_FOUND (void*)-1
1165 /* internal Parameter data */
1166 typedef struct tagTLBParDesc
1168 const TLBString *Name;
1169 struct list custdata_list;
1170 } TLBParDesc;
1172 /* internal Function data */
1173 typedef struct tagTLBFuncDesc
1175 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1176 const TLBString *Name; /* the name of this function */
1177 TLBParDesc *pParamDesc; /* array with param names and custom data */
1178 int helpcontext;
1179 int HelpStringContext;
1180 const TLBString *HelpString;
1181 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1182 struct list custdata_list;
1183 } TLBFuncDesc;
1185 /* internal Variable data */
1186 typedef struct tagTLBVarDesc
1188 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1189 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1190 const TLBString *Name; /* the name of this variable */
1191 int HelpContext;
1192 int HelpStringContext;
1193 const TLBString *HelpString;
1194 struct list custdata_list;
1195 } TLBVarDesc;
1197 /* internal implemented interface data */
1198 typedef struct tagTLBImplType
1200 HREFTYPE hRef; /* hRef of interface */
1201 int implflags; /* IMPLFLAG_*s */
1202 struct list custdata_list;
1203 } TLBImplType;
1205 /* internal TypeInfo data */
1206 typedef struct tagITypeInfoImpl
1208 ITypeInfo2 ITypeInfo2_iface;
1209 ITypeComp ITypeComp_iface;
1210 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1211 LONG ref;
1212 BOOL not_attached_to_typelib;
1213 BOOL needs_layout;
1215 TLBGuid *guid;
1216 TYPEATTR typeattr;
1217 TYPEDESC *tdescAlias;
1219 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1220 int index; /* index in this typelib; */
1221 HREFTYPE hreftype; /* hreftype for app object binding */
1222 /* type libs seem to store the doc strings in ascii
1223 * so why should we do it in unicode?
1225 const TLBString *Name;
1226 const TLBString *DocString;
1227 const TLBString *DllName;
1228 const TLBString *Schema;
1229 DWORD dwHelpContext;
1230 DWORD dwHelpStringContext;
1232 /* functions */
1233 TLBFuncDesc *funcdescs;
1235 /* variables */
1236 TLBVarDesc *vardescs;
1238 /* Implemented Interfaces */
1239 TLBImplType *impltypes;
1241 struct list *pcustdata_list;
1242 struct list custdata_list;
1243 } ITypeInfoImpl;
1245 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1247 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1250 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1252 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1255 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1257 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1260 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1262 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1265 static const ITypeInfo2Vtbl tinfvt;
1266 static const ITypeCompVtbl tcompvt;
1267 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1269 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1270 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1272 typedef struct tagTLBContext
1274 unsigned int oStart; /* start of TLB in file */
1275 unsigned int pos; /* current pos */
1276 unsigned int length; /* total length */
1277 void *mapping; /* memory mapping */
1278 MSFT_SegDir * pTblDir;
1279 ITypeLibImpl* pLibInfo;
1280 } TLBContext;
1283 static inline BSTR TLB_get_bstr(const TLBString *str)
1285 return str != NULL ? str->str : NULL;
1288 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1290 if(!str)
1291 return 1;
1292 return memcmp(left, str->str, len);
1295 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1297 return guid != NULL ? &guid->guid : NULL;
1300 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1302 return guid != NULL ? &guid->guid : &GUID_NULL;
1305 static int get_ptr_size(SYSKIND syskind)
1307 switch(syskind){
1308 case SYS_WIN64:
1309 return 8;
1310 case SYS_WIN32:
1311 case SYS_MAC:
1312 case SYS_WIN16:
1313 return 4;
1315 WARN("Unhandled syskind: 0x%x\n", syskind);
1316 return 4;
1320 debug
1322 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1323 if (pTD->vt & VT_RESERVED)
1324 szVarType += strlen(strcpy(szVarType, "reserved | "));
1325 if (pTD->vt & VT_BYREF)
1326 szVarType += strlen(strcpy(szVarType, "ref to "));
1327 if (pTD->vt & VT_ARRAY)
1328 szVarType += strlen(strcpy(szVarType, "array of "));
1329 if (pTD->vt & VT_VECTOR)
1330 szVarType += strlen(strcpy(szVarType, "vector of "));
1331 switch(pTD->vt & VT_TYPEMASK) {
1332 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1333 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1334 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1335 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1336 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1337 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1338 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1339 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1340 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1341 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1342 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1343 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1344 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1345 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1346 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1347 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1348 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1349 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1350 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1351 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1352 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx", pTD->hreftype); break;
1353 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1354 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1355 case VT_PTR: sprintf(szVarType, "ptr to ");
1356 dump_TypeDesc(pTD->lptdesc, szVarType + 7);
1357 break;
1358 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1359 dump_TypeDesc(pTD->lptdesc, szVarType + 13);
1360 break;
1361 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1362 pTD->lpadesc->cDims); /* FIXME print out sizes */
1363 dump_TypeDesc(&pTD->lpadesc->tdescElem, szVarType + strlen(szVarType));
1364 break;
1366 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1370 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1371 char buf[200];
1372 USHORT flags = edesc->paramdesc.wParamFlags;
1373 dump_TypeDesc(&edesc->tdesc,buf);
1374 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1375 MESSAGE("\t\tu.paramdesc.wParamFlags");
1376 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1377 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1378 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1379 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1380 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1381 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1382 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1383 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1384 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->paramdesc.pparamdescex);
1386 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1387 int i;
1388 MESSAGE("memid is %#lx\n", funcdesc->memid);
1389 for (i=0;i<funcdesc->cParams;i++) {
1390 MESSAGE("Param %d:\n",i);
1391 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1393 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1394 switch (funcdesc->funckind) {
1395 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1396 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1397 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1398 case FUNC_STATIC: MESSAGE("static");break;
1399 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1400 default: MESSAGE("unknown");break;
1402 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1403 switch (funcdesc->invkind) {
1404 case INVOKE_FUNC: MESSAGE("func");break;
1405 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1406 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1407 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1409 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1410 switch (funcdesc->callconv) {
1411 case CC_CDECL: MESSAGE("cdecl");break;
1412 case CC_PASCAL: MESSAGE("pascal");break;
1413 case CC_STDCALL: MESSAGE("stdcall");break;
1414 case CC_SYSCALL: MESSAGE("syscall");break;
1415 default:break;
1417 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1418 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1419 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1421 MESSAGE("\telemdescFunc (return value type):\n");
1422 dump_ELEMDESC(&funcdesc->elemdescFunc);
1425 static const char * const typekind_desc[] =
1427 "TKIND_ENUM",
1428 "TKIND_RECORD",
1429 "TKIND_MODULE",
1430 "TKIND_INTERFACE",
1431 "TKIND_DISPATCH",
1432 "TKIND_COCLASS",
1433 "TKIND_ALIAS",
1434 "TKIND_UNION",
1435 "TKIND_MAX"
1438 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1440 int i;
1441 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1442 for (i=0;i<pfd->funcdesc.cParams;i++)
1443 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1446 dump_FUNCDESC(&(pfd->funcdesc));
1448 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1449 if(pfd->Entry == NULL)
1450 MESSAGE("\tentry: (null)\n");
1451 else if(pfd->Entry == (void*)-1)
1452 MESSAGE("\tentry: invalid\n");
1453 else if(IS_INTRESOURCE(pfd->Entry))
1454 MESSAGE("\tentry: %p\n", pfd->Entry);
1455 else
1456 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1458 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1460 while (n)
1462 dump_TLBFuncDescOne(pfd);
1463 ++pfd;
1464 --n;
1467 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1469 while (n)
1471 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1472 ++pvd;
1473 --n;
1477 static void dump_TLBImpLib(const TLBImpLib *import)
1479 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1480 debugstr_w(import->name));
1481 TRACE_(typelib)("v%d.%d lcid %#lx offset=%x\n", import->wVersionMajor, import->wVersionMinor, import->lcid, import->offset);
1484 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1486 TLBRefType *ref;
1488 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1490 TRACE_(typelib)("href:%#lx\n", ref->reference);
1491 if(ref->index == -1)
1492 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1493 else
1494 TRACE_(typelib)("type no: %d\n", ref->index);
1496 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1498 TRACE_(typelib)("in lib\n");
1499 dump_TLBImpLib(ref->pImpTLInfo);
1504 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1506 if(!impl)
1507 return;
1508 while (n) {
1509 TRACE_(typelib)("implementing/inheriting interface hRef = %lx implflags %x\n",
1510 impl->hRef, impl->implflags);
1511 ++impl;
1512 --n;
1516 static void dump_DispParms(const DISPPARAMS * pdp)
1518 unsigned int index;
1520 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1522 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1524 TRACE("named args:\n");
1525 for (index = 0; index < pdp->cNamedArgs; index++)
1526 TRACE( "\t0x%lx\n", pdp->rgdispidNamedArgs[index] );
1529 if (pdp->cArgs && pdp->rgvarg)
1531 TRACE("args:\n");
1532 for (index = 0; index < pdp->cArgs; index++)
1533 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1537 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1539 TRACE("%p ref %lu\n", pty, pty->ref);
1540 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1541 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1542 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1543 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1544 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1545 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1546 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1547 if (TRACE_ON(ole))
1548 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1549 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1550 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1553 static void dump_VARDESC(const VARDESC *v)
1555 MESSAGE("memid %ld\n",v->memid);
1556 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1557 MESSAGE("oInst %ld\n", v->oInst);
1558 dump_ELEMDESC(&(v->elemdescVar));
1559 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1560 MESSAGE("varkind %d\n",v->varkind);
1563 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1565 /* VT_LPWSTR is largest type that, may appear in type description */
1566 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1567 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1568 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1569 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1570 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1571 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1572 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1573 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1576 static void TLB_abort(void)
1578 DebugBreak();
1581 /* returns the size required for a deep copy of a typedesc into a
1582 * flat buffer */
1583 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1585 SIZE_T size = 0;
1587 if (alloc_initial_space)
1588 size += sizeof(TYPEDESC);
1590 switch (tdesc->vt)
1592 case VT_PTR:
1593 case VT_SAFEARRAY:
1594 size += TLB_SizeTypeDesc(tdesc->lptdesc, TRUE);
1595 break;
1596 case VT_CARRAY:
1597 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->lpadesc->cDims]);
1598 size += TLB_SizeTypeDesc(&tdesc->lpadesc->tdescElem, FALSE);
1599 break;
1601 return size;
1604 /* deep copy a typedesc into a flat buffer */
1605 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1607 if (!dest)
1609 dest = buffer;
1610 buffer = (char *)buffer + sizeof(TYPEDESC);
1613 *dest = *src;
1615 switch (src->vt)
1617 case VT_PTR:
1618 case VT_SAFEARRAY:
1619 dest->lptdesc = buffer;
1620 buffer = TLB_CopyTypeDesc(NULL, src->lptdesc, buffer);
1621 break;
1622 case VT_CARRAY:
1623 dest->lpadesc = buffer;
1624 memcpy(dest->lpadesc, src->lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->lpadesc->cDims]));
1625 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->lpadesc->cDims]);
1626 buffer = TLB_CopyTypeDesc(&dest->lpadesc->tdescElem, &src->lpadesc->tdescElem, buffer);
1627 break;
1629 return buffer;
1632 /* free custom data allocated by MSFT_CustData */
1633 static inline void TLB_FreeCustData(struct list *custdata_list)
1635 TLBCustData *cd, *cdn;
1636 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1638 list_remove(&cd->entry);
1639 VariantClear(&cd->data);
1640 free(cd);
1644 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1646 DWORD len;
1647 BSTR ret;
1649 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1650 ret = SysAllocStringLen(NULL, len - 1);
1651 if (!ret) return ret;
1652 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1653 return ret;
1656 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1658 int i;
1660 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1662 if (typeinfo->funcdescs[i].funcdesc.memid == memid)
1663 return &typeinfo->funcdescs[i];
1666 return NULL;
1669 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl *typeinfo, MEMBERID memid, INVOKEKIND invkind)
1671 int i;
1673 for (i = 0; i < typeinfo->typeattr.cFuncs; ++i)
1675 if (typeinfo->funcdescs[i].funcdesc.memid == memid && typeinfo->funcdescs[i].funcdesc.invkind == invkind)
1676 return &typeinfo->funcdescs[i];
1679 return NULL;
1682 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(ITypeInfoImpl *typeinfo, MEMBERID memid)
1684 int i;
1686 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1688 if (typeinfo->vardescs[i].vardesc.memid == memid)
1689 return &typeinfo->vardescs[i];
1692 return NULL;
1695 static inline TLBVarDesc *TLB_get_vardesc_by_name(ITypeInfoImpl *typeinfo, const OLECHAR *name)
1697 int i;
1699 for (i = 0; i < typeinfo->typeattr.cVars; ++i)
1701 if (!lstrcmpiW(TLB_get_bstr(typeinfo->vardescs[i].Name), name))
1702 return &typeinfo->vardescs[i];
1705 return NULL;
1708 static inline TLBCustData *TLB_get_custdata_by_guid(const struct list *custdata_list, REFGUID guid)
1710 TLBCustData *cust_data;
1711 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1712 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1713 return cust_data;
1714 return NULL;
1717 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeLibImpl *typelib, const OLECHAR *name)
1719 int i;
1721 for (i = 0; i < typelib->TypeInfoCount; ++i)
1723 if (!lstrcmpiW(TLB_get_bstr(typelib->typeinfos[i]->Name), name))
1724 return typelib->typeinfos[i];
1727 return NULL;
1730 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1732 list_init(&var_desc->custdata_list);
1735 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1737 TLBVarDesc *ret;
1739 ret = calloc(n, sizeof(TLBVarDesc));
1740 if(!ret)
1741 return NULL;
1743 while(n){
1744 TLBVarDesc_Constructor(&ret[n-1]);
1745 --n;
1748 return ret;
1751 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1753 TLBParDesc *ret;
1755 ret = calloc(n, sizeof(TLBParDesc));
1756 if(!ret)
1757 return NULL;
1759 while(n){
1760 list_init(&ret[n-1].custdata_list);
1761 --n;
1764 return ret;
1767 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1769 list_init(&func_desc->custdata_list);
1772 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1774 TLBFuncDesc *ret;
1776 ret = calloc(n, sizeof(TLBFuncDesc));
1777 if(!ret)
1778 return NULL;
1780 while(n){
1781 TLBFuncDesc_Constructor(&ret[n-1]);
1782 --n;
1785 return ret;
1788 static void TLBImplType_Constructor(TLBImplType *impl)
1790 list_init(&impl->custdata_list);
1793 static TLBImplType *TLBImplType_Alloc(UINT n)
1795 TLBImplType *ret;
1797 ret = calloc(n, sizeof(TLBImplType));
1798 if(!ret)
1799 return NULL;
1801 while(n){
1802 TLBImplType_Constructor(&ret[n-1]);
1803 --n;
1806 return ret;
1809 static TLBGuid *TLB_append_guid(struct list *guid_list,
1810 const GUID *new_guid, HREFTYPE hreftype)
1812 TLBGuid *guid;
1814 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1815 if (IsEqualGUID(&guid->guid, new_guid))
1816 return guid;
1819 guid = malloc(sizeof(TLBGuid));
1820 if (!guid)
1821 return NULL;
1823 memcpy(&guid->guid, new_guid, sizeof(GUID));
1824 guid->hreftype = hreftype;
1826 list_add_tail(guid_list, &guid->entry);
1828 return guid;
1831 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1833 TLBCustData *cust_data;
1835 switch(V_VT(var)){
1836 case VT_I4:
1837 case VT_R4:
1838 case VT_UI4:
1839 case VT_INT:
1840 case VT_UINT:
1841 case VT_HRESULT:
1842 case VT_BSTR:
1843 break;
1844 default:
1845 return DISP_E_BADVARTYPE;
1848 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1850 if (!cust_data) {
1851 cust_data = malloc(sizeof(TLBCustData));
1852 if (!cust_data)
1853 return E_OUTOFMEMORY;
1855 cust_data->guid = tlbguid;
1856 VariantInit(&cust_data->data);
1858 list_add_tail(custdata_list, &cust_data->entry);
1859 }else
1860 VariantClear(&cust_data->data);
1862 return VariantCopy(&cust_data->data, var);
1865 /* Used to update list pointers after list itself was moved. */
1866 static void TLB_relink_custdata(struct list *custdata_list)
1868 if (custdata_list->prev == custdata_list->next)
1869 list_init(custdata_list);
1870 else
1872 custdata_list->prev->next = custdata_list;
1873 custdata_list->next->prev = custdata_list;
1877 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1879 TLBString *str;
1881 if(!new_str)
1882 return NULL;
1884 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1885 if (wcscmp(str->str, new_str) == 0)
1886 return str;
1889 str = malloc(sizeof(TLBString));
1890 if (!str)
1891 return NULL;
1893 str->str = SysAllocString(new_str);
1894 if (!str->str) {
1895 free(str);
1896 return NULL;
1899 list_add_tail(string_list, &str->entry);
1901 return str;
1904 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1905 ULONG *size, WORD *align)
1907 ITypeInfo *other;
1908 TYPEATTR *attr;
1909 HRESULT hr;
1911 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1912 if(FAILED(hr))
1913 return hr;
1915 hr = ITypeInfo_GetTypeAttr(other, &attr);
1916 if(FAILED(hr)){
1917 ITypeInfo_Release(other);
1918 return hr;
1921 if(size)
1922 *size = attr->cbSizeInstance;
1923 if(align)
1924 *align = attr->cbAlignment;
1926 ITypeInfo_ReleaseTypeAttr(other, attr);
1927 ITypeInfo_Release(other);
1929 return S_OK;
1932 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1933 TYPEDESC *tdesc, ULONG *size, WORD *align)
1935 ULONG i, sub, ptr_size;
1936 HRESULT hr;
1938 ptr_size = get_ptr_size(sys);
1940 switch(tdesc->vt){
1941 case VT_VOID:
1942 *size = 0;
1943 break;
1944 case VT_I1:
1945 case VT_UI1:
1946 *size = 1;
1947 break;
1948 case VT_I2:
1949 case VT_BOOL:
1950 case VT_UI2:
1951 *size = 2;
1952 break;
1953 case VT_I4:
1954 case VT_R4:
1955 case VT_ERROR:
1956 case VT_UI4:
1957 case VT_INT:
1958 case VT_UINT:
1959 case VT_HRESULT:
1960 *size = 4;
1961 break;
1962 case VT_R8:
1963 case VT_I8:
1964 case VT_UI8:
1965 *size = 8;
1966 break;
1967 case VT_BSTR:
1968 case VT_DISPATCH:
1969 case VT_UNKNOWN:
1970 case VT_PTR:
1971 case VT_SAFEARRAY:
1972 case VT_LPSTR:
1973 case VT_LPWSTR:
1974 *size = ptr_size;
1975 break;
1976 case VT_DATE:
1977 *size = sizeof(DATE);
1978 break;
1979 case VT_VARIANT:
1980 *size = sizeof(VARIANT);
1981 #ifdef _WIN64
1982 if(sys == SYS_WIN32)
1983 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1984 #endif
1985 break;
1986 case VT_DECIMAL:
1987 *size = sizeof(DECIMAL);
1988 break;
1989 case VT_CY:
1990 *size = sizeof(CY);
1991 break;
1992 case VT_CARRAY:
1993 *size = 0;
1994 for(i = 0; i < tdesc->lpadesc->cDims; ++i)
1995 *size += tdesc->lpadesc->rgbounds[i].cElements;
1996 hr = TLB_size_instance(info, sys, &tdesc->lpadesc->tdescElem, &sub, align);
1997 if(FAILED(hr))
1998 return hr;
1999 *size *= sub;
2000 return S_OK;
2001 case VT_USERDEFINED:
2002 return TLB_get_size_from_hreftype(info, tdesc->hreftype, size, align);
2003 default:
2004 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2005 return E_FAIL;
2008 if(align){
2009 if(*size < 4)
2010 *align = *size;
2011 else
2012 *align = 4;
2015 return S_OK;
2018 /**********************************************************************
2020 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2023 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2025 if (where != DO_NOT_SEEK)
2027 where += pcx->oStart;
2028 if (where > pcx->length)
2030 /* FIXME */
2031 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
2032 TLB_abort();
2034 pcx->pos = where;
2038 /* read function */
2039 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2041 TRACE_(typelib)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2042 pcx->pos, count, pcx->oStart, pcx->length, where);
2044 MSFT_Seek(pcx, where);
2045 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2046 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2047 pcx->pos += count;
2048 return count;
2051 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2052 LONG where )
2054 DWORD ret;
2056 ret = MSFT_Read(buffer, count, pcx, where);
2057 FromLEDWords(buffer, ret);
2059 return ret;
2062 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2063 LONG where )
2065 DWORD ret;
2067 ret = MSFT_Read(buffer, count, pcx, where);
2068 FromLEWords(buffer, ret);
2070 return ret;
2073 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2075 TLBGuid *guid;
2076 MSFT_GuidEntry entry;
2077 int offs = 0;
2079 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2080 while (1) {
2081 if (offs >= pcx->pTblDir->pGuidTab.length)
2082 return S_OK;
2084 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2086 guid = malloc(sizeof(TLBGuid));
2088 guid->offset = offs;
2089 guid->guid = entry.guid;
2090 guid->hreftype = entry.hreftype;
2092 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2094 offs += sizeof(MSFT_GuidEntry);
2098 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2100 TLBGuid *ret;
2102 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2103 if(ret->offset == offset){
2104 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2105 return ret;
2109 return NULL;
2112 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2114 MSFT_NameIntro niName;
2116 if (offset < 0)
2118 ERR_(typelib)("bad offset %d\n", offset);
2119 return -1;
2122 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2123 pcx->pTblDir->pNametab.offset+offset);
2125 return niName.hreftype;
2128 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2130 char *string;
2131 MSFT_NameIntro intro;
2132 INT16 len_piece;
2133 int offs = 0, lengthInChars;
2135 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2136 while (1) {
2137 TLBString *tlbstr;
2139 if (offs >= pcx->pTblDir->pNametab.length)
2140 return S_OK;
2142 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2143 intro.namelen &= 0xFF;
2144 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2145 if(len_piece % 4)
2146 len_piece = (len_piece + 4) & ~0x3;
2147 if(len_piece < 8)
2148 len_piece = 8;
2150 string = malloc(len_piece + 1);
2151 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2152 string[intro.namelen] = '\0';
2154 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2155 string, -1, NULL, 0);
2156 if (!lengthInChars) {
2157 free(string);
2158 return E_UNEXPECTED;
2161 tlbstr = malloc(sizeof(TLBString));
2163 tlbstr->offset = offs;
2164 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2165 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2167 free(string);
2169 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2171 offs += len_piece;
2175 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2177 TLBString *tlbstr;
2179 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2180 if (tlbstr->offset == offset) {
2181 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2182 return tlbstr;
2186 return NULL;
2189 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2191 TLBString *tlbstr;
2193 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2194 if (tlbstr->offset == offset) {
2195 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2196 return tlbstr;
2200 return NULL;
2204 * read a value and fill a VARIANT structure
2206 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2208 int size;
2210 TRACE_(typelib)("\n");
2212 if(offset <0) { /* data are packed in here */
2213 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2214 V_I4(pVar) = offset & 0x3ffffff;
2215 return;
2217 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2218 pcx->pTblDir->pCustData.offset + offset );
2219 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2220 switch (V_VT(pVar)){
2221 case VT_EMPTY: /* FIXME: is this right? */
2222 case VT_NULL: /* FIXME: is this right? */
2223 case VT_I2 : /* this should not happen */
2224 case VT_I4 :
2225 case VT_R4 :
2226 case VT_ERROR :
2227 case VT_BOOL :
2228 case VT_I1 :
2229 case VT_UI1 :
2230 case VT_UI2 :
2231 case VT_UI4 :
2232 case VT_INT :
2233 case VT_UINT :
2234 case VT_VOID : /* FIXME: is this right? */
2235 case VT_HRESULT :
2236 size=4; break;
2237 case VT_R8 :
2238 case VT_CY :
2239 case VT_DATE :
2240 case VT_I8 :
2241 case VT_UI8 :
2242 case VT_DECIMAL : /* FIXME: is this right? */
2243 case VT_FILETIME :
2244 size=8;break;
2245 /* pointer types with known behaviour */
2246 case VT_BSTR :{
2247 char * ptr;
2248 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2249 if(size == -1){
2250 V_BSTR(pVar) = NULL;
2251 }else{
2252 int len;
2253 ptr = calloc(1, size);
2254 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2255 len = MultiByteToWideChar(CP_ACP, 0, ptr, size, NULL, 0 );
2256 V_BSTR(pVar)=SysAllocStringLen(NULL,len);
2257 MultiByteToWideChar(CP_ACP, 0, ptr, size, V_BSTR(pVar), len );
2258 free(ptr);
2261 size=-4; break;
2262 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2263 case VT_DISPATCH :
2264 case VT_VARIANT :
2265 case VT_UNKNOWN :
2266 case VT_PTR :
2267 case VT_SAFEARRAY :
2268 case VT_CARRAY :
2269 case VT_USERDEFINED :
2270 case VT_LPSTR :
2271 case VT_LPWSTR :
2272 case VT_BLOB :
2273 case VT_STREAM :
2274 case VT_STORAGE :
2275 case VT_STREAMED_OBJECT :
2276 case VT_STORED_OBJECT :
2277 case VT_BLOB_OBJECT :
2278 case VT_CF :
2279 case VT_CLSID :
2280 default:
2281 size=0;
2282 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2283 V_VT(pVar));
2286 if(size>0) /* (big|small) endian correct? */
2287 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2288 return;
2291 * create a linked list with custom data
2293 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2295 MSFT_CDGuid entry;
2296 TLBCustData* pNew;
2297 int count=0;
2299 TRACE_(typelib)("\n");
2301 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2303 while(offset >=0){
2304 count++;
2305 pNew = calloc(1, sizeof(TLBCustData));
2306 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2307 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2308 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2309 list_add_head(custdata_list, &pNew->entry);
2310 offset = entry.next;
2312 return count;
2315 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2317 if(type <0)
2318 pTd->vt=type & VT_TYPEMASK;
2319 else
2320 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2322 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2325 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2327 return (invkind == INVOKE_PROPERTYGET ||
2328 invkind == INVOKE_PROPERTYPUT ||
2329 invkind == INVOKE_PROPERTYPUTREF);
2332 static void
2333 MSFT_DoFuncs(TLBContext* pcx,
2334 ITypeInfoImpl* pTI,
2335 int cFuncs,
2336 int cVars,
2337 int offset,
2338 TLBFuncDesc** pptfd)
2341 * member information is stored in a data structure at offset
2342 * indicated by the memoffset field of the typeinfo structure
2343 * There are several distinctive parts.
2344 * The first part starts with a field that holds the total length
2345 * of this (first) part excluding this field. Then follow the records,
2346 * for each member there is one record.
2348 * The first entry is always the length of the record (including this
2349 * length word).
2350 * The rest of the record depends on the type of the member. If there is
2351 * a field indicating the member type (function, variable, interface, etc)
2352 * I have not found it yet. At this time we depend on the information
2353 * in the type info and the usual order how things are stored.
2355 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2356 * for each member;
2358 * Third is an equal sized array with file offsets to the name entry
2359 * of each member.
2361 * The fourth and last (?) part is an array with offsets to the records
2362 * in the first part of this file segment.
2365 int infolen, nameoffset, reclength, i;
2366 int recoffset = offset + sizeof(INT);
2368 char *recbuf = malloc(0xffff);
2369 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2370 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2372 TRACE_(typelib)("\n");
2374 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2376 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2377 ptfd = *pptfd;
2378 for ( i = 0; i < cFuncs ; i++ )
2380 int optional;
2382 /* name, eventually add to a hash table */
2383 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2384 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2386 /* read the function information record */
2387 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2389 reclength &= 0xffff;
2391 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2393 /* size without argument data */
2394 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2395 if (pFuncRec->FKCCIC & 0x1000)
2396 optional -= pFuncRec->nrargs * sizeof(INT);
2398 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2399 ptfd->helpcontext = pFuncRec->HelpContext;
2401 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2402 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2404 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2406 if (pFuncRec->FKCCIC & 0x2000 )
2408 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2409 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2410 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2412 else
2413 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2415 else
2416 ptfd->Entry = (TLBString*)-1;
2418 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2419 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2421 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2422 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2424 /* fill the FuncDesc Structure */
2425 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2426 offset + infolen + ( i + 1) * sizeof(INT));
2428 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2429 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2430 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2431 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2432 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2433 if (ptfd->funcdesc.funckind == FUNC_DISPATCH)
2434 ptfd->funcdesc.oVft = 0;
2435 else
2436 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2437 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2439 /* nameoffset is sometimes -1 on the second half of a propget/propput
2440 * pair of functions */
2441 if ((nameoffset == -1) && (i > 0) &&
2442 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2443 TLB_is_propgetput(ptfd->funcdesc.invkind))
2444 ptfd->Name = ptfd_prev->Name;
2445 else
2446 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2448 MSFT_GetTdesc(pcx,
2449 pFuncRec->DataType,
2450 &ptfd->funcdesc.elemdescFunc.tdesc);
2452 /* do the parameters/arguments */
2453 if(pFuncRec->nrargs)
2455 int j = 0;
2456 MSFT_ParameterInfo paraminfo;
2458 ptfd->funcdesc.lprgelemdescParam =
2459 calloc(pFuncRec->nrargs, sizeof(ELEMDESC) + sizeof(PARAMDESCEX));
2461 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2463 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2464 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2466 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2468 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2470 MSFT_GetTdesc(pcx,
2471 paraminfo.DataType,
2472 &elemdesc->tdesc);
2474 elemdesc->paramdesc.wParamFlags = paraminfo.Flags;
2476 /* name */
2477 if (paraminfo.oName != -1)
2478 ptfd->pParamDesc[j].Name =
2479 MSFT_ReadName( pcx, paraminfo.oName );
2480 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2482 /* default value */
2483 if ( (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2484 (pFuncRec->FKCCIC & 0x1000) )
2486 INT* pInt = (INT *)((char *)pFuncRec +
2487 reclength -
2488 (pFuncRec->nrargs * 4) * sizeof(INT) );
2490 PARAMDESC* pParamDesc = &elemdesc->paramdesc;
2492 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2493 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2495 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2496 pInt[j], pcx);
2498 else
2499 elemdesc->paramdesc.pparamdescex = NULL;
2501 /* custom info */
2502 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2503 j*sizeof(pFuncRec->oArgCustData[0])) &&
2504 pFuncRec->FKCCIC & 0x80 )
2506 MSFT_CustData(pcx,
2507 pFuncRec->oArgCustData[j],
2508 &ptfd->pParamDesc[j].custdata_list);
2511 /* SEEK value = jump to offset,
2512 * from there jump to the end of record,
2513 * go back by (j-1) arguments
2515 MSFT_ReadLEDWords( &paraminfo ,
2516 sizeof(MSFT_ParameterInfo), pcx,
2517 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2518 * sizeof(MSFT_ParameterInfo)));
2522 /* scode is not used: archaic win16 stuff FIXME: right? */
2523 ptfd->funcdesc.cScodes = 0 ;
2524 ptfd->funcdesc.lprgscode = NULL ;
2526 ptfd_prev = ptfd;
2527 ++ptfd;
2528 recoffset += reclength;
2530 free(recbuf);
2533 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2534 int cVars, int offset, TLBVarDesc ** pptvd)
2536 int infolen, nameoffset, reclength;
2537 char recbuf[256];
2538 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2539 TLBVarDesc *ptvd;
2540 int i;
2541 int recoffset;
2543 TRACE_(typelib)("\n");
2545 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2546 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2547 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2548 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2549 recoffset += offset+sizeof(INT);
2550 for(i=0;i<cVars;i++, ++ptvd){
2551 /* name, eventually add to a hash table */
2552 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2553 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2554 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2555 /* read the variable information record */
2556 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2557 reclength &= 0xff;
2558 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2560 /* optional data */
2561 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2562 ptvd->HelpContext = pVarRec->HelpContext;
2564 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2565 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2567 if (reclength > FIELD_OFFSET(MSFT_VarRecord, oCustData))
2568 MSFT_CustData(pcx, pVarRec->oCustData, &ptvd->custdata_list);
2570 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2571 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2573 /* fill the VarDesc Structure */
2574 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2575 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2576 ptvd->vardesc.varkind = pVarRec->VarKind;
2577 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2578 MSFT_GetTdesc(pcx, pVarRec->DataType,
2579 &ptvd->vardesc.elemdescVar.tdesc);
2580 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2581 if(pVarRec->VarKind == VAR_CONST ){
2582 ptvd->vardesc.lpvarValue = calloc(1, sizeof(VARIANT));
2583 MSFT_ReadValue(ptvd->vardesc.lpvarValue,
2584 pVarRec->OffsValue, pcx);
2585 } else
2586 ptvd->vardesc.oInst=pVarRec->OffsValue;
2587 recoffset += reclength;
2591 /* process Implemented Interfaces of a com class */
2592 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2593 int offset)
2595 int i;
2596 MSFT_RefRecord refrec;
2597 TLBImplType *pImpl;
2599 TRACE_(typelib)("\n");
2601 pTI->impltypes = TLBImplType_Alloc(count);
2602 pImpl = pTI->impltypes;
2603 for(i=0;i<count;i++){
2604 if(offset<0) break; /* paranoia */
2605 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2606 pImpl->hRef = refrec.reftype;
2607 pImpl->implflags=refrec.flags;
2608 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2609 offset=refrec.onext;
2610 ++pImpl;
2614 #ifdef _WIN64
2615 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2616 * and some structures, and fix the alignment */
2617 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2619 if(info->typeattr.typekind == TKIND_ALIAS){
2620 switch(info->tdescAlias->vt){
2621 case VT_BSTR:
2622 case VT_DISPATCH:
2623 case VT_UNKNOWN:
2624 case VT_PTR:
2625 case VT_SAFEARRAY:
2626 case VT_LPSTR:
2627 case VT_LPWSTR:
2628 info->typeattr.cbSizeInstance = sizeof(void*);
2629 info->typeattr.cbAlignment = sizeof(void*);
2630 break;
2631 case VT_CARRAY:
2632 case VT_USERDEFINED:
2633 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2634 break;
2635 case VT_VARIANT:
2636 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2637 info->typeattr.cbAlignment = 8;
2638 default:
2639 if(info->typeattr.cbSizeInstance < sizeof(void*))
2640 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2641 else
2642 info->typeattr.cbAlignment = sizeof(void*);
2643 break;
2645 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2646 info->typeattr.typekind == TKIND_DISPATCH ||
2647 info->typeattr.typekind == TKIND_COCLASS){
2648 info->typeattr.cbSizeInstance = sizeof(void*);
2649 info->typeattr.cbAlignment = sizeof(void*);
2652 #endif
2655 * process a typeinfo record
2657 static ITypeInfoImpl * MSFT_DoTypeInfo(
2658 TLBContext *pcx,
2659 int count,
2660 ITypeLibImpl * pLibInfo)
2662 MSFT_TypeInfoBase tiBase;
2663 ITypeInfoImpl *ptiRet;
2665 TRACE_(typelib)("count=%u\n", count);
2667 ptiRet = ITypeInfoImpl_Constructor();
2668 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2669 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2671 /* this is where we are coming from */
2672 ptiRet->pTypeLib = pLibInfo;
2673 ptiRet->index=count;
2675 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2676 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2677 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2678 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2679 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2680 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2681 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2682 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2683 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2684 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2685 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2686 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2687 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2688 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2689 TYPEDESC tmp;
2690 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2691 ptiRet->tdescAlias = malloc(TLB_SizeTypeDesc(&tmp, TRUE));
2692 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2695 /* FIXME: */
2696 /* IDLDESC idldescType; *//* never saw this one != zero */
2698 /* name, eventually add to a hash table */
2699 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2700 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2701 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2702 /* help info */
2703 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2704 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2705 ptiRet->dwHelpContext=tiBase.helpcontext;
2707 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2708 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2710 /* note: InfoType's Help file and HelpStringDll come from the containing
2711 * library. Further HelpString and Docstring appear to be the same thing :(
2713 /* functions */
2714 if(ptiRet->typeattr.cFuncs >0 )
2715 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2716 ptiRet->typeattr.cVars,
2717 tiBase.memoffset, &ptiRet->funcdescs);
2718 /* variables */
2719 if(ptiRet->typeattr.cVars >0 )
2720 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2721 ptiRet->typeattr.cVars,
2722 tiBase.memoffset, &ptiRet->vardescs);
2723 if(ptiRet->typeattr.cImplTypes >0 ) {
2724 switch(ptiRet->typeattr.typekind)
2726 case TKIND_COCLASS:
2727 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2728 tiBase.datatype1);
2729 break;
2730 case TKIND_DISPATCH:
2731 /* This is not -1 when the interface is a non-base dual interface or
2732 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2733 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2734 not this interface.
2737 if (tiBase.datatype1 != -1)
2739 ptiRet->impltypes = TLBImplType_Alloc(1);
2740 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2742 break;
2743 default:
2744 ptiRet->impltypes = TLBImplType_Alloc(1);
2745 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2746 break;
2749 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2751 TRACE_(typelib)("%s guid: %s kind:%s\n",
2752 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2753 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2754 typekind_desc[ptiRet->typeattr.typekind]);
2755 if (TRACE_ON(typelib))
2756 dump_TypeInfo(ptiRet);
2758 return ptiRet;
2761 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2763 char *string;
2764 INT16 len_str, len_piece;
2765 int offs = 0, lengthInChars;
2767 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2768 while (1) {
2769 TLBString *tlbstr;
2771 if (offs >= pcx->pTblDir->pStringtab.length)
2772 return S_OK;
2774 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2775 len_piece = len_str + sizeof(INT16);
2776 if(len_piece % 4)
2777 len_piece = (len_piece + 4) & ~0x3;
2778 if(len_piece < 8)
2779 len_piece = 8;
2781 string = malloc(len_piece + 1);
2782 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2783 string[len_str] = '\0';
2785 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2786 string, -1, NULL, 0);
2787 if (!lengthInChars) {
2788 free(string);
2789 return E_UNEXPECTED;
2792 tlbstr = malloc(sizeof(TLBString));
2794 tlbstr->offset = offs;
2795 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2796 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2798 free(string);
2800 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2802 offs += len_piece;
2806 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2808 TLBRefType *ref;
2809 int offs = 0;
2811 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2812 while (offs < pcx->pTblDir->pImpInfo.length) {
2813 MSFT_ImpInfo impinfo;
2814 TLBImpLib *pImpLib;
2816 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2818 ref = calloc(1, sizeof(TLBRefType));
2819 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2821 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2822 if(pImpLib->offset==impinfo.oImpFile)
2823 break;
2825 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2826 ref->reference = offs;
2827 ref->pImpTLInfo = pImpLib;
2828 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2829 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2830 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2831 ref->index = TLB_REF_USE_GUID;
2832 } else
2833 ref->index = impinfo.oGuid;
2834 }else{
2835 ERR("Cannot find a reference\n");
2836 ref->reference = -1;
2837 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2840 offs += sizeof(impinfo);
2843 return S_OK;
2846 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2847 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2848 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2849 * tradeoff here.
2851 static struct list tlb_cache = LIST_INIT(tlb_cache);
2852 static CRITICAL_SECTION cache_section;
2853 static CRITICAL_SECTION_DEBUG cache_section_debug =
2855 0, 0, &cache_section,
2856 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2857 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2859 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2862 typedef struct TLB_PEFile
2864 IUnknown IUnknown_iface;
2865 LONG refs;
2866 HMODULE dll;
2867 HRSRC typelib_resource;
2868 HGLOBAL typelib_global;
2869 LPVOID typelib_base;
2870 } TLB_PEFile;
2872 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2874 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2877 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2879 if (IsEqualIID(riid, &IID_IUnknown))
2881 *ppv = iface;
2882 IUnknown_AddRef(iface);
2883 return S_OK;
2885 *ppv = NULL;
2886 return E_NOINTERFACE;
2889 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2891 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2892 return InterlockedIncrement(&This->refs);
2895 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2897 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2898 ULONG refs = InterlockedDecrement(&This->refs);
2899 if (!refs)
2901 if (This->typelib_global)
2902 FreeResource(This->typelib_global);
2903 if (This->dll)
2904 FreeLibrary(This->dll);
2905 free(This);
2907 return refs;
2910 static const IUnknownVtbl TLB_PEFile_Vtable =
2912 TLB_PEFile_QueryInterface,
2913 TLB_PEFile_AddRef,
2914 TLB_PEFile_Release
2917 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2919 TLB_PEFile *This;
2920 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2922 This = malloc(sizeof(TLB_PEFile));
2923 if (!This)
2924 return E_OUTOFMEMORY;
2926 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2927 This->refs = 1;
2928 This->dll = NULL;
2929 This->typelib_resource = NULL;
2930 This->typelib_global = NULL;
2931 This->typelib_base = NULL;
2933 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2934 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2936 if (This->dll)
2938 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), L"TYPELIB");
2939 if (This->typelib_resource)
2941 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2942 if (This->typelib_global)
2944 This->typelib_base = LockResource(This->typelib_global);
2946 if (This->typelib_base)
2948 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2949 *ppBase = This->typelib_base;
2950 *ppFile = &This->IUnknown_iface;
2951 return S_OK;
2956 TRACE("No TYPELIB resource found\n");
2957 hr = E_FAIL;
2960 TLB_PEFile_Release(&This->IUnknown_iface);
2961 return hr;
2964 typedef struct TLB_NEFile
2966 IUnknown IUnknown_iface;
2967 LONG refs;
2968 LPVOID typelib_base;
2969 } TLB_NEFile;
2971 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2973 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2976 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2978 if (IsEqualIID(riid, &IID_IUnknown))
2980 *ppv = iface;
2981 IUnknown_AddRef(iface);
2982 return S_OK;
2984 *ppv = NULL;
2985 return E_NOINTERFACE;
2988 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2990 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2991 return InterlockedIncrement(&This->refs);
2994 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2996 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2997 ULONG refs = InterlockedDecrement(&This->refs);
2998 if (!refs)
3000 free(This->typelib_base);
3001 free(This);
3003 return refs;
3006 static const IUnknownVtbl TLB_NEFile_Vtable =
3008 TLB_NEFile_QueryInterface,
3009 TLB_NEFile_AddRef,
3010 TLB_NEFile_Release
3013 /***********************************************************************
3014 * read_xx_header [internal]
3016 static int read_xx_header( HFILE lzfd )
3018 IMAGE_DOS_HEADER mzh;
3019 char magic[3];
3021 LZSeek( lzfd, 0, SEEK_SET );
3022 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3023 return 0;
3024 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3025 return 0;
3027 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3028 if ( 2 != LZRead( lzfd, magic, 2 ) )
3029 return 0;
3031 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3033 if ( magic[0] == 'N' && magic[1] == 'E' )
3034 return IMAGE_OS2_SIGNATURE;
3035 if ( magic[0] == 'P' && magic[1] == 'E' )
3036 return IMAGE_NT_SIGNATURE;
3038 magic[2] = '\0';
3039 WARN("Can't handle %s files.\n", magic );
3040 return 0;
3044 /***********************************************************************
3045 * find_ne_resource [internal]
3047 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3048 DWORD *resLen, DWORD *resOff )
3050 IMAGE_OS2_HEADER nehd;
3051 NE_TYPEINFO *typeInfo;
3052 NE_NAMEINFO *nameInfo;
3053 DWORD nehdoffset;
3054 LPBYTE resTab;
3055 DWORD resTabSize;
3056 int count;
3058 /* Read in NE header */
3059 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3060 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3062 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3063 if ( !resTabSize )
3065 TRACE("No resources in NE dll\n" );
3066 return FALSE;
3069 /* Read in resource table */
3070 resTab = malloc( resTabSize );
3071 if ( !resTab ) return FALSE;
3073 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3074 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3076 free( resTab );
3077 return FALSE;
3080 /* Find resource */
3081 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3083 if (!IS_INTRESOURCE(typeid)) /* named type */
3085 BYTE len = strlen( typeid );
3086 while (typeInfo->type_id)
3088 if (!(typeInfo->type_id & 0x8000))
3090 BYTE *p = resTab + typeInfo->type_id;
3091 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3093 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3094 typeInfo->count * sizeof(NE_NAMEINFO));
3097 else /* numeric type id */
3099 WORD id = LOWORD(typeid) | 0x8000;
3100 while (typeInfo->type_id)
3102 if (typeInfo->type_id == id) goto found_type;
3103 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3104 typeInfo->count * sizeof(NE_NAMEINFO));
3107 TRACE("No typeid entry found for %p\n", typeid );
3108 free( resTab );
3109 return FALSE;
3111 found_type:
3112 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3114 if (!IS_INTRESOURCE(resid)) /* named resource */
3116 BYTE len = strlen( resid );
3117 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3119 BYTE *p = resTab + nameInfo->id;
3120 if (nameInfo->id & 0x8000) continue;
3121 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3124 else /* numeric resource id */
3126 WORD id = LOWORD(resid) | 0x8000;
3127 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3128 if (nameInfo->id == id) goto found_name;
3130 TRACE("No resid entry found for %p\n", typeid );
3131 free( resTab );
3132 return FALSE;
3134 found_name:
3135 /* Return resource data */
3136 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3137 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3139 free( resTab );
3140 return TRUE;
3143 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3145 HFILE lzfd = -1;
3146 OFSTRUCT ofs;
3147 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3148 TLB_NEFile *This;
3150 This = malloc(sizeof(TLB_NEFile));
3151 if (!This) return E_OUTOFMEMORY;
3153 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3154 This->refs = 1;
3155 This->typelib_base = NULL;
3157 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3158 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3160 DWORD reslen, offset;
3161 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3163 This->typelib_base = malloc(reslen);
3164 if( !This->typelib_base )
3165 hr = E_OUTOFMEMORY;
3166 else
3168 LZSeek( lzfd, offset, SEEK_SET );
3169 reslen = LZRead( lzfd, This->typelib_base, reslen );
3170 LZClose( lzfd );
3171 *ppBase = This->typelib_base;
3172 *pdwTLBLength = reslen;
3173 *ppFile = &This->IUnknown_iface;
3174 return S_OK;
3179 if( lzfd >= 0) LZClose( lzfd );
3180 TLB_NEFile_Release(&This->IUnknown_iface);
3181 return hr;
3184 typedef struct TLB_Mapping
3186 IUnknown IUnknown_iface;
3187 LONG refs;
3188 HANDLE file;
3189 HANDLE mapping;
3190 LPVOID typelib_base;
3191 } TLB_Mapping;
3193 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3195 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3198 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3200 if (IsEqualIID(riid, &IID_IUnknown))
3202 *ppv = iface;
3203 IUnknown_AddRef(iface);
3204 return S_OK;
3206 *ppv = NULL;
3207 return E_NOINTERFACE;
3210 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3212 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3213 return InterlockedIncrement(&This->refs);
3216 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3218 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3219 ULONG refs = InterlockedDecrement(&This->refs);
3220 if (!refs)
3222 if (This->typelib_base)
3223 UnmapViewOfFile(This->typelib_base);
3224 if (This->mapping)
3225 CloseHandle(This->mapping);
3226 if (This->file != INVALID_HANDLE_VALUE)
3227 CloseHandle(This->file);
3228 free(This);
3230 return refs;
3233 static const IUnknownVtbl TLB_Mapping_Vtable =
3235 TLB_Mapping_QueryInterface,
3236 TLB_Mapping_AddRef,
3237 TLB_Mapping_Release
3240 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3242 TLB_Mapping *This;
3244 This = malloc(sizeof(TLB_Mapping));
3245 if (!This)
3246 return E_OUTOFMEMORY;
3248 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3249 This->refs = 1;
3250 This->file = INVALID_HANDLE_VALUE;
3251 This->mapping = NULL;
3252 This->typelib_base = NULL;
3254 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3255 if (INVALID_HANDLE_VALUE != This->file)
3257 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3258 if (This->mapping)
3260 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3261 if(This->typelib_base)
3263 /* retrieve file size */
3264 *pdwTLBLength = GetFileSize(This->file, NULL);
3265 *ppBase = This->typelib_base;
3266 *ppFile = &This->IUnknown_iface;
3267 return S_OK;
3272 IUnknown_Release(&This->IUnknown_iface);
3273 return TYPE_E_CANTLOADLIBRARY;
3276 /****************************************************************************
3277 * TLB_ReadTypeLib
3279 * find the type of the typelib file and map the typelib resource into
3280 * the memory
3283 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3284 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3286 ITypeLibImpl *entry;
3287 HRESULT ret;
3288 INT index = 1;
3289 LPWSTR index_str, file = (LPWSTR)pszFileName;
3290 LPVOID pBase = NULL;
3291 DWORD dwTLBLength = 0;
3292 IUnknown *pFile = NULL;
3293 HANDLE h;
3295 *ppTypeLib = NULL;
3297 index_str = wcsrchr(pszFileName, '\\');
3298 if(index_str && *++index_str != '\0')
3300 LPWSTR end_ptr;
3301 LONG idx = wcstol(index_str, &end_ptr, 10);
3302 if(*end_ptr == '\0')
3304 int str_len = index_str - pszFileName - 1;
3305 index = idx;
3306 file = malloc((str_len + 1) * sizeof(WCHAR));
3307 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3308 file[str_len] = 0;
3312 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3314 if(wcschr(file, '\\'))
3316 lstrcpyW(pszPath, file);
3318 else
3320 int len = GetSystemDirectoryW(pszPath, cchPath);
3321 pszPath[len] = '\\';
3322 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3326 if(file != pszFileName) free(file);
3328 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3329 if(h != INVALID_HANDLE_VALUE){
3330 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3331 CloseHandle(h);
3334 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3336 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3337 EnterCriticalSection(&cache_section);
3338 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3340 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3342 TRACE("cache hit\n");
3343 *ppTypeLib = &entry->ITypeLib2_iface;
3344 ITypeLib2_AddRef(*ppTypeLib);
3345 LeaveCriticalSection(&cache_section);
3346 return S_OK;
3349 LeaveCriticalSection(&cache_section);
3351 /* now actually load and parse the typelib */
3353 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3354 if (ret == TYPE_E_CANTLOADLIBRARY)
3355 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3356 if (ret == TYPE_E_CANTLOADLIBRARY)
3357 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3358 if (SUCCEEDED(ret))
3360 if (dwTLBLength >= 4)
3362 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3363 if (dwSignature == MSFT_SIGNATURE)
3364 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3365 else if (dwSignature == SLTG_SIGNATURE)
3366 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3367 else
3369 FIXME("Header type magic %#lx not supported.\n", dwSignature);
3370 ret = TYPE_E_CANTLOADLIBRARY;
3373 else
3374 ret = TYPE_E_CANTLOADLIBRARY;
3375 IUnknown_Release(pFile);
3378 if(*ppTypeLib) {
3379 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3381 TRACE("adding to cache\n");
3382 impl->path = wcsdup(pszPath);
3383 /* We should really canonicalise the path here. */
3384 impl->index = index;
3386 /* FIXME: check if it has added already in the meantime */
3387 EnterCriticalSection(&cache_section);
3388 list_add_head(&tlb_cache, &impl->entry);
3389 LeaveCriticalSection(&cache_section);
3390 ret = S_OK;
3392 else
3394 if(ret != E_FAIL)
3395 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
3397 ret = TYPE_E_CANTLOADLIBRARY;
3401 return ret;
3404 /*================== ITypeLib(2) Methods ===================================*/
3406 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3408 ITypeLibImpl* pTypeLibImpl;
3410 pTypeLibImpl = calloc(1, sizeof(ITypeLibImpl));
3411 if (!pTypeLibImpl) return NULL;
3413 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3414 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3415 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3416 pTypeLibImpl->ref = 1;
3418 list_init(&pTypeLibImpl->implib_list);
3419 list_init(&pTypeLibImpl->custdata_list);
3420 list_init(&pTypeLibImpl->name_list);
3421 list_init(&pTypeLibImpl->string_list);
3422 list_init(&pTypeLibImpl->guid_list);
3423 list_init(&pTypeLibImpl->ref_list);
3424 pTypeLibImpl->dispatch_href = -1;
3426 return pTypeLibImpl;
3429 /****************************************************************************
3430 * ITypeLib2_Constructor_MSFT
3432 * loading an MSFT typelib from an in-memory image
3434 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3436 TLBContext cx;
3437 LONG lPSegDir;
3438 MSFT_Header tlbHeader;
3439 MSFT_SegDir tlbSegDir;
3440 ITypeLibImpl * pTypeLibImpl;
3441 int i;
3443 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3445 pTypeLibImpl = TypeLibImpl_Constructor();
3446 if (!pTypeLibImpl) return NULL;
3448 /* get pointer to beginning of typelib data */
3449 cx.pos = 0;
3450 cx.oStart=0;
3451 cx.mapping = pLib;
3452 cx.pLibInfo = pTypeLibImpl;
3453 cx.length = dwTLBLength;
3455 /* read header */
3456 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3457 TRACE_(typelib)("header:\n");
3458 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3459 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3460 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3461 return NULL;
3463 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3465 /* there is a small amount of information here until the next important
3466 * part:
3467 * the segment directory . Try to calculate the amount of data */
3468 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3470 /* now read the segment directory */
3471 TRACE("read segment directory (at %ld)\n",lPSegDir);
3472 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3473 cx.pTblDir = &tlbSegDir;
3475 /* just check two entries */
3476 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3478 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir);
3479 free(pTypeLibImpl);
3480 return NULL;
3483 MSFT_ReadAllNames(&cx);
3484 MSFT_ReadAllStrings(&cx);
3485 MSFT_ReadAllGuids(&cx);
3487 /* now fill our internal data */
3488 /* TLIBATTR fields */
3489 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3491 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3492 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3493 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3494 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3495 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3497 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3498 pTypeLibImpl->lcid = tlbHeader.lcid;
3500 /* name, eventually add to a hash table */
3501 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3503 /* help info */
3504 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3505 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3507 if( tlbHeader.varflags & HELPDLLFLAG)
3509 int offset;
3510 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3511 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3514 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3516 /* custom data */
3517 if(tlbHeader.CustomDataOffset >= 0)
3519 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3522 /* fill in type descriptions */
3523 if(tlbSegDir.pTypdescTab.length > 0)
3525 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3526 INT16 td[4];
3527 pTypeLibImpl->ctTypeDesc = cTD;
3528 pTypeLibImpl->pTypeDesc = calloc(cTD, sizeof(TYPEDESC));
3529 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3530 for(i=0; i<cTD; )
3532 /* FIXME: add several sanity checks here */
3533 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3534 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3536 /* FIXME: check safearray */
3537 if(td[3] < 0)
3538 pTypeLibImpl->pTypeDesc[i].lptdesc = &std_typedesc[td[2]];
3539 else
3540 pTypeLibImpl->pTypeDesc[i].lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3542 else if(td[0] == VT_CARRAY)
3544 /* array descr table here */
3545 pTypeLibImpl->pTypeDesc[i].lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3547 else if(td[0] == VT_USERDEFINED)
3549 pTypeLibImpl->pTypeDesc[i].hreftype = MAKELONG(td[2],td[3]);
3551 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3554 /* second time around to fill the array subscript info */
3555 for(i=0;i<cTD;i++)
3557 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3558 if(tlbSegDir.pArrayDescriptions.offset>0)
3560 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].lpadesc);
3561 pTypeLibImpl->pTypeDesc[i].lpadesc = calloc(1, sizeof(ARRAYDESC) + sizeof(SAFEARRAYBOUND) * (td[3] - 1));
3563 if(td[1]<0)
3564 pTypeLibImpl->pTypeDesc[i].lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3565 else
3566 pTypeLibImpl->pTypeDesc[i].lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3568 pTypeLibImpl->pTypeDesc[i].lpadesc->cDims = td[2];
3570 for(j = 0; j<td[2]; j++)
3572 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].lpadesc->rgbounds[j].cElements,
3573 sizeof(INT), &cx, DO_NOT_SEEK);
3574 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].lpadesc->rgbounds[j].lLbound,
3575 sizeof(INT), &cx, DO_NOT_SEEK);
3578 else
3580 pTypeLibImpl->pTypeDesc[i].lpadesc = NULL;
3581 ERR("didn't find array description data\n");
3586 /* imported type libs */
3587 if(tlbSegDir.pImpFiles.offset>0)
3589 TLBImpLib *pImpLib;
3590 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3591 UINT16 size;
3593 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3595 char *name;
3597 pImpLib = calloc(1, sizeof(TLBImpLib));
3598 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3599 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3601 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3602 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3603 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3604 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3606 size >>= 2;
3607 name = calloc(1, size + 1);
3608 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3609 pImpLib->name = TLB_MultiByteToBSTR(name);
3610 free(name);
3612 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3613 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3615 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3619 MSFT_ReadAllRefs(&cx);
3621 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3623 /* type infos */
3624 if(tlbHeader.nrtypeinfos >= 0 )
3626 ITypeInfoImpl **ppTI;
3628 ppTI = pTypeLibImpl->typeinfos = calloc(tlbHeader.nrtypeinfos, sizeof(ITypeInfoImpl*));
3630 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3632 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3634 ++ppTI;
3635 (pTypeLibImpl->TypeInfoCount)++;
3639 #ifdef _WIN64
3640 if(pTypeLibImpl->syskind == SYS_WIN32){
3641 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3642 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3644 #endif
3646 TRACE("(%p)\n", pTypeLibImpl);
3647 return &pTypeLibImpl->ITypeLib2_iface;
3651 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3653 char b[3];
3654 int i;
3655 short s;
3657 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3658 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3659 return FALSE;
3662 guid->Data4[0] = s >> 8;
3663 guid->Data4[1] = s & 0xff;
3665 b[2] = '\0';
3666 for(i = 0; i < 6; i++) {
3667 memcpy(b, str + 24 + 2 * i, 2);
3668 guid->Data4[i + 2] = strtol(b, NULL, 16);
3670 return TRUE;
3673 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3675 WORD bytelen;
3676 DWORD len;
3677 BSTR tmp_str;
3679 *pStr = NULL;
3680 bytelen = *(const WORD*)ptr;
3681 if(bytelen == 0xffff) return 2;
3683 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3684 tmp_str = SysAllocStringLen(NULL, len);
3685 if (tmp_str) {
3686 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3687 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3688 SysFreeString(tmp_str);
3690 return bytelen + 2;
3693 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3695 WORD bytelen;
3697 *str = NULL;
3698 bytelen = *(const WORD*)ptr;
3699 if(bytelen == 0xffff) return 2;
3700 *str = malloc(bytelen + 1);
3701 memcpy(*str, ptr + 2, bytelen);
3702 (*str)[bytelen] = '\0';
3703 return bytelen + 2;
3706 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3708 BSTR tmp_str;
3709 TLBString *tlbstr;
3711 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3712 if (tlbstr->offset == offset)
3713 return tlbstr;
3716 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3717 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3718 SysFreeString(tmp_str);
3720 return tlbstr;
3723 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3725 char *ptr = pLibBlk;
3726 WORD w;
3728 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3729 FIXME("libblk magic = %04x\n", w);
3730 return 0;
3733 ptr += 6;
3734 if((w = *(WORD*)ptr) != 0xffff) {
3735 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3736 ptr += w;
3738 ptr += 2;
3740 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3742 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3744 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3745 ptr += 4;
3747 pTypeLibImpl->syskind = *(WORD*)ptr;
3748 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3749 ptr += 2;
3751 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3752 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3753 else
3754 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3755 ptr += 2;
3757 ptr += 4; /* skip res12 */
3759 pTypeLibImpl->libflags = *(WORD*)ptr;
3760 ptr += 2;
3762 pTypeLibImpl->ver_major = *(WORD*)ptr;
3763 ptr += 2;
3765 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3766 ptr += 2;
3768 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3769 ptr += sizeof(GUID);
3771 return ptr - (char*)pLibBlk;
3774 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3775 typedef struct
3777 unsigned int num;
3778 HREFTYPE refs[1];
3779 } sltg_ref_lookup_t;
3781 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3782 HREFTYPE *typelib_ref)
3784 if(table && typeinfo_ref < table->num)
3786 *typelib_ref = table->refs[typeinfo_ref];
3787 return S_OK;
3790 ERR_(typelib)("Unable to find reference\n");
3791 *typelib_ref = -1;
3792 return E_FAIL;
3795 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3797 BOOL done = FALSE;
3799 while(!done) {
3800 if((*pType & 0xe00) == 0xe00) {
3801 pTD->vt = VT_PTR;
3802 pTD->lptdesc = calloc(1, sizeof(TYPEDESC));
3803 pTD = pTD->lptdesc;
3805 switch(*pType & 0x3f) {
3806 case VT_PTR:
3807 pTD->vt = VT_PTR;
3808 pTD->lptdesc = calloc(1, sizeof(TYPEDESC));
3809 pTD = pTD->lptdesc;
3810 break;
3812 case VT_USERDEFINED:
3813 pTD->vt = VT_USERDEFINED;
3814 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->hreftype);
3815 done = TRUE;
3816 break;
3818 case VT_CARRAY:
3820 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3821 array */
3823 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3825 pTD->vt = VT_CARRAY;
3826 pTD->lpadesc = calloc(1, sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3827 pTD->lpadesc->cDims = pSA->cDims;
3828 memcpy(pTD->lpadesc->rgbounds, pSA->rgsabound,
3829 pSA->cDims * sizeof(SAFEARRAYBOUND));
3831 pTD = &pTD->lpadesc->tdescElem;
3832 break;
3835 case VT_SAFEARRAY:
3837 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3838 useful? */
3840 pType++;
3841 pTD->vt = VT_SAFEARRAY;
3842 pTD->lptdesc = calloc(1, sizeof(TYPEDESC));
3843 pTD = pTD->lptdesc;
3844 break;
3846 default:
3847 pTD->vt = *pType & 0x3f;
3848 done = TRUE;
3849 break;
3851 pType++;
3853 return pType;
3856 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3857 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3859 /* Handle [in/out] first */
3860 if((*pType & 0xc000) == 0xc000)
3861 pElem->paramdesc.wParamFlags = PARAMFLAG_NONE;
3862 else if(*pType & 0x8000)
3863 pElem->paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3864 else if(*pType & 0x4000)
3865 pElem->paramdesc.wParamFlags = PARAMFLAG_FOUT;
3866 else
3867 pElem->paramdesc.wParamFlags = PARAMFLAG_FIN;
3869 if(*pType & 0x2000)
3870 pElem->paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3872 if(*pType & 0x80)
3873 pElem->paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3875 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3879 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3880 char *pNameTable)
3882 unsigned int ref;
3883 char *name;
3884 TLBRefType *ref_type;
3885 sltg_ref_lookup_t *table;
3886 HREFTYPE typelib_ref;
3888 if(pRef->magic != SLTG_REF_MAGIC) {
3889 FIXME("Ref magic = %x\n", pRef->magic);
3890 return NULL;
3892 name = ( (char*)pRef->names + pRef->number);
3894 table = malloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3895 table->num = pRef->number >> 3;
3897 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3899 /* We don't want the first href to be 0 */
3900 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3902 for(ref = 0; ref < pRef->number >> 3; ref++) {
3903 char *refname;
3904 unsigned int lib_offs, type_num;
3906 ref_type = calloc(1, sizeof(TLBRefType));
3908 name += SLTG_ReadStringA(name, &refname);
3909 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3910 FIXME_(typelib)("Can't sscanf ref\n");
3911 if(lib_offs != 0xffff) {
3912 TLBImpLib *import;
3914 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3915 if(import->offset == lib_offs)
3916 break;
3918 if(&import->entry == &pTL->implib_list) {
3919 char fname[MAX_PATH+1];
3920 int len;
3921 GUID tmpguid;
3923 import = calloc(1, sizeof(*import));
3924 import->offset = lib_offs;
3925 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3926 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3927 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
3928 &import->wVersionMajor,
3929 &import->wVersionMinor,
3930 &import->lcid, fname) != 4) {
3931 FIXME_(typelib)("can't sscanf ref %s\n",
3932 pNameTable + lib_offs + 40);
3934 len = strlen(fname);
3935 if(fname[len-1] != '#')
3936 FIXME("fname = %s\n", fname);
3937 fname[len-1] = '\0';
3938 import->name = TLB_MultiByteToBSTR(fname);
3939 list_add_tail(&pTL->implib_list, &import->entry);
3941 ref_type->pImpTLInfo = import;
3943 /* Store a reference to IDispatch */
3944 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3945 pTL->dispatch_href = typelib_ref;
3947 } else { /* internal ref */
3948 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3950 ref_type->reference = typelib_ref;
3951 ref_type->index = type_num;
3953 free(refname);
3954 list_add_tail(&pTL->ref_list, &ref_type->entry);
3956 table->refs[ref] = typelib_ref;
3957 typelib_ref += 4;
3959 if((BYTE)*name != SLTG_REF_MAGIC)
3960 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3961 dump_TLBRefType(pTL);
3962 return table;
3965 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3966 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3968 SLTG_ImplInfo *info;
3969 TLBImplType *pImplType;
3970 /* I don't really get this structure, usually it's 0x16 bytes
3971 long, but iuser.tlb contains some that are 0x18 bytes long.
3972 That's ok because we can use the next ptr to jump to the next
3973 one. But how do we know the length of the last one? The WORD
3974 at offs 0x8 might be the clue. For now I'm just assuming that
3975 the last one is the regular 0x16 bytes. */
3977 info = (SLTG_ImplInfo*)pBlk;
3978 while(1){
3979 pTI->typeattr.cImplTypes++;
3980 if(info->next == 0xffff)
3981 break;
3982 info = (SLTG_ImplInfo*)(pBlk + info->next);
3985 info = (SLTG_ImplInfo*)pBlk;
3986 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3987 pImplType = pTI->impltypes;
3988 while(1) {
3989 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3990 pImplType->implflags = info->impltypeflags;
3991 ++pImplType;
3993 if(info->next == 0xffff)
3994 break;
3995 if(OneOnly)
3996 FIXME_(typelib)("Interface inheriting more than one interface\n");
3997 info = (SLTG_ImplInfo*)(pBlk + info->next);
3999 info++; /* see comment at top of function */
4000 return (char*)info;
4003 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4004 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4006 TLBVarDesc *pVarDesc;
4007 const TLBString *prevName = NULL;
4008 SLTG_Variable *pItem;
4009 unsigned short i;
4010 WORD *pType;
4012 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4014 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4015 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4017 pVarDesc->vardesc.memid = pItem->memid;
4019 if (pItem->magic != SLTG_VAR_MAGIC &&
4020 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4021 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4022 return;
4025 if (pItem->name == 0xfffe)
4026 pVarDesc->Name = prevName;
4027 else
4028 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4030 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4031 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4032 TRACE_(typelib)("memid = %#lx\n", pItem->memid);
4034 if(pItem->flags & 0x02)
4035 pType = &pItem->type;
4036 else
4037 pType = (WORD*)(pBlk + pItem->type);
4039 if (pItem->flags & ~0xda)
4040 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4042 SLTG_DoElem(pType, pBlk,
4043 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4045 if (TRACE_ON(typelib)) {
4046 char buf[300];
4047 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4048 TRACE_(typelib)("elemdescVar: %s\n", buf);
4051 if (pItem->flags & 0x40) {
4052 TRACE_(typelib)("VAR_DISPATCH\n");
4053 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4055 else if (pItem->flags & 0x10) {
4056 TRACE_(typelib)("VAR_CONST\n");
4057 pVarDesc->vardesc.varkind = VAR_CONST;
4058 pVarDesc->vardesc.lpvarValue = malloc(sizeof(VARIANT));
4059 V_VT(pVarDesc->vardesc.lpvarValue) = VT_INT;
4060 if (pItem->flags & 0x08)
4061 V_INT(pVarDesc->vardesc.lpvarValue) = pItem->byte_offs;
4062 else {
4063 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4065 case VT_LPSTR:
4066 case VT_LPWSTR:
4067 case VT_BSTR:
4069 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4070 BSTR str;
4071 TRACE_(typelib)("len = %u\n", len);
4072 if (len == 0xffff) {
4073 str = NULL;
4074 } else {
4075 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4076 str = SysAllocStringLen(NULL, alloc_len);
4077 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4079 V_VT(pVarDesc->vardesc.lpvarValue) = VT_BSTR;
4080 V_BSTR(pVarDesc->vardesc.lpvarValue) = str;
4081 break;
4083 case VT_I2:
4084 case VT_UI2:
4085 case VT_I4:
4086 case VT_UI4:
4087 case VT_INT:
4088 case VT_UINT:
4089 V_INT(pVarDesc->vardesc.lpvarValue) =
4090 *(INT*)(pBlk + pItem->byte_offs);
4091 break;
4092 default:
4093 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4097 else {
4098 TRACE_(typelib)("VAR_PERINSTANCE\n");
4099 pVarDesc->vardesc.oInst = pItem->byte_offs;
4100 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4103 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4104 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4106 if (pItem->flags & 0x80)
4107 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4109 prevName = pVarDesc->Name;
4111 pTI->typeattr.cVars = cVars;
4114 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4115 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4117 SLTG_Function *pFunc;
4118 unsigned short i;
4119 TLBFuncDesc *pFuncDesc;
4121 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4123 pFuncDesc = pTI->funcdescs;
4124 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4125 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4127 int param;
4128 WORD *pType, *pArg;
4130 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4131 case SLTG_FUNCTION_MAGIC:
4132 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4133 break;
4134 case SLTG_DISPATCH_FUNCTION_MAGIC:
4135 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4136 break;
4137 case SLTG_STATIC_FUNCTION_MAGIC:
4138 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4139 break;
4140 default:
4141 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4142 continue;
4144 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4146 pFuncDesc->funcdesc.memid = pFunc->dispid;
4147 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4148 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4149 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4150 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4151 if (pFuncDesc->funcdesc.funckind == FUNC_DISPATCH)
4152 pFuncDesc->funcdesc.oVft = 0;
4153 else
4154 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4156 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4157 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4159 if(pFunc->retnextopt & 0x80)
4160 pType = &pFunc->rettype;
4161 else
4162 pType = (WORD*)(pBlk + pFunc->rettype);
4164 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4166 pFuncDesc->funcdesc.lprgelemdescParam =
4167 calloc(pFuncDesc->funcdesc.cParams, sizeof(ELEMDESC));
4168 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4170 pArg = (WORD*)(pBlk + pFunc->arg_off);
4172 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4173 char *paramName = pNameTable + *pArg;
4174 BOOL HaveOffs;
4175 /* If arg type follows then paramName points to the 2nd
4176 letter of the name, else the next WORD is an offset to
4177 the arg type and paramName points to the first letter.
4178 So let's take one char off paramName and see if we're
4179 pointing at an alphanumeric char. However if *pArg is
4180 0xffff or 0xfffe then the param has no name, the former
4181 meaning that the next WORD is the type, the latter
4182 meaning that the next WORD is an offset to the type. */
4184 HaveOffs = FALSE;
4185 if(*pArg == 0xffff)
4186 paramName = NULL;
4187 else if(*pArg == 0xfffe) {
4188 paramName = NULL;
4189 HaveOffs = TRUE;
4191 else if(paramName[-1] && !isalnum(paramName[-1]))
4192 HaveOffs = TRUE;
4194 pArg++;
4196 if(HaveOffs) { /* the next word is an offset to type */
4197 pType = (WORD*)(pBlk + *pArg);
4198 SLTG_DoElem(pType, pBlk,
4199 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4200 pArg++;
4201 } else {
4202 if(paramName)
4203 paramName--;
4204 pArg = SLTG_DoElem(pArg, pBlk,
4205 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4208 /* Are we an optional param ? */
4209 if(pFuncDesc->funcdesc.cParams - param <=
4210 pFuncDesc->funcdesc.cParamsOpt)
4211 pFuncDesc->funcdesc.lprgelemdescParam[param].paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4213 if(paramName) {
4214 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4215 paramName - pNameTable, pTI->pTypeLib);
4216 } else {
4217 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4221 pTI->typeattr.cFuncs = cFuncs;
4224 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4225 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4226 SLTG_TypeInfoTail *pTITail)
4228 char *pFirstItem;
4229 sltg_ref_lookup_t *ref_lookup = NULL;
4231 if(pTIHeader->href_table != 0xffffffff) {
4232 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4233 pNameTable);
4236 pFirstItem = pBlk;
4238 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4239 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4241 free(ref_lookup);
4245 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4246 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4247 const SLTG_TypeInfoTail *pTITail)
4249 char *pFirstItem;
4250 sltg_ref_lookup_t *ref_lookup = NULL;
4252 if(pTIHeader->href_table != 0xffffffff) {
4253 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4254 pNameTable);
4257 pFirstItem = pBlk;
4259 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4260 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4263 if (pTITail->funcs_off != 0xffff)
4264 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4266 free(ref_lookup);
4268 if (TRACE_ON(typelib))
4269 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4272 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4273 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4274 const SLTG_TypeInfoTail *pTITail)
4276 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4279 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4280 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4281 const SLTG_TypeInfoTail *pTITail)
4283 WORD *pType;
4284 sltg_ref_lookup_t *ref_lookup = NULL;
4286 if (pTITail->simple_alias) {
4287 /* if simple alias, no more processing required */
4288 pTI->tdescAlias = calloc(1, sizeof(TYPEDESC));
4289 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4290 return;
4293 if(pTIHeader->href_table != 0xffffffff) {
4294 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4295 pNameTable);
4298 /* otherwise it is an offset to a type */
4299 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4301 pTI->tdescAlias = malloc(sizeof(TYPEDESC));
4302 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4304 free(ref_lookup);
4307 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4308 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4309 const SLTG_TypeInfoTail *pTITail)
4311 sltg_ref_lookup_t *ref_lookup = NULL;
4312 if (pTIHeader->href_table != 0xffffffff)
4313 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4314 pNameTable);
4316 if (pTITail->vars_off != 0xffff)
4317 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4319 if (pTITail->funcs_off != 0xffff)
4320 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4322 if (pTITail->impls_off != 0xffff)
4323 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4325 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4326 * of dispinterface functions including the IDispatch ones, so
4327 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4328 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4330 free(ref_lookup);
4331 if (TRACE_ON(typelib))
4332 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4335 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4336 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4337 const SLTG_TypeInfoTail *pTITail)
4339 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4342 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4343 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4344 const SLTG_TypeInfoTail *pTITail)
4346 sltg_ref_lookup_t *ref_lookup = NULL;
4347 if (pTIHeader->href_table != 0xffffffff)
4348 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4349 pNameTable);
4351 if (pTITail->vars_off != 0xffff)
4352 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4354 if (pTITail->funcs_off != 0xffff)
4355 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4356 free(ref_lookup);
4357 if (TRACE_ON(typelib))
4358 dump_TypeInfo(pTI);
4361 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4362 manageable copy of it into this */
4363 typedef struct {
4364 WORD small_no;
4365 char *index_name;
4366 char *other_name;
4367 WORD res1a;
4368 WORD name_offs;
4369 WORD more_bytes;
4370 char *extra;
4371 WORD res20;
4372 DWORD helpcontext;
4373 WORD res26;
4374 GUID uuid;
4375 } SLTG_InternalOtherTypeInfo;
4377 /****************************************************************************
4378 * ITypeLib2_Constructor_SLTG
4380 * loading a SLTG typelib from an in-memory image
4382 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4384 ITypeLibImpl *pTypeLibImpl;
4385 SLTG_Header *pHeader;
4386 SLTG_BlkEntry *pBlkEntry;
4387 SLTG_Magic *pMagic;
4388 SLTG_Index *pIndex;
4389 SLTG_Pad9 *pPad9;
4390 LPVOID pBlk, pFirstBlk;
4391 SLTG_LibBlk *pLibBlk;
4392 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4393 char *pAfterOTIBlks = NULL;
4394 char *pNameTable, *ptr;
4395 int i;
4396 DWORD len, order;
4397 ITypeInfoImpl **ppTypeInfoImpl;
4399 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
4402 pTypeLibImpl = TypeLibImpl_Constructor();
4403 if (!pTypeLibImpl) return NULL;
4405 pHeader = pLib;
4407 TRACE_(typelib)("header:\n");
4408 TRACE_(typelib)("\tmagic %#lx, file blocks = %d\n", pHeader->SLTG_magic,
4409 pHeader->nrOfFileBlks );
4410 if (pHeader->SLTG_magic != SLTG_SIGNATURE)
4412 FIXME_(typelib)("Header type magic %#lx not supported.\n", pHeader->SLTG_magic);
4413 return NULL;
4416 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4417 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4419 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4420 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4422 /* Next we have a magic block */
4423 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4425 /* Let's see if we're still in sync */
4426 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4427 sizeof(SLTG_COMPOBJ_MAGIC))) {
4428 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4429 return NULL;
4431 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4432 sizeof(SLTG_DIR_MAGIC))) {
4433 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4434 return NULL;
4437 pIndex = (SLTG_Index*)(pMagic+1);
4439 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4441 pFirstBlk = pPad9 + 1;
4443 /* We'll set up a ptr to the main library block, which is the last one. */
4445 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4446 pBlkEntry[order].next != 0;
4447 order = pBlkEntry[order].next - 1) {
4448 pBlk = (char*)pBlk + pBlkEntry[order].len;
4450 pLibBlk = pBlk;
4452 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4454 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4455 interspersed */
4457 len += 0x40;
4459 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4461 pOtherTypeInfoBlks = calloc(pTypeLibImpl->TypeInfoCount, sizeof(*pOtherTypeInfoBlks));
4464 ptr = (char*)pLibBlk + len;
4466 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4467 WORD w, extra;
4468 len = 0;
4470 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4472 w = *(WORD*)(ptr + 2);
4473 if(w != 0xffff) {
4474 len += w;
4475 pOtherTypeInfoBlks[i].index_name = malloc(w + 1);
4476 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4477 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4479 w = *(WORD*)(ptr + 4 + len);
4480 if(w != 0xffff) {
4481 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4482 len += w;
4483 pOtherTypeInfoBlks[i].other_name = malloc(w + 1);
4484 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4485 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4487 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4488 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4489 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4490 if(extra) {
4491 pOtherTypeInfoBlks[i].extra = malloc(extra);
4492 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4493 len += extra;
4495 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4496 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4497 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4498 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4499 len += sizeof(SLTG_OtherTypeInfo);
4500 ptr += len;
4503 pAfterOTIBlks = ptr;
4505 /* Skip this WORD and get the next DWORD */
4506 len = *(DWORD*)(pAfterOTIBlks + 2);
4508 /* Now add this to pLibBLk look at what we're pointing at and
4509 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4510 dust and we should be pointing at the beginning of the name
4511 table */
4513 pNameTable = (char*)pLibBlk + len;
4515 switch(*(WORD*)pNameTable) {
4516 case 0xffff:
4517 break;
4518 case 0x0200:
4519 pNameTable += 0x20;
4520 break;
4521 default:
4522 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4523 break;
4526 pNameTable += 0x216;
4528 pNameTable += 2;
4530 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4532 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4535 /* Hopefully we now have enough ptrs set up to actually read in
4536 some TypeInfos. It's not clear which order to do them in, so
4537 I'll just follow the links along the BlkEntry chain and read
4538 them in the order in which they are in the file */
4540 pTypeLibImpl->typeinfos = calloc(pTypeLibImpl->TypeInfoCount, sizeof(ITypeInfoImpl*));
4541 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4543 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4544 pBlkEntry[order].next != 0;
4545 order = pBlkEntry[order].next - 1, i++) {
4547 SLTG_TypeInfoHeader *pTIHeader;
4548 SLTG_TypeInfoTail *pTITail;
4549 SLTG_MemberHeader *pMemHeader;
4551 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4552 FIXME_(typelib)("Index strings don't match\n");
4553 free(pOtherTypeInfoBlks);
4554 return NULL;
4557 pTIHeader = pBlk;
4558 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4559 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4560 free(pOtherTypeInfoBlks);
4561 return NULL;
4563 TRACE_(typelib)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4564 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4565 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4567 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4568 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4569 (*ppTypeInfoImpl)->index = i;
4570 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4571 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4572 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4573 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4574 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4575 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4576 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4577 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4579 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4580 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4582 if((pTIHeader->typeflags1 & 7) != 2)
4583 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4584 if(pTIHeader->typeflags3 != 2)
4585 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4587 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4588 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4589 typekind_desc[pTIHeader->typekind],
4590 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4591 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4593 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4595 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4597 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4598 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4599 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4601 switch(pTIHeader->typekind) {
4602 case TKIND_ENUM:
4603 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4604 pTIHeader, pTITail);
4605 break;
4607 case TKIND_RECORD:
4608 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4609 pTIHeader, pTITail);
4610 break;
4612 case TKIND_INTERFACE:
4613 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4614 pTIHeader, pTITail);
4615 break;
4617 case TKIND_COCLASS:
4618 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4619 pTIHeader, pTITail);
4620 break;
4622 case TKIND_ALIAS:
4623 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4624 pTIHeader, pTITail);
4625 break;
4627 case TKIND_DISPATCH:
4628 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4629 pTIHeader, pTITail);
4630 break;
4632 case TKIND_MODULE:
4633 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4634 pTIHeader, pTITail);
4635 break;
4637 default:
4638 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4639 break;
4643 /* could get cFuncs, cVars and cImplTypes from here
4644 but we've already set those */
4645 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4646 X(06);
4647 X(16);
4648 X(18);
4649 X(1a);
4650 X(1e);
4651 X(24);
4652 X(26);
4653 X(2a);
4654 X(2c);
4655 X(2e);
4656 X(30);
4657 X(32);
4658 X(34);
4659 #undef X
4660 ++ppTypeInfoImpl;
4661 pBlk = (char*)pBlk + pBlkEntry[order].len;
4664 if(i != pTypeLibImpl->TypeInfoCount) {
4665 FIXME("Somehow processed %d TypeInfos\n", i);
4666 free(pOtherTypeInfoBlks);
4667 return NULL;
4670 free(pOtherTypeInfoBlks);
4671 return &pTypeLibImpl->ITypeLib2_iface;
4674 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4676 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4678 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4680 if(IsEqualIID(riid, &IID_IUnknown) ||
4681 IsEqualIID(riid,&IID_ITypeLib)||
4682 IsEqualIID(riid,&IID_ITypeLib2))
4684 *ppv = &This->ITypeLib2_iface;
4686 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4687 IsEqualIID(riid, &IID_ICreateTypeLib2))
4689 *ppv = &This->ICreateTypeLib2_iface;
4691 else
4693 *ppv = NULL;
4694 TRACE("-- Interface: E_NOINTERFACE\n");
4695 return E_NOINTERFACE;
4698 IUnknown_AddRef((IUnknown*)*ppv);
4699 return S_OK;
4702 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4704 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4705 ULONG ref = InterlockedIncrement(&This->ref);
4707 TRACE("%p, refcount %lu.\n", iface, ref);
4709 return ref;
4712 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4714 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4715 ULONG ref = InterlockedDecrement(&This->ref);
4717 TRACE("%p, refcount %lu.\n", iface, ref);
4719 if (!ref)
4721 TLBImpLib *pImpLib, *pImpLibNext;
4722 TLBRefType *ref_type, *ref_type_next;
4723 TLBString *tlbstr, *tlbstr_next;
4724 TLBGuid *tlbguid, *tlbguid_next;
4725 int i;
4727 /* remove cache entry */
4728 if(This->path)
4730 TRACE("removing from cache list\n");
4731 EnterCriticalSection(&cache_section);
4732 if(This->entry.next)
4733 list_remove(&This->entry);
4734 LeaveCriticalSection(&cache_section);
4735 free(This->path);
4737 TRACE(" destroying ITypeLib(%p)\n",This);
4739 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4740 list_remove(&tlbstr->entry);
4741 SysFreeString(tlbstr->str);
4742 free(tlbstr);
4745 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4746 list_remove(&tlbstr->entry);
4747 SysFreeString(tlbstr->str);
4748 free(tlbstr);
4751 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4752 list_remove(&tlbguid->entry);
4753 free(tlbguid);
4756 TLB_FreeCustData(&This->custdata_list);
4758 for (i = 0; i < This->ctTypeDesc; i++)
4759 if (This->pTypeDesc[i].vt == VT_CARRAY)
4760 free(This->pTypeDesc[i].lpadesc);
4762 free(This->pTypeDesc);
4764 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4766 if (pImpLib->pImpTypeLib)
4767 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4768 SysFreeString(pImpLib->name);
4770 list_remove(&pImpLib->entry);
4771 free(pImpLib);
4774 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4776 list_remove(&ref_type->entry);
4777 free(ref_type);
4780 for (i = 0; i < This->TypeInfoCount; ++i){
4781 free(This->typeinfos[i]->tdescAlias);
4782 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4784 free(This->typeinfos);
4785 free(This);
4786 return 0;
4789 return ref;
4792 /* ITypeLib::GetTypeInfoCount
4794 * Returns the number of type descriptions in the type library
4796 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4798 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4799 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4800 return This->TypeInfoCount;
4803 /* ITypeLib::GetTypeInfo
4805 * retrieves the specified type description in the library.
4807 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4808 ITypeLib2 *iface,
4809 UINT index,
4810 ITypeInfo **ppTInfo)
4812 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4814 TRACE("%p %u %p\n", This, index, ppTInfo);
4816 if(!ppTInfo)
4817 return E_INVALIDARG;
4819 if(index >= This->TypeInfoCount)
4820 return TYPE_E_ELEMENTNOTFOUND;
4822 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4823 ITypeInfo_AddRef(*ppTInfo);
4825 return S_OK;
4829 /* ITypeLibs::GetTypeInfoType
4831 * Retrieves the type of a type description.
4833 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4834 ITypeLib2 *iface,
4835 UINT index,
4836 TYPEKIND *pTKind)
4838 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4840 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4842 if(!pTKind)
4843 return E_INVALIDARG;
4845 if(index >= This->TypeInfoCount)
4846 return TYPE_E_ELEMENTNOTFOUND;
4848 *pTKind = This->typeinfos[index]->typeattr.typekind;
4850 return S_OK;
4853 /* ITypeLib::GetTypeInfoOfGuid
4855 * Retrieves the type description that corresponds to the specified GUID.
4858 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4859 ITypeLib2 *iface,
4860 REFGUID guid,
4861 ITypeInfo **ppTInfo)
4863 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4864 int i;
4866 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4868 for(i = 0; i < This->TypeInfoCount; ++i){
4869 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4870 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4871 ITypeInfo_AddRef(*ppTInfo);
4872 return S_OK;
4876 return TYPE_E_ELEMENTNOTFOUND;
4879 /* ITypeLib::GetLibAttr
4881 * Retrieves the structure that contains the library's attributes.
4884 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4885 ITypeLib2 *iface,
4886 LPTLIBATTR *attr)
4888 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4890 TRACE("(%p, %p)\n", This, attr);
4892 if (!attr) return E_INVALIDARG;
4894 *attr = malloc(sizeof(**attr));
4895 if (!*attr) return E_OUTOFMEMORY;
4897 (*attr)->guid = *TLB_get_guid_null(This->guid);
4898 (*attr)->lcid = This->set_lcid;
4899 (*attr)->syskind = This->syskind;
4900 (*attr)->wMajorVerNum = This->ver_major;
4901 (*attr)->wMinorVerNum = This->ver_minor;
4902 (*attr)->wLibFlags = This->libflags;
4904 return S_OK;
4907 /* ITypeLib::GetTypeComp
4909 * Enables a client compiler to bind to a library's types, variables,
4910 * constants, and global functions.
4913 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4914 ITypeLib2 *iface,
4915 ITypeComp **ppTComp)
4917 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4919 TRACE("(%p)->(%p)\n",This,ppTComp);
4920 *ppTComp = &This->ITypeComp_iface;
4921 ITypeComp_AddRef(*ppTComp);
4923 return S_OK;
4926 /* ITypeLib::GetDocumentation
4928 * Retrieves the library's documentation string, the complete Help file name
4929 * and path, and the context identifier for the library Help topic in the Help
4930 * file.
4932 * On a successful return all non-null BSTR pointers will have been set,
4933 * possibly to NULL.
4935 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4936 ITypeLib2 *iface,
4937 INT index,
4938 BSTR *pBstrName,
4939 BSTR *pBstrDocString,
4940 DWORD *pdwHelpContext,
4941 BSTR *pBstrHelpFile)
4943 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4944 HRESULT result = E_INVALIDARG;
4945 ITypeInfo *pTInfo;
4947 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4948 This, index,
4949 pBstrName, pBstrDocString,
4950 pdwHelpContext, pBstrHelpFile);
4952 if(index<0)
4954 /* documentation for the typelib */
4955 if(pBstrName)
4957 if (This->Name)
4959 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4960 goto memerr1;
4962 else
4963 *pBstrName = NULL;
4965 if(pBstrDocString)
4967 if (This->DocString)
4969 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4970 goto memerr2;
4972 else
4973 *pBstrDocString = NULL;
4975 if(pdwHelpContext)
4977 *pdwHelpContext = This->dwHelpContext;
4979 if(pBstrHelpFile)
4981 if (This->HelpFile)
4983 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4984 goto memerr3;
4986 else
4987 *pBstrHelpFile = NULL;
4990 result = S_OK;
4992 else
4994 /* for a typeinfo */
4995 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4997 if(SUCCEEDED(result))
4999 result = ITypeInfo_GetDocumentation(pTInfo,
5000 MEMBERID_NIL,
5001 pBstrName,
5002 pBstrDocString,
5003 pdwHelpContext, pBstrHelpFile);
5005 ITypeInfo_Release(pTInfo);
5008 return result;
5009 memerr3:
5010 if (pBstrDocString) SysFreeString (*pBstrDocString);
5011 memerr2:
5012 if (pBstrName) SysFreeString (*pBstrName);
5013 memerr1:
5014 return STG_E_INSUFFICIENTMEMORY;
5017 /* ITypeLib::IsName
5019 * Indicates whether a passed-in string contains the name of a type or member
5020 * described in the library.
5023 static HRESULT WINAPI ITypeLib2_fnIsName(
5024 ITypeLib2 *iface,
5025 LPOLESTR szNameBuf,
5026 ULONG lHashVal,
5027 BOOL *pfName)
5029 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5030 int tic;
5031 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5033 TRACE("%p, %s, %#lx, %p.\n", iface, debugstr_w(szNameBuf), lHashVal, pfName);
5035 *pfName=TRUE;
5036 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5037 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5038 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5039 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5040 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5041 int pc;
5042 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5043 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5044 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5045 goto ITypeLib2_fnIsName_exit;
5048 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5049 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5050 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5054 *pfName=FALSE;
5056 ITypeLib2_fnIsName_exit:
5057 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5058 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5060 return S_OK;
5063 /* ITypeLib::FindName
5065 * Finds occurrences of a type description in a type library. This may be used
5066 * to quickly verify that a name exists in a type library.
5069 static HRESULT WINAPI ITypeLib2_fnFindName(
5070 ITypeLib2 *iface,
5071 LPOLESTR name,
5072 ULONG hash,
5073 ITypeInfo **ppTInfo,
5074 MEMBERID *memid,
5075 UINT16 *found)
5077 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5078 int tic;
5079 UINT count = 0;
5080 UINT len;
5082 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface, debugstr_w(name), hash, ppTInfo, memid, found);
5084 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5085 return E_INVALIDARG;
5087 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5088 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5089 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5090 TLBVarDesc *var;
5091 UINT fdc;
5093 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5094 memid[count] = MEMBERID_NIL;
5095 goto ITypeLib2_fnFindName_exit;
5098 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5099 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5101 if(!TLB_str_memcmp(name, func->Name, len)) {
5102 memid[count] = func->funcdesc.memid;
5103 goto ITypeLib2_fnFindName_exit;
5107 var = TLB_get_vardesc_by_name(pTInfo, name);
5108 if (var) {
5109 memid[count] = var->vardesc.memid;
5110 goto ITypeLib2_fnFindName_exit;
5113 continue;
5114 ITypeLib2_fnFindName_exit:
5115 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5116 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5117 count++;
5119 TRACE("found %d typeinfos\n", count);
5121 *found = count;
5123 return S_OK;
5126 /* ITypeLib::ReleaseTLibAttr
5128 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5131 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5132 ITypeLib2 *iface,
5133 TLIBATTR *pTLibAttr)
5135 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5136 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5137 free(pTLibAttr);
5140 /* ITypeLib2::GetCustData
5142 * gets the custom data
5144 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5145 ITypeLib2 * iface,
5146 REFGUID guid,
5147 VARIANT *pVarVal)
5149 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5150 TLBCustData *pCData;
5152 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5154 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5155 if(!pCData)
5156 return TYPE_E_ELEMENTNOTFOUND;
5158 VariantInit(pVarVal);
5159 VariantCopy(pVarVal, &pCData->data);
5161 return S_OK;
5164 /* ITypeLib2::GetLibStatistics
5166 * Returns statistics about a type library that are required for efficient
5167 * sizing of hash tables.
5170 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5171 ITypeLib2 * iface,
5172 ULONG *pcUniqueNames,
5173 ULONG *pcchUniqueNames)
5175 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5177 FIXME("(%p): stub!\n", This);
5179 if(pcUniqueNames) *pcUniqueNames=1;
5180 if(pcchUniqueNames) *pcchUniqueNames=1;
5181 return S_OK;
5184 /* ITypeLib2::GetDocumentation2
5186 * Retrieves the library's documentation string, the complete Help file name
5187 * and path, the localization context to use, and the context ID for the
5188 * library Help topic in the Help file.
5191 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5192 ITypeLib2 * iface,
5193 INT index,
5194 LCID lcid,
5195 BSTR *pbstrHelpString,
5196 DWORD *pdwHelpStringContext,
5197 BSTR *pbstrHelpStringDll)
5199 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5200 HRESULT result;
5201 ITypeInfo *pTInfo;
5203 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface, index, lcid);
5205 /* the help string should be obtained from the helpstringdll,
5206 * using the _DLLGetDocumentation function, based on the supplied
5207 * lcid. Nice to do sometime...
5209 if(index<0)
5211 /* documentation for the typelib */
5212 if(pbstrHelpString)
5213 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5214 if(pdwHelpStringContext)
5215 *pdwHelpStringContext=This->dwHelpContext;
5216 if(pbstrHelpStringDll)
5217 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5219 result = S_OK;
5221 else
5223 /* for a typeinfo */
5224 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5226 if(SUCCEEDED(result))
5228 ITypeInfo2 * pTInfo2;
5229 result = ITypeInfo_QueryInterface(pTInfo,
5230 &IID_ITypeInfo2,
5231 (LPVOID*) &pTInfo2);
5233 if(SUCCEEDED(result))
5235 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5236 MEMBERID_NIL,
5237 lcid,
5238 pbstrHelpString,
5239 pdwHelpStringContext,
5240 pbstrHelpStringDll);
5242 ITypeInfo2_Release(pTInfo2);
5245 ITypeInfo_Release(pTInfo);
5248 return result;
5251 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5253 TLBCustData *pCData;
5254 unsigned int ct;
5255 CUSTDATAITEM *cdi;
5256 HRESULT hr = S_OK;
5258 ct = list_count(custdata_list);
5260 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5261 if(!pCustData->prgCustData)
5262 return E_OUTOFMEMORY;
5264 pCustData->cCustData = ct;
5266 cdi = pCustData->prgCustData;
5267 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5268 cdi->guid = *TLB_get_guid_null(pCData->guid);
5269 VariantInit(&cdi->varValue);
5270 hr = VariantCopy(&cdi->varValue, &pCData->data);
5271 if(FAILED(hr)) break;
5272 ++cdi;
5275 return hr;
5279 /* ITypeLib2::GetAllCustData
5281 * Gets all custom data items for the library.
5284 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5285 ITypeLib2 * iface,
5286 CUSTDATA *pCustData)
5288 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5289 TRACE("(%p)->(%p)\n", This, pCustData);
5290 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5293 static const ITypeLib2Vtbl tlbvt = {
5294 ITypeLib2_fnQueryInterface,
5295 ITypeLib2_fnAddRef,
5296 ITypeLib2_fnRelease,
5297 ITypeLib2_fnGetTypeInfoCount,
5298 ITypeLib2_fnGetTypeInfo,
5299 ITypeLib2_fnGetTypeInfoType,
5300 ITypeLib2_fnGetTypeInfoOfGuid,
5301 ITypeLib2_fnGetLibAttr,
5302 ITypeLib2_fnGetTypeComp,
5303 ITypeLib2_fnGetDocumentation,
5304 ITypeLib2_fnIsName,
5305 ITypeLib2_fnFindName,
5306 ITypeLib2_fnReleaseTLibAttr,
5308 ITypeLib2_fnGetCustData,
5309 ITypeLib2_fnGetLibStatistics,
5310 ITypeLib2_fnGetDocumentation2,
5311 ITypeLib2_fnGetAllCustData
5315 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5317 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5319 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5322 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5324 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5326 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5329 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5331 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5333 return ITypeLib2_Release(&This->ITypeLib2_iface);
5336 static HRESULT WINAPI ITypeLibComp_fnBind(
5337 ITypeComp * iface,
5338 OLECHAR * szName,
5339 ULONG lHash,
5340 WORD wFlags,
5341 ITypeInfo ** ppTInfo,
5342 DESCKIND * pDescKind,
5343 BINDPTR * pBindPtr)
5345 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5346 BOOL typemismatch = FALSE;
5347 int i;
5349 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5351 *pDescKind = DESCKIND_NONE;
5352 pBindPtr->lptcomp = NULL;
5353 *ppTInfo = NULL;
5355 for(i = 0; i < This->TypeInfoCount; ++i){
5356 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5357 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5359 /* FIXME: check wFlags here? */
5360 /* FIXME: we should use a hash table to look this info up using lHash
5361 * instead of an O(n) search */
5362 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5363 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5365 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5367 *pDescKind = DESCKIND_TYPECOMP;
5368 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5369 ITypeComp_AddRef(pBindPtr->lptcomp);
5370 TRACE("module or enum: %s\n", debugstr_w(szName));
5371 return S_OK;
5375 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5376 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5378 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5379 HRESULT hr;
5381 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5382 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5384 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5385 return S_OK;
5387 else if (hr == TYPE_E_TYPEMISMATCH)
5388 typemismatch = TRUE;
5391 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5392 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5394 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5395 HRESULT hr;
5396 ITypeInfo *subtypeinfo;
5397 BINDPTR subbindptr;
5398 DESCKIND subdesckind;
5400 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5401 &subtypeinfo, &subdesckind, &subbindptr);
5402 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5404 TYPEDESC tdesc_appobject;
5405 const VARDESC vardesc_appobject =
5407 -2, /* memid */
5408 NULL, /* lpstrSchema */
5410 0 /* oInst */
5413 /* ELEMDESC */
5415 /* TYPEDESC */
5417 &tdesc_appobject
5419 VT_PTR
5422 0, /* wVarFlags */
5423 VAR_STATIC /* varkind */
5426 tdesc_appobject.hreftype = pTypeInfo->hreftype;
5427 tdesc_appobject.vt = VT_USERDEFINED;
5429 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5431 /* cleanup things filled in by Bind call so we can put our
5432 * application object data in there instead */
5433 switch (subdesckind)
5435 case DESCKIND_FUNCDESC:
5436 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5437 break;
5438 case DESCKIND_VARDESC:
5439 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5440 break;
5441 default:
5442 break;
5444 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5446 if (pTypeInfo->hreftype == -1)
5447 FIXME("no hreftype for interface %p\n", pTypeInfo);
5449 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5450 if (FAILED(hr))
5451 return hr;
5453 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5454 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5455 ITypeInfo_AddRef(*ppTInfo);
5456 return S_OK;
5458 else if (hr == TYPE_E_TYPEMISMATCH)
5459 typemismatch = TRUE;
5463 if (typemismatch)
5465 TRACE("type mismatch %s\n", debugstr_w(szName));
5466 return TYPE_E_TYPEMISMATCH;
5468 else
5470 TRACE("name not found %s\n", debugstr_w(szName));
5471 return S_OK;
5475 static HRESULT WINAPI ITypeLibComp_fnBindType(
5476 ITypeComp * iface,
5477 OLECHAR * szName,
5478 ULONG lHash,
5479 ITypeInfo ** ppTInfo,
5480 ITypeComp ** ppTComp)
5482 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5483 ITypeInfoImpl *info;
5485 TRACE("%p, %s, %#lx, %p, %p.\n", iface, debugstr_w(szName), lHash, ppTInfo, ppTComp);
5487 if(!szName || !ppTInfo || !ppTComp)
5488 return E_INVALIDARG;
5490 info = TLB_get_typeinfo_by_name(This, szName);
5491 if(!info){
5492 *ppTInfo = NULL;
5493 *ppTComp = NULL;
5494 return S_OK;
5497 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5498 ITypeInfo_AddRef(*ppTInfo);
5499 *ppTComp = &info->ITypeComp_iface;
5500 ITypeComp_AddRef(*ppTComp);
5502 return S_OK;
5505 static const ITypeCompVtbl tlbtcvt =
5508 ITypeLibComp_fnQueryInterface,
5509 ITypeLibComp_fnAddRef,
5510 ITypeLibComp_fnRelease,
5512 ITypeLibComp_fnBind,
5513 ITypeLibComp_fnBindType
5516 /*================== ITypeInfo(2) Methods ===================================*/
5517 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5519 ITypeInfoImpl *pTypeInfoImpl;
5521 pTypeInfoImpl = calloc(1, sizeof(ITypeInfoImpl));
5522 if (pTypeInfoImpl)
5524 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5525 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5526 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5527 pTypeInfoImpl->ref = 0;
5528 pTypeInfoImpl->hreftype = -1;
5529 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5530 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5531 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5532 list_init(pTypeInfoImpl->pcustdata_list);
5534 TRACE("(%p)\n", pTypeInfoImpl);
5535 return pTypeInfoImpl;
5538 /* ITypeInfo::QueryInterface
5540 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5541 ITypeInfo2 *iface,
5542 REFIID riid,
5543 VOID **ppvObject)
5545 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5547 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5549 *ppvObject=NULL;
5550 if(IsEqualIID(riid, &IID_IUnknown) ||
5551 IsEqualIID(riid,&IID_ITypeInfo)||
5552 IsEqualIID(riid,&IID_ITypeInfo2))
5553 *ppvObject = &This->ITypeInfo2_iface;
5554 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5555 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5556 *ppvObject = &This->ICreateTypeInfo2_iface;
5557 else if(IsEqualIID(riid, &IID_ITypeComp))
5558 *ppvObject = &This->ITypeComp_iface;
5560 if(*ppvObject){
5561 IUnknown_AddRef((IUnknown*)*ppvObject);
5562 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5563 return S_OK;
5565 TRACE("-- Interface: E_NOINTERFACE\n");
5566 return E_NOINTERFACE;
5569 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5571 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5572 ULONG ref = InterlockedIncrement(&This->ref);
5574 TRACE("%p, refcount %lu.\n", iface, ref);
5576 if (ref == 1 /* incremented from 0 */)
5577 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5579 return ref;
5582 static void typeinfo_release_funcdesc(TLBFuncDesc *func)
5584 unsigned int i;
5586 for (i = 0; i < func->funcdesc.cParams; ++i)
5588 ELEMDESC *elemdesc = &func->funcdesc.lprgelemdescParam[i];
5589 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5590 VariantClear(&elemdesc->paramdesc.pparamdescex->varDefaultValue);
5591 TLB_FreeCustData(&func->pParamDesc[i].custdata_list);
5593 free(func->funcdesc.lprgelemdescParam);
5594 free(func->pParamDesc);
5595 TLB_FreeCustData(&func->custdata_list);
5598 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5600 UINT i;
5602 TRACE("destroying ITypeInfo(%p)\n",This);
5604 for (i = 0; i < This->typeattr.cFuncs; ++i)
5606 typeinfo_release_funcdesc(&This->funcdescs[i]);
5608 free(This->funcdescs);
5610 for(i = 0; i < This->typeattr.cVars; ++i)
5612 TLBVarDesc *pVInfo = &This->vardescs[i];
5613 if (pVInfo->vardesc_create) {
5614 TLB_FreeVarDesc(pVInfo->vardesc_create);
5615 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5616 VariantClear(pVInfo->vardesc.lpvarValue);
5617 free(pVInfo->vardesc.lpvarValue);
5619 TLB_FreeCustData(&pVInfo->custdata_list);
5621 free(This->vardescs);
5623 if(This->impltypes){
5624 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5625 TLBImplType *pImpl = &This->impltypes[i];
5626 TLB_FreeCustData(&pImpl->custdata_list);
5628 free(This->impltypes);
5631 TLB_FreeCustData(&This->custdata_list);
5633 free(This);
5636 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5638 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5639 ULONG ref = InterlockedDecrement(&This->ref);
5641 TRACE("%p, refcount %lu.\n", iface, ref);
5643 if (!ref)
5645 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5646 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5647 if (not_attached_to_typelib)
5648 free(This);
5649 /* otherwise This will be freed when typelib is freed */
5652 return ref;
5655 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5656 LPTYPEATTR *ppTypeAttr)
5658 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5659 SIZE_T size;
5661 TRACE("(%p)\n",This);
5663 size = sizeof(**ppTypeAttr);
5664 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5665 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5667 *ppTypeAttr = malloc(size);
5668 if (!*ppTypeAttr)
5669 return E_OUTOFMEMORY;
5671 **ppTypeAttr = This->typeattr;
5672 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5674 if (This->tdescAlias)
5675 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5677 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5678 /* This should include all the inherited funcs */
5679 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5680 /* This is always the size of IDispatch's vtbl */
5681 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5682 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5684 return S_OK;
5687 /* ITypeInfo::GetTypeComp
5689 * Retrieves the ITypeComp interface for the type description, which enables a
5690 * client compiler to bind to the type description's members.
5693 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5694 ITypeComp * *ppTComp)
5696 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5698 TRACE("(%p)->(%p)\n", This, ppTComp);
5700 *ppTComp = &This->ITypeComp_iface;
5701 ITypeComp_AddRef(*ppTComp);
5702 return S_OK;
5705 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5707 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5708 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5709 size += sizeof(*elemdesc->paramdesc.pparamdescex);
5710 return size;
5713 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5715 *dest = *src;
5716 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5717 if (src->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5719 const PARAMDESCEX *pparamdescex_src = src->paramdesc.pparamdescex;
5720 PARAMDESCEX *pparamdescex_dest = dest->paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5721 *buffer += sizeof(PARAMDESCEX);
5722 *pparamdescex_dest = *pparamdescex_src;
5723 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5724 VariantInit(&pparamdescex_dest->varDefaultValue);
5725 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5726 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5728 else
5729 dest->paramdesc.pparamdescex = NULL;
5730 return S_OK;
5733 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5735 if (V_VT(var) == VT_INT)
5736 return VariantChangeType(var, var, 0, VT_I4);
5737 else if (V_VT(var) == VT_UINT)
5738 return VariantChangeType(var, var, 0, VT_UI4);
5740 return S_OK;
5743 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5745 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5746 VariantClear(&elemdesc->paramdesc.pparamdescex->varDefaultValue);
5749 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5751 FUNCDESC *dest;
5752 char *buffer;
5753 SIZE_T size = sizeof(*src);
5754 SHORT i;
5755 HRESULT hr;
5757 size += sizeof(*src->lprgscode) * src->cScodes;
5758 size += TLB_SizeElemDesc(&src->elemdescFunc);
5759 for (i = 0; i < src->cParams; i++)
5761 size += sizeof(ELEMDESC);
5762 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5765 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5766 if (!dest) return E_OUTOFMEMORY;
5768 *dest = *src;
5769 if (dispinterface) /* overwrite funckind */
5770 dest->funckind = FUNC_DISPATCH;
5771 buffer = (char *)(dest + 1);
5773 dest->oVft = dest->oVft & 0xFFFC;
5775 if (dest->cScodes) {
5776 dest->lprgscode = (SCODE *)buffer;
5777 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5778 buffer += sizeof(*src->lprgscode) * src->cScodes;
5779 } else
5780 dest->lprgscode = NULL;
5782 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5783 if (FAILED(hr))
5785 SysFreeString((BSTR)dest);
5786 return hr;
5789 if (dest->cParams) {
5790 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5791 buffer += sizeof(ELEMDESC) * src->cParams;
5792 for (i = 0; i < src->cParams; i++)
5794 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5795 if (FAILED(hr))
5796 break;
5798 if (FAILED(hr))
5800 /* undo the above actions */
5801 for (i = i - 1; i >= 0; i--)
5802 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5803 TLB_FreeElemDesc(&dest->elemdescFunc);
5804 SysFreeString((BSTR)dest);
5805 return hr;
5807 } else
5808 dest->lprgelemdescParam = NULL;
5810 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5811 * This accounts for several arguments that are separate in the signature of
5812 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5813 if (dispinterface && (src->funckind != FUNC_DISPATCH))
5815 /* functions that have a [retval] parameter return this value into pVarResult.
5816 * [retval] is always the last parameter (if present) */
5817 if (dest->cParams &&
5818 (dest->lprgelemdescParam[dest->cParams - 1].paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5820 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5821 if (elemdesc->tdesc.vt != VT_PTR)
5823 ERR("elemdesc should have started with VT_PTR instead of:\n");
5824 if (ERR_ON(ole))
5825 dump_ELEMDESC(elemdesc);
5826 return E_UNEXPECTED;
5829 /* the type pointed to by this [retval] becomes elemdescFunc,
5830 * i.e. the function signature's return type.
5831 * We are using a flat buffer so there is no danger of leaking memory */
5832 dest->elemdescFunc.tdesc = *elemdesc->tdesc.lptdesc;
5834 /* remove the last parameter */
5835 dest->cParams--;
5837 else if (dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5838 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5839 * not pVarResult. So the function signature should show no return value. */
5840 dest->elemdescFunc.tdesc.vt = VT_VOID;
5842 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5843 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5844 if (dest->cParams && (dest->lprgelemdescParam[dest->cParams - 1].paramdesc.wParamFlags & PARAMFLAG_FLCID))
5845 dest->cParams--;
5848 *dest_ptr = dest;
5849 return S_OK;
5852 static void TLB_FreeVarDesc(VARDESC *var_desc)
5854 TLB_FreeElemDesc(&var_desc->elemdescVar);
5855 if (var_desc->varkind == VAR_CONST)
5856 VariantClear(var_desc->lpvarValue);
5857 SysFreeString((BSTR)var_desc);
5860 /* internal function to make the inherited interfaces' methods appear
5861 * part of the interface */
5862 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5863 UINT index, const TLBFuncDesc **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5865 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5866 HRESULT hr;
5867 UINT implemented_funcs = 0;
5869 if (funcs)
5870 *funcs = 0;
5871 else
5872 *hrefoffset = DISPATCH_HREF_OFFSET;
5874 if(This->impltypes)
5876 ITypeInfo *pSubTypeInfo;
5877 UINT sub_funcs;
5879 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5880 if (FAILED(hr))
5881 return hr;
5883 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5884 index,
5885 ppFuncDesc,
5886 &sub_funcs, hrefoffset);
5887 implemented_funcs += sub_funcs;
5888 ITypeInfo_Release(pSubTypeInfo);
5889 if (SUCCEEDED(hr))
5890 return hr;
5891 *hrefoffset += DISPATCH_HREF_OFFSET;
5894 if (funcs)
5895 *funcs = implemented_funcs + This->typeattr.cFuncs;
5896 else
5897 *hrefoffset = 0;
5899 if (index < implemented_funcs)
5900 return E_INVALIDARG;
5901 index -= implemented_funcs;
5903 if (index >= This->typeattr.cFuncs)
5904 return TYPE_E_ELEMENTNOTFOUND;
5906 *ppFuncDesc = &This->funcdescs[index];
5907 return S_OK;
5910 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5912 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5914 if (This->typeattr.typekind == TKIND_DISPATCH)
5915 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5917 if (index >= This->typeattr.cFuncs)
5918 return TYPE_E_ELEMENTNOTFOUND;
5920 *func_desc = &This->funcdescs[index];
5921 return S_OK;
5924 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5926 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5927 while (TRUE)
5929 switch (pTypeDesc->vt)
5931 case VT_USERDEFINED:
5932 pTypeDesc->hreftype += hrefoffset;
5933 return;
5934 case VT_PTR:
5935 case VT_SAFEARRAY:
5936 pTypeDesc = pTypeDesc->lptdesc;
5937 break;
5938 case VT_CARRAY:
5939 pTypeDesc = &pTypeDesc->lpadesc->tdescElem;
5940 break;
5941 default:
5942 return;
5947 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5949 SHORT i;
5950 for (i = 0; i < pFuncDesc->cParams; i++)
5951 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5952 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5955 /* ITypeInfo::GetFuncDesc
5957 * Retrieves the FUNCDESC structure that contains information about a
5958 * specified function.
5961 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5962 LPFUNCDESC *ppFuncDesc)
5964 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5965 const TLBFuncDesc *internal_funcdesc;
5966 HRESULT hr;
5967 UINT hrefoffset = 0;
5969 TRACE("(%p) index %d\n", This, index);
5971 if (!ppFuncDesc)
5972 return E_INVALIDARG;
5974 if (This->needs_layout)
5975 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5977 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5978 &internal_funcdesc, &hrefoffset);
5979 if (FAILED(hr))
5981 WARN("description for function %d not found\n", index);
5982 return hr;
5985 hr = TLB_AllocAndInitFuncDesc(
5986 &internal_funcdesc->funcdesc,
5987 ppFuncDesc,
5988 This->typeattr.typekind == TKIND_DISPATCH);
5990 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
5991 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5993 TRACE("-- %#lx.\n", hr);
5994 return hr;
5997 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5999 VARDESC *dest;
6000 char *buffer;
6001 SIZE_T size = sizeof(*src);
6002 HRESULT hr;
6004 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6005 if (src->varkind == VAR_CONST)
6006 size += sizeof(VARIANT);
6007 size += TLB_SizeElemDesc(&src->elemdescVar);
6009 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6010 if (!dest) return E_OUTOFMEMORY;
6012 *dest = *src;
6013 buffer = (char *)(dest + 1);
6014 if (src->lpstrSchema)
6016 int len;
6017 dest->lpstrSchema = (LPOLESTR)buffer;
6018 len = lstrlenW(src->lpstrSchema);
6019 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6020 buffer += (len + 1) * sizeof(WCHAR);
6023 if (src->varkind == VAR_CONST)
6025 HRESULT hr;
6027 dest->lpvarValue = (VARIANT *)buffer;
6028 *dest->lpvarValue = *src->lpvarValue;
6029 buffer += sizeof(VARIANT);
6030 VariantInit(dest->lpvarValue);
6031 hr = VariantCopy(dest->lpvarValue, src->lpvarValue);
6032 if (FAILED(hr))
6034 SysFreeString((BSTR)dest);
6035 return hr;
6038 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6039 if (FAILED(hr))
6041 if (src->varkind == VAR_CONST)
6042 VariantClear(dest->lpvarValue);
6043 SysFreeString((BSTR)dest);
6044 return hr;
6046 *dest_ptr = dest;
6047 return S_OK;
6050 /* ITypeInfo::GetVarDesc
6052 * Retrieves a VARDESC structure that describes the specified variable.
6055 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6056 LPVARDESC *ppVarDesc)
6058 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6059 const TLBVarDesc *pVDesc = &This->vardescs[index];
6061 TRACE("(%p) index %d\n", This, index);
6063 if(index >= This->typeattr.cVars)
6064 return TYPE_E_ELEMENTNOTFOUND;
6066 if (This->needs_layout)
6067 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6069 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6072 /* internal function to make the inherited interfaces' methods appear
6073 * part of the interface, remembering if the top-level was dispinterface */
6074 static HRESULT typeinfo_getnames( ITypeInfo *iface, MEMBERID memid, BSTR *names,
6075 UINT max_names, UINT *num_names, BOOL dispinterface)
6077 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6078 const TLBFuncDesc *func_desc;
6079 const TLBVarDesc *var_desc;
6080 int i;
6082 *num_names = 0;
6084 func_desc = TLB_get_funcdesc_by_memberid(This, memid);
6085 if (func_desc)
6087 UINT params = func_desc->funcdesc.cParams;
6088 if (!max_names || !func_desc->Name)
6089 return S_OK;
6091 *names = SysAllocString(TLB_get_bstr(func_desc->Name));
6092 ++(*num_names);
6094 if (dispinterface && (func_desc->funcdesc.funckind != FUNC_DISPATCH))
6096 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6097 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
6098 --params; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6099 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].paramdesc.wParamFlags & PARAMFLAG_FLCID))
6100 --params; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6103 for (i = 0; i < params; i++)
6105 if (*num_names >= max_names || !func_desc->pParamDesc[i].Name)
6106 return S_OK;
6107 names[*num_names] = SysAllocString(TLB_get_bstr(func_desc->pParamDesc[i].Name));
6108 ++(*num_names);
6110 return S_OK;
6113 var_desc = TLB_get_vardesc_by_memberid(This, memid);
6114 if (var_desc)
6116 *names = SysAllocString(TLB_get_bstr(var_desc->Name));
6117 *num_names = 1;
6119 else
6121 if (This->impltypes &&
6122 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH))
6124 /* recursive search */
6125 ITypeInfo *parent;
6126 HRESULT result;
6127 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &parent);
6128 if (SUCCEEDED(result))
6130 result = typeinfo_getnames(parent, memid, names, max_names, num_names, dispinterface);
6131 ITypeInfo_Release(parent);
6132 return result;
6134 WARN("Could not search inherited interface!\n");
6136 else
6138 WARN("no names found\n");
6140 *num_names = 0;
6141 return TYPE_E_ELEMENTNOTFOUND;
6143 return S_OK;
6146 /* ITypeInfo_GetNames
6148 * Retrieves the variable with the specified member ID (or the name of the
6149 * property or method and its parameters) that correspond to the specified
6150 * function ID.
6152 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6153 BSTR *names, UINT max_names, UINT *num_names)
6155 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6157 TRACE("%p, %#lx, %p, %d, %p\n", iface, memid, names, max_names, num_names);
6159 if (!names) return E_INVALIDARG;
6161 return typeinfo_getnames((ITypeInfo *)iface, memid, names, max_names, num_names,
6162 This->typeattr.typekind == TKIND_DISPATCH);
6165 /* ITypeInfo::GetRefTypeOfImplType
6167 * If a type description describes a COM class, it retrieves the type
6168 * description of the implemented interface types. For an interface,
6169 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6170 * if any exist.
6173 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6174 ITypeInfo2 *iface,
6175 UINT index,
6176 HREFTYPE *pRefType)
6178 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6179 HRESULT hr = S_OK;
6181 TRACE("(%p) index %d\n", This, index);
6182 if (TRACE_ON(ole)) dump_TypeInfo(This);
6184 if(index==(UINT)-1)
6186 /* only valid on dual interfaces;
6187 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6190 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6192 *pRefType = -2;
6194 else
6196 hr = TYPE_E_ELEMENTNOTFOUND;
6199 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6201 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6202 *pRefType = This->pTypeLib->dispatch_href;
6204 else
6206 if(index >= This->typeattr.cImplTypes)
6207 hr = TYPE_E_ELEMENTNOTFOUND;
6208 else{
6209 *pRefType = This->impltypes[index].hRef;
6210 if (This->typeattr.typekind == TKIND_INTERFACE)
6211 *pRefType |= 0x2;
6215 if(TRACE_ON(ole))
6217 if(SUCCEEDED(hr))
6218 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType );
6219 else
6220 TRACE("FAILURE -- hresult %#lx.\n", hr);
6223 return hr;
6226 /* ITypeInfo::GetImplTypeFlags
6228 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6229 * or base interface in a type description.
6231 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6232 UINT index, INT *pImplTypeFlags)
6234 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6236 TRACE("(%p) index %d\n", This, index);
6238 if(!pImplTypeFlags)
6239 return E_INVALIDARG;
6241 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6242 *pImplTypeFlags = 0;
6243 return S_OK;
6246 if(index >= This->typeattr.cImplTypes)
6247 return TYPE_E_ELEMENTNOTFOUND;
6249 *pImplTypeFlags = This->impltypes[index].implflags;
6251 return S_OK;
6254 /* GetIDsOfNames
6255 * Maps between member names and member IDs, and parameter names and
6256 * parameter IDs.
6258 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6259 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6261 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6262 const TLBVarDesc *pVDesc;
6263 HRESULT ret=S_OK;
6264 UINT i, fdc;
6266 TRACE("%p, %s, %d.\n", iface, debugstr_w(*rgszNames), cNames);
6268 /* init out parameters in case of failure */
6269 for (i = 0; i < cNames; i++)
6270 pMemId[i] = MEMBERID_NIL;
6272 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6273 int j;
6274 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6275 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6276 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6277 for(i=1; i < cNames; i++){
6278 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6279 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6280 break;
6281 if( j<pFDesc->funcdesc.cParams)
6282 pMemId[i]=j;
6283 else
6284 ret=DISP_E_UNKNOWNNAME;
6286 TRACE("-- %#lx.\n", ret);
6287 return ret;
6290 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6291 if(pVDesc){
6292 if(cNames)
6293 *pMemId = pVDesc->vardesc.memid;
6294 return ret;
6296 /* not found, see if it can be found in an inherited interface */
6297 if(This->impltypes) {
6298 /* recursive search */
6299 ITypeInfo *pTInfo;
6300 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6301 if(SUCCEEDED(ret)){
6302 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6303 ITypeInfo_Release(pTInfo);
6304 return ret;
6306 WARN("Could not search inherited interface!\n");
6307 } else
6308 WARN("no names found\n");
6309 return DISP_E_UNKNOWNNAME;
6313 #ifdef __i386__
6315 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6316 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6317 __ASM_GLOBAL_FUNC( call_method,
6318 "pushl %ebp\n\t"
6319 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6320 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6321 "movl %esp,%ebp\n\t"
6322 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6323 "pushl %esi\n\t"
6324 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6325 "pushl %edi\n\t"
6326 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6327 "movl 12(%ebp),%edx\n\t"
6328 "movl %esp,%edi\n\t"
6329 "shll $2,%edx\n\t"
6330 "jz 1f\n\t"
6331 "subl %edx,%edi\n\t"
6332 "andl $~15,%edi\n\t"
6333 "movl %edi,%esp\n\t"
6334 "movl 12(%ebp),%ecx\n\t"
6335 "movl 16(%ebp),%esi\n\t"
6336 "cld\n\t"
6337 "rep; movsl\n"
6338 "1:\tcall *8(%ebp)\n\t"
6339 "subl %esp,%edi\n\t"
6340 "movl 20(%ebp),%ecx\n\t"
6341 "movl %edi,(%ecx)\n\t"
6342 "leal -8(%ebp),%esp\n\t"
6343 "popl %edi\n\t"
6344 __ASM_CFI(".cfi_same_value %edi\n\t")
6345 "popl %esi\n\t"
6346 __ASM_CFI(".cfi_same_value %esi\n\t")
6347 "popl %ebp\n\t"
6348 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6349 __ASM_CFI(".cfi_same_value %ebp\n\t")
6350 "ret" )
6351 __ASM_GLOBAL_FUNC( call_double_method,
6352 "jmp " __ASM_NAME("call_method") )
6354 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6355 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6357 int argspos = 0, stack_offset;
6358 void *func;
6359 UINT i;
6360 DWORD *args;
6362 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6363 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6364 pvargResult, V_VT(pvargResult));
6366 if (cc != CC_STDCALL && cc != CC_CDECL)
6368 FIXME("unsupported calling convention %d\n",cc);
6369 return E_INVALIDARG;
6372 /* maximum size for an argument is sizeof(VARIANT) */
6373 args = malloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6375 if (pvInstance)
6377 const FARPROC *vtable = *(FARPROC **)pvInstance;
6378 func = vtable[oVft/sizeof(void *)];
6379 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6381 else func = (void *)oVft;
6383 switch (vtReturn)
6385 case VT_DECIMAL:
6386 case VT_VARIANT:
6387 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6388 break;
6389 case VT_HRESULT:
6390 WARN("invalid return type %u\n", vtReturn);
6391 free( args );
6392 return E_INVALIDARG;
6393 default:
6394 break;
6397 for (i = 0; i < cActuals; i++)
6399 VARIANT *arg = prgpvarg[i];
6401 switch (prgvt[i])
6403 case VT_EMPTY:
6404 break;
6405 case VT_I8:
6406 case VT_UI8:
6407 case VT_R8:
6408 case VT_DATE:
6409 case VT_CY:
6410 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6411 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6412 break;
6413 case VT_DECIMAL:
6414 case VT_VARIANT:
6415 memcpy( &args[argspos], arg, sizeof(*arg) );
6416 argspos += sizeof(*arg) / sizeof(DWORD);
6417 break;
6418 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6419 args[argspos++] = V_BOOL(arg);
6420 break;
6421 default:
6422 args[argspos++] = V_UI4(arg);
6423 break;
6425 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6428 switch (vtReturn)
6430 case VT_EMPTY:
6431 case VT_DECIMAL:
6432 case VT_VARIANT:
6433 call_method( func, argspos, args, &stack_offset );
6434 break;
6435 case VT_R4:
6436 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6437 break;
6438 case VT_R8:
6439 case VT_DATE:
6440 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6441 break;
6442 case VT_I8:
6443 case VT_UI8:
6444 case VT_CY:
6445 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6446 break;
6447 default:
6448 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6449 break;
6451 free( args );
6452 if (stack_offset && cc == CC_STDCALL)
6454 WARN( "stack pointer off by %d\n", stack_offset );
6455 return DISP_E_BADCALLEE;
6457 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6458 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6459 return S_OK;
6462 #elif defined(__x86_64__)
6464 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6465 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6466 __ASM_GLOBAL_FUNC( call_method,
6467 "pushq %rbp\n\t"
6468 __ASM_SEH(".seh_pushreg %rbp\n\t")
6469 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6470 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6471 "movq %rsp,%rbp\n\t"
6472 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6473 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6474 "pushq %rsi\n\t"
6475 __ASM_SEH(".seh_pushreg %rsi\n\t")
6476 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6477 "pushq %rdi\n\t"
6478 __ASM_SEH(".seh_pushreg %rdi\n\t")
6479 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6480 __ASM_SEH(".seh_endprologue\n\t")
6481 "movq %rcx,%rax\n\t"
6482 "movq $4,%rcx\n\t"
6483 "cmp %rcx,%rdx\n\t"
6484 "cmovgq %rdx,%rcx\n\t"
6485 "leaq 0(,%rcx,8),%rdx\n\t"
6486 "subq %rdx,%rsp\n\t"
6487 "andq $~15,%rsp\n\t"
6488 "movq %rsp,%rdi\n\t"
6489 "movq %r8,%rsi\n\t"
6490 "rep; movsq\n\t"
6491 "movq 0(%rsp),%rcx\n\t"
6492 "movq 8(%rsp),%rdx\n\t"
6493 "movq 16(%rsp),%r8\n\t"
6494 "movq 24(%rsp),%r9\n\t"
6495 "movq 0(%rsp),%xmm0\n\t"
6496 "movq 8(%rsp),%xmm1\n\t"
6497 "movq 16(%rsp),%xmm2\n\t"
6498 "movq 24(%rsp),%xmm3\n\t"
6499 "callq *%rax\n\t"
6500 "leaq -16(%rbp),%rsp\n\t"
6501 "popq %rdi\n\t"
6502 __ASM_CFI(".cfi_same_value %rdi\n\t")
6503 "popq %rsi\n\t"
6504 __ASM_CFI(".cfi_same_value %rsi\n\t")
6505 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6506 "popq %rbp\n\t"
6507 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6508 __ASM_CFI(".cfi_same_value %rbp\n\t")
6509 "ret")
6510 __ASM_GLOBAL_FUNC( call_double_method,
6511 "jmp " __ASM_NAME("call_method") )
6513 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6514 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6516 int argspos = 0;
6517 UINT i;
6518 DWORD_PTR *args;
6519 void *func;
6521 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6522 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6523 pvargResult, V_VT(pvargResult));
6525 if (cc != CC_STDCALL && cc != CC_CDECL)
6527 FIXME("unsupported calling convention %d\n",cc);
6528 return E_INVALIDARG;
6531 /* maximum size for an argument is sizeof(DWORD_PTR) */
6532 args = malloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6534 if (pvInstance)
6536 const FARPROC *vtable = *(FARPROC **)pvInstance;
6537 func = vtable[oVft/sizeof(void *)];
6538 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6540 else func = (void *)oVft;
6542 switch (vtReturn)
6544 case VT_DECIMAL:
6545 case VT_VARIANT:
6546 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6547 break;
6548 case VT_HRESULT:
6549 WARN("invalid return type %u\n", vtReturn);
6550 free( args );
6551 return E_INVALIDARG;
6552 default:
6553 break;
6556 for (i = 0; i < cActuals; i++)
6558 VARIANT *arg = prgpvarg[i];
6560 switch (prgvt[i])
6562 case VT_DECIMAL:
6563 case VT_VARIANT:
6564 args[argspos++] = (ULONG_PTR)arg;
6565 break;
6566 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6567 args[argspos++] = V_BOOL(arg);
6568 break;
6569 default:
6570 args[argspos++] = V_UI8(arg);
6571 break;
6573 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6576 switch (vtReturn)
6578 case VT_R4:
6579 V_R4(pvargResult) = call_double_method( func, argspos, args );
6580 break;
6581 case VT_R8:
6582 case VT_DATE:
6583 V_R8(pvargResult) = call_double_method( func, argspos, args );
6584 break;
6585 case VT_DECIMAL:
6586 case VT_VARIANT:
6587 call_method( func, argspos, args );
6588 break;
6589 default:
6590 V_UI8(pvargResult) = call_method( func, argspos, args );
6591 break;
6593 free( args );
6594 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6595 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6596 return S_OK;
6599 #elif defined(__arm__)
6601 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6602 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6603 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6604 __ASM_GLOBAL_FUNC( call_method,
6605 /* r0 = *func
6606 * r1 = nb_stk_args
6607 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6608 * 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)
6611 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6612 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6614 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6615 "beq 1f\n\t" /* Skip allocation if no stack args */
6616 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6617 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6618 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6619 "subs r1, r1, #4\n\t" /* Decrement count */
6620 "bgt 2b\n\t" /* Loop till done */
6622 "1:\n\t"
6623 #ifndef __SOFTFP__
6624 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6625 #endif
6626 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6627 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6629 "blx ip\n\t" /* Call the target function */
6631 "mov sp, fp\n\t" /* Clean the stack using fp */
6632 "pop {fp, pc}\n\t" /* Restore fp and return */
6634 __ASM_GLOBAL_FUNC( call_float_method,
6635 "b " __ASM_NAME("call_method") )
6636 __ASM_GLOBAL_FUNC( call_double_method,
6637 "b " __ASM_NAME("call_method") )
6639 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6640 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6642 int argspos;
6643 void *func;
6644 UINT i;
6645 DWORD *args;
6646 struct {
6647 #ifndef __SOFTFP__
6648 union {
6649 float s[16];
6650 double d[8];
6651 } sd;
6652 #endif
6653 DWORD r[4];
6654 } regs;
6655 int rcount; /* 32-bit register index count */
6656 #ifndef __SOFTFP__
6657 int scount = 0; /* single-precision float register index count */
6658 int dcount = 0; /* double-precision float register index count */
6659 #endif
6661 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6662 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6664 if (cc != CC_STDCALL && cc != CC_CDECL)
6666 FIXME("unsupported calling convention %d\n",cc);
6667 return E_INVALIDARG;
6670 argspos = 0;
6671 rcount = 0;
6673 if (pvInstance)
6675 const FARPROC *vtable = *(FARPROC **)pvInstance;
6676 func = vtable[oVft/sizeof(void *)];
6677 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6679 else func = (void *)oVft;
6681 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6682 /* first as it will need to be in the 'r' registers: */
6683 switch (vtReturn)
6685 case VT_DECIMAL:
6686 case VT_VARIANT:
6687 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6688 break;
6689 case VT_HRESULT:
6690 WARN("invalid return type %u\n", vtReturn);
6691 return E_INVALIDARG;
6692 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6693 break;
6696 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6697 args = malloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6699 for (i = 0; i < cActuals; i++)
6701 VARIANT *arg = prgpvarg[i];
6702 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6703 int ntemp; /* Used for counting words split between registers and stack */
6705 switch (prgvt[i])
6707 case VT_EMPTY:
6708 break;
6709 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6710 case VT_DATE:
6711 #ifndef __SOFTFP__
6712 dcount = max( (scount + 1) / 2, dcount );
6713 if (dcount < 8)
6715 regs.sd.d[dcount++] = V_R8(arg);
6717 else
6719 argspos += (argspos % 2); /* align argspos to 8-bytes */
6720 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6721 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6723 break;
6724 #endif
6725 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6726 case VT_UI8:
6727 case VT_CY:
6728 if (rcount < 3)
6730 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6731 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6732 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6734 else
6736 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6737 argspos += (argspos % 2); /* align argspos to 8-bytes */
6738 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6739 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6741 break;
6742 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6743 case VT_VARIANT:
6744 /* 8-byte align 'r' and/or stack: */
6745 if (rcount < 3)
6746 rcount += (rcount % 2);
6747 else
6749 rcount = 4;
6750 argspos += (argspos % 2);
6752 ntemp = sizeof(*arg) / sizeof(DWORD);
6753 while (ntemp > 0)
6755 if (rcount < 4)
6756 regs.r[rcount++] = *pdwarg++;
6757 else
6758 args[argspos++] = *pdwarg++;
6759 --ntemp;
6761 break;
6762 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6763 if (rcount < 4)
6764 regs.r[rcount++] = V_BOOL(arg);
6765 else
6766 args[argspos++] = V_BOOL(arg);
6767 break;
6768 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6769 #ifndef __SOFTFP__
6770 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6771 if (scount < 16)
6772 regs.sd.s[scount++] = V_R4(arg);
6773 else
6774 args[argspos++] = V_UI4(arg);
6775 break;
6776 #endif
6777 default:
6778 if (rcount < 4)
6779 regs.r[rcount++] = V_UI4(arg);
6780 else
6781 args[argspos++] = V_UI4(arg);
6782 break;
6784 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6787 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6789 switch (vtReturn)
6791 case VT_EMPTY: /* EMPTY = no return value */
6792 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6793 case VT_VARIANT:
6794 call_method( func, argspos, args, (DWORD*)&regs );
6795 break;
6796 case VT_R4:
6797 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6798 break;
6799 case VT_R8:
6800 case VT_DATE:
6801 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6802 break;
6803 case VT_I8:
6804 case VT_UI8:
6805 case VT_CY:
6806 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6807 break;
6808 default:
6809 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6810 break;
6812 free( args );
6813 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6814 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6815 return S_OK;
6818 #elif defined(__aarch64__)
6820 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6821 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6822 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6823 __ASM_GLOBAL_FUNC( call_method,
6824 "stp x29, x30, [sp, #-16]!\n\t"
6825 __ASM_SEH(".seh_save_fplr_x 16\n\t")
6826 "mov x29, sp\n\t"
6827 __ASM_SEH(".seh_set_fp\n\t")
6828 __ASM_SEH(".seh_endprologue\n\t")
6829 "sub sp, sp, x1, lsl #3\n\t"
6830 "cbz x1, 2f\n"
6831 "1:\tsub x1, x1, #1\n\t"
6832 "ldr x4, [x2, x1, lsl #3]\n\t"
6833 "str x4, [sp, x1, lsl #3]\n\t"
6834 "cbnz x1, 1b\n"
6835 "2:\tmov x16, x0\n\t"
6836 "mov x9, x3\n\t"
6837 "ldp d0, d1, [x9]\n\t"
6838 "ldp d2, d3, [x9, #0x10]\n\t"
6839 "ldp d4, d5, [x9, #0x20]\n\t"
6840 "ldp d6, d7, [x9, #0x30]\n\t"
6841 "ldp x0, x1, [x9, #0x40]\n\t"
6842 "ldp x2, x3, [x9, #0x50]\n\t"
6843 "ldp x4, x5, [x9, #0x60]\n\t"
6844 "ldp x6, x7, [x9, #0x70]\n\t"
6845 "ldr x8, [x9, #0x80]\n\t"
6846 "blr x16\n\t"
6847 "mov sp, x29\n\t"
6848 "ldp x29, x30, [sp], #16\n\t"
6849 "ret" )
6850 __ASM_GLOBAL_FUNC( call_float_method,
6851 "b " __ASM_NAME("call_method") )
6852 __ASM_GLOBAL_FUNC( call_double_method,
6853 "b " __ASM_NAME("call_method") )
6855 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6856 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6858 int argspos;
6859 void *func;
6860 UINT i;
6861 DWORD_PTR *args;
6862 struct
6864 union
6866 float f;
6867 double d;
6868 } fp[8];
6869 DWORD_PTR x[9];
6870 } regs;
6871 int rcount; /* 64-bit register index count */
6872 int fpcount = 0; /* float register index count */
6874 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6875 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6877 if (cc != CC_STDCALL && cc != CC_CDECL)
6879 FIXME("unsupported calling convention %d\n",cc);
6880 return E_INVALIDARG;
6883 argspos = 0;
6884 rcount = 0;
6886 if (instance)
6888 const FARPROC *vtable = *(FARPROC **)instance;
6889 func = vtable[offset/sizeof(void *)];
6890 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6892 else func = (void *)offset;
6894 /* maximum size for an argument is 16 */
6895 args = malloc( 16 * count );
6897 for (i = 0; i < count; i++)
6899 VARIANT *arg = vargs[i];
6901 switch (types[i])
6903 case VT_R4:
6904 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6905 else *(float *)&args[argspos++] = V_R4(arg);
6906 break;
6907 case VT_R8:
6908 case VT_DATE:
6909 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6910 else *(double *)&args[argspos++] = V_R8(arg);
6911 break;
6912 case VT_DECIMAL:
6913 if (rcount < 7)
6915 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6916 rcount += 2;
6918 else
6920 memcpy( &args[argspos], arg, sizeof(*arg) );
6921 argspos += 2;
6923 break;
6924 case VT_VARIANT:
6925 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6926 else args[argspos++] = (DWORD_PTR)arg;
6927 break;
6928 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6929 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6930 else args[argspos++] = V_BOOL(arg);
6931 break;
6932 default:
6933 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6934 else args[argspos++] = V_UI8(arg);
6935 break;
6937 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6940 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6942 switch (ret_type)
6944 case VT_HRESULT:
6945 free( args );
6946 return E_INVALIDARG;
6947 case VT_DECIMAL:
6948 case VT_VARIANT:
6949 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6950 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6951 break;
6952 case VT_R4:
6953 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6954 break;
6955 case VT_R8:
6956 case VT_DATE:
6957 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6958 break;
6959 default:
6960 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6961 break;
6963 free( args );
6964 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6965 TRACE("retval: %s\n", debugstr_variant(result));
6966 return S_OK;
6969 #else /* __aarch64__ */
6971 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6972 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6974 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6975 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6976 return E_NOTIMPL;
6979 #endif
6981 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6983 HRESULT hr = S_OK;
6984 ITypeInfo *tinfo2 = NULL;
6985 TYPEATTR *tattr = NULL;
6987 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->hreftype, &tinfo2);
6988 if (hr)
6990 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc->hreftype, hr);
6991 return hr;
6993 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6994 if (hr)
6996 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr);
6997 ITypeInfo_Release(tinfo2);
6998 return hr;
7001 switch (tattr->typekind)
7003 case TKIND_ENUM:
7004 *vt |= VT_I4;
7005 break;
7007 case TKIND_ALIAS:
7008 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7009 break;
7011 case TKIND_INTERFACE:
7012 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7013 *vt |= VT_DISPATCH;
7014 else
7015 *vt |= VT_UNKNOWN;
7016 break;
7018 case TKIND_DISPATCH:
7019 *vt |= VT_DISPATCH;
7020 break;
7022 case TKIND_COCLASS:
7023 *vt |= VT_DISPATCH;
7024 break;
7026 case TKIND_RECORD:
7027 FIXME("TKIND_RECORD unhandled.\n");
7028 hr = E_NOTIMPL;
7029 break;
7031 case TKIND_UNION:
7032 FIXME("TKIND_UNION unhandled.\n");
7033 hr = E_NOTIMPL;
7034 break;
7036 default:
7037 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7038 hr = E_NOTIMPL;
7039 break;
7041 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7042 ITypeInfo_Release(tinfo2);
7043 return hr;
7046 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7048 HRESULT hr = S_OK;
7050 /* enforce only one level of pointer indirection */
7051 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7053 tdesc = tdesc->lptdesc;
7055 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7056 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7057 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7058 if ((tdesc->vt == VT_USERDEFINED) ||
7059 ((tdesc->vt == VT_PTR) && (tdesc->lptdesc->vt == VT_USERDEFINED)))
7061 VARTYPE vt_userdefined = 0;
7062 const TYPEDESC *tdesc_userdefined = tdesc;
7063 if (tdesc->vt == VT_PTR)
7065 vt_userdefined = VT_BYREF;
7066 tdesc_userdefined = tdesc->lptdesc;
7068 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7069 if ((hr == S_OK) &&
7070 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7071 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7073 *vt |= vt_userdefined;
7074 return S_OK;
7077 *vt = VT_BYREF;
7080 switch (tdesc->vt)
7082 case VT_HRESULT:
7083 *vt |= VT_ERROR;
7084 break;
7085 case VT_USERDEFINED:
7086 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7087 break;
7088 case VT_VOID:
7089 case VT_CARRAY:
7090 case VT_PTR:
7091 case VT_LPSTR:
7092 case VT_LPWSTR:
7093 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7094 hr = DISP_E_BADVARTYPE;
7095 break;
7096 case VT_SAFEARRAY:
7097 *vt |= VT_ARRAY;
7098 hr = typedescvt_to_variantvt(tinfo, tdesc->lptdesc, vt);
7099 break;
7100 case VT_INT:
7101 *vt |= VT_I4;
7102 break;
7103 case VT_UINT:
7104 *vt |= VT_UI4;
7105 break;
7106 default:
7107 *vt |= tdesc->vt;
7108 break;
7110 return hr;
7113 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7115 ITypeInfo *tinfo2;
7116 TYPEATTR *tattr;
7117 HRESULT hres;
7118 int flags, i;
7120 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7121 if(FAILED(hres))
7122 return hres;
7124 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7125 if(FAILED(hres)) {
7126 ITypeInfo_Release(tinfo2);
7127 return hres;
7130 switch(tattr->typekind) {
7131 case TKIND_ALIAS:
7132 hres = get_iface_guid(tinfo2, tattr->tdescAlias.hreftype, guid);
7133 break;
7135 case TKIND_INTERFACE:
7136 case TKIND_DISPATCH:
7137 *guid = tattr->guid;
7138 break;
7140 case TKIND_COCLASS:
7141 for (i = 0; i < tattr->cImplTypes; i++)
7143 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7144 if (flags & IMPLTYPEFLAG_FDEFAULT)
7145 break;
7148 if (i == tattr->cImplTypes)
7149 i = 0;
7151 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7152 if (SUCCEEDED(hres))
7153 hres = get_iface_guid(tinfo2, href, guid);
7154 break;
7156 default:
7157 ERR("Unexpected typekind %d\n", tattr->typekind);
7158 hres = E_UNEXPECTED;
7161 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7162 ITypeInfo_Release(tinfo2);
7163 return hres;
7166 static inline BOOL func_restricted( const FUNCDESC *desc )
7168 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7171 #define INVBUF_ELEMENT_SIZE \
7172 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7173 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7174 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7175 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7176 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7177 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7178 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7179 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7181 static HRESULT WINAPI ITypeInfo_fnInvoke(
7182 ITypeInfo2 *iface,
7183 VOID *pIUnk,
7184 MEMBERID memid,
7185 UINT16 wFlags,
7186 DISPPARAMS *pDispParams,
7187 VARIANT *pVarResult,
7188 EXCEPINFO *pExcepInfo,
7189 UINT *pArgErr)
7191 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7192 int i, j;
7193 unsigned int var_index;
7194 TYPEKIND type_kind;
7195 HRESULT hres;
7196 const TLBFuncDesc *pFuncInfo;
7197 UINT fdc;
7199 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface, pIUnk, memid, wFlags, pDispParams,
7200 pVarResult, pExcepInfo, pArgErr);
7202 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7203 return DISP_E_MEMBERNOTFOUND;
7205 if (!pDispParams)
7207 ERR("NULL pDispParams not allowed\n");
7208 return E_INVALIDARG;
7211 dump_DispParms(pDispParams);
7213 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7215 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7216 pDispParams->cNamedArgs, pDispParams->cArgs);
7217 return E_INVALIDARG;
7220 /* we do this instead of using GetFuncDesc since it will return a fake
7221 * FUNCDESC for dispinterfaces and we want the real function description */
7222 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7223 pFuncInfo = &This->funcdescs[fdc];
7224 if ((memid == pFuncInfo->funcdesc.memid) &&
7225 (wFlags & pFuncInfo->funcdesc.invkind) &&
7226 !func_restricted( &pFuncInfo->funcdesc ))
7227 break;
7230 if (fdc < This->typeattr.cFuncs) {
7231 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7233 if (TRACE_ON(ole))
7235 TRACE("invoking:\n");
7236 dump_TLBFuncDescOne(pFuncInfo);
7239 switch (func_desc->funckind) {
7240 case FUNC_PUREVIRTUAL:
7241 case FUNC_VIRTUAL: {
7242 void *buffer = calloc(func_desc->cParams, INVBUF_ELEMENT_SIZE);
7243 VARIANT varresult;
7244 VARIANT retval = {{{0}}}; /* pointer for storing byref retvals in */
7245 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7246 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7247 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7248 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7249 UINT cNamedArgs = pDispParams->cNamedArgs;
7250 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7251 UINT vargs_converted=0;
7252 SAFEARRAY *a;
7254 hres = S_OK;
7256 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7258 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7260 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7261 hres = DISP_E_PARAMNOTFOUND;
7262 goto func_fail;
7266 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7268 ERR("functions with the vararg attribute do not support named arguments\n");
7269 hres = DISP_E_NONAMEDARGS;
7270 goto func_fail;
7273 for (i = 0; i < func_desc->cParams; i++)
7275 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7276 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7277 if (FAILED(hres))
7278 goto func_fail;
7281 TRACE("changing args\n");
7282 for (i = 0; i < func_desc->cParams; i++)
7284 USHORT wParamFlags = func_desc->lprgelemdescParam[i].paramdesc.wParamFlags;
7285 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7286 VARIANTARG *src_arg;
7288 if (wParamFlags & PARAMFLAG_FLCID)
7290 prgpvarg[i] = &rgvarg[i];
7291 V_VT(prgpvarg[i]) = VT_I4;
7292 V_I4(prgpvarg[i]) = This->pTypeLib->lcid;
7293 continue;
7296 src_arg = NULL;
7298 for (j = 0; j < cNamedArgs; j++)
7300 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7302 src_arg = &pDispParams->rgvarg[j];
7303 break;
7307 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7309 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7310 vargs_converted++;
7313 if (wParamFlags & PARAMFLAG_FRETVAL)
7315 /* under most conditions the caller is not allowed to
7316 * pass in a dispparam arg in the index of what would be
7317 * the retval parameter. however, there is an exception
7318 * where the extra parameter is used in an extra
7319 * IDispatch::Invoke below */
7320 if ((i < pDispParams->cArgs) &&
7321 ((func_desc->cParams != 1) || !pVarResult ||
7322 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7324 hres = DISP_E_BADPARAMCOUNT;
7325 break;
7328 /* note: this check is placed so that if the caller passes
7329 * in a VARIANTARG for the retval we just ignore it, like
7330 * native does */
7331 if (i == func_desc->cParams - 1)
7333 prgpvarg[i] = &rgvarg[i];
7334 V_BYREF(prgpvarg[i]) = &retval;
7335 V_VT(prgpvarg[i]) = rgvt[i];
7337 else
7339 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7340 hres = E_UNEXPECTED;
7341 break;
7344 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7345 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7347 TRACE("%s\n", debugstr_variant(src_arg));
7349 if(rgvt[i]!=V_VT(src_arg))
7351 if (rgvt[i] == VT_VARIANT)
7352 hres = VariantCopy(&rgvarg[i], src_arg);
7353 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7355 if (rgvt[i] == V_VT(src_arg))
7356 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7357 else
7359 if (wParamFlags & PARAMFLAG_FIN)
7360 hres = VariantCopy(&missing_arg[i], src_arg);
7361 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7363 V_VT(&rgvarg[i]) = rgvt[i];
7365 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7367 SAFEARRAYBOUND bound;
7368 VARIANT *v;
7370 bound.lLbound = 0;
7371 bound.cElements = pDispParams->cArgs-i;
7372 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7374 ERR("SafeArrayCreate failed\n");
7375 break;
7377 hres = SafeArrayAccessData(a, (LPVOID)&v);
7378 if (hres != S_OK)
7380 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7381 SafeArrayDestroy(a);
7382 break;
7384 for (j = 0; j < bound.cElements; j++)
7385 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7386 hres = SafeArrayUnaccessData(a);
7387 if (hres != S_OK)
7389 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7390 SafeArrayDestroy(a);
7391 break;
7393 if (rgvt[i] & VT_BYREF)
7394 V_BYREF(&rgvarg[i]) = &a;
7395 else
7396 V_ARRAY(&rgvarg[i]) = a;
7397 V_VT(&rgvarg[i]) = rgvt[i];
7399 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7401 if (wParamFlags & PARAMFLAG_FIN)
7402 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7403 else
7404 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7405 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7406 V_VT(&rgvarg[i]) = rgvt[i];
7408 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7410 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7411 V_VT(&rgvarg[i]) = rgvt[i];
7413 else
7415 /* FIXME: this doesn't work for VT_BYREF arguments if
7416 * they are not the same type as in the paramdesc */
7417 V_VT(&rgvarg[i]) = V_VT(src_arg);
7418 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7419 V_VT(&rgvarg[i]) = rgvt[i];
7422 if (FAILED(hres))
7424 ERR("failed to convert param %d to %s from %s\n", i,
7425 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7426 break;
7428 prgpvarg[i] = &rgvarg[i];
7430 else
7432 prgpvarg[i] = src_arg;
7435 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->lptdesc->vt == VT_USERDEFINED))
7436 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7437 && V_UNKNOWN(prgpvarg[i])) {
7438 IUnknown *userdefined_iface;
7439 GUID guid;
7441 if (tdesc->vt == VT_PTR)
7442 tdesc = tdesc->lptdesc;
7444 hres = get_iface_guid((ITypeInfo*)iface, tdesc->hreftype, &guid);
7445 if(FAILED(hres))
7446 break;
7448 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7449 if(FAILED(hres)) {
7450 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7451 break;
7454 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7455 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7458 else if (wParamFlags & PARAMFLAG_FOPT)
7460 VARIANTARG *arg;
7461 arg = prgpvarg[i] = &rgvarg[i];
7462 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7464 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].paramdesc.pparamdescex->varDefaultValue);
7465 if (FAILED(hres))
7466 break;
7468 else
7470 /* if the function wants a pointer to a variant then
7471 * set that up, otherwise just pass the VT_ERROR in
7472 * the argument by value */
7473 if (rgvt[i] & VT_BYREF)
7475 V_VT(&missing_arg[i]) = VT_ERROR;
7476 V_ERROR(&missing_arg[i]) = DISP_E_PARAMNOTFOUND;
7478 V_VT(arg) = VT_VARIANT | VT_BYREF;
7479 V_VARIANTREF(arg) = &missing_arg[i];
7481 else
7483 V_VT(arg) = VT_ERROR;
7484 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
7488 else
7490 hres = DISP_E_BADPARAMCOUNT;
7491 break;
7494 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7496 /* VT_VOID is a special case for return types, so it is not
7497 * handled in the general function */
7498 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7499 V_VT(&varresult) = VT_EMPTY;
7500 else
7502 V_VT(&varresult) = 0;
7503 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7504 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7507 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7508 V_VT(&varresult), func_desc->cParams, rgvt,
7509 prgpvarg, &varresult);
7511 vargs_converted = 0;
7513 for (i = 0; i < func_desc->cParams; i++)
7515 USHORT wParamFlags = func_desc->lprgelemdescParam[i].paramdesc.wParamFlags;
7517 if (wParamFlags & PARAMFLAG_FLCID)
7518 continue;
7519 else if (wParamFlags & PARAMFLAG_FRETVAL)
7521 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7523 if (pVarResult)
7525 VariantInit(pVarResult);
7526 /* deref return value */
7527 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7530 VARIANT_ClearInd(prgpvarg[i]);
7532 else if (vargs_converted < pDispParams->cArgs)
7534 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7535 if (wParamFlags & PARAMFLAG_FOUT)
7537 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7539 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7541 if (FAILED(hres))
7543 ERR("failed to convert param %d to vt %d\n", i,
7544 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7545 break;
7549 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7550 func_desc->cParamsOpt < 0 &&
7551 i == func_desc->cParams-1)
7553 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7554 LONG ubound;
7555 VARIANT *v;
7556 hres = SafeArrayGetUBound(a, 1, &ubound);
7557 if (hres != S_OK)
7559 ERR("SafeArrayGetUBound failed with %#lx.\n", hres);
7560 break;
7562 hres = SafeArrayAccessData(a, (LPVOID)&v);
7563 if (hres != S_OK)
7565 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7566 break;
7568 for (j = 0; j <= ubound; j++)
7569 VariantClear(&v[j]);
7570 hres = SafeArrayUnaccessData(a);
7571 if (hres != S_OK)
7573 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7574 break;
7577 VariantClear(&rgvarg[i]);
7578 vargs_converted++;
7580 else if (wParamFlags & PARAMFLAG_FOPT)
7582 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7583 VariantClear(&rgvarg[i]);
7586 VariantClear(&missing_arg[i]);
7589 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7591 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult));
7592 hres = DISP_E_EXCEPTION;
7593 if (pExcepInfo)
7595 IErrorInfo *pErrorInfo;
7596 pExcepInfo->scode = V_ERROR(&varresult);
7597 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7599 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7600 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7601 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7602 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7604 IErrorInfo_Release(pErrorInfo);
7608 if (V_VT(&varresult) != VT_ERROR)
7610 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7612 if (pVarResult)
7614 VariantClear(pVarResult);
7615 *pVarResult = varresult;
7617 else
7618 VariantClear(&varresult);
7621 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7622 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7623 (func_desc->lprgelemdescParam[0].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7624 (pDispParams->cArgs != 0))
7626 if (V_VT(pVarResult) == VT_DISPATCH)
7628 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7629 /* Note: not VariantClear; we still need the dispatch
7630 * pointer to be valid */
7631 VariantInit(pVarResult);
7632 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7633 GetSystemDefaultLCID(), wFlags,
7634 pDispParams, pVarResult, pExcepInfo, pArgErr);
7635 IDispatch_Release(pDispatch);
7637 else
7639 VariantClear(pVarResult);
7640 hres = DISP_E_NOTACOLLECTION;
7644 func_fail:
7645 free(buffer);
7646 break;
7648 case FUNC_DISPATCH: {
7649 IDispatch *disp;
7651 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7652 if (SUCCEEDED(hres)) {
7653 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7654 hres = IDispatch_Invoke(
7655 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7656 pVarResult,pExcepInfo,pArgErr
7658 if (FAILED(hres))
7659 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres);
7660 IDispatch_Release(disp);
7661 } else
7662 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7663 break;
7665 default:
7666 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7667 hres = E_FAIL;
7668 break;
7671 TRACE("-- %#lx\n", hres);
7672 return hres;
7674 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7675 VARDESC *var_desc;
7677 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7678 if(FAILED(hres)) return hres;
7680 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7681 dump_VARDESC(var_desc);
7682 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7683 return E_NOTIMPL;
7686 /* not found, look for it in inherited interfaces */
7687 ITypeInfo2_GetTypeKind(iface, &type_kind);
7688 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7689 if(This->impltypes) {
7690 /* recursive search */
7691 ITypeInfo *pTInfo;
7692 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7693 if(SUCCEEDED(hres)){
7694 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7695 ITypeInfo_Release(pTInfo);
7696 return hres;
7698 WARN("Could not search inherited interface!\n");
7701 WARN("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
7702 return DISP_E_MEMBERNOTFOUND;
7705 /* ITypeInfo::GetDocumentation
7707 * Retrieves the documentation string, the complete Help file name and path,
7708 * and the context ID for the Help topic for a specified type description.
7710 * (Can be tested by the Visual Basic Editor in Word for instance.)
7712 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7713 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7714 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7716 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7717 const TLBFuncDesc *pFDesc;
7718 const TLBVarDesc *pVDesc;
7719 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7720 iface, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7721 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7722 if(pBstrName)
7723 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7724 if(pBstrDocString)
7725 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7726 if(pdwHelpContext)
7727 *pdwHelpContext=This->dwHelpContext;
7728 if(pBstrHelpFile)
7729 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7730 return S_OK;
7731 }else {/* for a member */
7732 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7733 if(pFDesc){
7734 if(pBstrName)
7735 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7736 if(pBstrDocString)
7737 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7738 if(pdwHelpContext)
7739 *pdwHelpContext=pFDesc->helpcontext;
7740 if(pBstrHelpFile)
7741 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7742 return S_OK;
7744 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7745 if(pVDesc){
7746 if(pBstrName)
7747 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7748 if(pBstrDocString)
7749 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7750 if(pdwHelpContext)
7751 *pdwHelpContext=pVDesc->HelpContext;
7752 if(pBstrHelpFile)
7753 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7754 return S_OK;
7758 if(This->impltypes &&
7759 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7760 /* recursive search */
7761 ITypeInfo *pTInfo;
7762 HRESULT result;
7763 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7764 if(SUCCEEDED(result)) {
7765 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7766 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7767 ITypeInfo_Release(pTInfo);
7768 return result;
7770 WARN("Could not search inherited interface!\n");
7773 WARN("member %ld not found\n", memid);
7774 return TYPE_E_ELEMENTNOTFOUND;
7777 /* ITypeInfo::GetDllEntry
7779 * Retrieves a description or specification of an entry point for a function
7780 * in a DLL.
7782 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7783 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7784 WORD *pwOrdinal)
7786 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7787 const TLBFuncDesc *pFDesc;
7789 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7791 if (pBstrDllName) *pBstrDllName = NULL;
7792 if (pBstrName) *pBstrName = NULL;
7793 if (pwOrdinal) *pwOrdinal = 0;
7795 if (This->typeattr.typekind != TKIND_MODULE)
7796 return TYPE_E_BADMODULEKIND;
7798 pFDesc = TLB_get_funcdesc_by_memberid_invkind(This, memid, invKind);
7799 if (!pFDesc) return TYPE_E_ELEMENTNOTFOUND;
7801 dump_TypeInfo(This);
7802 if (TRACE_ON(ole)) dump_TLBFuncDescOne(pFDesc);
7804 if (pBstrDllName) *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7806 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1))
7808 if (pBstrName) *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7809 if (pwOrdinal) *pwOrdinal = -1;
7811 else
7813 if (pBstrName) *pBstrName = NULL;
7814 if (pwOrdinal) *pwOrdinal = LOWORD(pFDesc->Entry);
7816 return S_OK;
7819 /* internal function to make the inherited interfaces' methods appear
7820 * part of the interface */
7821 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7822 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7824 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7825 HRESULT hr;
7827 TRACE("%p, %#lx.\n", iface, *hRefType);
7829 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7831 ITypeInfo *pSubTypeInfo;
7833 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7834 if (FAILED(hr))
7835 return hr;
7837 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7838 hRefType, ppTInfo);
7839 ITypeInfo_Release(pSubTypeInfo);
7840 if (SUCCEEDED(hr))
7841 return hr;
7843 *hRefType -= DISPATCH_HREF_OFFSET;
7845 if (!(*hRefType & DISPATCH_HREF_MASK))
7846 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7847 else
7848 return E_FAIL;
7851 /* ITypeInfo::GetRefTypeInfo
7853 * If a type description references other type descriptions, it retrieves
7854 * the referenced type descriptions.
7856 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7857 ITypeInfo2 *iface,
7858 HREFTYPE hRefType,
7859 ITypeInfo **ppTInfo)
7861 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7862 ITypeInfo *type_info = NULL;
7863 HRESULT result = E_FAIL;
7864 TLBRefType *ref_type;
7865 UINT i;
7867 if(!ppTInfo)
7868 return E_INVALIDARG;
7870 if ((INT)hRefType < 0) {
7871 ITypeInfoImpl *pTypeInfoImpl;
7873 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7874 !(This->typeattr.typekind == TKIND_INTERFACE ||
7875 This->typeattr.typekind == TKIND_DISPATCH))
7876 return TYPE_E_ELEMENTNOTFOUND;
7878 /* when we meet a DUAL typeinfo, we must create the alternate
7879 * version of it.
7881 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7883 *pTypeInfoImpl = *This;
7884 pTypeInfoImpl->ref = 0;
7885 list_init(&pTypeInfoImpl->custdata_list);
7887 if (This->typeattr.typekind == TKIND_INTERFACE)
7888 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7889 else
7890 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7892 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7893 /* the AddRef implicitly adds a reference to the parent typelib, which
7894 * stops the copied data from being destroyed until the new typeinfo's
7895 * refcount goes to zero, but we need to signal to the new instance to
7896 * not free its data structures when it is destroyed */
7897 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7898 ITypeInfo_AddRef(*ppTInfo);
7900 TRACE("got dual interface %p\n", *ppTInfo);
7901 return S_OK;
7904 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7905 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7907 if(!(hRefType & 0x1))
7909 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7911 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7913 result = S_OK;
7914 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7915 ITypeInfo_AddRef(type_info);
7916 break;
7921 if (!type_info)
7923 ITypeLib *pTLib = NULL;
7925 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7927 if(ref_type->reference == (hRefType & (~0x3)))
7928 break;
7930 if(&ref_type->entry == &This->pTypeLib->ref_list)
7932 FIXME("Can't find pRefType for ref %lx\n", hRefType);
7933 return E_FAIL;
7936 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7937 UINT Index;
7938 TRACE("internal reference\n");
7939 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7940 } else {
7941 if(ref_type->pImpTLInfo->pImpTypeLib) {
7942 TRACE("typeinfo in imported typelib that is already loaded\n");
7943 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7944 ITypeLib_AddRef(pTLib);
7945 result = S_OK;
7946 } else {
7947 /* Search in cached typelibs */
7948 ITypeLibImpl *entry;
7950 EnterCriticalSection(&cache_section);
7951 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
7953 if (entry->guid
7954 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
7955 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
7956 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
7957 && entry->set_lcid == ref_type->pImpTLInfo->lcid
7958 && entry->syskind == This->pTypeLib->syskind)
7960 TRACE("got cached %p\n", entry);
7961 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
7962 ITypeLib_AddRef(pTLib);
7963 result = S_OK;
7964 break;
7967 LeaveCriticalSection(&cache_section);
7969 if (!pTLib)
7971 BSTR libnam;
7973 /* Search on disk */
7974 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7975 ref_type->pImpTLInfo->wVersionMajor,
7976 ref_type->pImpTLInfo->wVersionMinor,
7977 This->pTypeLib->syskind,
7978 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7979 if (FAILED(result))
7980 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7982 result = LoadTypeLib(libnam, &pTLib);
7983 SysFreeString(libnam);
7986 if(SUCCEEDED(result)) {
7987 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7988 ITypeLib_AddRef(pTLib);
7992 if(SUCCEEDED(result)) {
7993 if(ref_type->index == TLB_REF_USE_GUID)
7994 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
7995 else
7996 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
7998 if (pTLib != NULL)
7999 ITypeLib_Release(pTLib);
8000 if (FAILED(result))
8002 WARN("(%p) failed hreftype %#lx.\n", iface, hRefType);
8003 return result;
8007 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
8008 ITypeInfo_Release(type_info);
8009 else *ppTInfo = type_info;
8011 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface, hRefType,
8012 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8013 return result;
8016 /* ITypeInfo::AddressOfMember
8018 * Retrieves the addresses of static functions or variables, such as those
8019 * defined in a DLL.
8021 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8022 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8024 HRESULT hr;
8025 BSTR dll, entry;
8026 WORD ordinal;
8027 HMODULE module;
8029 TRACE("%p, %lx, %#x, %p.\n", iface, memid, invKind, ppv);
8031 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8032 if (FAILED(hr))
8033 return hr;
8035 module = LoadLibraryW(dll);
8036 if (!module)
8038 ERR("couldn't load %s\n", debugstr_w(dll));
8039 SysFreeString(dll);
8040 SysFreeString(entry);
8041 return STG_E_FILENOTFOUND;
8043 /* FIXME: store library somewhere where we can free it */
8045 if (entry)
8047 LPSTR entryA;
8048 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8049 entryA = malloc(len);
8050 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8052 *ppv = GetProcAddress(module, entryA);
8053 if (!*ppv)
8054 ERR("function not found %s\n", debugstr_a(entryA));
8056 free(entryA);
8058 else
8060 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8061 if (!*ppv)
8062 ERR("function not found %d\n", ordinal);
8065 SysFreeString(dll);
8066 SysFreeString(entry);
8068 if (!*ppv)
8069 return TYPE_E_DLLFUNCTIONNOTFOUND;
8071 return S_OK;
8074 /* ITypeInfo::CreateInstance
8076 * Creates a new instance of a type that describes a component object class
8077 * (coclass).
8079 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8080 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8082 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8083 HRESULT hr;
8084 TYPEATTR *pTA;
8086 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8088 *ppvObj = NULL;
8090 if(pOuterUnk)
8092 WARN("Not able to aggregate\n");
8093 return CLASS_E_NOAGGREGATION;
8096 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8097 if(FAILED(hr)) return hr;
8099 if(pTA->typekind != TKIND_COCLASS)
8101 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8102 hr = E_INVALIDARG;
8103 goto end;
8106 hr = S_FALSE;
8107 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8109 IUnknown *pUnk;
8110 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8111 TRACE("GetActiveObject rets %#lx.\n", hr);
8112 if(hr == S_OK)
8114 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8115 IUnknown_Release(pUnk);
8119 if(hr != S_OK)
8120 hr = CoCreateInstance(&pTA->guid, NULL,
8121 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8122 riid, ppvObj);
8124 end:
8125 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8126 return hr;
8129 /* ITypeInfo::GetMops
8131 * Retrieves marshalling information.
8133 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, BSTR *pBstrMops)
8135 FIXME("%p, %ld stub!\n", iface, memid);
8136 *pBstrMops = NULL;
8137 return S_OK;
8140 /* ITypeInfo::GetContainingTypeLib
8142 * Retrieves the containing type library and the index of the type description
8143 * within that type library.
8145 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8146 ITypeLib * *ppTLib, UINT *pIndex)
8148 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8150 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8151 if (pIndex) {
8152 *pIndex=This->index;
8153 TRACE("returning pIndex=%d\n", *pIndex);
8156 if (ppTLib) {
8157 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8158 ITypeLib_AddRef(*ppTLib);
8159 TRACE("returning ppTLib=%p\n", *ppTLib);
8162 return S_OK;
8165 /* ITypeInfo::ReleaseTypeAttr
8167 * Releases a TYPEATTR previously returned by Get
8170 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8171 TYPEATTR* pTypeAttr)
8173 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8174 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8175 free(pTypeAttr);
8178 /* ITypeInfo::ReleaseFuncDesc
8180 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8182 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8183 ITypeInfo2 *iface,
8184 FUNCDESC *pFuncDesc)
8186 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8187 SHORT i;
8189 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8191 for (i = 0; i < pFuncDesc->cParams; i++)
8192 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8193 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8195 SysFreeString((BSTR)pFuncDesc);
8198 /* ITypeInfo::ReleaseVarDesc
8200 * Releases a VARDESC previously returned by GetVarDesc.
8202 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8203 VARDESC *pVarDesc)
8205 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8206 TRACE("(%p)->(%p)\n", This, pVarDesc);
8208 TLB_FreeVarDesc(pVarDesc);
8211 /* ITypeInfo2::GetTypeKind
8213 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8216 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8217 TYPEKIND *pTypeKind)
8219 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8220 *pTypeKind = This->typeattr.typekind;
8221 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8222 return S_OK;
8225 /* ITypeInfo2::GetTypeFlags
8227 * Returns the type flags without any allocations. This returns a DWORD type
8228 * flag, which expands the type flags without growing the TYPEATTR (type
8229 * attribute).
8232 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8234 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8235 TRACE("%p, %p.\n", iface, pTypeFlags);
8236 *pTypeFlags=This->typeattr.wTypeFlags;
8237 return S_OK;
8240 /* ITypeInfo2::GetFuncIndexOfMemId
8241 * Binds to a specific member based on a known DISPID, where the member name
8242 * is not known (for example, when binding to a default member).
8245 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8246 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8248 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8249 UINT fdc;
8250 HRESULT result;
8252 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8253 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8254 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8255 break;
8257 if(fdc < This->typeattr.cFuncs) {
8258 *pFuncIndex = fdc;
8259 result = S_OK;
8260 } else
8261 result = TYPE_E_ELEMENTNOTFOUND;
8263 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface, memid, invKind, result);
8264 return result;
8267 /* TypeInfo2::GetVarIndexOfMemId
8269 * Binds to a specific member based on a known DISPID, where the member name
8270 * is not known (for example, when binding to a default member).
8273 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8274 MEMBERID memid, UINT *pVarIndex)
8276 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8277 TLBVarDesc *pVarInfo;
8279 TRACE("%p, %ld, %p.\n", iface, memid, pVarIndex);
8281 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8282 if(!pVarInfo)
8283 return TYPE_E_ELEMENTNOTFOUND;
8285 *pVarIndex = (pVarInfo - This->vardescs);
8287 return S_OK;
8290 /* ITypeInfo2::GetCustData
8292 * Gets the custom data
8294 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8295 ITypeInfo2 * iface,
8296 REFGUID guid,
8297 VARIANT *pVarVal)
8299 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8300 TLBCustData *pCData;
8302 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8304 if(!guid || !pVarVal)
8305 return E_INVALIDARG;
8307 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8309 VariantInit( pVarVal);
8310 if (pCData)
8311 VariantCopy( pVarVal, &pCData->data);
8312 else
8313 VariantClear( pVarVal );
8314 return S_OK;
8317 /* ITypeInfo2::GetFuncCustData
8319 * Gets the custom data
8321 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8322 ITypeInfo2 * iface,
8323 UINT index,
8324 REFGUID guid,
8325 VARIANT *pVarVal)
8327 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8328 const TLBFuncDesc *desc;
8329 TLBCustData *data;
8330 UINT hrefoffset;
8331 HRESULT hr;
8333 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8335 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8336 if (FAILED(hr))
8338 WARN("description for function %d not found\n", index);
8339 return hr;
8342 VariantInit(pVarVal);
8343 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8344 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8347 /* ITypeInfo2::GetParamCustData
8349 * Gets the custom data
8351 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8352 ITypeInfo2 * iface,
8353 UINT indexFunc,
8354 UINT indexParam,
8355 REFGUID guid,
8356 VARIANT *pVarVal)
8358 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8359 const TLBFuncDesc *pFDesc;
8360 TLBCustData *pCData;
8361 UINT hrefoffset;
8362 HRESULT hr;
8364 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8365 debugstr_guid(guid), pVarVal);
8367 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8368 if (FAILED(hr))
8369 return hr;
8371 if(indexParam >= pFDesc->funcdesc.cParams)
8372 return TYPE_E_ELEMENTNOTFOUND;
8374 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8375 if(!pCData)
8376 return TYPE_E_ELEMENTNOTFOUND;
8378 VariantInit(pVarVal);
8379 VariantCopy(pVarVal, &pCData->data);
8381 return S_OK;
8384 /* ITypeInfo2::GetVarCustData
8386 * Gets the custom data
8388 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8389 ITypeInfo2 * iface,
8390 UINT index,
8391 REFGUID guid,
8392 VARIANT *pVarVal)
8394 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8395 TLBCustData *pCData;
8396 TLBVarDesc *pVDesc = &This->vardescs[index];
8398 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8400 if(index >= This->typeattr.cVars)
8401 return TYPE_E_ELEMENTNOTFOUND;
8403 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8404 if(!pCData)
8405 return TYPE_E_ELEMENTNOTFOUND;
8407 VariantInit(pVarVal);
8408 VariantCopy(pVarVal, &pCData->data);
8410 return S_OK;
8413 /* ITypeInfo2::GetImplCustData
8415 * Gets the custom data
8417 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8418 ITypeInfo2 * iface,
8419 UINT index,
8420 REFGUID guid,
8421 VARIANT *pVarVal)
8423 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8424 TLBCustData *pCData;
8425 TLBImplType *pRDesc = &This->impltypes[index];
8427 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8429 if(index >= This->typeattr.cImplTypes)
8430 return TYPE_E_ELEMENTNOTFOUND;
8432 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8433 if(!pCData)
8434 return TYPE_E_ELEMENTNOTFOUND;
8436 VariantInit(pVarVal);
8437 VariantCopy(pVarVal, &pCData->data);
8439 return S_OK;
8442 /* ITypeInfo2::GetDocumentation2
8444 * Retrieves the documentation string, the complete Help file name and path,
8445 * the localization context to use, and the context ID for the library Help
8446 * topic in the Help file.
8449 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8450 ITypeInfo2 * iface,
8451 MEMBERID memid,
8452 LCID lcid,
8453 BSTR *pbstrHelpString,
8454 DWORD *pdwHelpStringContext,
8455 BSTR *pbstrHelpStringDll)
8457 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8458 const TLBFuncDesc *pFDesc;
8459 const TLBVarDesc *pVDesc;
8460 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8461 iface, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8462 pbstrHelpStringDll );
8463 /* the help string should be obtained from the helpstringdll,
8464 * using the _DLLGetDocumentation function, based on the supplied
8465 * lcid. Nice to do sometime...
8467 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8468 if(pbstrHelpString)
8469 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8470 if(pdwHelpStringContext)
8471 *pdwHelpStringContext=This->dwHelpStringContext;
8472 if(pbstrHelpStringDll)
8473 *pbstrHelpStringDll=
8474 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8475 return S_OK;
8476 }else {/* for a member */
8477 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8478 if(pFDesc){
8479 if(pbstrHelpString)
8480 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8481 if(pdwHelpStringContext)
8482 *pdwHelpStringContext=pFDesc->HelpStringContext;
8483 if(pbstrHelpStringDll)
8484 *pbstrHelpStringDll=
8485 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8486 return S_OK;
8488 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8489 if(pVDesc){
8490 if(pbstrHelpString)
8491 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8492 if(pdwHelpStringContext)
8493 *pdwHelpStringContext=pVDesc->HelpStringContext;
8494 if(pbstrHelpStringDll)
8495 *pbstrHelpStringDll=
8496 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8497 return S_OK;
8500 return TYPE_E_ELEMENTNOTFOUND;
8503 /* ITypeInfo2::GetAllCustData
8505 * Gets all custom data items for the Type info.
8508 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8509 ITypeInfo2 * iface,
8510 CUSTDATA *pCustData)
8512 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8514 TRACE("%p %p\n", This, pCustData);
8516 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8519 /* ITypeInfo2::GetAllFuncCustData
8521 * Gets all custom data items for the specified Function
8524 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8525 ITypeInfo2 * iface,
8526 UINT index,
8527 CUSTDATA *pCustData)
8529 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8530 const TLBFuncDesc *pFDesc;
8531 UINT hrefoffset;
8532 HRESULT hr;
8534 TRACE("%p %u %p\n", This, index, pCustData);
8536 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8537 if (FAILED(hr))
8538 return hr;
8540 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8543 /* ITypeInfo2::GetAllParamCustData
8545 * Gets all custom data items for the Functions
8548 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8549 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8551 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8552 const TLBFuncDesc *pFDesc;
8553 UINT hrefoffset;
8554 HRESULT hr;
8556 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8558 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8559 if (FAILED(hr))
8560 return hr;
8562 if(indexParam >= pFDesc->funcdesc.cParams)
8563 return TYPE_E_ELEMENTNOTFOUND;
8565 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8568 /* ITypeInfo2::GetAllVarCustData
8570 * Gets all custom data items for the specified Variable
8573 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8574 UINT index, CUSTDATA *pCustData)
8576 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8577 TLBVarDesc * pVDesc = &This->vardescs[index];
8579 TRACE("%p %u %p\n", This, index, pCustData);
8581 if(index >= This->typeattr.cVars)
8582 return TYPE_E_ELEMENTNOTFOUND;
8584 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8587 /* ITypeInfo2::GetAllImplCustData
8589 * Gets all custom data items for the specified implementation type
8592 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8593 ITypeInfo2 * iface,
8594 UINT index,
8595 CUSTDATA *pCustData)
8597 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8598 TLBImplType *pRDesc = &This->impltypes[index];
8600 TRACE("%p %u %p\n", This, index, pCustData);
8602 if(index >= This->typeattr.cImplTypes)
8603 return TYPE_E_ELEMENTNOTFOUND;
8605 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8608 static const ITypeInfo2Vtbl tinfvt =
8611 ITypeInfo_fnQueryInterface,
8612 ITypeInfo_fnAddRef,
8613 ITypeInfo_fnRelease,
8615 ITypeInfo_fnGetTypeAttr,
8616 ITypeInfo_fnGetTypeComp,
8617 ITypeInfo_fnGetFuncDesc,
8618 ITypeInfo_fnGetVarDesc,
8619 ITypeInfo_fnGetNames,
8620 ITypeInfo_fnGetRefTypeOfImplType,
8621 ITypeInfo_fnGetImplTypeFlags,
8622 ITypeInfo_fnGetIDsOfNames,
8623 ITypeInfo_fnInvoke,
8624 ITypeInfo_fnGetDocumentation,
8625 ITypeInfo_fnGetDllEntry,
8626 ITypeInfo_fnGetRefTypeInfo,
8627 ITypeInfo_fnAddressOfMember,
8628 ITypeInfo_fnCreateInstance,
8629 ITypeInfo_fnGetMops,
8630 ITypeInfo_fnGetContainingTypeLib,
8631 ITypeInfo_fnReleaseTypeAttr,
8632 ITypeInfo_fnReleaseFuncDesc,
8633 ITypeInfo_fnReleaseVarDesc,
8635 ITypeInfo2_fnGetTypeKind,
8636 ITypeInfo2_fnGetTypeFlags,
8637 ITypeInfo2_fnGetFuncIndexOfMemId,
8638 ITypeInfo2_fnGetVarIndexOfMemId,
8639 ITypeInfo2_fnGetCustData,
8640 ITypeInfo2_fnGetFuncCustData,
8641 ITypeInfo2_fnGetParamCustData,
8642 ITypeInfo2_fnGetVarCustData,
8643 ITypeInfo2_fnGetImplTypeCustData,
8644 ITypeInfo2_fnGetDocumentation2,
8645 ITypeInfo2_fnGetAllCustData,
8646 ITypeInfo2_fnGetAllFuncCustData,
8647 ITypeInfo2_fnGetAllParamCustData,
8648 ITypeInfo2_fnGetAllVarCustData,
8649 ITypeInfo2_fnGetAllImplTypeCustData,
8652 /******************************************************************************
8653 * CreateDispTypeInfo [OLEAUT32.31]
8655 * Build type information for an object so it can be called through an
8656 * IDispatch interface.
8658 * RETURNS
8659 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8660 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8662 * NOTES
8663 * This call allows an objects methods to be accessed through IDispatch, by
8664 * building an ITypeInfo object that IDispatch can use to call through.
8666 HRESULT WINAPI CreateDispTypeInfo(
8667 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8668 LCID lcid, /* [I] Locale Id */
8669 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8671 ITypeInfoImpl *pTIClass, *pTIIface;
8672 ITypeLibImpl *pTypeLibImpl;
8673 unsigned int param, func;
8674 TLBFuncDesc *pFuncDesc;
8675 TLBRefType *ref;
8677 TRACE("\n");
8678 pTypeLibImpl = TypeLibImpl_Constructor();
8679 if (!pTypeLibImpl) return E_FAIL;
8681 pTypeLibImpl->TypeInfoCount = 2;
8682 pTypeLibImpl->typeinfos = calloc(pTypeLibImpl->TypeInfoCount, sizeof(ITypeInfoImpl*));
8684 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8685 pTIIface->pTypeLib = pTypeLibImpl;
8686 pTIIface->index = 0;
8687 pTIIface->Name = NULL;
8688 pTIIface->dwHelpContext = -1;
8689 pTIIface->guid = NULL;
8690 pTIIface->typeattr.lcid = lcid;
8691 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8692 pTIIface->typeattr.wMajorVerNum = 0;
8693 pTIIface->typeattr.wMinorVerNum = 0;
8694 pTIIface->typeattr.cbAlignment = 2;
8695 pTIIface->typeattr.cbSizeInstance = -1;
8696 pTIIface->typeattr.cbSizeVft = -1;
8697 pTIIface->typeattr.cFuncs = 0;
8698 pTIIface->typeattr.cImplTypes = 0;
8699 pTIIface->typeattr.cVars = 0;
8700 pTIIface->typeattr.wTypeFlags = 0;
8701 pTIIface->hreftype = 0;
8703 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8704 pFuncDesc = pTIIface->funcdescs;
8705 for(func = 0; func < pidata->cMembers; func++) {
8706 METHODDATA *md = pidata->pmethdata + func;
8707 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8708 pFuncDesc->funcdesc.memid = md->dispid;
8709 pFuncDesc->funcdesc.lprgscode = NULL;
8710 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8711 pFuncDesc->funcdesc.invkind = md->wFlags;
8712 pFuncDesc->funcdesc.callconv = md->cc;
8713 pFuncDesc->funcdesc.cParams = md->cArgs;
8714 pFuncDesc->funcdesc.cParamsOpt = 0;
8715 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8716 pFuncDesc->funcdesc.cScodes = 0;
8717 pFuncDesc->funcdesc.wFuncFlags = 0;
8718 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8719 pFuncDesc->funcdesc.elemdescFunc.paramdesc.wParamFlags = PARAMFLAG_NONE;
8720 pFuncDesc->funcdesc.elemdescFunc.paramdesc.pparamdescex = NULL;
8721 pFuncDesc->funcdesc.lprgelemdescParam = calloc(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 = calloc(1, 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 = wcsdup(szFile);
8935 if (!This->path) {
8936 ITypeLib2_Release(&This->ITypeLib2_iface);
8937 return E_OUTOFMEMORY;
8940 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8941 ITypeLib2_Release(&This->ITypeLib2_iface);
8942 return hres;
8945 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8946 REFIID riid, void **object)
8948 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8950 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8953 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8955 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8957 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8960 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8962 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8964 return ITypeLib2_Release(&This->ITypeLib2_iface);
8967 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8968 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8970 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8971 ITypeInfoImpl *info;
8972 HRESULT hres;
8974 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8976 if (!ctinfo || !name)
8977 return E_INVALIDARG;
8979 info = TLB_get_typeinfo_by_name(This, name);
8980 if (info)
8981 return TYPE_E_NAMECONFLICT;
8983 This->typeinfos = realloc(This->typeinfos, sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8985 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8987 info->pTypeLib = This;
8988 info->Name = TLB_append_str(&This->name_list, name);
8989 info->index = This->TypeInfoCount;
8990 info->typeattr.typekind = kind;
8991 info->typeattr.cbAlignment = 4;
8993 switch (info->typeattr.typekind) {
8994 case TKIND_ENUM:
8995 case TKIND_INTERFACE:
8996 case TKIND_DISPATCH:
8997 case TKIND_COCLASS:
8998 info->typeattr.cbSizeInstance = This->ptr_size;
8999 break;
9000 case TKIND_RECORD:
9001 case TKIND_UNION:
9002 info->typeattr.cbSizeInstance = 0;
9003 break;
9004 case TKIND_MODULE:
9005 info->typeattr.cbSizeInstance = 2;
9006 break;
9007 case TKIND_ALIAS:
9008 info->typeattr.cbSizeInstance = -0x75;
9009 break;
9010 default:
9011 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9012 info->typeattr.cbSizeInstance = 0xdeadbeef;
9013 break;
9016 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9017 &IID_ICreateTypeInfo, (void **)ctinfo);
9018 if (FAILED(hres)) {
9019 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9020 return hres;
9023 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9025 ++This->TypeInfoCount;
9027 return S_OK;
9030 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9031 LPOLESTR name)
9033 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9035 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9037 if (!name)
9038 return E_INVALIDARG;
9040 This->Name = TLB_append_str(&This->name_list, name);
9042 return S_OK;
9045 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9046 WORD majorVerNum, WORD minorVerNum)
9048 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9050 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9052 This->ver_major = majorVerNum;
9053 This->ver_minor = minorVerNum;
9055 return S_OK;
9058 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9059 REFGUID guid)
9061 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9063 TRACE("%p %s\n", This, debugstr_guid(guid));
9065 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9067 return S_OK;
9070 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9071 LPOLESTR doc)
9073 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9075 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9077 if (!doc)
9078 return E_INVALIDARG;
9080 This->DocString = TLB_append_str(&This->string_list, doc);
9082 return S_OK;
9085 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9086 LPOLESTR helpFileName)
9088 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9090 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9092 if (!helpFileName)
9093 return E_INVALIDARG;
9095 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9097 return S_OK;
9100 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9101 DWORD helpContext)
9103 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9105 TRACE("%p, %ld.\n", iface, helpContext);
9107 This->dwHelpContext = helpContext;
9109 return S_OK;
9112 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9113 LCID lcid)
9115 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9117 TRACE("%p, %#lx.\n", iface, lcid);
9119 This->set_lcid = lcid;
9121 return S_OK;
9124 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9125 UINT libFlags)
9127 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9129 TRACE("%p %x\n", This, libFlags);
9131 This->libflags = libFlags;
9133 return S_OK;
9136 typedef struct tagWMSFT_SegContents {
9137 DWORD len;
9138 void *data;
9139 } WMSFT_SegContents;
9141 typedef struct tagWMSFT_TLBFile {
9142 MSFT_Header header;
9143 WMSFT_SegContents typeinfo_seg;
9144 WMSFT_SegContents impfile_seg;
9145 WMSFT_SegContents impinfo_seg;
9146 WMSFT_SegContents ref_seg;
9147 WMSFT_SegContents guidhash_seg;
9148 WMSFT_SegContents guid_seg;
9149 WMSFT_SegContents namehash_seg;
9150 WMSFT_SegContents name_seg;
9151 WMSFT_SegContents string_seg;
9152 WMSFT_SegContents typdesc_seg;
9153 WMSFT_SegContents arraydesc_seg;
9154 WMSFT_SegContents custdata_seg;
9155 WMSFT_SegContents cdguids_seg;
9156 MSFT_SegDir segdir;
9157 WMSFT_SegContents aux_seg;
9158 } WMSFT_TLBFile;
9160 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9161 WMSFT_TLBFile *file)
9163 TLBString *str;
9164 UINT last_offs;
9165 char *data;
9167 file->string_seg.len = 0;
9168 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9169 int size;
9171 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9172 if (size == 0)
9173 return E_UNEXPECTED;
9175 size += sizeof(INT16);
9176 if (size % 4)
9177 size = (size + 4) & ~0x3;
9178 if (size < 8)
9179 size = 8;
9181 file->string_seg.len += size;
9183 /* temporarily use str->offset to store the length of the aligned,
9184 * converted string */
9185 str->offset = size;
9188 file->string_seg.data = data = malloc(file->string_seg.len);
9190 last_offs = 0;
9191 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9192 int size;
9194 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9195 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9196 if (size == 0) {
9197 free(file->string_seg.data);
9198 return E_UNEXPECTED;
9201 *((INT16*)data) = size;
9203 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9205 size = str->offset;
9206 data += size;
9207 str->offset = last_offs;
9208 last_offs += size;
9211 return S_OK;
9214 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9215 WMSFT_TLBFile *file)
9217 TLBString *str;
9218 UINT last_offs;
9219 char *data;
9220 MSFT_NameIntro *last_intro = NULL;
9222 file->header.nametablecount = 0;
9223 file->header.nametablechars = 0;
9225 file->name_seg.len = 0;
9226 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9227 int size;
9229 size = lstrlenW(str->str);
9230 file->header.nametablechars += size;
9231 file->header.nametablecount++;
9233 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9234 if (size == 0)
9235 return E_UNEXPECTED;
9237 size += sizeof(MSFT_NameIntro);
9238 if (size % 4)
9239 size = (size + 4) & ~0x3;
9240 if (size < 8)
9241 size = 8;
9243 file->name_seg.len += size;
9245 /* temporarily use str->offset to store the length of the aligned,
9246 * converted string */
9247 str->offset = size;
9250 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9251 file->name_seg.data = data = malloc(file->name_seg.len + 1);
9253 last_offs = 0;
9254 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9255 int size, hash;
9256 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9258 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9259 data + sizeof(MSFT_NameIntro),
9260 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9261 if (size == 0) {
9262 free(file->name_seg.data);
9263 return E_UNEXPECTED;
9265 data[sizeof(MSFT_NameIntro) + size] = '\0';
9267 intro->hreftype = -1; /* TODO? */
9268 intro->namelen = size & 0xFF;
9269 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9270 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9271 intro->namelen |= hash << 16;
9272 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9273 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9275 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9276 str->offset - size - sizeof(MSFT_NameIntro));
9278 /* update str->offset to actual value to use in other
9279 * compilation functions that require positions within
9280 * the string table */
9281 last_intro = intro;
9282 size = str->offset;
9283 data += size;
9284 str->offset = last_offs;
9285 last_offs += size;
9288 if(last_intro)
9289 last_intro->hreftype = 0; /* last one is 0? */
9291 return S_OK;
9294 static inline int hash_guid(GUID *guid)
9296 int i, hash = 0;
9298 for (i = 0; i < 8; i ++)
9299 hash ^= ((const short *)guid)[i];
9301 return hash & 0x1f;
9304 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9306 TLBGuid *guid;
9307 MSFT_GuidEntry *entry;
9308 DWORD offs;
9309 int hash_key, *guidhashtab;
9311 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9312 file->guid_seg.data = malloc(file->guid_seg.len);
9314 entry = file->guid_seg.data;
9315 offs = 0;
9316 guidhashtab = file->guidhash_seg.data;
9317 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9318 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9319 entry->hreftype = guid->hreftype;
9321 hash_key = hash_guid(&guid->guid);
9322 entry->next_hash = guidhashtab[hash_key];
9323 guidhashtab[hash_key] = offs;
9325 guid->offset = offs;
9326 offs += sizeof(MSFT_GuidEntry);
9327 ++entry;
9330 return S_OK;
9333 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9335 VARIANT v = *value;
9336 VARTYPE arg_type = V_VT(value);
9337 int mask = 0;
9338 HRESULT hres;
9339 DWORD ret = file->custdata_seg.len;
9341 if(arg_type == VT_INT)
9342 arg_type = VT_I4;
9343 if(arg_type == VT_UINT)
9344 arg_type = VT_UI4;
9346 v = *value;
9347 if(V_VT(value) != arg_type) {
9348 hres = VariantChangeType(&v, value, 0, arg_type);
9349 if(FAILED(hres)){
9350 ERR("VariantChangeType failed: %#lx.\n", hres);
9351 return -1;
9355 /* Check if default value can be stored in-place */
9356 switch(arg_type){
9357 case VT_I4:
9358 case VT_UI4:
9359 mask = 0x3ffffff;
9360 if(V_UI4(&v) > 0x3ffffff)
9361 break;
9362 /* fall through */
9363 case VT_I1:
9364 case VT_UI1:
9365 case VT_BOOL:
9366 if(!mask)
9367 mask = 0xff;
9368 /* fall through */
9369 case VT_I2:
9370 case VT_UI2:
9371 if(!mask)
9372 mask = 0xffff;
9373 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9376 /* have to allocate space in custdata_seg */
9377 switch(arg_type) {
9378 case VT_I4:
9379 case VT_R4:
9380 case VT_UI4:
9381 case VT_INT:
9382 case VT_UINT:
9383 case VT_HRESULT:
9384 case VT_PTR: {
9385 /* Construct the data to be allocated */
9386 int *data;
9388 if(file->custdata_seg.data){
9389 file->custdata_seg.data = realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9390 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9391 file->custdata_seg.len += sizeof(int) * 2;
9392 }else{
9393 file->custdata_seg.len = sizeof(int) * 2;
9394 data = file->custdata_seg.data = malloc(file->custdata_seg.len);
9397 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9398 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9400 /* TODO: Check if the encoded data is already present in custdata_seg */
9402 return ret;
9405 case VT_BSTR: {
9406 int mb_len = WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), NULL, 0, NULL, NULL );
9407 int i, len = (6 + mb_len + 3) & ~0x3;
9408 char *data;
9410 if(file->custdata_seg.data){
9411 file->custdata_seg.data = realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9412 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9413 file->custdata_seg.len += len;
9414 }else{
9415 file->custdata_seg.len = len;
9416 data = file->custdata_seg.data = malloc(file->custdata_seg.len);
9419 *((unsigned short *)data) = V_VT(value);
9420 *((unsigned int *)(data+2)) = mb_len;
9421 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], mb_len, NULL, NULL);
9422 for (i = 6 + mb_len; i < len; i++)
9423 data[i] = 0x57;
9425 /* TODO: Check if the encoded data is already present in custdata_seg */
9427 return ret;
9429 default:
9430 FIXME("Argument type not yet handled\n");
9431 return -1;
9435 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9437 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9439 DWORD offs = file->arraydesc_seg.len;
9440 DWORD *encoded;
9441 USHORT i;
9443 /* TODO: we should check for duplicates, but that's harder because each
9444 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9445 * at the library-level) */
9447 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9448 file->arraydesc_seg.data = realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9449 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9451 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9452 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9453 for(i = 0; i < desc->cDims; ++i){
9454 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9455 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9458 return offs;
9461 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9463 DWORD junk;
9464 INT16 junk2;
9465 DWORD offs = 0;
9466 DWORD encoded[2];
9467 VARTYPE vt, subtype;
9468 char *data;
9470 if(!desc)
9471 return -1;
9473 if(!out_mix)
9474 out_mix = &junk;
9475 if(!out_size)
9476 out_size = &junk2;
9478 vt = desc->vt & VT_TYPEMASK;
9480 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9481 DWORD mix;
9482 encoded[1] = WMSFT_append_typedesc(desc->lptdesc, file, &mix, out_size);
9483 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9484 *out_mix = 0x7FFF;
9485 *out_size += 2 * sizeof(DWORD);
9486 }else if(vt == VT_CARRAY){
9487 encoded[0] = desc->vt | (0x7FFE << 16);
9488 encoded[1] = WMSFT_append_arraydesc(desc->lpadesc, file);
9489 *out_mix = 0x7FFE;
9490 }else if(vt == VT_USERDEFINED){
9491 encoded[0] = desc->vt | (0x7FFF << 16);
9492 encoded[1] = desc->hreftype;
9493 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9494 }else{
9495 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9497 switch(vt){
9498 case VT_INT:
9499 subtype = VT_I4;
9500 break;
9501 case VT_UINT:
9502 subtype = VT_UI4;
9503 break;
9504 case VT_VOID:
9505 subtype = VT_EMPTY;
9506 break;
9507 default:
9508 subtype = vt;
9509 break;
9512 *out_mix = subtype;
9513 return 0x80000000 | (subtype << 16) | desc->vt;
9516 data = file->typdesc_seg.data;
9517 while(offs < file->typdesc_seg.len){
9518 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9519 return offs;
9520 offs += sizeof(encoded);
9523 file->typdesc_seg.len += sizeof(encoded);
9524 data = file->typdesc_seg.data = realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9526 memcpy(&data[offs], encoded, sizeof(encoded));
9528 return offs;
9531 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9533 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9534 DWORD ret = cdguids_seg->len, offs;
9535 MSFT_CDGuid *cdguid;
9536 TLBCustData *cd;
9538 if(list_empty(custdata_list))
9539 return -1;
9541 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9542 cdguids_seg->data = realloc(cdguids_seg->data, cdguids_seg->len);
9543 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9545 offs = ret + sizeof(MSFT_CDGuid);
9546 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9547 cdguid->GuidOffset = cd->guid->offset;
9548 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9549 cdguid->next = offs;
9550 offs += sizeof(MSFT_CDGuid);
9551 ++cdguid;
9554 --cdguid;
9555 cdguid->next = -1;
9557 return ret;
9560 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9561 WMSFT_TLBFile *file)
9563 WMSFT_SegContents *aux_seg = &file->aux_seg;
9564 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9565 MSFT_VarRecord *varrecord;
9566 MSFT_FuncRecord *funcrecord;
9567 MEMBERID *memid;
9568 DWORD *name, *offsets, offs;
9570 for(i = 0; i < info->typeattr.cFuncs; ++i){
9571 TLBFuncDesc *desc = &info->funcdescs[i];
9573 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9575 /* optional fields */
9576 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9577 if(!list_empty(&desc->custdata_list))
9578 recorded_size += 7 * sizeof(INT);
9579 else if(desc->HelpStringContext != 0)
9580 recorded_size += 6 * sizeof(INT);
9581 /* res9? resA? */
9582 else if(desc->Entry)
9583 recorded_size += 3 * sizeof(INT);
9584 else if(desc->HelpString)
9585 recorded_size += 2 * sizeof(INT);
9586 else if(desc->helpcontext)
9587 recorded_size += sizeof(INT);
9589 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9591 for(j = 0; j < desc->funcdesc.cParams; ++j){
9592 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9593 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9594 break;
9598 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9601 for(i = 0; i < info->typeattr.cVars; ++i){
9602 TLBVarDesc *desc = &info->vardescs[i];
9604 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9606 /* optional fields */
9607 if(desc->HelpStringContext != 0)
9608 recorded_size += 5 * sizeof(INT);
9609 else if(!list_empty(&desc->custdata_list))
9610 recorded_size += 4 * sizeof(INT);
9611 /* res9? */
9612 else if(desc->HelpString)
9613 recorded_size += 2 * sizeof(INT);
9614 else if(desc->HelpContext != 0)
9615 recorded_size += sizeof(INT);
9617 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9620 if(!recorded_size && !extra_size)
9621 return ret;
9623 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9625 aux_seg->len += recorded_size + extra_size;
9627 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9629 aux_seg->data = realloc(aux_seg->data, aux_seg->len);
9631 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9633 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9634 offs = 0;
9636 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9637 for(i = 0; i < info->typeattr.cFuncs; ++i){
9638 TLBFuncDesc *desc = &info->funcdescs[i];
9639 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9641 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9642 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9643 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9644 funcrecord->VtableOffset = desc->funcdesc.oVft;
9646 /* FKCCIC:
9647 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9648 * ^^^funckind
9649 * ^^^ ^invkind
9650 * ^has_cust_data
9651 * ^^^^callconv
9652 * ^has_param_defaults
9653 * ^oEntry_is_intresource
9655 funcrecord->FKCCIC =
9656 desc->funcdesc.funckind |
9657 (desc->funcdesc.invkind << 3) |
9658 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9659 (desc->funcdesc.callconv << 8);
9661 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9662 funcrecord->FKCCIC |= 0x2000;
9664 for(j = 0; j < desc->funcdesc.cParams; ++j){
9665 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9666 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9667 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9670 if(paramdefault_size > 0)
9671 funcrecord->FKCCIC |= 0x1000;
9673 funcrecord->nrargs = desc->funcdesc.cParams;
9674 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9676 /* optional fields */
9677 /* res9? resA? */
9678 if(!list_empty(&desc->custdata_list)){
9679 size += 7 * sizeof(INT);
9680 funcrecord->HelpContext = desc->helpcontext;
9681 if(desc->HelpString)
9682 funcrecord->oHelpString = desc->HelpString->offset;
9683 else
9684 funcrecord->oHelpString = -1;
9685 if(!desc->Entry)
9686 funcrecord->oEntry = -1;
9687 else if(IS_INTRESOURCE(desc->Entry))
9688 funcrecord->oEntry = LOWORD(desc->Entry);
9689 else
9690 funcrecord->oEntry = desc->Entry->offset;
9691 funcrecord->res9 = -1;
9692 funcrecord->resA = -1;
9693 funcrecord->HelpStringContext = desc->HelpStringContext;
9694 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9695 }else if(desc->HelpStringContext != 0){
9696 size += 6 * sizeof(INT);
9697 funcrecord->HelpContext = desc->helpcontext;
9698 if(desc->HelpString)
9699 funcrecord->oHelpString = desc->HelpString->offset;
9700 else
9701 funcrecord->oHelpString = -1;
9702 if(!desc->Entry)
9703 funcrecord->oEntry = -1;
9704 else if(IS_INTRESOURCE(desc->Entry))
9705 funcrecord->oEntry = LOWORD(desc->Entry);
9706 else
9707 funcrecord->oEntry = desc->Entry->offset;
9708 funcrecord->res9 = -1;
9709 funcrecord->resA = -1;
9710 funcrecord->HelpStringContext = desc->HelpStringContext;
9711 }else if(desc->Entry){
9712 size += 3 * sizeof(INT);
9713 funcrecord->HelpContext = desc->helpcontext;
9714 if(desc->HelpString)
9715 funcrecord->oHelpString = desc->HelpString->offset;
9716 else
9717 funcrecord->oHelpString = -1;
9718 if(!desc->Entry)
9719 funcrecord->oEntry = -1;
9720 else if(IS_INTRESOURCE(desc->Entry))
9721 funcrecord->oEntry = LOWORD(desc->Entry);
9722 else
9723 funcrecord->oEntry = desc->Entry->offset;
9724 }else if(desc->HelpString){
9725 size += 2 * sizeof(INT);
9726 funcrecord->HelpContext = desc->helpcontext;
9727 funcrecord->oHelpString = desc->HelpString->offset;
9728 }else if(desc->helpcontext){
9729 size += sizeof(INT);
9730 funcrecord->HelpContext = desc->helpcontext;
9733 paramdefault = (DWORD*)((char *)funcrecord + size);
9734 size += paramdefault_size;
9736 for(j = 0; j < desc->funcdesc.cParams; ++j){
9737 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9739 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9740 if(desc->pParamDesc[j].Name)
9741 info->oName = desc->pParamDesc[j].Name->offset;
9742 else
9743 info->oName = -1;
9744 info->Flags = desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags;
9746 if(paramdefault_size){
9747 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9748 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].paramdesc.pparamdescex->varDefaultValue, file);
9749 else if(paramdefault_size)
9750 *paramdefault = -1;
9751 ++paramdefault;
9754 size += sizeof(MSFT_ParameterInfo);
9757 funcrecord->Info = size | (i << 16); /* is it just the index? */
9759 *offsets = offs;
9760 offs += size;
9761 ++offsets;
9763 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9766 varrecord = (MSFT_VarRecord*)funcrecord;
9767 for(i = 0; i < info->typeattr.cVars; ++i){
9768 TLBVarDesc *desc = &info->vardescs[i];
9769 DWORD size = 5 * sizeof(INT);
9771 varrecord->vardescsize = sizeof(desc->vardesc);
9772 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9773 varrecord->Flags = desc->vardesc.wVarFlags;
9774 varrecord->VarKind = desc->vardesc.varkind;
9776 if(desc->vardesc.varkind == VAR_CONST){
9777 varrecord->vardescsize += sizeof(VARIANT);
9778 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.lpvarValue, file);
9779 }else
9780 varrecord->OffsValue = desc->vardesc.oInst;
9782 /* res9? */
9783 if(desc->HelpStringContext != 0){
9784 size += 5 * sizeof(INT);
9785 varrecord->HelpContext = desc->HelpContext;
9786 if(desc->HelpString)
9787 varrecord->HelpString = desc->HelpString->offset;
9788 else
9789 varrecord->HelpString = -1;
9790 varrecord->res9 = -1;
9791 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9792 varrecord->HelpStringContext = desc->HelpStringContext;
9793 }else if(!list_empty(&desc->custdata_list)){
9794 size += 4 * sizeof(INT);
9795 varrecord->HelpContext = desc->HelpContext;
9796 if(desc->HelpString)
9797 varrecord->HelpString = desc->HelpString->offset;
9798 else
9799 varrecord->HelpString = -1;
9800 varrecord->res9 = -1;
9801 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9802 }else if(desc->HelpString){
9803 size += 2 * sizeof(INT);
9804 varrecord->HelpContext = desc->HelpContext;
9805 if(desc->HelpString)
9806 varrecord->HelpString = desc->HelpString->offset;
9807 else
9808 varrecord->HelpString = -1;
9809 }else if(desc->HelpContext != 0){
9810 size += sizeof(INT);
9811 varrecord->HelpContext = desc->HelpContext;
9814 varrecord->Info = size | (i << 16);
9816 *offsets = offs;
9817 offs += size;
9818 ++offsets;
9820 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9823 memid = (MEMBERID*)varrecord;
9824 for(i = 0; i < info->typeattr.cFuncs; ++i){
9825 TLBFuncDesc *desc = &info->funcdescs[i];
9826 *memid = desc->funcdesc.memid;
9827 ++memid;
9829 for(i = 0; i < info->typeattr.cVars; ++i){
9830 TLBVarDesc *desc = &info->vardescs[i];
9831 *memid = desc->vardesc.memid;
9832 ++memid;
9835 name = (DWORD*)memid;
9836 for(i = 0; i < info->typeattr.cFuncs; ++i){
9837 TLBFuncDesc *desc = &info->funcdescs[i];
9838 if(desc->Name)
9839 *name = desc->Name->offset;
9840 else
9841 *name = -1;
9842 ++name;
9844 for(i = 0; i < info->typeattr.cVars; ++i){
9845 TLBVarDesc *desc = &info->vardescs[i];
9846 if(desc->Name)
9847 *name = desc->Name->offset;
9848 else
9849 *name = -1;
9850 ++name;
9853 return ret;
9856 typedef struct tagWMSFT_RefChunk {
9857 DWORD href;
9858 DWORD res04;
9859 DWORD res08;
9860 DWORD next;
9861 } WMSFT_RefChunk;
9863 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9865 DWORD offs = file->ref_seg.len, i;
9866 WMSFT_RefChunk *chunk;
9868 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9869 file->ref_seg.data = realloc(file->ref_seg.data, file->ref_seg.len);
9871 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9873 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9874 chunk->href = info->impltypes[i].hRef;
9875 chunk->res04 = info->impltypes[i].implflags;
9876 chunk->res08 = -1;
9877 if(i < info->typeattr.cImplTypes - 1)
9878 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9879 else
9880 chunk->next = -1;
9881 ++chunk;
9884 return offs;
9887 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9889 DWORD size;
9891 size = sizeof(MSFT_TypeInfoBase);
9893 if(data){
9894 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9895 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9896 base->typekind = TKIND_DISPATCH;
9897 else
9898 base->typekind = info->typeattr.typekind;
9899 base->typekind |= index << 16; /* TODO: There are some other flags here */
9900 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9901 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9902 base->res2 = 0;
9903 base->res3 = 0;
9904 base->res4 = 3;
9905 base->res5 = 0;
9906 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9907 base->res7 = 0;
9908 base->res8 = 0;
9909 base->res9 = 0;
9910 base->resA = 0;
9911 if(info->guid)
9912 base->posguid = info->guid->offset;
9913 else
9914 base->posguid = -1;
9915 base->flags = info->typeattr.wTypeFlags;
9916 if(info->Name) {
9917 base->NameOffset = info->Name->offset;
9919 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9920 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9921 }else {
9922 base->NameOffset = -1;
9924 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9925 if(info->DocString)
9926 base->docstringoffs = info->DocString->offset;
9927 else
9928 base->docstringoffs = -1;
9929 base->helpstringcontext = info->dwHelpStringContext;
9930 base->helpcontext = info->dwHelpContext;
9931 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9932 base->cImplTypes = info->typeattr.cImplTypes;
9933 base->cbSizeVft = info->typeattr.cbSizeVft;
9934 base->size = info->typeattr.cbSizeInstance;
9935 if(info->typeattr.typekind == TKIND_COCLASS){
9936 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9937 }else if(info->typeattr.typekind == TKIND_ALIAS){
9938 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9939 }else if(info->typeattr.typekind == TKIND_MODULE){
9940 if(info->DllName)
9941 base->datatype1 = info->DllName->offset;
9942 else
9943 base->datatype1 = -1;
9944 }else{
9945 if(info->typeattr.cImplTypes > 0)
9946 base->datatype1 = info->impltypes[0].hRef;
9947 else
9948 base->datatype1 = -1;
9950 base->datatype2 = index; /* FIXME: i think there's more here */
9951 base->res18 = 0;
9952 base->res19 = -1;
9955 return size;
9958 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9960 UINT i;
9962 file->typeinfo_seg.len = 0;
9963 for(i = 0; i < This->TypeInfoCount; ++i){
9964 ITypeInfoImpl *info = This->typeinfos[i];
9965 *junk = file->typeinfo_seg.len;
9966 ++junk;
9967 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9970 file->typeinfo_seg.data = malloc(file->typeinfo_seg.len);
9971 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9973 file->aux_seg.len = 0;
9974 file->aux_seg.data = NULL;
9976 file->typeinfo_seg.len = 0;
9977 for(i = 0; i < This->TypeInfoCount; ++i){
9978 ITypeInfoImpl *info = This->typeinfos[i];
9979 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9980 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9984 typedef struct tagWMSFT_ImpFile {
9985 INT guid_offs;
9986 LCID lcid;
9987 DWORD version;
9988 } WMSFT_ImpFile;
9990 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9992 TLBImpLib *implib;
9993 WMSFT_ImpFile *impfile;
9994 char *data;
9995 DWORD last_offs = 0;
9997 file->impfile_seg.len = 0;
9998 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9999 int size = 0;
10001 if(implib->name){
10002 WCHAR *path = wcsrchr(implib->name, '\\');
10003 if(path)
10004 ++path;
10005 else
10006 path = implib->name;
10007 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10008 if (size == 0)
10009 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10012 size += sizeof(INT16);
10013 if (size % 4)
10014 size = (size + 4) & ~0x3;
10015 if (size < 8)
10016 size = 8;
10018 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10021 data = file->impfile_seg.data = malloc(file->impfile_seg.len);
10023 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10024 int strlen = 0, size;
10026 impfile = (WMSFT_ImpFile*)data;
10027 impfile->guid_offs = implib->guid->offset;
10028 impfile->lcid = implib->lcid;
10029 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10031 data += sizeof(WMSFT_ImpFile);
10033 if(implib->name){
10034 WCHAR *path= wcsrchr(implib->name, '\\');
10035 if(path)
10036 ++path;
10037 else
10038 path = implib->name;
10039 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10040 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10041 if (strlen == 0)
10042 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10045 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10047 size = strlen + sizeof(INT16);
10048 if (size % 4)
10049 size = (size + 4) & ~0x3;
10050 if (size < 8)
10051 size = 8;
10052 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10054 data += size;
10055 implib->offset = last_offs;
10056 last_offs += size + sizeof(WMSFT_ImpFile);
10060 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10062 MSFT_ImpInfo *info;
10063 TLBRefType *ref_type;
10064 UINT i = 0;
10066 WMSFT_compile_impfile(This, file);
10068 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10069 info = file->impinfo_seg.data = malloc(file->impinfo_seg.len);
10071 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10072 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10073 if(ref_type->index == TLB_REF_USE_GUID){
10074 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10075 info->oGuid = ref_type->guid->offset;
10076 }else
10077 info->oGuid = ref_type->index;
10078 info->oImpFile = ref_type->pImpTLInfo->offset;
10079 ++i;
10080 ++info;
10084 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10086 file->guidhash_seg.len = 0x80;
10087 file->guidhash_seg.data = malloc(file->guidhash_seg.len);
10088 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10091 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10093 file->namehash_seg.len = 0x200;
10094 file->namehash_seg.data = malloc(file->namehash_seg.len);
10095 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10098 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10100 if(contents && contents->len){
10101 segdir->offset = *running_offset;
10102 segdir->length = contents->len;
10103 *running_offset += segdir->length;
10104 }else{
10105 segdir->offset = -1;
10106 segdir->length = 0;
10109 /* TODO: do these ever change? */
10110 segdir->res08 = -1;
10111 segdir->res0c = 0xf;
10114 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10116 DWORD written;
10117 if(segment)
10118 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10121 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10122 DWORD file_len)
10124 DWORD i;
10125 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10127 for(i = 0; i < This->TypeInfoCount; ++i){
10128 base->memoffset += file_len;
10129 ++base;
10132 return S_OK;
10135 static void WMSFT_free_file(WMSFT_TLBFile *file)
10137 free(file->typeinfo_seg.data);
10138 free(file->guidhash_seg.data);
10139 free(file->guid_seg.data);
10140 free(file->ref_seg.data);
10141 free(file->impinfo_seg.data);
10142 free(file->impfile_seg.data);
10143 free(file->namehash_seg.data);
10144 free(file->name_seg.data);
10145 free(file->string_seg.data);
10146 free(file->typdesc_seg.data);
10147 free(file->arraydesc_seg.data);
10148 free(file->custdata_seg.data);
10149 free(file->cdguids_seg.data);
10150 free(file->aux_seg.data);
10153 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10155 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10156 WMSFT_TLBFile file;
10157 DWORD written, junk_size, junk_offs, running_offset;
10158 BOOL br;
10159 HANDLE outfile;
10160 HRESULT hres;
10161 DWORD *junk;
10162 UINT i;
10164 TRACE("%p\n", This);
10166 for(i = 0; i < This->TypeInfoCount; ++i)
10167 if(This->typeinfos[i]->needs_layout)
10168 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10170 memset(&file, 0, sizeof(file));
10172 file.header.magic1 = 0x5446534D;
10173 file.header.magic2 = 0x00010002;
10174 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10175 file.header.lcid2 = This->set_lcid;
10176 file.header.varflags = 0x40 | This->syskind;
10177 if (This->HelpFile)
10178 file.header.varflags |= 0x10;
10179 if (This->HelpStringDll)
10180 file.header.varflags |= HELPDLLFLAG;
10181 file.header.version = (This->ver_minor << 16) | This->ver_major;
10182 file.header.flags = This->libflags;
10183 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10184 file.header.helpcontext = This->dwHelpContext;
10185 file.header.res44 = 0x20;
10186 file.header.res48 = 0x80;
10187 file.header.dispatchpos = This->dispatch_href;
10189 WMSFT_compile_namehash(This, &file);
10190 /* do name and string compilation to get offsets for other compilations */
10191 hres = WMSFT_compile_names(This, &file);
10192 if (FAILED(hres)){
10193 WMSFT_free_file(&file);
10194 return hres;
10197 hres = WMSFT_compile_strings(This, &file);
10198 if (FAILED(hres)){
10199 WMSFT_free_file(&file);
10200 return hres;
10203 WMSFT_compile_guidhash(This, &file);
10204 hres = WMSFT_compile_guids(This, &file);
10205 if (FAILED(hres)){
10206 WMSFT_free_file(&file);
10207 return hres;
10210 if(This->HelpFile)
10211 file.header.helpfile = This->HelpFile->offset;
10212 else
10213 file.header.helpfile = -1;
10215 if(This->DocString)
10216 file.header.helpstring = This->DocString->offset;
10217 else
10218 file.header.helpstring = -1;
10220 /* do some more segment compilation */
10221 file.header.nimpinfos = list_count(&This->ref_list);
10222 file.header.nrtypeinfos = This->TypeInfoCount;
10224 if(This->Name)
10225 file.header.NameOffset = This->Name->offset;
10226 else
10227 file.header.NameOffset = -1;
10229 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10231 if(This->guid)
10232 file.header.posguid = This->guid->offset;
10233 else
10234 file.header.posguid = -1;
10236 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10237 if(file.header.varflags & HELPDLLFLAG)
10238 junk_size += sizeof(DWORD);
10239 if(junk_size){
10240 junk = calloc(1, junk_size);
10241 if(file.header.varflags & HELPDLLFLAG){
10242 *junk = This->HelpStringDll->offset;
10243 junk_offs = 1;
10244 }else
10245 junk_offs = 0;
10246 }else{
10247 junk = NULL;
10248 junk_offs = 0;
10251 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10252 WMSFT_compile_impinfo(This, &file);
10254 running_offset = 0;
10256 TRACE("header at: 0x%lx\n", running_offset);
10257 running_offset += sizeof(file.header);
10259 TRACE("junk at: 0x%lx\n", running_offset);
10260 running_offset += junk_size;
10262 TRACE("segdir at: 0x%lx\n", running_offset);
10263 running_offset += sizeof(file.segdir);
10265 TRACE("typeinfo at: 0x%lx\n", running_offset);
10266 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10268 TRACE("guidhashtab at: 0x%lx\n", running_offset);
10269 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10271 TRACE("guidtab at: 0x%lx\n", running_offset);
10272 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10274 TRACE("reftab at: 0x%lx\n", running_offset);
10275 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10277 TRACE("impinfo at: 0x%lx\n", running_offset);
10278 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10280 TRACE("impfiles at: 0x%lx\n", running_offset);
10281 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10283 TRACE("namehashtab at: 0x%lx\n", running_offset);
10284 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10286 TRACE("nametab at: 0x%lx\n", running_offset);
10287 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10289 TRACE("stringtab at: 0x%lx\n", running_offset);
10290 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10292 TRACE("typdesc at: 0x%lx\n", running_offset);
10293 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10295 TRACE("arraydescriptions at: 0x%lx\n", running_offset);
10296 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10298 TRACE("custdata at: 0x%lx\n", running_offset);
10299 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10301 TRACE("cdguids at: 0x%lx\n", running_offset);
10302 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10304 TRACE("res0e at: 0x%lx\n", running_offset);
10305 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10307 TRACE("res0f at: 0x%lx\n", running_offset);
10308 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10310 TRACE("aux_seg at: 0x%lx\n", running_offset);
10312 WMSFT_fixup_typeinfos(This, &file, running_offset);
10314 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10315 FILE_ATTRIBUTE_NORMAL, 0);
10316 if (outfile == INVALID_HANDLE_VALUE){
10317 WMSFT_free_file(&file);
10318 free(junk);
10319 return TYPE_E_IOERROR;
10322 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10323 if (!br) {
10324 WMSFT_free_file(&file);
10325 CloseHandle(outfile);
10326 free(junk);
10327 return TYPE_E_IOERROR;
10330 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10331 free(junk);
10332 if (!br) {
10333 WMSFT_free_file(&file);
10334 CloseHandle(outfile);
10335 return TYPE_E_IOERROR;
10338 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10339 if (!br) {
10340 WMSFT_free_file(&file);
10341 CloseHandle(outfile);
10342 return TYPE_E_IOERROR;
10345 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10346 WMSFT_write_segment(outfile, &file.guidhash_seg);
10347 WMSFT_write_segment(outfile, &file.guid_seg);
10348 WMSFT_write_segment(outfile, &file.ref_seg);
10349 WMSFT_write_segment(outfile, &file.impinfo_seg);
10350 WMSFT_write_segment(outfile, &file.impfile_seg);
10351 WMSFT_write_segment(outfile, &file.namehash_seg);
10352 WMSFT_write_segment(outfile, &file.name_seg);
10353 WMSFT_write_segment(outfile, &file.string_seg);
10354 WMSFT_write_segment(outfile, &file.typdesc_seg);
10355 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10356 WMSFT_write_segment(outfile, &file.custdata_seg);
10357 WMSFT_write_segment(outfile, &file.cdguids_seg);
10358 WMSFT_write_segment(outfile, &file.aux_seg);
10360 WMSFT_free_file(&file);
10362 CloseHandle(outfile);
10364 return S_OK;
10367 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10368 LPOLESTR name)
10370 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10371 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10372 return E_NOTIMPL;
10375 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10376 REFGUID guid, VARIANT *varVal)
10378 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10379 TLBGuid *tlbguid;
10381 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10383 if (!guid || !varVal)
10384 return E_INVALIDARG;
10386 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10388 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10391 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10392 ULONG helpStringContext)
10394 FIXME("%p, %lu - stub\n", iface, helpStringContext);
10395 return E_NOTIMPL;
10398 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10399 LPOLESTR filename)
10401 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10402 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10404 if (!filename)
10405 return E_INVALIDARG;
10407 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10409 return S_OK;
10412 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10413 ICreateTypeLib2_fnQueryInterface,
10414 ICreateTypeLib2_fnAddRef,
10415 ICreateTypeLib2_fnRelease,
10416 ICreateTypeLib2_fnCreateTypeInfo,
10417 ICreateTypeLib2_fnSetName,
10418 ICreateTypeLib2_fnSetVersion,
10419 ICreateTypeLib2_fnSetGuid,
10420 ICreateTypeLib2_fnSetDocString,
10421 ICreateTypeLib2_fnSetHelpFileName,
10422 ICreateTypeLib2_fnSetHelpContext,
10423 ICreateTypeLib2_fnSetLcid,
10424 ICreateTypeLib2_fnSetLibFlags,
10425 ICreateTypeLib2_fnSaveAllChanges,
10426 ICreateTypeLib2_fnDeleteTypeInfo,
10427 ICreateTypeLib2_fnSetCustData,
10428 ICreateTypeLib2_fnSetHelpStringContext,
10429 ICreateTypeLib2_fnSetHelpStringDll
10432 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10433 REFIID riid, void **object)
10435 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10437 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10440 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10442 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10444 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10447 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10449 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10451 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10454 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10455 REFGUID guid)
10457 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10459 TRACE("%p %s\n", This, debugstr_guid(guid));
10461 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10463 return S_OK;
10466 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10467 UINT typeFlags)
10469 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10470 WORD old_flags;
10471 HRESULT hres;
10473 TRACE("%p %x\n", This, typeFlags);
10475 if (typeFlags & TYPEFLAG_FDUAL) {
10476 ITypeLib *stdole;
10477 ITypeInfo *dispatch;
10478 HREFTYPE hreftype;
10479 HRESULT hres;
10481 hres = LoadTypeLib(L"stdole2.tlb", &stdole);
10482 if(FAILED(hres))
10483 return hres;
10485 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10486 ITypeLib_Release(stdole);
10487 if(FAILED(hres))
10488 return hres;
10490 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10491 ITypeInfo_Release(dispatch);
10492 if(FAILED(hres))
10493 return hres;
10496 old_flags = This->typeattr.wTypeFlags;
10497 This->typeattr.wTypeFlags = typeFlags;
10499 hres = ICreateTypeInfo2_LayOut(iface);
10500 if (FAILED(hres)) {
10501 This->typeattr.wTypeFlags = old_flags;
10502 return hres;
10505 return S_OK;
10508 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10509 LPOLESTR doc)
10511 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10513 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10515 if (!doc)
10516 return E_INVALIDARG;
10518 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10520 return S_OK;
10523 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10524 DWORD helpContext)
10526 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10528 TRACE("%p, %ld.\n", iface, helpContext);
10530 This->dwHelpContext = helpContext;
10532 return S_OK;
10535 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10536 WORD majorVerNum, WORD minorVerNum)
10538 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10540 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10542 This->typeattr.wMajorVerNum = majorVerNum;
10543 This->typeattr.wMinorVerNum = minorVerNum;
10545 return S_OK;
10548 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10549 ITypeInfo *typeInfo, HREFTYPE *refType)
10551 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10552 UINT index;
10553 ITypeLib *container;
10554 TLBRefType *ref_type;
10555 TLBImpLib *implib;
10556 TYPEATTR *typeattr;
10557 TLIBATTR *libattr;
10558 HRESULT hres;
10560 TRACE("%p %p %p\n", This, typeInfo, refType);
10562 if (!typeInfo || !refType)
10563 return E_INVALIDARG;
10565 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10566 if (FAILED(hres))
10567 return hres;
10569 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10570 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10572 ITypeLib_Release(container);
10574 *refType = target->hreftype;
10576 return S_OK;
10579 hres = ITypeLib_GetLibAttr(container, &libattr);
10580 if (FAILED(hres)) {
10581 ITypeLib_Release(container);
10582 return hres;
10585 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10586 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10587 implib->lcid == libattr->lcid &&
10588 implib->wVersionMajor == libattr->wMajorVerNum &&
10589 implib->wVersionMinor == libattr->wMinorVerNum)
10590 break;
10593 if(&implib->entry == &This->pTypeLib->implib_list){
10594 implib = calloc(1, sizeof(TLBImpLib));
10596 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10597 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10598 implib->name = SysAllocString(our_container->path);
10599 }else{
10600 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10601 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10602 if(FAILED(hres)){
10603 implib->name = NULL;
10604 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres);
10608 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10609 implib->lcid = libattr->lcid;
10610 implib->wVersionMajor = libattr->wMajorVerNum;
10611 implib->wVersionMinor = libattr->wMinorVerNum;
10613 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10616 ITypeLib_ReleaseTLibAttr(container, libattr);
10617 ITypeLib_Release(container);
10619 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10620 if (FAILED(hres))
10621 return hres;
10623 index = 0;
10624 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10625 if(ref_type->index == TLB_REF_USE_GUID &&
10626 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10627 ref_type->tkind == typeattr->typekind)
10628 break;
10629 ++index;
10632 if(&ref_type->entry == &This->pTypeLib->ref_list){
10633 ref_type = calloc(1, sizeof(TLBRefType));
10635 ref_type->tkind = typeattr->typekind;
10636 ref_type->pImpTLInfo = implib;
10637 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10639 ref_type->index = TLB_REF_USE_GUID;
10641 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10643 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10646 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10648 *refType = ref_type->reference | 0x1;
10650 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10651 This->pTypeLib->dispatch_href = *refType;
10653 return S_OK;
10656 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10657 UINT index, FUNCDESC *funcDesc)
10659 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10660 TLBFuncDesc tmp_func_desc, *func_desc;
10661 int buf_size, i;
10662 char *buffer;
10663 HRESULT hres;
10665 TRACE("%p %u %p\n", This, index, funcDesc);
10667 if (!funcDesc || funcDesc->oVft & 3)
10668 return E_INVALIDARG;
10670 switch (This->typeattr.typekind) {
10671 case TKIND_MODULE:
10672 if (funcDesc->funckind != FUNC_STATIC)
10673 return TYPE_E_BADMODULEKIND;
10674 break;
10675 case TKIND_DISPATCH:
10676 if (funcDesc->funckind != FUNC_DISPATCH)
10677 return TYPE_E_BADMODULEKIND;
10678 break;
10679 default:
10680 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10681 return TYPE_E_BADMODULEKIND;
10684 if (index > This->typeattr.cFuncs)
10685 return TYPE_E_ELEMENTNOTFOUND;
10687 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10688 !funcDesc->cParams)
10689 return TYPE_E_INCONSISTENTPROPFUNCS;
10691 #ifdef _WIN64
10692 if(This->pTypeLib->syskind == SYS_WIN64 &&
10693 funcDesc->oVft % 8 != 0)
10694 return E_INVALIDARG;
10695 #endif
10697 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10698 TLBFuncDesc_Constructor(&tmp_func_desc);
10700 tmp_func_desc.funcdesc = *funcDesc;
10702 if (tmp_func_desc.funcdesc.oVft != 0)
10703 tmp_func_desc.funcdesc.oVft |= 1;
10705 if (funcDesc->cScodes && funcDesc->lprgscode) {
10706 tmp_func_desc.funcdesc.lprgscode = malloc(sizeof(SCODE) * funcDesc->cScodes);
10707 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10708 } else {
10709 tmp_func_desc.funcdesc.lprgscode = NULL;
10710 tmp_func_desc.funcdesc.cScodes = 0;
10713 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10714 for (i = 0; i < funcDesc->cParams; ++i) {
10715 buf_size += sizeof(ELEMDESC);
10716 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10718 tmp_func_desc.funcdesc.lprgelemdescParam = malloc(buf_size);
10719 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10721 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10722 if (FAILED(hres)) {
10723 free(tmp_func_desc.funcdesc.lprgelemdescParam);
10724 free(tmp_func_desc.funcdesc.lprgscode);
10725 return hres;
10728 for (i = 0; i < funcDesc->cParams; ++i) {
10729 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10730 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10731 if (FAILED(hres)) {
10732 free(tmp_func_desc.funcdesc.lprgelemdescParam);
10733 free(tmp_func_desc.funcdesc.lprgscode);
10734 return hres;
10736 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10737 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10738 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10739 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].paramdesc.pparamdescex->varDefaultValue);
10740 if (FAILED(hres)) {
10741 free(tmp_func_desc.funcdesc.lprgelemdescParam);
10742 free(tmp_func_desc.funcdesc.lprgscode);
10743 return hres;
10748 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10750 if (This->funcdescs) {
10751 This->funcdescs = realloc(This->funcdescs, sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10753 if (index < This->typeattr.cFuncs) {
10754 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10755 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10756 func_desc = This->funcdescs + index;
10757 } else
10758 func_desc = This->funcdescs + This->typeattr.cFuncs;
10760 /* move custdata lists to the new memory location */
10761 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10762 if(index != i)
10763 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10765 } else
10766 func_desc = This->funcdescs = malloc(sizeof(TLBFuncDesc));
10768 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10769 list_init(&func_desc->custdata_list);
10771 ++This->typeattr.cFuncs;
10773 This->needs_layout = TRUE;
10775 return S_OK;
10778 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10779 UINT index, HREFTYPE refType)
10781 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10782 TLBImplType *impl_type;
10783 HRESULT hres;
10785 TRACE("%p, %u, %ld.\n", iface, index, refType);
10787 switch(This->typeattr.typekind){
10788 case TKIND_COCLASS: {
10789 if (index == -1) {
10790 FIXME("Unhandled index: -1\n");
10791 return E_NOTIMPL;
10794 if(index != This->typeattr.cImplTypes)
10795 return TYPE_E_ELEMENTNOTFOUND;
10797 break;
10799 case TKIND_INTERFACE:
10800 case TKIND_DISPATCH:
10801 if (index != 0 || This->typeattr.cImplTypes)
10802 return TYPE_E_ELEMENTNOTFOUND;
10803 break;
10804 default:
10805 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10806 return E_NOTIMPL;
10809 if (This->impltypes){
10810 UINT i;
10812 This->impltypes = realloc(This->impltypes, sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10814 if (index < This->typeattr.cImplTypes) {
10815 memmove(This->impltypes + index + 1, This->impltypes + index,
10816 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10817 impl_type = This->impltypes + index;
10818 } else
10819 impl_type = This->impltypes + This->typeattr.cImplTypes;
10821 /* move custdata lists to the new memory location */
10822 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10823 if(index != i)
10824 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10826 } else
10827 impl_type = This->impltypes = malloc(sizeof(TLBImplType));
10829 memset(impl_type, 0, sizeof(TLBImplType));
10830 TLBImplType_Constructor(impl_type);
10831 impl_type->hRef = refType;
10833 ++This->typeattr.cImplTypes;
10835 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10836 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10838 hres = ICreateTypeInfo2_LayOut(iface);
10839 if (FAILED(hres))
10840 return hres;
10842 return S_OK;
10845 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10846 UINT index, INT implTypeFlags)
10848 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10849 TLBImplType *impl_type = &This->impltypes[index];
10851 TRACE("%p %u %x\n", This, index, implTypeFlags);
10853 if (This->typeattr.typekind != TKIND_COCLASS)
10854 return TYPE_E_BADMODULEKIND;
10856 if (index >= This->typeattr.cImplTypes)
10857 return TYPE_E_ELEMENTNOTFOUND;
10859 impl_type->implflags = implTypeFlags;
10861 return S_OK;
10864 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10865 WORD alignment)
10867 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10869 TRACE("%p %d\n", This, alignment);
10871 This->typeattr.cbAlignment = alignment;
10873 return S_OK;
10876 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10877 LPOLESTR schema)
10879 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10881 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10883 if (!schema)
10884 return E_INVALIDARG;
10886 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10888 This->typeattr.lpstrSchema = This->Schema->str;
10890 return S_OK;
10893 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10894 UINT index, VARDESC *varDesc)
10896 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10897 TLBVarDesc *var_desc;
10898 HRESULT hr;
10900 TRACE("%p %u %p\n", This, index, varDesc);
10902 if (This->vardescs){
10903 UINT i;
10905 This->vardescs = realloc(This->vardescs, sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10907 if (index < This->typeattr.cVars) {
10908 memmove(This->vardescs + index + 1, This->vardescs + index,
10909 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10910 var_desc = This->vardescs + index;
10911 } else {
10912 var_desc = This->vardescs + This->typeattr.cVars;
10913 memset(var_desc, 0, sizeof(TLBVarDesc));
10916 /* move custdata lists to the new memory location */
10917 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10918 if(index != i)
10919 TLB_relink_custdata(&This->vardescs[i].custdata_list);
10921 } else
10922 var_desc = This->vardescs = calloc(1, sizeof(TLBVarDesc));
10924 TLBVarDesc_Constructor(var_desc);
10925 hr = TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10926 if (FAILED(hr))
10927 return hr;
10928 var_desc->vardesc = *var_desc->vardesc_create;
10930 ++This->typeattr.cVars;
10932 This->needs_layout = TRUE;
10934 return S_OK;
10937 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10938 UINT index, LPOLESTR *names, UINT numNames)
10940 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10941 TLBFuncDesc *func_desc = &This->funcdescs[index];
10942 int i;
10944 TRACE("%p %u %p %u\n", This, index, names, numNames);
10946 if (!names)
10947 return E_INVALIDARG;
10949 if (index >= This->typeattr.cFuncs || numNames == 0)
10950 return TYPE_E_ELEMENTNOTFOUND;
10952 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10953 if(numNames > func_desc->funcdesc.cParams)
10954 return TYPE_E_ELEMENTNOTFOUND;
10955 } else
10956 if(numNames > func_desc->funcdesc.cParams + 1)
10957 return TYPE_E_ELEMENTNOTFOUND;
10959 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10960 TLBFuncDesc *iter = &This->funcdescs[i];
10961 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
10962 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10963 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10964 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10965 continue;
10966 return TYPE_E_AMBIGUOUSNAME;
10970 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10972 for (i = 1; i < numNames; ++i) {
10973 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10974 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10977 return S_OK;
10980 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10981 UINT index, LPOLESTR name)
10983 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10985 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10987 if(!name)
10988 return E_INVALIDARG;
10990 if(index >= This->typeattr.cVars)
10991 return TYPE_E_ELEMENTNOTFOUND;
10993 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10994 return S_OK;
10997 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10998 TYPEDESC *tdescAlias)
11000 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11001 HRESULT hr;
11003 TRACE("%p %p\n", This, tdescAlias);
11005 if(!tdescAlias)
11006 return E_INVALIDARG;
11008 if(This->typeattr.typekind != TKIND_ALIAS)
11009 return TYPE_E_BADMODULEKIND;
11011 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11012 if(FAILED(hr))
11013 return hr;
11015 free(This->tdescAlias);
11016 This->tdescAlias = malloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11017 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11019 return S_OK;
11022 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11023 UINT index, LPOLESTR dllName, LPOLESTR procName)
11025 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11026 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11027 return E_NOTIMPL;
11030 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11031 UINT index, LPOLESTR docString)
11033 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11034 TLBFuncDesc *func_desc = &This->funcdescs[index];
11036 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11038 if(!docString)
11039 return E_INVALIDARG;
11041 if(index >= This->typeattr.cFuncs)
11042 return TYPE_E_ELEMENTNOTFOUND;
11044 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11046 return S_OK;
11049 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11050 UINT index, LPOLESTR docString)
11052 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11053 TLBVarDesc *var_desc = &This->vardescs[index];
11055 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11057 if(!docString)
11058 return E_INVALIDARG;
11060 if(index >= This->typeattr.cVars)
11061 return TYPE_E_ELEMENTNOTFOUND;
11063 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11065 return S_OK;
11068 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11069 UINT index, DWORD helpContext)
11071 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11072 TLBFuncDesc *func_desc = &This->funcdescs[index];
11074 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
11076 if(index >= This->typeattr.cFuncs)
11077 return TYPE_E_ELEMENTNOTFOUND;
11079 func_desc->helpcontext = helpContext;
11081 return S_OK;
11084 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11085 UINT index, DWORD helpContext)
11087 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11088 TLBVarDesc *var_desc = &This->vardescs[index];
11090 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
11092 if(index >= This->typeattr.cVars)
11093 return TYPE_E_ELEMENTNOTFOUND;
11095 var_desc->HelpContext = helpContext;
11097 return S_OK;
11100 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11101 UINT index, BSTR bstrMops)
11103 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11104 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11105 return E_NOTIMPL;
11108 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11109 IDLDESC *idlDesc)
11111 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11113 TRACE("%p %p\n", This, idlDesc);
11115 if (!idlDesc)
11116 return E_INVALIDARG;
11118 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11119 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11121 return S_OK;
11124 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11126 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11127 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11128 TLBFuncDesc *func_desc;
11129 UINT user_vft = 0, i, depth = 0;
11130 HRESULT hres = S_OK;
11132 TRACE("%p\n", This);
11134 This->needs_layout = FALSE;
11136 if (This->typeattr.typekind == TKIND_INTERFACE) {
11137 ITypeInfo *inh;
11138 TYPEATTR *attr;
11139 HREFTYPE inh_href;
11141 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11143 if (SUCCEEDED(hres)) {
11144 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11146 if (SUCCEEDED(hres)) {
11147 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11148 if (FAILED(hres)) {
11149 ITypeInfo_Release(inh);
11150 return hres;
11152 This->typeattr.cbSizeVft = attr->cbSizeVft;
11153 ITypeInfo_ReleaseTypeAttr(inh, attr);
11156 ++depth;
11157 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11158 if(SUCCEEDED(hres)){
11159 ITypeInfo *next;
11160 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11161 if(SUCCEEDED(hres)){
11162 ITypeInfo_Release(inh);
11163 inh = next;
11166 }while(SUCCEEDED(hres));
11167 hres = S_OK;
11169 ITypeInfo_Release(inh);
11170 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11171 This->typeattr.cbSizeVft = 0;
11172 hres = S_OK;
11173 } else
11174 return hres;
11175 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11176 This->typeattr.cbSizeVft = 0;
11177 hres = S_OK;
11178 } else
11179 return hres;
11180 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11181 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11182 else
11183 This->typeattr.cbSizeVft = 0;
11185 func_desc = This->funcdescs;
11186 i = 0;
11187 while (i < This->typeattr.cFuncs) {
11188 if (!(func_desc->funcdesc.oVft & 0x1))
11189 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11191 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11192 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11194 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11196 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11197 TLBFuncDesc *iter;
11198 UINT j = 0;
11199 BOOL reset = FALSE;
11201 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11203 iter = This->funcdescs;
11204 while (j < This->typeattr.cFuncs) {
11205 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11206 if (!reset) {
11207 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11208 reset = TRUE;
11209 } else
11210 ++func_desc->funcdesc.memid;
11211 iter = This->funcdescs;
11212 j = 0;
11213 } else {
11214 ++iter;
11215 ++j;
11220 ++func_desc;
11221 ++i;
11224 if (user_vft > This->typeattr.cbSizeVft)
11225 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11227 for(i = 0; i < This->typeattr.cVars; ++i){
11228 TLBVarDesc *var_desc = &This->vardescs[i];
11229 if(var_desc->vardesc.memid == MEMBERID_NIL){
11230 UINT j = 0;
11231 BOOL reset = FALSE;
11232 TLBVarDesc *iter;
11234 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11236 iter = This->vardescs;
11237 while (j < This->typeattr.cVars) {
11238 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11239 if (!reset) {
11240 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11241 reset = TRUE;
11242 } else
11243 ++var_desc->vardesc.memid;
11244 iter = This->vardescs;
11245 j = 0;
11246 } else {
11247 ++iter;
11248 ++j;
11254 return hres;
11257 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11258 UINT index)
11260 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11261 unsigned int i;
11263 TRACE("%p %u\n", This, index);
11265 if (index >= This->typeattr.cFuncs)
11266 return TYPE_E_ELEMENTNOTFOUND;
11268 typeinfo_release_funcdesc(&This->funcdescs[index]);
11270 --This->typeattr.cFuncs;
11271 if (index != This->typeattr.cFuncs)
11273 memmove(This->funcdescs + index, This->funcdescs + index + 1,
11274 sizeof(*This->funcdescs) * (This->typeattr.cFuncs - index));
11275 for (i = index; i < This->typeattr.cFuncs; ++i)
11276 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
11279 This->needs_layout = TRUE;
11281 return S_OK;
11284 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11285 MEMBERID memid, INVOKEKIND invKind)
11287 FIXME("%p, %#lx, %d - stub\n", iface, memid, invKind);
11288 return E_NOTIMPL;
11291 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11292 UINT index)
11294 FIXME("%p, %u - stub\n", iface, index);
11295 return E_NOTIMPL;
11298 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11299 MEMBERID memid)
11301 FIXME("%p, %#lx - stub\n", iface, memid);
11302 return E_NOTIMPL;
11305 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11306 UINT index)
11308 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11309 int i;
11311 TRACE("%p %u\n", This, index);
11313 if (index >= This->typeattr.cImplTypes)
11314 return TYPE_E_ELEMENTNOTFOUND;
11316 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11317 --This->typeattr.cImplTypes;
11319 if (index < This->typeattr.cImplTypes)
11321 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11322 sizeof(*This->impltypes));
11323 for (i = index; i < This->typeattr.cImplTypes; ++i)
11324 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11327 return S_OK;
11330 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11331 REFGUID guid, VARIANT *varVal)
11333 TLBGuid *tlbguid;
11335 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11337 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11339 if (!guid || !varVal)
11340 return E_INVALIDARG;
11342 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11344 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11347 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11348 UINT index, REFGUID guid, VARIANT *varVal)
11350 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11351 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11352 return E_NOTIMPL;
11355 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11356 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11358 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11359 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11360 return E_NOTIMPL;
11363 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11364 UINT index, REFGUID guid, VARIANT *varVal)
11366 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11367 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11368 return E_NOTIMPL;
11371 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11372 UINT index, REFGUID guid, VARIANT *varVal)
11374 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11375 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11376 return E_NOTIMPL;
11379 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11380 ULONG helpStringContext)
11382 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11384 TRACE("%p, %lu.\n", iface, helpStringContext);
11386 This->dwHelpStringContext = helpStringContext;
11388 return S_OK;
11391 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11392 UINT index, ULONG helpStringContext)
11394 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11395 return E_NOTIMPL;
11398 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11399 UINT index, ULONG helpStringContext)
11401 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11402 return E_NOTIMPL;
11405 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11407 FIXME("%p - stub\n", iface);
11408 return E_NOTIMPL;
11411 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11412 LPOLESTR name)
11414 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11416 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11418 if (!name)
11419 return E_INVALIDARG;
11421 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11423 return S_OK;
11426 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11427 ICreateTypeInfo2_fnQueryInterface,
11428 ICreateTypeInfo2_fnAddRef,
11429 ICreateTypeInfo2_fnRelease,
11430 ICreateTypeInfo2_fnSetGuid,
11431 ICreateTypeInfo2_fnSetTypeFlags,
11432 ICreateTypeInfo2_fnSetDocString,
11433 ICreateTypeInfo2_fnSetHelpContext,
11434 ICreateTypeInfo2_fnSetVersion,
11435 ICreateTypeInfo2_fnAddRefTypeInfo,
11436 ICreateTypeInfo2_fnAddFuncDesc,
11437 ICreateTypeInfo2_fnAddImplType,
11438 ICreateTypeInfo2_fnSetImplTypeFlags,
11439 ICreateTypeInfo2_fnSetAlignment,
11440 ICreateTypeInfo2_fnSetSchema,
11441 ICreateTypeInfo2_fnAddVarDesc,
11442 ICreateTypeInfo2_fnSetFuncAndParamNames,
11443 ICreateTypeInfo2_fnSetVarName,
11444 ICreateTypeInfo2_fnSetTypeDescAlias,
11445 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11446 ICreateTypeInfo2_fnSetFuncDocString,
11447 ICreateTypeInfo2_fnSetVarDocString,
11448 ICreateTypeInfo2_fnSetFuncHelpContext,
11449 ICreateTypeInfo2_fnSetVarHelpContext,
11450 ICreateTypeInfo2_fnSetMops,
11451 ICreateTypeInfo2_fnSetTypeIdldesc,
11452 ICreateTypeInfo2_fnLayOut,
11453 ICreateTypeInfo2_fnDeleteFuncDesc,
11454 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11455 ICreateTypeInfo2_fnDeleteVarDesc,
11456 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11457 ICreateTypeInfo2_fnDeleteImplType,
11458 ICreateTypeInfo2_fnSetCustData,
11459 ICreateTypeInfo2_fnSetFuncCustData,
11460 ICreateTypeInfo2_fnSetParamCustData,
11461 ICreateTypeInfo2_fnSetVarCustData,
11462 ICreateTypeInfo2_fnSetImplTypeCustData,
11463 ICreateTypeInfo2_fnSetHelpStringContext,
11464 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11465 ICreateTypeInfo2_fnSetVarHelpStringContext,
11466 ICreateTypeInfo2_fnInvalidate,
11467 ICreateTypeInfo2_fnSetName
11470 /******************************************************************************
11471 * ClearCustData (OLEAUT32.171)
11473 * Clear a custom data type's data.
11475 * PARAMS
11476 * lpCust [I] The custom data type instance
11478 * RETURNS
11479 * Nothing.
11481 void WINAPI ClearCustData(CUSTDATA *lpCust)
11483 if (lpCust && lpCust->cCustData)
11485 if (lpCust->prgCustData)
11487 DWORD i;
11489 for (i = 0; i < lpCust->cCustData; i++)
11490 VariantClear(&lpCust->prgCustData[i].varValue);
11492 CoTaskMemFree(lpCust->prgCustData);
11493 lpCust->prgCustData = NULL;
11495 lpCust->cCustData = 0;