include: Add IFACEMETHOD macros.
[wine.git] / dlls / oleaut32 / typelib.c
blob196f059a5878f227cc96bde98be1df03e9486717
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 static const BOOL is_win64 = sizeof(void *) > sizeof(int);
78 typedef struct
80 WORD offset;
81 WORD length;
82 WORD flags;
83 WORD id;
84 WORD handle;
85 WORD usage;
86 } NE_NAMEINFO;
88 typedef struct
90 WORD type_id; /* Type identifier */
91 WORD count; /* Number of resources of this type */
92 DWORD resloader; /* SetResourceHandler() */
94 * Name info array.
96 } NE_TYPEINFO;
98 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
99 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
100 static void TLB_FreeVarDesc(VARDESC*);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 WCHAR buffer[60];
174 char key_name[16];
175 DWORD len, i;
176 INT best_maj = -1, best_min = -1;
177 HKEY hkey;
179 lstrcpyW( buffer, L"Typelib\\" );
180 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
182 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
183 return FALSE;
185 len = sizeof(key_name);
186 i = 0;
187 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
189 INT v_maj, v_min;
191 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
193 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
195 if (*wMaj == 0xffff && *wMin == 0xffff)
197 if (v_maj > best_maj) best_maj = v_maj;
198 if (v_min > best_min) best_min = v_min;
200 else if (*wMaj == v_maj)
202 best_maj = v_maj;
204 if (*wMin == v_min)
206 best_min = v_min;
207 break; /* exact match */
209 if (*wMin != 0xffff && v_min >= *wMin && v_min > best_min) best_min = v_min;
212 len = sizeof(key_name);
214 RegCloseKey( hkey );
216 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
218 if (*wMaj == 0xffff && *wMin == 0xffff)
220 if (best_maj >= 0 && best_min >= 0)
222 *wMaj = best_maj;
223 *wMin = best_min;
224 return TRUE;
228 if (*wMaj == best_maj && best_min >= 0)
230 *wMin = best_min;
231 return TRUE;
233 return FALSE;
236 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
237 /* buffer must be at least 60 characters long */
238 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
240 lstrcpyW( buffer, L"Typelib\\" );
241 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
242 swprintf( buffer + lstrlenW(buffer), 20, L"\\%x.%x", wMaj, wMin );
243 return buffer;
246 /* get the path of an interface key, in the form "Interface\\<guid>" */
247 /* buffer must be at least 50 characters long */
248 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
250 lstrcpyW( buffer, L"Interface\\" );
251 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
252 return buffer;
255 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
256 /* buffer must be at least 16 characters long */
257 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
259 swprintf( buffer, 16, L"%lx\\", lcid );
260 switch(syskind)
262 case SYS_WIN16: lstrcatW( buffer, L"win16" ); break;
263 case SYS_WIN32: lstrcatW( buffer, L"win32" ); break;
264 case SYS_WIN64: lstrcatW( buffer, L"win64" ); break;
265 default:
266 TRACE("Typelib is for unsupported syskind %i\n", syskind);
267 return NULL;
269 return buffer;
272 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
274 struct tlibredirect_data
276 ULONG size;
277 DWORD res;
278 ULONG name_len;
279 ULONG name_offset;
280 LANGID langid;
281 WORD flags;
282 ULONG help_len;
283 ULONG help_offset;
284 WORD major_version;
285 WORD minor_version;
288 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
289 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
290 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
292 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
293 LCID myLCID = lcid;
294 HKEY hkey;
295 WCHAR buffer[60];
296 WCHAR Path[MAX_PATH];
297 LONG res;
299 TRACE_(typelib)("%s, %x.%x, %#lx, %p\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
301 if (redir)
303 ACTCTX_SECTION_KEYED_DATA data;
305 data.cbSize = sizeof(data);
306 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
308 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
309 WCHAR *nameW;
310 DWORD len;
312 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
313 return TYPE_E_LIBNOTREGISTERED;
315 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
316 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
317 if (!len) return TYPE_E_LIBNOTREGISTERED;
319 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
320 *path = SysAllocString( Path );
321 return S_OK;
325 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
326 get_typelib_key( guid, wMaj, wMin, buffer );
328 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
329 if (res == ERROR_FILE_NOT_FOUND)
331 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
332 return TYPE_E_LIBNOTREGISTERED;
334 else if (res != ERROR_SUCCESS)
336 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
337 return TYPE_E_REGISTRYACCESS;
340 while (hr != S_OK)
342 LONG dwPathLen = sizeof(Path);
344 get_lcid_subkey( myLCID, syskind, buffer );
346 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
348 if (!lcid)
349 break;
350 else if (myLCID == lcid)
352 /* try with sub-langid */
353 myLCID = SUBLANGID(lcid);
355 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
357 /* try with system langid */
358 myLCID = 0;
360 else
362 break;
365 else
367 *path = SysAllocString( Path );
368 hr = S_OK;
371 RegCloseKey( hkey );
372 TRACE_(typelib)("-- %#lx\n", hr);
373 return hr;
376 /****************************************************************************
377 * QueryPathOfRegTypeLib [OLEAUT32.164]
379 * Gets the path to a registered type library.
381 * PARAMS
382 * guid [I] referenced guid
383 * wMaj [I] major version
384 * wMin [I] minor version
385 * lcid [I] locale id
386 * path [O] path of typelib
388 * RETURNS
389 * Success: S_OK.
390 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
391 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
392 * opened.
394 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
396 BOOL redir = TRUE;
397 HRESULT hres = query_typelib_path( guid, wMaj, wMin, is_win64 ? SYS_WIN64 : SYS_WIN32, lcid, path, TRUE );
398 if(SUCCEEDED(hres))
399 return hres;
400 redir = FALSE;
401 return query_typelib_path( guid, wMaj, wMin, is_win64 ? SYS_WIN32 : SYS_WIN64, 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 if(get_ptr_size(sys) != sizeof(void*))
1982 *size += is_win64 ? -8 : 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1983 break;
1984 case VT_DECIMAL:
1985 *size = sizeof(DECIMAL);
1986 break;
1987 case VT_CY:
1988 *size = sizeof(CY);
1989 break;
1990 case VT_CARRAY:
1991 *size = 0;
1992 for(i = 0; i < tdesc->lpadesc->cDims; ++i)
1993 *size += tdesc->lpadesc->rgbounds[i].cElements;
1994 hr = TLB_size_instance(info, sys, &tdesc->lpadesc->tdescElem, &sub, align);
1995 if(FAILED(hr))
1996 return hr;
1997 *size *= sub;
1998 return S_OK;
1999 case VT_USERDEFINED:
2000 return TLB_get_size_from_hreftype(info, tdesc->hreftype, size, align);
2001 default:
2002 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2003 return E_FAIL;
2006 if(align){
2007 if(*size < 4)
2008 *align = *size;
2009 else
2010 *align = 4;
2013 return S_OK;
2016 /**********************************************************************
2018 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2021 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2023 if (where != DO_NOT_SEEK)
2025 where += pcx->oStart;
2026 if (where > pcx->length)
2028 /* FIXME */
2029 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
2030 TLB_abort();
2032 pcx->pos = where;
2036 /* read function */
2037 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2039 TRACE_(typelib)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2040 pcx->pos, count, pcx->oStart, pcx->length, where);
2042 MSFT_Seek(pcx, where);
2043 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2044 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2045 pcx->pos += count;
2046 return count;
2049 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2050 LONG where )
2052 DWORD ret;
2054 ret = MSFT_Read(buffer, count, pcx, where);
2055 FromLEDWords(buffer, ret);
2057 return ret;
2060 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2061 LONG where )
2063 DWORD ret;
2065 ret = MSFT_Read(buffer, count, pcx, where);
2066 FromLEWords(buffer, ret);
2068 return ret;
2071 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2073 TLBGuid *guid;
2074 MSFT_GuidEntry entry;
2075 int offs = 0;
2077 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2078 while (1) {
2079 if (offs >= pcx->pTblDir->pGuidTab.length)
2080 return S_OK;
2082 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2084 guid = malloc(sizeof(TLBGuid));
2086 guid->offset = offs;
2087 guid->guid = entry.guid;
2088 guid->hreftype = entry.hreftype;
2090 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2092 offs += sizeof(MSFT_GuidEntry);
2096 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2098 TLBGuid *ret;
2100 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2101 if(ret->offset == offset){
2102 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2103 return ret;
2107 return NULL;
2110 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2112 MSFT_NameIntro niName;
2114 if (offset < 0)
2116 ERR_(typelib)("bad offset %d\n", offset);
2117 return -1;
2120 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2121 pcx->pTblDir->pNametab.offset+offset);
2123 return niName.hreftype;
2126 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2128 char *string;
2129 MSFT_NameIntro intro;
2130 INT16 len_piece;
2131 int offs = 0, lengthInChars;
2133 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2134 while (1) {
2135 TLBString *tlbstr;
2137 if (offs >= pcx->pTblDir->pNametab.length)
2138 return S_OK;
2140 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2141 intro.namelen &= 0xFF;
2142 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2143 if(len_piece % 4)
2144 len_piece = (len_piece + 4) & ~0x3;
2145 if(len_piece < 8)
2146 len_piece = 8;
2148 string = malloc(len_piece + 1);
2149 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2150 string[intro.namelen] = '\0';
2152 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2153 string, -1, NULL, 0);
2154 if (!lengthInChars) {
2155 free(string);
2156 return E_UNEXPECTED;
2159 tlbstr = malloc(sizeof(TLBString));
2161 tlbstr->offset = offs;
2162 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2163 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2165 free(string);
2167 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2169 offs += len_piece;
2173 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2175 TLBString *tlbstr;
2177 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2178 if (tlbstr->offset == offset) {
2179 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2180 return tlbstr;
2184 return NULL;
2187 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2189 TLBString *tlbstr;
2191 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2192 if (tlbstr->offset == offset) {
2193 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2194 return tlbstr;
2198 return NULL;
2202 * read a value and fill a VARIANT structure
2204 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2206 int size;
2208 TRACE_(typelib)("\n");
2210 if(offset <0) { /* data are packed in here */
2211 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2212 V_I4(pVar) = offset & 0x3ffffff;
2213 return;
2215 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2216 pcx->pTblDir->pCustData.offset + offset );
2217 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2218 switch (V_VT(pVar)){
2219 case VT_EMPTY: /* FIXME: is this right? */
2220 case VT_NULL: /* FIXME: is this right? */
2221 case VT_I2 : /* this should not happen */
2222 case VT_I4 :
2223 case VT_R4 :
2224 case VT_ERROR :
2225 case VT_BOOL :
2226 case VT_I1 :
2227 case VT_UI1 :
2228 case VT_UI2 :
2229 case VT_UI4 :
2230 case VT_INT :
2231 case VT_UINT :
2232 case VT_VOID : /* FIXME: is this right? */
2233 case VT_HRESULT :
2234 size=4; break;
2235 case VT_R8 :
2236 case VT_CY :
2237 case VT_DATE :
2238 case VT_I8 :
2239 case VT_UI8 :
2240 case VT_DECIMAL : /* FIXME: is this right? */
2241 case VT_FILETIME :
2242 size=8;break;
2243 /* pointer types with known behaviour */
2244 case VT_BSTR :{
2245 char * ptr;
2246 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2247 if(size == -1){
2248 V_BSTR(pVar) = NULL;
2249 }else{
2250 int len;
2251 ptr = calloc(1, size);
2252 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2253 len = MultiByteToWideChar(CP_ACP, 0, ptr, size, NULL, 0 );
2254 V_BSTR(pVar)=SysAllocStringLen(NULL,len);
2255 MultiByteToWideChar(CP_ACP, 0, ptr, size, V_BSTR(pVar), len );
2256 free(ptr);
2259 size=-4; break;
2260 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2261 case VT_DISPATCH :
2262 case VT_VARIANT :
2263 case VT_UNKNOWN :
2264 case VT_PTR :
2265 case VT_SAFEARRAY :
2266 case VT_CARRAY :
2267 case VT_USERDEFINED :
2268 case VT_LPSTR :
2269 case VT_LPWSTR :
2270 case VT_BLOB :
2271 case VT_STREAM :
2272 case VT_STORAGE :
2273 case VT_STREAMED_OBJECT :
2274 case VT_STORED_OBJECT :
2275 case VT_BLOB_OBJECT :
2276 case VT_CF :
2277 case VT_CLSID :
2278 default:
2279 size=0;
2280 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2281 V_VT(pVar));
2284 if(size>0) /* (big|small) endian correct? */
2285 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2286 return;
2289 * create a linked list with custom data
2291 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2293 MSFT_CDGuid entry;
2294 TLBCustData* pNew;
2295 int count=0;
2297 TRACE_(typelib)("\n");
2299 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2301 while(offset >=0){
2302 count++;
2303 pNew = calloc(1, sizeof(TLBCustData));
2304 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2305 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2306 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2307 list_add_head(custdata_list, &pNew->entry);
2308 offset = entry.next;
2310 return count;
2313 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2315 if(type <0)
2316 pTd->vt=type & VT_TYPEMASK;
2317 else
2318 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2320 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2323 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2325 return (invkind == INVOKE_PROPERTYGET ||
2326 invkind == INVOKE_PROPERTYPUT ||
2327 invkind == INVOKE_PROPERTYPUTREF);
2330 static void
2331 MSFT_DoFuncs(TLBContext* pcx,
2332 ITypeInfoImpl* pTI,
2333 int cFuncs,
2334 int cVars,
2335 int offset,
2336 TLBFuncDesc** pptfd)
2339 * member information is stored in a data structure at offset
2340 * indicated by the memoffset field of the typeinfo structure
2341 * There are several distinctive parts.
2342 * The first part starts with a field that holds the total length
2343 * of this (first) part excluding this field. Then follow the records,
2344 * for each member there is one record.
2346 * The first entry is always the length of the record (including this
2347 * length word).
2348 * The rest of the record depends on the type of the member. If there is
2349 * a field indicating the member type (function, variable, interface, etc)
2350 * I have not found it yet. At this time we depend on the information
2351 * in the type info and the usual order how things are stored.
2353 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2354 * for each member;
2356 * Third is an equal sized array with file offsets to the name entry
2357 * of each member.
2359 * The fourth and last (?) part is an array with offsets to the records
2360 * in the first part of this file segment.
2363 int infolen, nameoffset, reclength, i;
2364 int recoffset = offset + sizeof(INT);
2366 char *recbuf = malloc(0xffff);
2367 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2368 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2370 TRACE_(typelib)("\n");
2372 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2374 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2375 ptfd = *pptfd;
2376 for ( i = 0; i < cFuncs ; i++ )
2378 int optional;
2380 /* name, eventually add to a hash table */
2381 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2382 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2384 /* read the function information record */
2385 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2387 reclength &= 0xffff;
2389 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2391 /* size without argument data */
2392 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2393 if (pFuncRec->FKCCIC & 0x1000)
2394 optional -= pFuncRec->nrargs * sizeof(INT);
2396 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2397 ptfd->helpcontext = pFuncRec->HelpContext;
2399 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2400 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2402 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2404 if (pFuncRec->FKCCIC & 0x2000 )
2406 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2407 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2408 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2410 else
2411 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2413 else
2414 ptfd->Entry = (TLBString*)-1;
2416 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2417 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2419 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2420 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2422 /* fill the FuncDesc Structure */
2423 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2424 offset + infolen + ( i + 1) * sizeof(INT));
2426 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2427 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2428 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2429 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2430 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2431 if (ptfd->funcdesc.funckind == FUNC_DISPATCH)
2432 ptfd->funcdesc.oVft = 0;
2433 else
2434 ptfd->funcdesc.oVft = (unsigned short)(pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2435 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2437 /* nameoffset is sometimes -1 on the second half of a propget/propput
2438 * pair of functions */
2439 if ((nameoffset == -1) && (i > 0) &&
2440 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2441 TLB_is_propgetput(ptfd->funcdesc.invkind))
2442 ptfd->Name = ptfd_prev->Name;
2443 else
2444 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2446 MSFT_GetTdesc(pcx,
2447 pFuncRec->DataType,
2448 &ptfd->funcdesc.elemdescFunc.tdesc);
2450 /* do the parameters/arguments */
2451 if(pFuncRec->nrargs)
2453 int j = 0;
2454 MSFT_ParameterInfo paraminfo;
2456 ptfd->funcdesc.lprgelemdescParam =
2457 calloc(pFuncRec->nrargs, sizeof(ELEMDESC) + sizeof(PARAMDESCEX));
2459 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2461 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2462 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2464 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2466 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2468 MSFT_GetTdesc(pcx,
2469 paraminfo.DataType,
2470 &elemdesc->tdesc);
2472 elemdesc->paramdesc.wParamFlags = paraminfo.Flags;
2474 /* name */
2475 if (paraminfo.oName != -1)
2476 ptfd->pParamDesc[j].Name =
2477 MSFT_ReadName( pcx, paraminfo.oName );
2478 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2480 /* default value */
2481 if ( (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2482 (pFuncRec->FKCCIC & 0x1000) )
2484 INT* pInt = (INT *)((char *)pFuncRec +
2485 reclength -
2486 (pFuncRec->nrargs * 4) * sizeof(INT) );
2488 PARAMDESC* pParamDesc = &elemdesc->paramdesc;
2490 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2491 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2493 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2494 pInt[j], pcx);
2496 else
2497 elemdesc->paramdesc.pparamdescex = NULL;
2499 /* custom info */
2500 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2501 j*sizeof(pFuncRec->oArgCustData[0])) &&
2502 pFuncRec->FKCCIC & 0x80 )
2504 MSFT_CustData(pcx,
2505 pFuncRec->oArgCustData[j],
2506 &ptfd->pParamDesc[j].custdata_list);
2509 /* SEEK value = jump to offset,
2510 * from there jump to the end of record,
2511 * go back by (j-1) arguments
2513 MSFT_ReadLEDWords( &paraminfo ,
2514 sizeof(MSFT_ParameterInfo), pcx,
2515 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2516 * sizeof(MSFT_ParameterInfo)));
2520 /* scode is not used: archaic win16 stuff FIXME: right? */
2521 ptfd->funcdesc.cScodes = 0 ;
2522 ptfd->funcdesc.lprgscode = NULL ;
2524 ptfd_prev = ptfd;
2525 ++ptfd;
2526 recoffset += reclength;
2528 free(recbuf);
2531 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2532 int cVars, int offset, TLBVarDesc ** pptvd)
2534 int infolen, nameoffset, reclength;
2535 char recbuf[256];
2536 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2537 TLBVarDesc *ptvd;
2538 int i;
2539 int recoffset;
2541 TRACE_(typelib)("\n");
2543 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2544 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2545 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2546 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2547 recoffset += offset+sizeof(INT);
2548 for(i=0;i<cVars;i++, ++ptvd){
2549 /* name, eventually add to a hash table */
2550 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2551 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2552 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2553 /* read the variable information record */
2554 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2555 reclength &= 0xff;
2556 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2558 /* optional data */
2559 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2560 ptvd->HelpContext = pVarRec->HelpContext;
2562 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2563 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2565 if (reclength > FIELD_OFFSET(MSFT_VarRecord, oCustData))
2566 MSFT_CustData(pcx, pVarRec->oCustData, &ptvd->custdata_list);
2568 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2569 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2571 /* fill the VarDesc Structure */
2572 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2573 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2574 ptvd->vardesc.varkind = pVarRec->VarKind;
2575 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2576 MSFT_GetTdesc(pcx, pVarRec->DataType,
2577 &ptvd->vardesc.elemdescVar.tdesc);
2578 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2579 if(pVarRec->VarKind == VAR_CONST ){
2580 ptvd->vardesc.lpvarValue = calloc(1, sizeof(VARIANT));
2581 MSFT_ReadValue(ptvd->vardesc.lpvarValue,
2582 pVarRec->OffsValue, pcx);
2583 } else
2584 ptvd->vardesc.oInst=pVarRec->OffsValue;
2585 recoffset += reclength;
2589 /* process Implemented Interfaces of a com class */
2590 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2591 int offset)
2593 int i;
2594 MSFT_RefRecord refrec;
2595 TLBImplType *pImpl;
2597 TRACE_(typelib)("\n");
2599 pTI->impltypes = TLBImplType_Alloc(count);
2600 pImpl = pTI->impltypes;
2601 for(i=0;i<count;i++){
2602 if(offset<0) break; /* paranoia */
2603 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2604 pImpl->hRef = refrec.reftype;
2605 pImpl->implflags=refrec.flags;
2606 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2607 offset=refrec.onext;
2608 ++pImpl;
2612 /* when a typelib is loaded in a different 32/64-bit mode, we need to resize pointers
2613 * and some structures, and fix the alignment */
2614 static void TLB_fix_typeinfo_ptr_size(ITypeInfoImpl *info)
2616 if(info->typeattr.typekind == TKIND_ALIAS){
2617 switch(info->tdescAlias->vt){
2618 case VT_BSTR:
2619 case VT_DISPATCH:
2620 case VT_UNKNOWN:
2621 case VT_PTR:
2622 case VT_SAFEARRAY:
2623 case VT_LPSTR:
2624 case VT_LPWSTR:
2625 info->typeattr.cbSizeInstance = sizeof(void*);
2626 info->typeattr.cbAlignment = sizeof(void*);
2627 break;
2628 case VT_CARRAY:
2629 case VT_USERDEFINED:
2630 TLB_size_instance(info, is_win64 ? SYS_WIN64 : SYS_WIN32, info->tdescAlias,
2631 &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2632 break;
2633 case VT_VARIANT:
2634 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2635 info->typeattr.cbAlignment = sizeof(void *);
2636 break;
2637 default:
2638 if(info->typeattr.cbSizeInstance < sizeof(void*))
2639 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2640 else
2641 info->typeattr.cbAlignment = sizeof(void*);
2642 break;
2644 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2645 info->typeattr.typekind == TKIND_DISPATCH ||
2646 info->typeattr.typekind == TKIND_COCLASS){
2647 info->typeattr.cbSizeInstance = sizeof(void*);
2648 info->typeattr.cbAlignment = sizeof(void*);
2653 * process a typeinfo record
2655 static ITypeInfoImpl * MSFT_DoTypeInfo(
2656 TLBContext *pcx,
2657 int count,
2658 ITypeLibImpl * pLibInfo)
2660 MSFT_TypeInfoBase tiBase;
2661 ITypeInfoImpl *ptiRet;
2663 TRACE_(typelib)("count=%u\n", count);
2665 ptiRet = ITypeInfoImpl_Constructor();
2666 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2667 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2669 /* this is where we are coming from */
2670 ptiRet->pTypeLib = pLibInfo;
2671 ptiRet->index=count;
2673 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2674 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2675 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2676 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2677 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2678 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2679 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2680 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2681 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2682 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2683 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2684 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2685 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2686 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2687 TYPEDESC tmp;
2688 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2689 ptiRet->tdescAlias = malloc(TLB_SizeTypeDesc(&tmp, TRUE));
2690 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2693 /* FIXME: */
2694 /* IDLDESC idldescType; *//* never saw this one != zero */
2696 /* name, eventually add to a hash table */
2697 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2698 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2699 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2700 /* help info */
2701 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2702 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2703 ptiRet->dwHelpContext=tiBase.helpcontext;
2705 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2706 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2708 /* note: InfoType's Help file and HelpStringDll come from the containing
2709 * library. Further HelpString and Docstring appear to be the same thing :(
2711 /* functions */
2712 if(ptiRet->typeattr.cFuncs >0 )
2713 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2714 ptiRet->typeattr.cVars,
2715 tiBase.memoffset, &ptiRet->funcdescs);
2716 /* variables */
2717 if(ptiRet->typeattr.cVars >0 )
2718 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2719 ptiRet->typeattr.cVars,
2720 tiBase.memoffset, &ptiRet->vardescs);
2721 if(ptiRet->typeattr.cImplTypes >0 ) {
2722 switch(ptiRet->typeattr.typekind)
2724 case TKIND_COCLASS:
2725 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2726 tiBase.datatype1);
2727 break;
2728 case TKIND_DISPATCH:
2729 /* This is not -1 when the interface is a non-base dual interface or
2730 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2731 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2732 not this interface.
2735 if (tiBase.datatype1 != -1)
2737 ptiRet->impltypes = TLBImplType_Alloc(1);
2738 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2740 break;
2741 default:
2742 ptiRet->impltypes = TLBImplType_Alloc(1);
2743 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2744 break;
2747 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2749 TRACE_(typelib)("%s guid: %s kind:%s\n",
2750 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2751 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2752 typekind_desc[ptiRet->typeattr.typekind]);
2753 if (TRACE_ON(typelib))
2754 dump_TypeInfo(ptiRet);
2756 return ptiRet;
2759 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2761 char *string;
2762 INT16 len_str, len_piece;
2763 int offs = 0, lengthInChars;
2765 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2766 while (1) {
2767 TLBString *tlbstr;
2769 if (offs >= pcx->pTblDir->pStringtab.length)
2770 return S_OK;
2772 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2773 len_piece = len_str + sizeof(INT16);
2774 if(len_piece % 4)
2775 len_piece = (len_piece + 4) & ~0x3;
2776 if(len_piece < 8)
2777 len_piece = 8;
2779 string = malloc(len_piece + 1);
2780 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2781 string[len_str] = '\0';
2783 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2784 string, -1, NULL, 0);
2785 if (!lengthInChars) {
2786 free(string);
2787 return E_UNEXPECTED;
2790 tlbstr = malloc(sizeof(TLBString));
2792 tlbstr->offset = offs;
2793 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2794 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2796 free(string);
2798 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2800 offs += len_piece;
2804 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2806 TLBRefType *ref;
2807 int offs = 0;
2809 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2810 while (offs < pcx->pTblDir->pImpInfo.length) {
2811 MSFT_ImpInfo impinfo;
2812 TLBImpLib *pImpLib;
2814 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2816 ref = calloc(1, sizeof(TLBRefType));
2817 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2819 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2820 if(pImpLib->offset==impinfo.oImpFile)
2821 break;
2823 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2824 ref->reference = offs;
2825 ref->pImpTLInfo = pImpLib;
2826 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2827 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2828 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2829 ref->index = TLB_REF_USE_GUID;
2830 } else
2831 ref->index = impinfo.oGuid;
2832 }else{
2833 ERR("Cannot find a reference\n");
2834 ref->reference = -1;
2835 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2838 offs += sizeof(impinfo);
2841 return S_OK;
2844 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2845 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2846 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2847 * tradeoff here.
2849 static struct list tlb_cache = LIST_INIT(tlb_cache);
2850 static CRITICAL_SECTION cache_section;
2851 static CRITICAL_SECTION_DEBUG cache_section_debug =
2853 0, 0, &cache_section,
2854 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2855 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2857 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2860 typedef struct TLB_PEFile
2862 IUnknown IUnknown_iface;
2863 LONG refs;
2864 HMODULE dll;
2865 HRSRC typelib_resource;
2866 HGLOBAL typelib_global;
2867 LPVOID typelib_base;
2868 } TLB_PEFile;
2870 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2872 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2875 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2877 if (IsEqualIID(riid, &IID_IUnknown))
2879 *ppv = iface;
2880 IUnknown_AddRef(iface);
2881 return S_OK;
2883 *ppv = NULL;
2884 return E_NOINTERFACE;
2887 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2889 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2890 return InterlockedIncrement(&This->refs);
2893 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2895 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2896 ULONG refs = InterlockedDecrement(&This->refs);
2897 if (!refs)
2899 if (This->typelib_global)
2900 FreeResource(This->typelib_global);
2901 if (This->dll)
2902 FreeLibrary(This->dll);
2903 free(This);
2905 return refs;
2908 static const IUnknownVtbl TLB_PEFile_Vtable =
2910 TLB_PEFile_QueryInterface,
2911 TLB_PEFile_AddRef,
2912 TLB_PEFile_Release
2915 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2917 TLB_PEFile *This;
2918 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2920 This = malloc(sizeof(TLB_PEFile));
2921 if (!This)
2922 return E_OUTOFMEMORY;
2924 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2925 This->refs = 1;
2926 This->dll = NULL;
2927 This->typelib_resource = NULL;
2928 This->typelib_global = NULL;
2929 This->typelib_base = NULL;
2931 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2932 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2934 if (This->dll)
2936 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), L"TYPELIB");
2937 if (This->typelib_resource)
2939 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2940 if (This->typelib_global)
2942 This->typelib_base = LockResource(This->typelib_global);
2944 if (This->typelib_base)
2946 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2947 *ppBase = This->typelib_base;
2948 *ppFile = &This->IUnknown_iface;
2949 return S_OK;
2954 TRACE("No TYPELIB resource found\n");
2955 hr = E_FAIL;
2958 TLB_PEFile_Release(&This->IUnknown_iface);
2959 return hr;
2962 typedef struct TLB_NEFile
2964 IUnknown IUnknown_iface;
2965 LONG refs;
2966 LPVOID typelib_base;
2967 } TLB_NEFile;
2969 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2971 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2974 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2976 if (IsEqualIID(riid, &IID_IUnknown))
2978 *ppv = iface;
2979 IUnknown_AddRef(iface);
2980 return S_OK;
2982 *ppv = NULL;
2983 return E_NOINTERFACE;
2986 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2988 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2989 return InterlockedIncrement(&This->refs);
2992 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2994 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2995 ULONG refs = InterlockedDecrement(&This->refs);
2996 if (!refs)
2998 free(This->typelib_base);
2999 free(This);
3001 return refs;
3004 static const IUnknownVtbl TLB_NEFile_Vtable =
3006 TLB_NEFile_QueryInterface,
3007 TLB_NEFile_AddRef,
3008 TLB_NEFile_Release
3011 /***********************************************************************
3012 * read_xx_header [internal]
3014 static int read_xx_header( HFILE lzfd )
3016 IMAGE_DOS_HEADER mzh;
3017 char magic[3];
3019 LZSeek( lzfd, 0, SEEK_SET );
3020 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3021 return 0;
3022 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3023 return 0;
3025 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3026 if ( 2 != LZRead( lzfd, magic, 2 ) )
3027 return 0;
3029 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3031 if ( magic[0] == 'N' && magic[1] == 'E' )
3032 return IMAGE_OS2_SIGNATURE;
3033 if ( magic[0] == 'P' && magic[1] == 'E' )
3034 return IMAGE_NT_SIGNATURE;
3036 magic[2] = '\0';
3037 WARN("Can't handle %s files.\n", magic );
3038 return 0;
3042 /***********************************************************************
3043 * find_ne_resource [internal]
3045 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3046 DWORD *resLen, DWORD *resOff )
3048 IMAGE_OS2_HEADER nehd;
3049 NE_TYPEINFO *typeInfo;
3050 NE_NAMEINFO *nameInfo;
3051 DWORD nehdoffset;
3052 LPBYTE resTab;
3053 DWORD resTabSize;
3054 int count;
3056 /* Read in NE header */
3057 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3058 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3060 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3061 if ( !resTabSize )
3063 TRACE("No resources in NE dll\n" );
3064 return FALSE;
3067 /* Read in resource table */
3068 resTab = malloc( resTabSize );
3069 if ( !resTab ) return FALSE;
3071 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3072 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3074 free( resTab );
3075 return FALSE;
3078 /* Find resource */
3079 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3081 if (!IS_INTRESOURCE(typeid)) /* named type */
3083 BYTE len = strlen( typeid );
3084 while (typeInfo->type_id)
3086 if (!(typeInfo->type_id & 0x8000))
3088 BYTE *p = resTab + typeInfo->type_id;
3089 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3091 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3092 typeInfo->count * sizeof(NE_NAMEINFO));
3095 else /* numeric type id */
3097 WORD id = LOWORD(typeid) | 0x8000;
3098 while (typeInfo->type_id)
3100 if (typeInfo->type_id == id) goto found_type;
3101 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3102 typeInfo->count * sizeof(NE_NAMEINFO));
3105 TRACE("No typeid entry found for %p\n", typeid );
3106 free( resTab );
3107 return FALSE;
3109 found_type:
3110 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3112 if (!IS_INTRESOURCE(resid)) /* named resource */
3114 BYTE len = strlen( resid );
3115 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3117 BYTE *p = resTab + nameInfo->id;
3118 if (nameInfo->id & 0x8000) continue;
3119 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3122 else /* numeric resource id */
3124 WORD id = LOWORD(resid) | 0x8000;
3125 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3126 if (nameInfo->id == id) goto found_name;
3128 TRACE("No resid entry found for %p\n", typeid );
3129 free( resTab );
3130 return FALSE;
3132 found_name:
3133 /* Return resource data */
3134 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3135 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3137 free( resTab );
3138 return TRUE;
3141 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3143 HFILE lzfd = -1;
3144 OFSTRUCT ofs;
3145 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3146 TLB_NEFile *This;
3148 This = malloc(sizeof(TLB_NEFile));
3149 if (!This) return E_OUTOFMEMORY;
3151 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3152 This->refs = 1;
3153 This->typelib_base = NULL;
3155 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3156 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3158 DWORD reslen, offset;
3159 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3161 This->typelib_base = malloc(reslen);
3162 if( !This->typelib_base )
3163 hr = E_OUTOFMEMORY;
3164 else
3166 LZSeek( lzfd, offset, SEEK_SET );
3167 reslen = LZRead( lzfd, This->typelib_base, reslen );
3168 LZClose( lzfd );
3169 *ppBase = This->typelib_base;
3170 *pdwTLBLength = reslen;
3171 *ppFile = &This->IUnknown_iface;
3172 return S_OK;
3177 if( lzfd >= 0) LZClose( lzfd );
3178 TLB_NEFile_Release(&This->IUnknown_iface);
3179 return hr;
3182 typedef struct TLB_Mapping
3184 IUnknown IUnknown_iface;
3185 LONG refs;
3186 HANDLE file;
3187 HANDLE mapping;
3188 LPVOID typelib_base;
3189 } TLB_Mapping;
3191 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3193 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3196 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3198 if (IsEqualIID(riid, &IID_IUnknown))
3200 *ppv = iface;
3201 IUnknown_AddRef(iface);
3202 return S_OK;
3204 *ppv = NULL;
3205 return E_NOINTERFACE;
3208 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3210 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3211 return InterlockedIncrement(&This->refs);
3214 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3216 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3217 ULONG refs = InterlockedDecrement(&This->refs);
3218 if (!refs)
3220 if (This->typelib_base)
3221 UnmapViewOfFile(This->typelib_base);
3222 if (This->mapping)
3223 CloseHandle(This->mapping);
3224 if (This->file != INVALID_HANDLE_VALUE)
3225 CloseHandle(This->file);
3226 free(This);
3228 return refs;
3231 static const IUnknownVtbl TLB_Mapping_Vtable =
3233 TLB_Mapping_QueryInterface,
3234 TLB_Mapping_AddRef,
3235 TLB_Mapping_Release
3238 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3240 TLB_Mapping *This;
3242 This = malloc(sizeof(TLB_Mapping));
3243 if (!This)
3244 return E_OUTOFMEMORY;
3246 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3247 This->refs = 1;
3248 This->file = INVALID_HANDLE_VALUE;
3249 This->mapping = NULL;
3250 This->typelib_base = NULL;
3252 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3253 if (INVALID_HANDLE_VALUE != This->file)
3255 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3256 if (This->mapping)
3258 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3259 if(This->typelib_base)
3261 /* retrieve file size */
3262 *pdwTLBLength = GetFileSize(This->file, NULL);
3263 *ppBase = This->typelib_base;
3264 *ppFile = &This->IUnknown_iface;
3265 return S_OK;
3270 IUnknown_Release(&This->IUnknown_iface);
3271 return TYPE_E_CANTLOADLIBRARY;
3274 /****************************************************************************
3275 * TLB_ReadTypeLib
3277 * find the type of the typelib file and map the typelib resource into
3278 * the memory
3281 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3282 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3284 ITypeLibImpl *entry;
3285 HRESULT ret;
3286 INT index = 1;
3287 LPWSTR index_str, file = (LPWSTR)pszFileName;
3288 LPVOID pBase = NULL;
3289 DWORD dwTLBLength = 0;
3290 IUnknown *pFile = NULL;
3291 HANDLE h;
3293 *ppTypeLib = NULL;
3295 index_str = wcsrchr(pszFileName, '\\');
3296 if(index_str && *++index_str != '\0')
3298 LPWSTR end_ptr;
3299 LONG idx = wcstol(index_str, &end_ptr, 10);
3300 if(*end_ptr == '\0')
3302 int str_len = index_str - pszFileName - 1;
3303 index = idx;
3304 file = malloc((str_len + 1) * sizeof(WCHAR));
3305 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3306 file[str_len] = 0;
3310 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3312 if(wcschr(file, '\\'))
3314 lstrcpyW(pszPath, file);
3316 else
3318 int len = GetSystemDirectoryW(pszPath, cchPath);
3319 pszPath[len] = '\\';
3320 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3324 if(file != pszFileName) free(file);
3326 h = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3327 if(h != INVALID_HANDLE_VALUE){
3328 GetFinalPathNameByHandleW(h, pszPath, cchPath, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
3329 CloseHandle(h);
3332 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3334 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3335 EnterCriticalSection(&cache_section);
3336 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3338 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3340 TRACE("cache hit\n");
3341 *ppTypeLib = &entry->ITypeLib2_iface;
3342 ITypeLib2_AddRef(*ppTypeLib);
3343 LeaveCriticalSection(&cache_section);
3344 return S_OK;
3347 LeaveCriticalSection(&cache_section);
3349 /* now actually load and parse the typelib */
3351 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3352 if (ret == TYPE_E_CANTLOADLIBRARY)
3353 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3354 if (ret == TYPE_E_CANTLOADLIBRARY)
3355 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3356 if (SUCCEEDED(ret))
3358 if (dwTLBLength >= 4)
3360 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3361 if (dwSignature == MSFT_SIGNATURE)
3362 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3363 else if (dwSignature == SLTG_SIGNATURE)
3364 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3365 else
3367 FIXME("Header type magic %#lx not supported.\n", dwSignature);
3368 ret = TYPE_E_CANTLOADLIBRARY;
3371 else
3372 ret = TYPE_E_CANTLOADLIBRARY;
3373 IUnknown_Release(pFile);
3376 if(*ppTypeLib) {
3377 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3379 TRACE("adding to cache\n");
3380 impl->path = wcsdup(pszPath);
3381 /* We should really canonicalise the path here. */
3382 impl->index = index;
3384 /* FIXME: check if it has added already in the meantime */
3385 EnterCriticalSection(&cache_section);
3386 list_add_head(&tlb_cache, &impl->entry);
3387 LeaveCriticalSection(&cache_section);
3388 ret = S_OK;
3390 else
3392 if(ret != E_FAIL)
3393 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
3395 ret = TYPE_E_CANTLOADLIBRARY;
3399 return ret;
3402 /*================== ITypeLib(2) Methods ===================================*/
3404 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3406 ITypeLibImpl* pTypeLibImpl;
3408 pTypeLibImpl = calloc(1, sizeof(ITypeLibImpl));
3409 if (!pTypeLibImpl) return NULL;
3411 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3412 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3413 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3414 pTypeLibImpl->ref = 1;
3416 list_init(&pTypeLibImpl->implib_list);
3417 list_init(&pTypeLibImpl->custdata_list);
3418 list_init(&pTypeLibImpl->name_list);
3419 list_init(&pTypeLibImpl->string_list);
3420 list_init(&pTypeLibImpl->guid_list);
3421 list_init(&pTypeLibImpl->ref_list);
3422 pTypeLibImpl->dispatch_href = -1;
3424 return pTypeLibImpl;
3427 /****************************************************************************
3428 * ITypeLib2_Constructor_MSFT
3430 * loading an MSFT typelib from an in-memory image
3432 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3434 TLBContext cx;
3435 LONG lPSegDir;
3436 MSFT_Header tlbHeader;
3437 MSFT_SegDir tlbSegDir;
3438 ITypeLibImpl * pTypeLibImpl;
3439 int i;
3441 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3443 pTypeLibImpl = TypeLibImpl_Constructor();
3444 if (!pTypeLibImpl) return NULL;
3446 /* get pointer to beginning of typelib data */
3447 cx.pos = 0;
3448 cx.oStart=0;
3449 cx.mapping = pLib;
3450 cx.pLibInfo = pTypeLibImpl;
3451 cx.length = dwTLBLength;
3453 /* read header */
3454 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3455 TRACE_(typelib)("header:\n");
3456 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3457 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3458 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3459 return NULL;
3461 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3463 /* there is a small amount of information here until the next important
3464 * part:
3465 * the segment directory . Try to calculate the amount of data */
3466 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3468 /* now read the segment directory */
3469 TRACE("read segment directory (at %ld)\n",lPSegDir);
3470 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3471 cx.pTblDir = &tlbSegDir;
3473 /* just check two entries */
3474 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3476 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir);
3477 free(pTypeLibImpl);
3478 return NULL;
3481 MSFT_ReadAllNames(&cx);
3482 MSFT_ReadAllStrings(&cx);
3483 MSFT_ReadAllGuids(&cx);
3485 /* now fill our internal data */
3486 /* TLIBATTR fields */
3487 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3489 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3490 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3491 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3492 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3493 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3495 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3496 pTypeLibImpl->lcid = tlbHeader.lcid;
3498 /* name, eventually add to a hash table */
3499 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3501 /* help info */
3502 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3503 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3505 if( tlbHeader.varflags & HELPDLLFLAG)
3507 int offset;
3508 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3509 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3512 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3514 /* custom data */
3515 if(tlbHeader.CustomDataOffset >= 0)
3517 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3520 /* fill in type descriptions */
3521 if(tlbSegDir.pTypdescTab.length > 0)
3523 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3524 INT16 td[4];
3525 pTypeLibImpl->ctTypeDesc = cTD;
3526 pTypeLibImpl->pTypeDesc = calloc(cTD, sizeof(TYPEDESC));
3527 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3528 for(i=0; i<cTD; )
3530 /* FIXME: add several sanity checks here */
3531 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3532 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3534 /* FIXME: check safearray */
3535 if(td[3] < 0)
3536 pTypeLibImpl->pTypeDesc[i].lptdesc = &std_typedesc[td[2]];
3537 else
3538 pTypeLibImpl->pTypeDesc[i].lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3540 else if(td[0] == VT_CARRAY)
3542 /* array descr table here */
3543 pTypeLibImpl->pTypeDesc[i].lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3545 else if(td[0] == VT_USERDEFINED)
3547 pTypeLibImpl->pTypeDesc[i].hreftype = MAKELONG(td[2],td[3]);
3549 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3552 /* second time around to fill the array subscript info */
3553 for(i=0;i<cTD;i++)
3555 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3556 if(tlbSegDir.pArrayDescriptions.offset>0)
3558 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].lpadesc);
3559 pTypeLibImpl->pTypeDesc[i].lpadesc = calloc(1, sizeof(ARRAYDESC) + sizeof(SAFEARRAYBOUND) * (td[3] - 1));
3561 if(td[1]<0)
3562 pTypeLibImpl->pTypeDesc[i].lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3563 else
3564 pTypeLibImpl->pTypeDesc[i].lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3566 pTypeLibImpl->pTypeDesc[i].lpadesc->cDims = td[2];
3568 for(j = 0; j<td[2]; j++)
3570 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].lpadesc->rgbounds[j].cElements,
3571 sizeof(INT), &cx, DO_NOT_SEEK);
3572 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].lpadesc->rgbounds[j].lLbound,
3573 sizeof(INT), &cx, DO_NOT_SEEK);
3576 else
3578 pTypeLibImpl->pTypeDesc[i].lpadesc = NULL;
3579 ERR("didn't find array description data\n");
3584 /* imported type libs */
3585 if(tlbSegDir.pImpFiles.offset>0)
3587 TLBImpLib *pImpLib;
3588 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3589 UINT16 size;
3591 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3593 char *name;
3595 pImpLib = calloc(1, sizeof(TLBImpLib));
3596 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3597 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3599 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3600 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3601 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3602 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3604 size >>= 2;
3605 name = calloc(1, size + 1);
3606 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3607 pImpLib->name = TLB_MultiByteToBSTR(name);
3608 free(name);
3610 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3611 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3613 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3617 MSFT_ReadAllRefs(&cx);
3619 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3621 /* type infos */
3622 if(tlbHeader.nrtypeinfos >= 0 )
3624 ITypeInfoImpl **ppTI;
3626 ppTI = pTypeLibImpl->typeinfos = calloc(tlbHeader.nrtypeinfos, sizeof(ITypeInfoImpl*));
3628 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3630 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3632 ++ppTI;
3633 (pTypeLibImpl->TypeInfoCount)++;
3637 if (pTypeLibImpl->ptr_size != sizeof(void *))
3639 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3640 TLB_fix_typeinfo_ptr_size(pTypeLibImpl->typeinfos[i]);
3643 TRACE("(%p)\n", pTypeLibImpl);
3644 return &pTypeLibImpl->ITypeLib2_iface;
3648 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3650 char b[3];
3651 int i;
3652 short s;
3654 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3655 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3656 return FALSE;
3659 guid->Data4[0] = s >> 8;
3660 guid->Data4[1] = s & 0xff;
3662 b[2] = '\0';
3663 for(i = 0; i < 6; i++) {
3664 memcpy(b, str + 24 + 2 * i, 2);
3665 guid->Data4[i + 2] = strtol(b, NULL, 16);
3667 return TRUE;
3670 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3672 WORD bytelen;
3673 DWORD len;
3674 BSTR tmp_str;
3676 *pStr = NULL;
3677 bytelen = *(const WORD*)ptr;
3678 if(bytelen == 0xffff) return 2;
3680 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3681 tmp_str = SysAllocStringLen(NULL, len);
3682 if (tmp_str) {
3683 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3684 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3685 SysFreeString(tmp_str);
3687 return bytelen + 2;
3690 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3692 WORD bytelen;
3694 *str = NULL;
3695 bytelen = *(const WORD*)ptr;
3696 if(bytelen == 0xffff) return 2;
3697 *str = malloc(bytelen + 1);
3698 memcpy(*str, ptr + 2, bytelen);
3699 (*str)[bytelen] = '\0';
3700 return bytelen + 2;
3703 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3705 BSTR tmp_str;
3706 TLBString *tlbstr;
3708 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3709 if (tlbstr->offset == offset)
3710 return tlbstr;
3713 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3714 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3715 SysFreeString(tmp_str);
3717 return tlbstr;
3720 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3722 char *ptr = pLibBlk;
3723 WORD w;
3725 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3726 FIXME("libblk magic = %04x\n", w);
3727 return 0;
3730 ptr += 6;
3731 if((w = *(WORD*)ptr) != 0xffff) {
3732 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w);
3733 ptr += w;
3735 ptr += 2;
3737 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3739 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3741 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3742 ptr += 4;
3744 pTypeLibImpl->syskind = *(WORD*)ptr;
3745 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3746 ptr += 2;
3748 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3749 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3750 else
3751 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3752 ptr += 2;
3754 ptr += 4; /* skip res12 */
3756 pTypeLibImpl->libflags = *(WORD*)ptr;
3757 ptr += 2;
3759 pTypeLibImpl->ver_major = *(WORD*)ptr;
3760 ptr += 2;
3762 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3763 ptr += 2;
3765 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3766 ptr += sizeof(GUID);
3768 return ptr - (char*)pLibBlk;
3771 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3772 typedef struct
3774 unsigned int num;
3775 HREFTYPE refs[1];
3776 } sltg_ref_lookup_t;
3778 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3779 HREFTYPE *typelib_ref)
3781 if(table && typeinfo_ref < table->num)
3783 *typelib_ref = table->refs[typeinfo_ref];
3784 return S_OK;
3787 ERR_(typelib)("Unable to find reference\n");
3788 *typelib_ref = -1;
3789 return E_FAIL;
3792 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3794 BOOL done = FALSE;
3796 while(!done) {
3797 if((*pType & 0xe00) == 0xe00) {
3798 pTD->vt = VT_PTR;
3799 pTD->lptdesc = calloc(1, sizeof(TYPEDESC));
3800 pTD = pTD->lptdesc;
3802 switch(*pType & 0x3f) {
3803 case VT_PTR:
3804 pTD->vt = VT_PTR;
3805 pTD->lptdesc = calloc(1, sizeof(TYPEDESC));
3806 pTD = pTD->lptdesc;
3807 break;
3809 case VT_USERDEFINED:
3810 pTD->vt = VT_USERDEFINED;
3811 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->hreftype);
3812 done = TRUE;
3813 break;
3815 case VT_CARRAY:
3817 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3818 array */
3820 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3822 pTD->vt = VT_CARRAY;
3823 pTD->lpadesc = calloc(1, sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3824 pTD->lpadesc->cDims = pSA->cDims;
3825 memcpy(pTD->lpadesc->rgbounds, pSA->rgsabound,
3826 pSA->cDims * sizeof(SAFEARRAYBOUND));
3828 pTD = &pTD->lpadesc->tdescElem;
3829 break;
3832 case VT_SAFEARRAY:
3834 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3835 useful? */
3837 pType++;
3838 pTD->vt = VT_SAFEARRAY;
3839 pTD->lptdesc = calloc(1, sizeof(TYPEDESC));
3840 pTD = pTD->lptdesc;
3841 break;
3843 default:
3844 pTD->vt = *pType & 0x3f;
3845 done = TRUE;
3846 break;
3848 pType++;
3850 return pType;
3853 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3854 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3856 /* Handle [in/out] first */
3857 if((*pType & 0xc000) == 0xc000)
3858 pElem->paramdesc.wParamFlags = PARAMFLAG_NONE;
3859 else if(*pType & 0x8000)
3860 pElem->paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3861 else if(*pType & 0x4000)
3862 pElem->paramdesc.wParamFlags = PARAMFLAG_FOUT;
3863 else
3864 pElem->paramdesc.wParamFlags = PARAMFLAG_FIN;
3866 if(*pType & 0x2000)
3867 pElem->paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3869 if(*pType & 0x80)
3870 pElem->paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3872 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3876 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3877 char *pNameTable)
3879 unsigned int ref;
3880 char *name;
3881 TLBRefType *ref_type;
3882 sltg_ref_lookup_t *table;
3883 HREFTYPE typelib_ref;
3885 if(pRef->magic != SLTG_REF_MAGIC) {
3886 FIXME("Ref magic = %x\n", pRef->magic);
3887 return NULL;
3889 name = ( (char*)pRef->names + pRef->number);
3891 table = malloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3892 table->num = pRef->number >> 3;
3894 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3896 /* We don't want the first href to be 0 */
3897 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3899 for(ref = 0; ref < pRef->number >> 3; ref++) {
3900 char *refname;
3901 unsigned int lib_offs, type_num;
3903 ref_type = calloc(1, sizeof(TLBRefType));
3905 name += SLTG_ReadStringA(name, &refname);
3906 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3907 FIXME_(typelib)("Can't sscanf ref\n");
3908 if(lib_offs != 0xffff) {
3909 TLBImpLib *import;
3911 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3912 if(import->offset == lib_offs)
3913 break;
3915 if(&import->entry == &pTL->implib_list) {
3916 char fname[MAX_PATH+1];
3917 int len;
3918 GUID tmpguid;
3920 import = calloc(1, sizeof(*import));
3921 import->offset = lib_offs;
3922 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3923 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3924 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
3925 &import->wVersionMajor,
3926 &import->wVersionMinor,
3927 &import->lcid, fname) != 4) {
3928 FIXME_(typelib)("can't sscanf ref %s\n",
3929 pNameTable + lib_offs + 40);
3931 len = strlen(fname);
3932 if(fname[len-1] != '#')
3933 FIXME("fname = %s\n", fname);
3934 fname[len-1] = '\0';
3935 import->name = TLB_MultiByteToBSTR(fname);
3936 list_add_tail(&pTL->implib_list, &import->entry);
3938 ref_type->pImpTLInfo = import;
3940 /* Store a reference to IDispatch */
3941 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3942 pTL->dispatch_href = typelib_ref;
3944 } else { /* internal ref */
3945 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3947 ref_type->reference = typelib_ref;
3948 ref_type->index = type_num;
3950 free(refname);
3951 list_add_tail(&pTL->ref_list, &ref_type->entry);
3953 table->refs[ref] = typelib_ref;
3954 typelib_ref += 4;
3956 if((BYTE)*name != SLTG_REF_MAGIC)
3957 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3958 dump_TLBRefType(pTL);
3959 return table;
3962 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3963 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3965 SLTG_ImplInfo *info;
3966 TLBImplType *pImplType;
3967 /* I don't really get this structure, usually it's 0x16 bytes
3968 long, but iuser.tlb contains some that are 0x18 bytes long.
3969 That's ok because we can use the next ptr to jump to the next
3970 one. But how do we know the length of the last one? The WORD
3971 at offs 0x8 might be the clue. For now I'm just assuming that
3972 the last one is the regular 0x16 bytes. */
3974 info = (SLTG_ImplInfo*)pBlk;
3975 while(1){
3976 pTI->typeattr.cImplTypes++;
3977 if(info->next == 0xffff)
3978 break;
3979 info = (SLTG_ImplInfo*)(pBlk + info->next);
3982 info = (SLTG_ImplInfo*)pBlk;
3983 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3984 pImplType = pTI->impltypes;
3985 while(1) {
3986 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3987 pImplType->implflags = info->impltypeflags;
3988 ++pImplType;
3990 if(info->next == 0xffff)
3991 break;
3992 if(OneOnly)
3993 FIXME_(typelib)("Interface inheriting more than one interface\n");
3994 info = (SLTG_ImplInfo*)(pBlk + info->next);
3996 info++; /* see comment at top of function */
3997 return (char*)info;
4000 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4001 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4003 TLBVarDesc *pVarDesc;
4004 const TLBString *prevName = NULL;
4005 SLTG_Variable *pItem;
4006 unsigned short i;
4007 WORD *pType;
4009 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4011 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4012 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4014 pVarDesc->vardesc.memid = pItem->memid;
4016 if (pItem->magic != SLTG_VAR_MAGIC &&
4017 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4018 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4019 return;
4022 if (pItem->name == 0xfffe)
4023 pVarDesc->Name = prevName;
4024 else
4025 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4027 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4028 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4029 TRACE_(typelib)("memid = %#lx\n", pItem->memid);
4031 if(pItem->flags & 0x02)
4032 pType = &pItem->type;
4033 else
4034 pType = (WORD*)(pBlk + pItem->type);
4036 if (pItem->flags & ~0xda)
4037 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4039 SLTG_DoElem(pType, pBlk,
4040 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4042 if (TRACE_ON(typelib)) {
4043 char buf[300];
4044 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4045 TRACE_(typelib)("elemdescVar: %s\n", buf);
4048 if (pItem->flags & 0x40) {
4049 TRACE_(typelib)("VAR_DISPATCH\n");
4050 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4052 else if (pItem->flags & 0x10) {
4053 TRACE_(typelib)("VAR_CONST\n");
4054 pVarDesc->vardesc.varkind = VAR_CONST;
4055 pVarDesc->vardesc.lpvarValue = malloc(sizeof(VARIANT));
4056 V_VT(pVarDesc->vardesc.lpvarValue) = VT_INT;
4057 if (pItem->flags & 0x08)
4058 V_INT(pVarDesc->vardesc.lpvarValue) = pItem->byte_offs;
4059 else {
4060 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4062 case VT_LPSTR:
4063 case VT_LPWSTR:
4064 case VT_BSTR:
4066 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4067 BSTR str;
4068 TRACE_(typelib)("len = %u\n", len);
4069 if (len == 0xffff) {
4070 str = NULL;
4071 } else {
4072 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4073 str = SysAllocStringLen(NULL, alloc_len);
4074 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4076 V_VT(pVarDesc->vardesc.lpvarValue) = VT_BSTR;
4077 V_BSTR(pVarDesc->vardesc.lpvarValue) = str;
4078 break;
4080 case VT_I2:
4081 case VT_UI2:
4082 case VT_I4:
4083 case VT_UI4:
4084 case VT_INT:
4085 case VT_UINT:
4086 V_INT(pVarDesc->vardesc.lpvarValue) =
4087 *(INT*)(pBlk + pItem->byte_offs);
4088 break;
4089 default:
4090 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4094 else {
4095 TRACE_(typelib)("VAR_PERINSTANCE\n");
4096 pVarDesc->vardesc.oInst = pItem->byte_offs;
4097 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4100 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4101 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4103 if (pItem->flags & 0x80)
4104 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4106 prevName = pVarDesc->Name;
4108 pTI->typeattr.cVars = cVars;
4111 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4112 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4114 SLTG_Function *pFunc;
4115 unsigned short i;
4116 TLBFuncDesc *pFuncDesc;
4118 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4120 pFuncDesc = pTI->funcdescs;
4121 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4122 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4124 int param;
4125 WORD *pType, *pArg;
4127 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4128 case SLTG_FUNCTION_MAGIC:
4129 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4130 break;
4131 case SLTG_DISPATCH_FUNCTION_MAGIC:
4132 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4133 break;
4134 case SLTG_STATIC_FUNCTION_MAGIC:
4135 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4136 break;
4137 default:
4138 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4139 continue;
4141 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4143 pFuncDesc->funcdesc.memid = pFunc->dispid;
4144 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4145 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4146 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4147 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4148 if (pFuncDesc->funcdesc.funckind == FUNC_DISPATCH)
4149 pFuncDesc->funcdesc.oVft = 0;
4150 else
4151 pFuncDesc->funcdesc.oVft = (unsigned short)(pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4153 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4154 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4156 if(pFunc->retnextopt & 0x80)
4157 pType = &pFunc->rettype;
4158 else
4159 pType = (WORD*)(pBlk + pFunc->rettype);
4161 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4163 pFuncDesc->funcdesc.lprgelemdescParam =
4164 calloc(pFuncDesc->funcdesc.cParams, sizeof(ELEMDESC));
4165 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4167 pArg = (WORD*)(pBlk + pFunc->arg_off);
4169 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4170 char *paramName = pNameTable + *pArg;
4171 BOOL HaveOffs;
4172 /* If arg type follows then paramName points to the 2nd
4173 letter of the name, else the next WORD is an offset to
4174 the arg type and paramName points to the first letter.
4175 So let's take one char off paramName and see if we're
4176 pointing at an alphanumeric char. However if *pArg is
4177 0xffff or 0xfffe then the param has no name, the former
4178 meaning that the next WORD is the type, the latter
4179 meaning that the next WORD is an offset to the type. */
4181 HaveOffs = FALSE;
4182 if(*pArg == 0xffff)
4183 paramName = NULL;
4184 else if(*pArg == 0xfffe) {
4185 paramName = NULL;
4186 HaveOffs = TRUE;
4188 else if(paramName[-1] && !isalnum(paramName[-1]))
4189 HaveOffs = TRUE;
4191 pArg++;
4193 if(HaveOffs) { /* the next word is an offset to type */
4194 pType = (WORD*)(pBlk + *pArg);
4195 SLTG_DoElem(pType, pBlk,
4196 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4197 pArg++;
4198 } else {
4199 if(paramName)
4200 paramName--;
4201 pArg = SLTG_DoElem(pArg, pBlk,
4202 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4205 /* Are we an optional param ? */
4206 if(pFuncDesc->funcdesc.cParams - param <=
4207 pFuncDesc->funcdesc.cParamsOpt)
4208 pFuncDesc->funcdesc.lprgelemdescParam[param].paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4210 if(paramName) {
4211 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4212 paramName - pNameTable, pTI->pTypeLib);
4213 } else {
4214 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4218 pTI->typeattr.cFuncs = cFuncs;
4221 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4222 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4223 SLTG_TypeInfoTail *pTITail)
4225 char *pFirstItem;
4226 sltg_ref_lookup_t *ref_lookup = NULL;
4228 if(pTIHeader->href_table != 0xffffffff) {
4229 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4230 pNameTable);
4233 pFirstItem = pBlk;
4235 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4236 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4238 free(ref_lookup);
4242 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4243 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4244 const SLTG_TypeInfoTail *pTITail)
4246 char *pFirstItem;
4247 sltg_ref_lookup_t *ref_lookup = NULL;
4249 if(pTIHeader->href_table != 0xffffffff) {
4250 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4251 pNameTable);
4254 pFirstItem = pBlk;
4256 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4257 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4260 if (pTITail->funcs_off != 0xffff)
4261 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4263 free(ref_lookup);
4265 if (TRACE_ON(typelib))
4266 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4269 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4270 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4271 const SLTG_TypeInfoTail *pTITail)
4273 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4276 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4277 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4278 const SLTG_TypeInfoTail *pTITail)
4280 WORD *pType;
4281 sltg_ref_lookup_t *ref_lookup = NULL;
4283 if (pTITail->simple_alias) {
4284 /* if simple alias, no more processing required */
4285 pTI->tdescAlias = calloc(1, sizeof(TYPEDESC));
4286 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4287 return;
4290 if(pTIHeader->href_table != 0xffffffff) {
4291 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4292 pNameTable);
4295 /* otherwise it is an offset to a type */
4296 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4298 pTI->tdescAlias = malloc(sizeof(TYPEDESC));
4299 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4301 free(ref_lookup);
4304 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4305 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4306 const SLTG_TypeInfoTail *pTITail)
4308 sltg_ref_lookup_t *ref_lookup = NULL;
4309 if (pTIHeader->href_table != 0xffffffff)
4310 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4311 pNameTable);
4313 if (pTITail->vars_off != 0xffff)
4314 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4316 if (pTITail->funcs_off != 0xffff)
4317 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4319 if (pTITail->impls_off != 0xffff)
4320 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4322 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4323 * of dispinterface functions including the IDispatch ones, so
4324 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4325 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4327 free(ref_lookup);
4328 if (TRACE_ON(typelib))
4329 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4332 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4333 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4334 const SLTG_TypeInfoTail *pTITail)
4336 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4339 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4340 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4341 const SLTG_TypeInfoTail *pTITail)
4343 sltg_ref_lookup_t *ref_lookup = NULL;
4344 if (pTIHeader->href_table != 0xffffffff)
4345 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4346 pNameTable);
4348 if (pTITail->vars_off != 0xffff)
4349 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4351 if (pTITail->funcs_off != 0xffff)
4352 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4353 free(ref_lookup);
4354 if (TRACE_ON(typelib))
4355 dump_TypeInfo(pTI);
4358 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4359 manageable copy of it into this */
4360 typedef struct {
4361 WORD small_no;
4362 char *index_name;
4363 char *other_name;
4364 WORD res1a;
4365 WORD name_offs;
4366 WORD more_bytes;
4367 char *extra;
4368 WORD res20;
4369 DWORD helpcontext;
4370 WORD res26;
4371 GUID uuid;
4372 } SLTG_InternalOtherTypeInfo;
4374 /****************************************************************************
4375 * ITypeLib2_Constructor_SLTG
4377 * loading a SLTG typelib from an in-memory image
4379 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4381 ITypeLibImpl *pTypeLibImpl;
4382 SLTG_Header *pHeader;
4383 SLTG_BlkEntry *pBlkEntry;
4384 SLTG_Magic *pMagic;
4385 SLTG_Index *pIndex;
4386 SLTG_Pad9 *pPad9;
4387 LPVOID pBlk, pFirstBlk;
4388 SLTG_LibBlk *pLibBlk;
4389 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4390 char *pAfterOTIBlks = NULL;
4391 char *pNameTable, *ptr;
4392 int i;
4393 DWORD len, order;
4394 ITypeInfoImpl **ppTypeInfoImpl;
4396 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
4399 pTypeLibImpl = TypeLibImpl_Constructor();
4400 if (!pTypeLibImpl) return NULL;
4402 pHeader = pLib;
4404 TRACE_(typelib)("header:\n");
4405 TRACE_(typelib)("\tmagic %#lx, file blocks = %d\n", pHeader->SLTG_magic,
4406 pHeader->nrOfFileBlks );
4407 if (pHeader->SLTG_magic != SLTG_SIGNATURE)
4409 FIXME_(typelib)("Header type magic %#lx not supported.\n", pHeader->SLTG_magic);
4410 return NULL;
4413 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4414 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4416 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4417 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4419 /* Next we have a magic block */
4420 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4422 /* Let's see if we're still in sync */
4423 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4424 sizeof(SLTG_COMPOBJ_MAGIC))) {
4425 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4426 return NULL;
4428 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4429 sizeof(SLTG_DIR_MAGIC))) {
4430 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4431 return NULL;
4434 pIndex = (SLTG_Index*)(pMagic+1);
4436 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4438 pFirstBlk = pPad9 + 1;
4440 /* We'll set up a ptr to the main library block, which is the last one. */
4442 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4443 pBlkEntry[order].next != 0;
4444 order = pBlkEntry[order].next - 1) {
4445 pBlk = (char*)pBlk + pBlkEntry[order].len;
4447 pLibBlk = pBlk;
4449 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4451 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4452 interspersed */
4454 len += 0x40;
4456 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4458 pOtherTypeInfoBlks = calloc(pTypeLibImpl->TypeInfoCount, sizeof(*pOtherTypeInfoBlks));
4461 ptr = (char*)pLibBlk + len;
4463 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4464 WORD w, extra;
4465 len = 0;
4467 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4469 w = *(WORD*)(ptr + 2);
4470 if(w != 0xffff) {
4471 len += w;
4472 pOtherTypeInfoBlks[i].index_name = malloc(w + 1);
4473 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4474 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4476 w = *(WORD*)(ptr + 4 + len);
4477 if(w != 0xffff) {
4478 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4479 len += w;
4480 pOtherTypeInfoBlks[i].other_name = malloc(w + 1);
4481 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4482 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4484 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4485 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4486 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4487 if(extra) {
4488 pOtherTypeInfoBlks[i].extra = malloc(extra);
4489 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4490 len += extra;
4492 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4493 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4494 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4495 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4496 len += sizeof(SLTG_OtherTypeInfo);
4497 ptr += len;
4500 pAfterOTIBlks = ptr;
4502 /* Skip this WORD and get the next DWORD */
4503 len = *(DWORD*)(pAfterOTIBlks + 2);
4505 /* Now add this to pLibBLk look at what we're pointing at and
4506 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4507 dust and we should be pointing at the beginning of the name
4508 table */
4510 pNameTable = (char*)pLibBlk + len;
4512 switch(*(WORD*)pNameTable) {
4513 case 0xffff:
4514 break;
4515 case 0x0200:
4516 pNameTable += 0x20;
4517 break;
4518 default:
4519 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4520 break;
4523 pNameTable += 0x216;
4525 pNameTable += 2;
4527 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4529 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4532 /* Hopefully we now have enough ptrs set up to actually read in
4533 some TypeInfos. It's not clear which order to do them in, so
4534 I'll just follow the links along the BlkEntry chain and read
4535 them in the order in which they are in the file */
4537 pTypeLibImpl->typeinfos = calloc(pTypeLibImpl->TypeInfoCount, sizeof(ITypeInfoImpl*));
4538 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4540 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4541 pBlkEntry[order].next != 0;
4542 order = pBlkEntry[order].next - 1, i++) {
4544 SLTG_TypeInfoHeader *pTIHeader;
4545 SLTG_TypeInfoTail *pTITail;
4546 SLTG_MemberHeader *pMemHeader;
4548 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4549 FIXME_(typelib)("Index strings don't match\n");
4550 free(pOtherTypeInfoBlks);
4551 return NULL;
4554 pTIHeader = pBlk;
4555 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4556 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4557 free(pOtherTypeInfoBlks);
4558 return NULL;
4560 TRACE_(typelib)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4561 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4562 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4564 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4565 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4566 (*ppTypeInfoImpl)->index = i;
4567 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4568 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4569 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4570 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4571 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4572 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4573 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4574 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4576 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4577 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4579 if((pTIHeader->typeflags1 & 7) != 2)
4580 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4581 if(pTIHeader->typeflags3 != 2)
4582 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4584 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4585 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4586 typekind_desc[pTIHeader->typekind],
4587 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4588 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4590 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4592 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4594 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4595 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4596 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4598 switch(pTIHeader->typekind) {
4599 case TKIND_ENUM:
4600 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4601 pTIHeader, pTITail);
4602 break;
4604 case TKIND_RECORD:
4605 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4606 pTIHeader, pTITail);
4607 break;
4609 case TKIND_INTERFACE:
4610 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4611 pTIHeader, pTITail);
4612 break;
4614 case TKIND_COCLASS:
4615 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4616 pTIHeader, pTITail);
4617 break;
4619 case TKIND_ALIAS:
4620 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4621 pTIHeader, pTITail);
4622 break;
4624 case TKIND_DISPATCH:
4625 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4626 pTIHeader, pTITail);
4627 break;
4629 case TKIND_MODULE:
4630 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4631 pTIHeader, pTITail);
4632 break;
4634 default:
4635 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4636 break;
4640 /* could get cFuncs, cVars and cImplTypes from here
4641 but we've already set those */
4642 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4643 X(06);
4644 X(16);
4645 X(18);
4646 X(1a);
4647 X(1e);
4648 X(24);
4649 X(26);
4650 X(2a);
4651 X(2c);
4652 X(2e);
4653 X(30);
4654 X(32);
4655 X(34);
4656 #undef X
4657 ++ppTypeInfoImpl;
4658 pBlk = (char*)pBlk + pBlkEntry[order].len;
4661 if(i != pTypeLibImpl->TypeInfoCount) {
4662 FIXME("Somehow processed %d TypeInfos\n", i);
4663 free(pOtherTypeInfoBlks);
4664 return NULL;
4667 free(pOtherTypeInfoBlks);
4668 return &pTypeLibImpl->ITypeLib2_iface;
4671 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4673 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4675 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4677 if(IsEqualIID(riid, &IID_IUnknown) ||
4678 IsEqualIID(riid,&IID_ITypeLib)||
4679 IsEqualIID(riid,&IID_ITypeLib2))
4681 *ppv = &This->ITypeLib2_iface;
4683 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4684 IsEqualIID(riid, &IID_ICreateTypeLib2))
4686 *ppv = &This->ICreateTypeLib2_iface;
4688 else
4690 *ppv = NULL;
4691 TRACE("-- Interface: E_NOINTERFACE\n");
4692 return E_NOINTERFACE;
4695 IUnknown_AddRef((IUnknown*)*ppv);
4696 return S_OK;
4699 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4701 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4702 ULONG ref = InterlockedIncrement(&This->ref);
4704 TRACE("%p, refcount %lu.\n", iface, ref);
4706 return ref;
4709 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4711 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4712 ULONG ref;
4714 EnterCriticalSection(&cache_section);
4715 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 if(This->entry.next)
4732 list_remove(&This->entry);
4733 free(This->path);
4735 TRACE(" destroying ITypeLib(%p)\n",This);
4737 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4738 list_remove(&tlbstr->entry);
4739 SysFreeString(tlbstr->str);
4740 free(tlbstr);
4743 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4744 list_remove(&tlbstr->entry);
4745 SysFreeString(tlbstr->str);
4746 free(tlbstr);
4749 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4750 list_remove(&tlbguid->entry);
4751 free(tlbguid);
4754 TLB_FreeCustData(&This->custdata_list);
4756 for (i = 0; i < This->ctTypeDesc; i++)
4757 if (This->pTypeDesc[i].vt == VT_CARRAY)
4758 free(This->pTypeDesc[i].lpadesc);
4760 free(This->pTypeDesc);
4762 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4764 if (pImpLib->pImpTypeLib)
4765 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4766 SysFreeString(pImpLib->name);
4768 list_remove(&pImpLib->entry);
4769 free(pImpLib);
4772 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4774 list_remove(&ref_type->entry);
4775 free(ref_type);
4778 for (i = 0; i < This->TypeInfoCount; ++i){
4779 free(This->typeinfos[i]->tdescAlias);
4780 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4782 free(This->typeinfos);
4783 free(This);
4786 LeaveCriticalSection(&cache_section);
4787 return ref;
4790 /* ITypeLib::GetTypeInfoCount
4792 * Returns the number of type descriptions in the type library
4794 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4796 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4797 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4798 return This->TypeInfoCount;
4801 /* ITypeLib::GetTypeInfo
4803 * retrieves the specified type description in the library.
4805 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4806 ITypeLib2 *iface,
4807 UINT index,
4808 ITypeInfo **ppTInfo)
4810 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4812 TRACE("%p %u %p\n", This, index, ppTInfo);
4814 if(!ppTInfo)
4815 return E_INVALIDARG;
4817 if(index >= This->TypeInfoCount)
4818 return TYPE_E_ELEMENTNOTFOUND;
4820 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4821 ITypeInfo_AddRef(*ppTInfo);
4823 return S_OK;
4827 /* ITypeLibs::GetTypeInfoType
4829 * Retrieves the type of a type description.
4831 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4832 ITypeLib2 *iface,
4833 UINT index,
4834 TYPEKIND *pTKind)
4836 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4838 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4840 if(!pTKind)
4841 return E_INVALIDARG;
4843 if(index >= This->TypeInfoCount)
4844 return TYPE_E_ELEMENTNOTFOUND;
4846 *pTKind = This->typeinfos[index]->typeattr.typekind;
4848 return S_OK;
4851 /* ITypeLib::GetTypeInfoOfGuid
4853 * Retrieves the type description that corresponds to the specified GUID.
4856 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4857 ITypeLib2 *iface,
4858 REFGUID guid,
4859 ITypeInfo **ppTInfo)
4861 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4862 int i;
4864 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4866 for(i = 0; i < This->TypeInfoCount; ++i){
4867 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4868 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4869 ITypeInfo_AddRef(*ppTInfo);
4870 return S_OK;
4874 return TYPE_E_ELEMENTNOTFOUND;
4877 /* ITypeLib::GetLibAttr
4879 * Retrieves the structure that contains the library's attributes.
4882 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4883 ITypeLib2 *iface,
4884 LPTLIBATTR *attr)
4886 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4888 TRACE("(%p, %p)\n", This, attr);
4890 if (!attr) return E_INVALIDARG;
4892 *attr = malloc(sizeof(**attr));
4893 if (!*attr) return E_OUTOFMEMORY;
4895 (*attr)->guid = *TLB_get_guid_null(This->guid);
4896 (*attr)->lcid = This->set_lcid;
4897 (*attr)->syskind = This->syskind;
4898 (*attr)->wMajorVerNum = This->ver_major;
4899 (*attr)->wMinorVerNum = This->ver_minor;
4900 (*attr)->wLibFlags = This->libflags;
4902 return S_OK;
4905 /* ITypeLib::GetTypeComp
4907 * Enables a client compiler to bind to a library's types, variables,
4908 * constants, and global functions.
4911 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4912 ITypeLib2 *iface,
4913 ITypeComp **ppTComp)
4915 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4917 TRACE("(%p)->(%p)\n",This,ppTComp);
4918 *ppTComp = &This->ITypeComp_iface;
4919 ITypeComp_AddRef(*ppTComp);
4921 return S_OK;
4924 /* ITypeLib::GetDocumentation
4926 * Retrieves the library's documentation string, the complete Help file name
4927 * and path, and the context identifier for the library Help topic in the Help
4928 * file.
4930 * On a successful return all non-null BSTR pointers will have been set,
4931 * possibly to NULL.
4933 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4934 ITypeLib2 *iface,
4935 INT index,
4936 BSTR *pBstrName,
4937 BSTR *pBstrDocString,
4938 DWORD *pdwHelpContext,
4939 BSTR *pBstrHelpFile)
4941 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4942 HRESULT result = E_INVALIDARG;
4943 ITypeInfo *pTInfo;
4945 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4946 This, index,
4947 pBstrName, pBstrDocString,
4948 pdwHelpContext, pBstrHelpFile);
4950 if(index<0)
4952 /* documentation for the typelib */
4953 if(pBstrName)
4955 if (This->Name)
4957 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4958 goto memerr1;
4960 else
4961 *pBstrName = NULL;
4963 if(pBstrDocString)
4965 if (This->DocString)
4967 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4968 goto memerr2;
4970 else
4971 *pBstrDocString = NULL;
4973 if(pdwHelpContext)
4975 *pdwHelpContext = This->dwHelpContext;
4977 if(pBstrHelpFile)
4979 if (This->HelpFile)
4981 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4982 goto memerr3;
4984 else
4985 *pBstrHelpFile = NULL;
4988 result = S_OK;
4990 else
4992 /* for a typeinfo */
4993 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4995 if(SUCCEEDED(result))
4997 result = ITypeInfo_GetDocumentation(pTInfo,
4998 MEMBERID_NIL,
4999 pBstrName,
5000 pBstrDocString,
5001 pdwHelpContext, pBstrHelpFile);
5003 ITypeInfo_Release(pTInfo);
5006 return result;
5007 memerr3:
5008 if (pBstrDocString) SysFreeString (*pBstrDocString);
5009 memerr2:
5010 if (pBstrName) SysFreeString (*pBstrName);
5011 memerr1:
5012 return STG_E_INSUFFICIENTMEMORY;
5015 /* ITypeLib::IsName
5017 * Indicates whether a passed-in string contains the name of a type or member
5018 * described in the library.
5021 static HRESULT WINAPI ITypeLib2_fnIsName(
5022 ITypeLib2 *iface,
5023 LPOLESTR szNameBuf,
5024 ULONG lHashVal,
5025 BOOL *pfName)
5027 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5028 int tic;
5029 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5031 TRACE("%p, %s, %#lx, %p.\n", iface, debugstr_w(szNameBuf), lHashVal, pfName);
5033 *pfName=TRUE;
5034 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5035 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5036 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5037 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5038 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5039 int pc;
5040 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5041 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5042 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5043 goto ITypeLib2_fnIsName_exit;
5046 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5047 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5048 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5052 *pfName=FALSE;
5054 ITypeLib2_fnIsName_exit:
5055 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5056 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5058 return S_OK;
5061 /* ITypeLib::FindName
5063 * Finds occurrences of a type description in a type library. This may be used
5064 * to quickly verify that a name exists in a type library.
5067 static HRESULT WINAPI ITypeLib2_fnFindName(
5068 ITypeLib2 *iface,
5069 LPOLESTR name,
5070 ULONG hash,
5071 ITypeInfo **ppTInfo,
5072 MEMBERID *memid,
5073 UINT16 *found)
5075 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5076 int tic;
5077 UINT count = 0;
5078 UINT len;
5080 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface, debugstr_w(name), hash, ppTInfo, memid, found);
5082 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5083 return E_INVALIDARG;
5085 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5086 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5087 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5088 TLBVarDesc *var;
5089 UINT fdc;
5091 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5092 memid[count] = MEMBERID_NIL;
5093 goto ITypeLib2_fnFindName_exit;
5096 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5097 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5099 if(!TLB_str_memcmp(name, func->Name, len)) {
5100 memid[count] = func->funcdesc.memid;
5101 goto ITypeLib2_fnFindName_exit;
5105 var = TLB_get_vardesc_by_name(pTInfo, name);
5106 if (var) {
5107 memid[count] = var->vardesc.memid;
5108 goto ITypeLib2_fnFindName_exit;
5111 continue;
5112 ITypeLib2_fnFindName_exit:
5113 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5114 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5115 count++;
5117 TRACE("found %d typeinfos\n", count);
5119 *found = count;
5121 return S_OK;
5124 /* ITypeLib::ReleaseTLibAttr
5126 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5129 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5130 ITypeLib2 *iface,
5131 TLIBATTR *pTLibAttr)
5133 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5134 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5135 free(pTLibAttr);
5138 /* ITypeLib2::GetCustData
5140 * gets the custom data
5142 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5143 ITypeLib2 * iface,
5144 REFGUID guid,
5145 VARIANT *pVarVal)
5147 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5148 TLBCustData *pCData;
5150 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5152 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5153 if(!pCData)
5154 return TYPE_E_ELEMENTNOTFOUND;
5156 VariantInit(pVarVal);
5157 VariantCopy(pVarVal, &pCData->data);
5159 return S_OK;
5162 /* ITypeLib2::GetLibStatistics
5164 * Returns statistics about a type library that are required for efficient
5165 * sizing of hash tables.
5168 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5169 ITypeLib2 * iface,
5170 ULONG *pcUniqueNames,
5171 ULONG *pcchUniqueNames)
5173 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5175 FIXME("(%p): stub!\n", This);
5177 if(pcUniqueNames) *pcUniqueNames=1;
5178 if(pcchUniqueNames) *pcchUniqueNames=1;
5179 return S_OK;
5182 /* ITypeLib2::GetDocumentation2
5184 * Retrieves the library's documentation string, the complete Help file name
5185 * and path, the localization context to use, and the context ID for the
5186 * library Help topic in the Help file.
5189 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5190 ITypeLib2 * iface,
5191 INT index,
5192 LCID lcid,
5193 BSTR *pbstrHelpString,
5194 DWORD *pdwHelpStringContext,
5195 BSTR *pbstrHelpStringDll)
5197 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5198 HRESULT result;
5199 ITypeInfo *pTInfo;
5201 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface, index, lcid);
5203 /* the help string should be obtained from the helpstringdll,
5204 * using the _DLLGetDocumentation function, based on the supplied
5205 * lcid. Nice to do sometime...
5207 if(index<0)
5209 /* documentation for the typelib */
5210 if(pbstrHelpString)
5211 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5212 if(pdwHelpStringContext)
5213 *pdwHelpStringContext=This->dwHelpContext;
5214 if(pbstrHelpStringDll)
5215 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5217 result = S_OK;
5219 else
5221 /* for a typeinfo */
5222 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5224 if(SUCCEEDED(result))
5226 ITypeInfo2 * pTInfo2;
5227 result = ITypeInfo_QueryInterface(pTInfo,
5228 &IID_ITypeInfo2,
5229 (LPVOID*) &pTInfo2);
5231 if(SUCCEEDED(result))
5233 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5234 MEMBERID_NIL,
5235 lcid,
5236 pbstrHelpString,
5237 pdwHelpStringContext,
5238 pbstrHelpStringDll);
5240 ITypeInfo2_Release(pTInfo2);
5243 ITypeInfo_Release(pTInfo);
5246 return result;
5249 static HRESULT TLB_copy_all_custdata(const struct list *custdata_list, CUSTDATA *pCustData)
5251 TLBCustData *pCData;
5252 unsigned int ct;
5253 CUSTDATAITEM *cdi;
5254 HRESULT hr = S_OK;
5256 ct = list_count(custdata_list);
5258 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5259 if(!pCustData->prgCustData)
5260 return E_OUTOFMEMORY;
5262 pCustData->cCustData = ct;
5264 cdi = pCustData->prgCustData;
5265 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5266 cdi->guid = *TLB_get_guid_null(pCData->guid);
5267 VariantInit(&cdi->varValue);
5268 hr = VariantCopy(&cdi->varValue, &pCData->data);
5269 if(FAILED(hr)) break;
5270 ++cdi;
5273 return hr;
5277 /* ITypeLib2::GetAllCustData
5279 * Gets all custom data items for the library.
5282 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5283 ITypeLib2 * iface,
5284 CUSTDATA *pCustData)
5286 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5287 TRACE("(%p)->(%p)\n", This, pCustData);
5288 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5291 static const ITypeLib2Vtbl tlbvt = {
5292 ITypeLib2_fnQueryInterface,
5293 ITypeLib2_fnAddRef,
5294 ITypeLib2_fnRelease,
5295 ITypeLib2_fnGetTypeInfoCount,
5296 ITypeLib2_fnGetTypeInfo,
5297 ITypeLib2_fnGetTypeInfoType,
5298 ITypeLib2_fnGetTypeInfoOfGuid,
5299 ITypeLib2_fnGetLibAttr,
5300 ITypeLib2_fnGetTypeComp,
5301 ITypeLib2_fnGetDocumentation,
5302 ITypeLib2_fnIsName,
5303 ITypeLib2_fnFindName,
5304 ITypeLib2_fnReleaseTLibAttr,
5306 ITypeLib2_fnGetCustData,
5307 ITypeLib2_fnGetLibStatistics,
5308 ITypeLib2_fnGetDocumentation2,
5309 ITypeLib2_fnGetAllCustData
5313 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5315 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5317 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5320 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5322 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5324 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5327 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5329 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5331 return ITypeLib2_Release(&This->ITypeLib2_iface);
5334 static HRESULT WINAPI ITypeLibComp_fnBind(
5335 ITypeComp * iface,
5336 OLECHAR * szName,
5337 ULONG lHash,
5338 WORD wFlags,
5339 ITypeInfo ** ppTInfo,
5340 DESCKIND * pDescKind,
5341 BINDPTR * pBindPtr)
5343 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5344 BOOL typemismatch = FALSE;
5345 int i;
5347 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5349 *pDescKind = DESCKIND_NONE;
5350 pBindPtr->lptcomp = NULL;
5351 *ppTInfo = NULL;
5353 for(i = 0; i < This->TypeInfoCount; ++i){
5354 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5355 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5357 /* FIXME: check wFlags here? */
5358 /* FIXME: we should use a hash table to look this info up using lHash
5359 * instead of an O(n) search */
5360 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5361 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5363 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5365 *pDescKind = DESCKIND_TYPECOMP;
5366 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5367 ITypeComp_AddRef(pBindPtr->lptcomp);
5368 TRACE("module or enum: %s\n", debugstr_w(szName));
5369 return S_OK;
5373 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5374 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5376 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5377 HRESULT hr;
5379 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5380 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5382 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5383 return S_OK;
5385 else if (hr == TYPE_E_TYPEMISMATCH)
5386 typemismatch = TRUE;
5389 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5390 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5392 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5393 HRESULT hr;
5394 ITypeInfo *subtypeinfo;
5395 BINDPTR subbindptr;
5396 DESCKIND subdesckind;
5398 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5399 &subtypeinfo, &subdesckind, &subbindptr);
5400 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5402 TYPEDESC tdesc_appobject;
5403 const VARDESC vardesc_appobject =
5405 -2, /* memid */
5406 NULL, /* lpstrSchema */
5408 0 /* oInst */
5411 /* ELEMDESC */
5413 /* TYPEDESC */
5415 &tdesc_appobject
5417 VT_PTR
5420 0, /* wVarFlags */
5421 VAR_STATIC /* varkind */
5424 tdesc_appobject.hreftype = pTypeInfo->hreftype;
5425 tdesc_appobject.vt = VT_USERDEFINED;
5427 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5429 /* cleanup things filled in by Bind call so we can put our
5430 * application object data in there instead */
5431 switch (subdesckind)
5433 case DESCKIND_FUNCDESC:
5434 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5435 break;
5436 case DESCKIND_VARDESC:
5437 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5438 break;
5439 default:
5440 break;
5442 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5444 if (pTypeInfo->hreftype == -1)
5445 FIXME("no hreftype for interface %p\n", pTypeInfo);
5447 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5448 if (FAILED(hr))
5449 return hr;
5451 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5452 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5453 ITypeInfo_AddRef(*ppTInfo);
5454 return S_OK;
5456 else if (hr == TYPE_E_TYPEMISMATCH)
5457 typemismatch = TRUE;
5461 if (typemismatch)
5463 TRACE("type mismatch %s\n", debugstr_w(szName));
5464 return TYPE_E_TYPEMISMATCH;
5466 else
5468 TRACE("name not found %s\n", debugstr_w(szName));
5469 return S_OK;
5473 static HRESULT WINAPI ITypeLibComp_fnBindType(
5474 ITypeComp * iface,
5475 OLECHAR * szName,
5476 ULONG lHash,
5477 ITypeInfo ** ppTInfo,
5478 ITypeComp ** ppTComp)
5480 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5481 ITypeInfoImpl *info;
5483 TRACE("%p, %s, %#lx, %p, %p.\n", iface, debugstr_w(szName), lHash, ppTInfo, ppTComp);
5485 if(!szName || !ppTInfo || !ppTComp)
5486 return E_INVALIDARG;
5488 info = TLB_get_typeinfo_by_name(This, szName);
5489 if(!info){
5490 *ppTInfo = NULL;
5491 *ppTComp = NULL;
5492 return S_OK;
5495 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5496 ITypeInfo_AddRef(*ppTInfo);
5497 *ppTComp = &info->ITypeComp_iface;
5498 ITypeComp_AddRef(*ppTComp);
5500 return S_OK;
5503 static const ITypeCompVtbl tlbtcvt =
5506 ITypeLibComp_fnQueryInterface,
5507 ITypeLibComp_fnAddRef,
5508 ITypeLibComp_fnRelease,
5510 ITypeLibComp_fnBind,
5511 ITypeLibComp_fnBindType
5514 /*================== ITypeInfo(2) Methods ===================================*/
5515 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5517 ITypeInfoImpl *pTypeInfoImpl;
5519 pTypeInfoImpl = calloc(1, sizeof(ITypeInfoImpl));
5520 if (pTypeInfoImpl)
5522 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5523 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5524 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5525 pTypeInfoImpl->ref = 0;
5526 pTypeInfoImpl->hreftype = -1;
5527 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5528 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5529 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5530 list_init(pTypeInfoImpl->pcustdata_list);
5532 TRACE("(%p)\n", pTypeInfoImpl);
5533 return pTypeInfoImpl;
5536 /* ITypeInfo::QueryInterface
5538 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5539 ITypeInfo2 *iface,
5540 REFIID riid,
5541 VOID **ppvObject)
5543 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5545 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5547 *ppvObject=NULL;
5548 if(IsEqualIID(riid, &IID_IUnknown) ||
5549 IsEqualIID(riid,&IID_ITypeInfo)||
5550 IsEqualIID(riid,&IID_ITypeInfo2))
5551 *ppvObject = &This->ITypeInfo2_iface;
5552 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5553 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5554 *ppvObject = &This->ICreateTypeInfo2_iface;
5555 else if(IsEqualIID(riid, &IID_ITypeComp))
5556 *ppvObject = &This->ITypeComp_iface;
5558 if(*ppvObject){
5559 IUnknown_AddRef((IUnknown*)*ppvObject);
5560 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5561 return S_OK;
5563 TRACE("-- Interface: E_NOINTERFACE\n");
5564 return E_NOINTERFACE;
5567 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5569 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5570 ULONG ref = InterlockedIncrement(&This->ref);
5572 TRACE("%p, refcount %lu.\n", iface, ref);
5574 if (ref == 1 /* incremented from 0 */)
5575 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5577 return ref;
5580 static void typeinfo_release_funcdesc(TLBFuncDesc *func)
5582 unsigned int i;
5584 for (i = 0; i < func->funcdesc.cParams; ++i)
5586 ELEMDESC *elemdesc = &func->funcdesc.lprgelemdescParam[i];
5587 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5588 VariantClear(&elemdesc->paramdesc.pparamdescex->varDefaultValue);
5589 TLB_FreeCustData(&func->pParamDesc[i].custdata_list);
5591 free(func->funcdesc.lprgelemdescParam);
5592 free(func->pParamDesc);
5593 TLB_FreeCustData(&func->custdata_list);
5596 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5598 UINT i;
5600 TRACE("destroying ITypeInfo(%p)\n",This);
5602 for (i = 0; i < This->typeattr.cFuncs; ++i)
5604 typeinfo_release_funcdesc(&This->funcdescs[i]);
5606 free(This->funcdescs);
5608 for(i = 0; i < This->typeattr.cVars; ++i)
5610 TLBVarDesc *pVInfo = &This->vardescs[i];
5611 if (pVInfo->vardesc_create) {
5612 TLB_FreeVarDesc(pVInfo->vardesc_create);
5613 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5614 VariantClear(pVInfo->vardesc.lpvarValue);
5615 free(pVInfo->vardesc.lpvarValue);
5617 TLB_FreeCustData(&pVInfo->custdata_list);
5619 free(This->vardescs);
5621 if(This->impltypes){
5622 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5623 TLBImplType *pImpl = &This->impltypes[i];
5624 TLB_FreeCustData(&pImpl->custdata_list);
5626 free(This->impltypes);
5629 TLB_FreeCustData(&This->custdata_list);
5631 free(This);
5634 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5636 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5637 ULONG ref = InterlockedDecrement(&This->ref);
5639 TRACE("%p, refcount %lu.\n", iface, ref);
5641 if (!ref)
5643 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5644 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5645 if (not_attached_to_typelib)
5646 free(This);
5647 /* otherwise This will be freed when typelib is freed */
5650 return ref;
5653 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5654 LPTYPEATTR *ppTypeAttr)
5656 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5657 SIZE_T size;
5659 TRACE("(%p)\n",This);
5661 size = sizeof(**ppTypeAttr);
5662 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5663 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5665 *ppTypeAttr = malloc(size);
5666 if (!*ppTypeAttr)
5667 return E_OUTOFMEMORY;
5669 **ppTypeAttr = This->typeattr;
5670 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5672 if (This->tdescAlias)
5673 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5675 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5676 /* This should include all the inherited funcs */
5677 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5678 /* This is always the size of IDispatch's vtbl */
5679 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5680 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5682 return S_OK;
5685 /* ITypeInfo::GetTypeComp
5687 * Retrieves the ITypeComp interface for the type description, which enables a
5688 * client compiler to bind to the type description's members.
5691 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5692 ITypeComp * *ppTComp)
5694 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5696 TRACE("(%p)->(%p)\n", This, ppTComp);
5698 *ppTComp = &This->ITypeComp_iface;
5699 ITypeComp_AddRef(*ppTComp);
5700 return S_OK;
5703 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5705 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5706 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5707 size += sizeof(*elemdesc->paramdesc.pparamdescex);
5708 return size;
5711 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5713 *dest = *src;
5714 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5715 if (src->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5717 const PARAMDESCEX *pparamdescex_src = src->paramdesc.pparamdescex;
5718 PARAMDESCEX *pparamdescex_dest = dest->paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5719 *buffer += sizeof(PARAMDESCEX);
5720 *pparamdescex_dest = *pparamdescex_src;
5721 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5722 VariantInit(&pparamdescex_dest->varDefaultValue);
5723 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5724 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5726 else
5727 dest->paramdesc.pparamdescex = NULL;
5728 return S_OK;
5731 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5733 if (V_VT(var) == VT_INT)
5734 return VariantChangeType(var, var, 0, VT_I4);
5735 else if (V_VT(var) == VT_UINT)
5736 return VariantChangeType(var, var, 0, VT_UI4);
5738 return S_OK;
5741 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5743 if (elemdesc->paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5744 VariantClear(&elemdesc->paramdesc.pparamdescex->varDefaultValue);
5747 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5749 FUNCDESC *dest;
5750 char *buffer;
5751 SIZE_T size = sizeof(*src);
5752 SHORT i;
5753 HRESULT hr;
5755 size += sizeof(*src->lprgscode) * src->cScodes;
5756 size += TLB_SizeElemDesc(&src->elemdescFunc);
5757 for (i = 0; i < src->cParams; i++)
5759 size += sizeof(ELEMDESC);
5760 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5763 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5764 if (!dest) return E_OUTOFMEMORY;
5766 *dest = *src;
5767 if (dispinterface) /* overwrite funckind */
5768 dest->funckind = FUNC_DISPATCH;
5769 buffer = (char *)(dest + 1);
5771 dest->oVft = dest->oVft & 0xFFFC;
5773 if (dest->cScodes) {
5774 dest->lprgscode = (SCODE *)buffer;
5775 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5776 buffer += sizeof(*src->lprgscode) * src->cScodes;
5777 } else
5778 dest->lprgscode = NULL;
5780 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5781 if (FAILED(hr))
5783 SysFreeString((BSTR)dest);
5784 return hr;
5787 if (dest->cParams) {
5788 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5789 buffer += sizeof(ELEMDESC) * src->cParams;
5790 for (i = 0; i < src->cParams; i++)
5792 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5793 if (FAILED(hr))
5794 break;
5796 if (FAILED(hr))
5798 /* undo the above actions */
5799 for (i = i - 1; i >= 0; i--)
5800 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5801 TLB_FreeElemDesc(&dest->elemdescFunc);
5802 SysFreeString((BSTR)dest);
5803 return hr;
5805 } else
5806 dest->lprgelemdescParam = NULL;
5808 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5809 * This accounts for several arguments that are separate in the signature of
5810 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5811 if (dispinterface && (src->funckind != FUNC_DISPATCH))
5813 /* functions that have a [retval] parameter return this value into pVarResult.
5814 * [retval] is always the last parameter (if present) */
5815 if (dest->cParams &&
5816 (dest->lprgelemdescParam[dest->cParams - 1].paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5818 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5819 if (elemdesc->tdesc.vt != VT_PTR)
5821 ERR("elemdesc should have started with VT_PTR instead of:\n");
5822 if (ERR_ON(ole))
5823 dump_ELEMDESC(elemdesc);
5824 return E_UNEXPECTED;
5827 /* the type pointed to by this [retval] becomes elemdescFunc,
5828 * i.e. the function signature's return type.
5829 * We are using a flat buffer so there is no danger of leaking memory */
5830 dest->elemdescFunc.tdesc = *elemdesc->tdesc.lptdesc;
5832 /* remove the last parameter */
5833 dest->cParams--;
5835 else if (dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5836 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5837 * not pVarResult. So the function signature should show no return value. */
5838 dest->elemdescFunc.tdesc.vt = VT_VOID;
5840 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5841 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5842 if (dest->cParams && (dest->lprgelemdescParam[dest->cParams - 1].paramdesc.wParamFlags & PARAMFLAG_FLCID))
5843 dest->cParams--;
5846 *dest_ptr = dest;
5847 return S_OK;
5850 static void TLB_FreeVarDesc(VARDESC *var_desc)
5852 TLB_FreeElemDesc(&var_desc->elemdescVar);
5853 if (var_desc->varkind == VAR_CONST)
5854 VariantClear(var_desc->lpvarValue);
5855 SysFreeString((BSTR)var_desc);
5858 /* internal function to make the inherited interfaces' methods appear
5859 * part of the interface */
5860 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5861 UINT index, const TLBFuncDesc **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5863 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5864 HRESULT hr;
5865 UINT implemented_funcs = 0;
5867 if (funcs)
5868 *funcs = 0;
5869 else
5870 *hrefoffset = DISPATCH_HREF_OFFSET;
5872 if(This->impltypes)
5874 ITypeInfo *pSubTypeInfo;
5875 UINT sub_funcs;
5877 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5878 if (FAILED(hr))
5879 return hr;
5881 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5882 index,
5883 ppFuncDesc,
5884 &sub_funcs, hrefoffset);
5885 implemented_funcs += sub_funcs;
5886 ITypeInfo_Release(pSubTypeInfo);
5887 if (SUCCEEDED(hr))
5888 return hr;
5889 *hrefoffset += DISPATCH_HREF_OFFSET;
5892 if (funcs)
5893 *funcs = implemented_funcs + This->typeattr.cFuncs;
5894 else
5895 *hrefoffset = 0;
5897 if (index < implemented_funcs)
5898 return E_INVALIDARG;
5899 index -= implemented_funcs;
5901 if (index >= This->typeattr.cFuncs)
5902 return TYPE_E_ELEMENTNOTFOUND;
5904 *ppFuncDesc = &This->funcdescs[index];
5905 return S_OK;
5908 static HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const TLBFuncDesc **func_desc, UINT *hrefoffset )
5910 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5912 if (This->typeattr.typekind == TKIND_DISPATCH)
5913 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface, index, func_desc, NULL, hrefoffset);
5915 if (index >= This->typeattr.cFuncs)
5916 return TYPE_E_ELEMENTNOTFOUND;
5918 *func_desc = &This->funcdescs[index];
5919 return S_OK;
5922 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5924 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5925 while (TRUE)
5927 switch (pTypeDesc->vt)
5929 case VT_USERDEFINED:
5930 pTypeDesc->hreftype += hrefoffset;
5931 return;
5932 case VT_PTR:
5933 case VT_SAFEARRAY:
5934 pTypeDesc = pTypeDesc->lptdesc;
5935 break;
5936 case VT_CARRAY:
5937 pTypeDesc = &pTypeDesc->lpadesc->tdescElem;
5938 break;
5939 default:
5940 return;
5945 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5947 SHORT i;
5948 for (i = 0; i < pFuncDesc->cParams; i++)
5949 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5950 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5953 /* ITypeInfo::GetFuncDesc
5955 * Retrieves the FUNCDESC structure that contains information about a
5956 * specified function.
5959 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5960 LPFUNCDESC *ppFuncDesc)
5962 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5963 const TLBFuncDesc *internal_funcdesc;
5964 HRESULT hr;
5965 UINT hrefoffset = 0;
5967 TRACE("(%p) index %d\n", This, index);
5969 if (!ppFuncDesc)
5970 return E_INVALIDARG;
5972 if (This->needs_layout)
5973 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5975 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5976 &internal_funcdesc, &hrefoffset);
5977 if (FAILED(hr))
5979 WARN("description for function %d not found\n", index);
5980 return hr;
5983 hr = TLB_AllocAndInitFuncDesc(
5984 &internal_funcdesc->funcdesc,
5985 ppFuncDesc,
5986 This->typeattr.typekind == TKIND_DISPATCH);
5988 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
5989 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5991 TRACE("-- %#lx.\n", hr);
5992 return hr;
5995 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5997 VARDESC *dest;
5998 char *buffer;
5999 SIZE_T size = sizeof(*src);
6000 HRESULT hr;
6002 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6003 if (src->varkind == VAR_CONST)
6004 size += sizeof(VARIANT);
6005 size += TLB_SizeElemDesc(&src->elemdescVar);
6007 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6008 if (!dest) return E_OUTOFMEMORY;
6010 *dest = *src;
6011 buffer = (char *)(dest + 1);
6012 if (src->lpstrSchema)
6014 int len;
6015 dest->lpstrSchema = (LPOLESTR)buffer;
6016 len = lstrlenW(src->lpstrSchema);
6017 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6018 buffer += (len + 1) * sizeof(WCHAR);
6021 if (src->varkind == VAR_CONST)
6023 HRESULT hr;
6025 dest->lpvarValue = (VARIANT *)buffer;
6026 *dest->lpvarValue = *src->lpvarValue;
6027 buffer += sizeof(VARIANT);
6028 VariantInit(dest->lpvarValue);
6029 hr = VariantCopy(dest->lpvarValue, src->lpvarValue);
6030 if (FAILED(hr))
6032 SysFreeString((BSTR)dest);
6033 return hr;
6036 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6037 if (FAILED(hr))
6039 if (src->varkind == VAR_CONST)
6040 VariantClear(dest->lpvarValue);
6041 SysFreeString((BSTR)dest);
6042 return hr;
6044 *dest_ptr = dest;
6045 return S_OK;
6048 /* ITypeInfo::GetVarDesc
6050 * Retrieves a VARDESC structure that describes the specified variable.
6053 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6054 LPVARDESC *ppVarDesc)
6056 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6057 const TLBVarDesc *pVDesc = &This->vardescs[index];
6059 TRACE("(%p) index %d\n", This, index);
6061 if(index >= This->typeattr.cVars)
6062 return TYPE_E_ELEMENTNOTFOUND;
6064 if (This->needs_layout)
6065 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6067 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6070 /* internal function to make the inherited interfaces' methods appear
6071 * part of the interface, remembering if the top-level was dispinterface */
6072 static HRESULT typeinfo_getnames( ITypeInfo *iface, MEMBERID memid, BSTR *names,
6073 UINT max_names, UINT *num_names, BOOL dispinterface)
6075 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6076 const TLBFuncDesc *func_desc;
6077 const TLBVarDesc *var_desc;
6078 int i;
6080 *num_names = 0;
6082 func_desc = TLB_get_funcdesc_by_memberid(This, memid);
6083 if (func_desc)
6085 UINT params = func_desc->funcdesc.cParams;
6086 if (!max_names || !func_desc->Name)
6087 return S_OK;
6089 *names = SysAllocString(TLB_get_bstr(func_desc->Name));
6090 ++(*num_names);
6092 if (dispinterface && (func_desc->funcdesc.funckind != FUNC_DISPATCH))
6094 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6095 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
6096 --params; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6097 if ((params > 0) && (func_desc->funcdesc.lprgelemdescParam[params - 1].paramdesc.wParamFlags & PARAMFLAG_FLCID))
6098 --params; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6101 for (i = 0; i < params; i++)
6103 if (*num_names >= max_names || !func_desc->pParamDesc[i].Name)
6104 return S_OK;
6105 names[*num_names] = SysAllocString(TLB_get_bstr(func_desc->pParamDesc[i].Name));
6106 ++(*num_names);
6108 return S_OK;
6111 var_desc = TLB_get_vardesc_by_memberid(This, memid);
6112 if (var_desc)
6114 *names = SysAllocString(TLB_get_bstr(var_desc->Name));
6115 *num_names = 1;
6117 else
6119 if (This->impltypes &&
6120 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH))
6122 /* recursive search */
6123 ITypeInfo *parent;
6124 HRESULT result;
6125 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &parent);
6126 if (SUCCEEDED(result))
6128 result = typeinfo_getnames(parent, memid, names, max_names, num_names, dispinterface);
6129 ITypeInfo_Release(parent);
6130 return result;
6132 WARN("Could not search inherited interface!\n");
6134 else
6136 WARN("no names found\n");
6138 *num_names = 0;
6139 return TYPE_E_ELEMENTNOTFOUND;
6141 return S_OK;
6144 /* ITypeInfo_GetNames
6146 * Retrieves the variable with the specified member ID (or the name of the
6147 * property or method and its parameters) that correspond to the specified
6148 * function ID.
6150 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6151 BSTR *names, UINT max_names, UINT *num_names)
6153 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6155 TRACE("%p, %#lx, %p, %d, %p\n", iface, memid, names, max_names, num_names);
6157 if (!names) return E_INVALIDARG;
6159 return typeinfo_getnames((ITypeInfo *)iface, memid, names, max_names, num_names,
6160 This->typeattr.typekind == TKIND_DISPATCH);
6163 /* ITypeInfo::GetRefTypeOfImplType
6165 * If a type description describes a COM class, it retrieves the type
6166 * description of the implemented interface types. For an interface,
6167 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6168 * if any exist.
6171 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6172 ITypeInfo2 *iface,
6173 UINT index,
6174 HREFTYPE *pRefType)
6176 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6177 HRESULT hr = S_OK;
6179 TRACE("(%p) index %d\n", This, index);
6180 if (TRACE_ON(ole)) dump_TypeInfo(This);
6182 if(index==(UINT)-1)
6184 /* only valid on dual interfaces;
6185 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6188 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6190 *pRefType = -2;
6192 else
6194 hr = TYPE_E_ELEMENTNOTFOUND;
6197 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6199 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6200 *pRefType = This->pTypeLib->dispatch_href;
6202 else
6204 if(index >= This->typeattr.cImplTypes)
6205 hr = TYPE_E_ELEMENTNOTFOUND;
6206 else{
6207 *pRefType = This->impltypes[index].hRef;
6208 if (This->typeattr.typekind == TKIND_INTERFACE)
6209 *pRefType |= 0x2;
6213 if(TRACE_ON(ole))
6215 if(SUCCEEDED(hr))
6216 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType );
6217 else
6218 TRACE("FAILURE -- hresult %#lx.\n", hr);
6221 return hr;
6224 /* ITypeInfo::GetImplTypeFlags
6226 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6227 * or base interface in a type description.
6229 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6230 UINT index, INT *pImplTypeFlags)
6232 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6234 TRACE("(%p) index %d\n", This, index);
6236 if(!pImplTypeFlags)
6237 return E_INVALIDARG;
6239 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6240 *pImplTypeFlags = 0;
6241 return S_OK;
6244 if(index >= This->typeattr.cImplTypes)
6245 return TYPE_E_ELEMENTNOTFOUND;
6247 *pImplTypeFlags = This->impltypes[index].implflags;
6249 return S_OK;
6252 /* GetIDsOfNames
6253 * Maps between member names and member IDs, and parameter names and
6254 * parameter IDs.
6256 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6257 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6259 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6260 const TLBVarDesc *pVDesc;
6261 HRESULT ret=S_OK;
6262 UINT i, fdc;
6264 TRACE("%p, %s, %d.\n", iface, debugstr_w(*rgszNames), cNames);
6266 /* init out parameters in case of failure */
6267 for (i = 0; i < cNames; i++)
6268 pMemId[i] = MEMBERID_NIL;
6270 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6271 int j;
6272 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6273 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6274 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6275 for(i=1; i < cNames; i++){
6276 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6277 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6278 break;
6279 if( j<pFDesc->funcdesc.cParams)
6280 pMemId[i]=j;
6281 else
6282 ret=DISP_E_UNKNOWNNAME;
6284 TRACE("-- %#lx.\n", ret);
6285 return ret;
6288 pVDesc = TLB_get_vardesc_by_name(This, *rgszNames);
6289 if(pVDesc){
6290 if(cNames)
6291 *pMemId = pVDesc->vardesc.memid;
6292 return ret;
6294 /* not found, see if it can be found in an inherited interface */
6295 if(This->impltypes) {
6296 /* recursive search */
6297 ITypeInfo *pTInfo;
6298 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6299 if(SUCCEEDED(ret)){
6300 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6301 ITypeInfo_Release(pTInfo);
6302 return ret;
6304 WARN("Could not search inherited interface!\n");
6305 } else
6306 WARN("no names found\n");
6307 return DISP_E_UNKNOWNNAME;
6311 #ifdef __i386__
6313 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6314 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6316 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6317 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6319 int argspos = 0, stack_offset;
6320 void *func;
6321 UINT i;
6322 DWORD *args;
6324 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6325 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6326 pvargResult, V_VT(pvargResult));
6328 if (cc != CC_STDCALL && cc != CC_CDECL)
6330 FIXME("unsupported calling convention %d\n",cc);
6331 return E_INVALIDARG;
6334 /* maximum size for an argument is sizeof(VARIANT) */
6335 args = malloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6337 if (pvInstance)
6339 const FARPROC *vtable = *(FARPROC **)pvInstance;
6340 func = vtable[oVft/sizeof(void *)];
6341 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6343 else func = (void *)oVft;
6345 switch (vtReturn)
6347 case VT_DECIMAL:
6348 case VT_VARIANT:
6349 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6350 break;
6351 case VT_HRESULT:
6352 WARN("invalid return type %u\n", vtReturn);
6353 free( args );
6354 return E_INVALIDARG;
6355 default:
6356 break;
6359 for (i = 0; i < cActuals; i++)
6361 VARIANT *arg = prgpvarg[i];
6363 switch (prgvt[i])
6365 case VT_EMPTY:
6366 break;
6367 case VT_I8:
6368 case VT_UI8:
6369 case VT_R8:
6370 case VT_DATE:
6371 case VT_CY:
6372 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6373 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6374 break;
6375 case VT_DECIMAL:
6376 case VT_VARIANT:
6377 memcpy( &args[argspos], arg, sizeof(*arg) );
6378 argspos += sizeof(*arg) / sizeof(DWORD);
6379 break;
6380 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6381 args[argspos++] = V_BOOL(arg);
6382 break;
6383 default:
6384 args[argspos++] = V_UI4(arg);
6385 break;
6387 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6390 switch (vtReturn)
6392 case VT_EMPTY:
6393 case VT_DECIMAL:
6394 case VT_VARIANT:
6395 call_method( func, argspos, args, &stack_offset );
6396 break;
6397 case VT_R4:
6398 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6399 break;
6400 case VT_R8:
6401 case VT_DATE:
6402 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6403 break;
6404 case VT_I8:
6405 case VT_UI8:
6406 case VT_CY:
6407 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6408 break;
6409 default:
6410 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6411 break;
6413 free( args );
6414 if (stack_offset && cc == CC_STDCALL)
6416 WARN( "stack pointer off by %d\n", stack_offset );
6417 return DISP_E_BADCALLEE;
6419 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6420 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6421 return S_OK;
6424 #elif defined(__x86_64__)
6426 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6427 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6429 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6430 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6432 int argspos = 0;
6433 UINT i;
6434 DWORD_PTR *args;
6435 void *func;
6437 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6438 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6439 pvargResult, V_VT(pvargResult));
6441 if (cc != CC_STDCALL && cc != CC_CDECL)
6443 FIXME("unsupported calling convention %d\n",cc);
6444 return E_INVALIDARG;
6447 /* maximum size for an argument is sizeof(DWORD_PTR) */
6448 args = malloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6450 if (pvInstance)
6452 const FARPROC *vtable = *(FARPROC **)pvInstance;
6453 func = vtable[oVft/sizeof(void *)];
6454 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6456 else func = (void *)oVft;
6458 switch (vtReturn)
6460 case VT_DECIMAL:
6461 case VT_VARIANT:
6462 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6463 break;
6464 case VT_HRESULT:
6465 WARN("invalid return type %u\n", vtReturn);
6466 free( args );
6467 return E_INVALIDARG;
6468 default:
6469 break;
6472 for (i = 0; i < cActuals; i++)
6474 VARIANT *arg = prgpvarg[i];
6476 switch (prgvt[i])
6478 case VT_DECIMAL:
6479 case VT_VARIANT:
6480 args[argspos++] = (ULONG_PTR)arg;
6481 break;
6482 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6483 args[argspos++] = V_BOOL(arg);
6484 break;
6485 default:
6486 args[argspos++] = V_UI8(arg);
6487 break;
6489 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6492 switch (vtReturn)
6494 case VT_R4:
6495 V_R4(pvargResult) = call_double_method( func, argspos, args );
6496 break;
6497 case VT_R8:
6498 case VT_DATE:
6499 V_R8(pvargResult) = call_double_method( func, argspos, args );
6500 break;
6501 case VT_DECIMAL:
6502 case VT_VARIANT:
6503 call_method( func, argspos, args );
6504 break;
6505 default:
6506 V_UI8(pvargResult) = call_method( func, argspos, args );
6507 break;
6509 free( args );
6510 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6511 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6512 return S_OK;
6515 #elif defined(__arm__)
6517 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6518 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6519 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6521 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6522 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6524 int argspos;
6525 void *func;
6526 UINT i;
6527 DWORD *args;
6528 struct {
6529 union {
6530 float s[16];
6531 double d[8];
6532 } sd;
6533 DWORD r[4];
6534 } regs;
6535 int rcount; /* 32-bit register index count */
6536 int scount = 0; /* single-precision float register index count */
6537 int dcount = 0; /* double-precision float register index count */
6539 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6540 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6542 if (cc != CC_STDCALL && cc != CC_CDECL)
6544 FIXME("unsupported calling convention %d\n",cc);
6545 return E_INVALIDARG;
6548 argspos = 0;
6549 rcount = 0;
6551 if (pvInstance)
6553 const FARPROC *vtable = *(FARPROC **)pvInstance;
6554 func = vtable[oVft/sizeof(void *)];
6555 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6557 else func = (void *)oVft;
6559 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6560 /* first as it will need to be in the 'r' registers: */
6561 switch (vtReturn)
6563 case VT_DECIMAL:
6564 case VT_VARIANT:
6565 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6566 break;
6567 case VT_HRESULT:
6568 WARN("invalid return type %u\n", vtReturn);
6569 return E_INVALIDARG;
6570 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6571 break;
6574 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6575 args = malloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6577 for (i = 0; i < cActuals; i++)
6579 VARIANT *arg = prgpvarg[i];
6580 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6581 int ntemp; /* Used for counting words split between registers and stack */
6583 switch (prgvt[i])
6585 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6586 case VT_DATE:
6587 dcount = max( (scount + 1) / 2, dcount );
6588 if (dcount < 8)
6590 regs.sd.d[dcount++] = V_R8(arg);
6592 else
6594 argspos += (argspos % 2); /* align argspos to 8-bytes */
6595 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6596 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6598 break;
6599 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6600 case VT_UI8:
6601 case VT_CY:
6602 if (rcount < 3)
6604 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6605 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6606 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6608 else
6610 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6611 argspos += (argspos % 2); /* align argspos to 8-bytes */
6612 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6613 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6615 break;
6616 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6617 case VT_VARIANT:
6618 /* 8-byte align 'r' and/or stack: */
6619 if (rcount < 3)
6620 rcount += (rcount % 2);
6621 else
6623 rcount = 4;
6624 argspos += (argspos % 2);
6626 ntemp = sizeof(*arg) / sizeof(DWORD);
6627 while (ntemp > 0)
6629 if (rcount < 4)
6630 regs.r[rcount++] = *pdwarg++;
6631 else
6632 args[argspos++] = *pdwarg++;
6633 --ntemp;
6635 break;
6636 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6637 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6638 if (scount < 16)
6639 regs.sd.s[scount++] = V_R4(arg);
6640 else
6641 args[argspos++] = V_UI4(arg);
6642 break;
6643 /* extend parameters to 32 bits */
6644 case VT_I1:
6645 if (rcount < 4) regs.r[rcount++] = V_I1(arg);
6646 else args[argspos++] = V_I1(arg);
6647 break;
6648 case VT_UI1:
6649 if (rcount < 4) regs.r[rcount++] = V_UI1(arg);
6650 else args[argspos++] = V_UI1(arg);
6651 break;
6652 case VT_I2:
6653 if (rcount < 4) regs.r[rcount++] = V_I2(arg);
6654 else args[argspos++] = V_I2(arg);
6655 break;
6656 case VT_UI2:
6657 if (rcount < 4) regs.r[rcount++] = V_UI2(arg);
6658 else args[argspos++] = V_UI2(arg);
6659 break;
6660 case VT_BOOL:
6661 if (rcount < 4) regs.r[rcount++] = V_BOOL(arg);
6662 else args[argspos++] = V_BOOL(arg);
6663 break;
6664 default:
6665 if (rcount < 4) regs.r[rcount++] = V_UI4(arg);
6666 else args[argspos++] = V_UI4(arg);
6667 break;
6669 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6672 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6674 switch (vtReturn)
6676 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6677 case VT_VARIANT:
6678 call_method( func, argspos, args, (DWORD*)&regs );
6679 break;
6680 case VT_R4:
6681 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
6682 break;
6683 case VT_R8:
6684 case VT_DATE:
6685 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
6686 break;
6687 case VT_I8:
6688 case VT_UI8:
6689 case VT_CY:
6690 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6691 break;
6692 default:
6693 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
6694 break;
6696 free( args );
6697 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6698 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6699 return S_OK;
6702 #elif defined(__aarch64__)
6704 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6705 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6706 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6708 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6709 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6711 int argspos;
6712 void *func;
6713 UINT i;
6714 DWORD_PTR *args;
6715 struct
6717 union
6719 float f;
6720 double d;
6721 } fp[8];
6722 DWORD_PTR x[9];
6723 } regs;
6724 int rcount; /* 64-bit register index count */
6725 int fpcount = 0; /* float register index count */
6727 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6728 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6730 if (cc != CC_STDCALL && cc != CC_CDECL)
6732 FIXME("unsupported calling convention %d\n",cc);
6733 return E_INVALIDARG;
6736 argspos = 0;
6737 rcount = 0;
6739 if (instance)
6741 const FARPROC *vtable = *(FARPROC **)instance;
6742 func = vtable[offset/sizeof(void *)];
6743 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6745 else func = (void *)offset;
6747 /* maximum size for an argument is 16 */
6748 args = malloc( 16 * count );
6750 for (i = 0; i < count; i++)
6752 VARIANT *arg = vargs[i];
6754 switch (types[i])
6756 case VT_R4:
6757 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
6758 else *(float *)&args[argspos++] = V_R4(arg);
6759 break;
6760 case VT_R8:
6761 case VT_DATE:
6762 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
6763 else *(double *)&args[argspos++] = V_R8(arg);
6764 break;
6765 case VT_DECIMAL:
6766 if (rcount < 7)
6768 memcpy( &regs.x[rcount], arg, sizeof(*arg) );
6769 rcount += 2;
6771 else
6773 memcpy( &args[argspos], arg, sizeof(*arg) );
6774 argspos += 2;
6776 break;
6777 case VT_VARIANT:
6778 if (rcount < 8) regs.x[rcount++] = (DWORD_PTR)arg;
6779 else args[argspos++] = (DWORD_PTR)arg;
6780 break;
6781 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6782 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
6783 else args[argspos++] = V_BOOL(arg);
6784 break;
6785 default:
6786 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
6787 else args[argspos++] = V_UI8(arg);
6788 break;
6790 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
6793 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
6795 switch (ret_type)
6797 case VT_HRESULT:
6798 free( args );
6799 return E_INVALIDARG;
6800 case VT_DECIMAL:
6801 case VT_VARIANT:
6802 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6803 call_method( func, argspos, args, (DWORD_PTR *)&regs );
6804 break;
6805 case VT_R4:
6806 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)&regs );
6807 break;
6808 case VT_R8:
6809 case VT_DATE:
6810 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)&regs );
6811 break;
6812 default:
6813 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)&regs );
6814 break;
6816 free( args );
6817 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
6818 TRACE("retval: %s\n", debugstr_variant(result));
6819 return S_OK;
6822 #else /* __aarch64__ */
6824 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6825 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6827 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6828 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6829 return E_NOTIMPL;
6832 #endif
6834 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6836 HRESULT hr = S_OK;
6837 ITypeInfo *tinfo2 = NULL;
6838 TYPEATTR *tattr = NULL;
6840 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->hreftype, &tinfo2);
6841 if (hr)
6843 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc->hreftype, hr);
6844 return hr;
6846 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6847 if (hr)
6849 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr);
6850 ITypeInfo_Release(tinfo2);
6851 return hr;
6854 switch (tattr->typekind)
6856 case TKIND_ENUM:
6857 *vt |= VT_I4;
6858 break;
6860 case TKIND_ALIAS:
6861 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6862 break;
6864 case TKIND_INTERFACE:
6865 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6866 *vt |= VT_DISPATCH;
6867 else
6868 *vt |= VT_UNKNOWN;
6869 break;
6871 case TKIND_DISPATCH:
6872 *vt |= VT_DISPATCH;
6873 break;
6875 case TKIND_COCLASS:
6876 *vt |= VT_DISPATCH;
6877 break;
6879 case TKIND_RECORD:
6880 FIXME("TKIND_RECORD unhandled.\n");
6881 hr = E_NOTIMPL;
6882 break;
6884 case TKIND_UNION:
6885 FIXME("TKIND_UNION unhandled.\n");
6886 hr = E_NOTIMPL;
6887 break;
6889 default:
6890 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6891 hr = E_NOTIMPL;
6892 break;
6894 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6895 ITypeInfo_Release(tinfo2);
6896 return hr;
6899 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6901 HRESULT hr = S_OK;
6903 /* enforce only one level of pointer indirection */
6904 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6906 tdesc = tdesc->lptdesc;
6908 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6909 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6910 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6911 if ((tdesc->vt == VT_USERDEFINED) ||
6912 ((tdesc->vt == VT_PTR) && (tdesc->lptdesc->vt == VT_USERDEFINED)))
6914 VARTYPE vt_userdefined = 0;
6915 const TYPEDESC *tdesc_userdefined = tdesc;
6916 if (tdesc->vt == VT_PTR)
6918 vt_userdefined = VT_BYREF;
6919 tdesc_userdefined = tdesc->lptdesc;
6921 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6922 if ((hr == S_OK) &&
6923 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6924 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6926 *vt |= vt_userdefined;
6927 return S_OK;
6930 *vt = VT_BYREF;
6933 switch (tdesc->vt)
6935 case VT_HRESULT:
6936 *vt |= VT_ERROR;
6937 break;
6938 case VT_USERDEFINED:
6939 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6940 break;
6941 case VT_VOID:
6942 case VT_CARRAY:
6943 case VT_PTR:
6944 case VT_LPSTR:
6945 case VT_LPWSTR:
6946 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6947 hr = DISP_E_BADVARTYPE;
6948 break;
6949 case VT_SAFEARRAY:
6950 *vt |= VT_ARRAY;
6951 hr = typedescvt_to_variantvt(tinfo, tdesc->lptdesc, vt);
6952 break;
6953 case VT_INT:
6954 *vt |= VT_I4;
6955 break;
6956 case VT_UINT:
6957 *vt |= VT_UI4;
6958 break;
6959 default:
6960 *vt |= tdesc->vt;
6961 break;
6963 return hr;
6966 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
6968 ITypeInfo *tinfo2;
6969 TYPEATTR *tattr;
6970 HRESULT hres;
6971 int flags, i;
6973 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
6974 if(FAILED(hres))
6975 return hres;
6977 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6978 if(FAILED(hres)) {
6979 ITypeInfo_Release(tinfo2);
6980 return hres;
6983 switch(tattr->typekind) {
6984 case TKIND_ALIAS:
6985 hres = get_iface_guid(tinfo2, tattr->tdescAlias.hreftype, guid);
6986 break;
6988 case TKIND_INTERFACE:
6989 case TKIND_DISPATCH:
6990 *guid = tattr->guid;
6991 break;
6993 case TKIND_COCLASS:
6994 for (i = 0; i < tattr->cImplTypes; i++)
6996 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
6997 if (flags & IMPLTYPEFLAG_FDEFAULT)
6998 break;
7001 if (i == tattr->cImplTypes)
7002 i = 0;
7004 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7005 if (SUCCEEDED(hres))
7006 hres = get_iface_guid(tinfo2, href, guid);
7007 break;
7009 default:
7010 ERR("Unexpected typekind %d\n", tattr->typekind);
7011 hres = E_UNEXPECTED;
7014 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7015 ITypeInfo_Release(tinfo2);
7016 return hres;
7019 static inline BOOL func_restricted( const FUNCDESC *desc )
7021 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7024 #define INVBUF_ELEMENT_SIZE \
7025 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7026 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7027 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7028 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7029 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7030 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7031 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7032 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7034 static HRESULT WINAPI ITypeInfo_fnInvoke(
7035 ITypeInfo2 *iface,
7036 VOID *pIUnk,
7037 MEMBERID memid,
7038 UINT16 wFlags,
7039 DISPPARAMS *pDispParams,
7040 VARIANT *pVarResult,
7041 EXCEPINFO *pExcepInfo,
7042 UINT *pArgErr)
7044 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7045 int i, j;
7046 unsigned int var_index;
7047 TYPEKIND type_kind;
7048 HRESULT hres;
7049 const TLBFuncDesc *pFuncInfo;
7050 UINT fdc;
7052 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface, pIUnk, memid, wFlags, pDispParams,
7053 pVarResult, pExcepInfo, pArgErr);
7055 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7056 return DISP_E_MEMBERNOTFOUND;
7058 if (!pDispParams)
7060 ERR("NULL pDispParams not allowed\n");
7061 return E_INVALIDARG;
7064 dump_DispParms(pDispParams);
7066 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7068 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7069 pDispParams->cNamedArgs, pDispParams->cArgs);
7070 return E_INVALIDARG;
7073 /* we do this instead of using GetFuncDesc since it will return a fake
7074 * FUNCDESC for dispinterfaces and we want the real function description */
7075 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7076 pFuncInfo = &This->funcdescs[fdc];
7077 if ((memid == pFuncInfo->funcdesc.memid) &&
7078 (wFlags & pFuncInfo->funcdesc.invkind) &&
7079 !func_restricted( &pFuncInfo->funcdesc ))
7080 break;
7083 if (fdc < This->typeattr.cFuncs) {
7084 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7086 if (TRACE_ON(ole))
7088 TRACE("invoking:\n");
7089 dump_TLBFuncDescOne(pFuncInfo);
7092 switch (func_desc->funckind) {
7093 case FUNC_PUREVIRTUAL:
7094 case FUNC_VIRTUAL: {
7095 void *buffer = calloc(func_desc->cParams, INVBUF_ELEMENT_SIZE);
7096 VARIANT varresult;
7097 VARIANT retval = {{{0}}}; /* pointer for storing byref retvals in */
7098 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7099 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7100 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7101 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7102 UINT cNamedArgs = pDispParams->cNamedArgs;
7103 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7104 UINT vargs_converted=0;
7105 SAFEARRAY *a;
7107 hres = S_OK;
7109 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7111 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7113 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7114 hres = DISP_E_PARAMNOTFOUND;
7115 goto func_fail;
7119 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7121 ERR("functions with the vararg attribute do not support named arguments\n");
7122 hres = DISP_E_NONAMEDARGS;
7123 goto func_fail;
7126 for (i = 0; i < func_desc->cParams; i++)
7128 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7129 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7130 if (FAILED(hres))
7131 goto func_fail;
7134 TRACE("changing args\n");
7135 for (i = 0; i < func_desc->cParams; i++)
7137 USHORT wParamFlags = func_desc->lprgelemdescParam[i].paramdesc.wParamFlags;
7138 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7139 VARIANTARG *src_arg;
7141 if (wParamFlags & PARAMFLAG_FLCID)
7143 prgpvarg[i] = &rgvarg[i];
7144 V_VT(prgpvarg[i]) = VT_I4;
7145 V_I4(prgpvarg[i]) = This->pTypeLib->lcid;
7146 continue;
7149 src_arg = NULL;
7151 for (j = 0; j < cNamedArgs; j++)
7153 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7155 src_arg = &pDispParams->rgvarg[j];
7156 break;
7160 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7162 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7163 vargs_converted++;
7166 if (wParamFlags & PARAMFLAG_FRETVAL)
7168 /* under most conditions the caller is not allowed to
7169 * pass in a dispparam arg in the index of what would be
7170 * the retval parameter. however, there is an exception
7171 * where the extra parameter is used in an extra
7172 * IDispatch::Invoke below */
7173 if ((i < pDispParams->cArgs) &&
7174 ((func_desc->cParams != 1) || !pVarResult ||
7175 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7177 hres = DISP_E_BADPARAMCOUNT;
7178 break;
7181 /* note: this check is placed so that if the caller passes
7182 * in a VARIANTARG for the retval we just ignore it, like
7183 * native does */
7184 if (i == func_desc->cParams - 1)
7186 prgpvarg[i] = &rgvarg[i];
7187 V_BYREF(prgpvarg[i]) = &retval;
7188 V_VT(prgpvarg[i]) = rgvt[i];
7190 else
7192 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7193 hres = E_UNEXPECTED;
7194 break;
7197 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7198 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7200 TRACE("%s\n", debugstr_variant(src_arg));
7202 if(rgvt[i]!=V_VT(src_arg))
7204 if (rgvt[i] == VT_VARIANT)
7205 hres = VariantCopy(&rgvarg[i], src_arg);
7206 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7208 if (rgvt[i] == V_VT(src_arg))
7209 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7210 else
7212 if (wParamFlags & PARAMFLAG_FIN)
7213 hres = VariantCopy(&missing_arg[i], src_arg);
7214 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7216 V_VT(&rgvarg[i]) = rgvt[i];
7218 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7220 SAFEARRAYBOUND bound;
7221 VARIANT *v;
7223 bound.lLbound = 0;
7224 bound.cElements = pDispParams->cArgs-i;
7225 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7227 ERR("SafeArrayCreate failed\n");
7228 break;
7230 hres = SafeArrayAccessData(a, (LPVOID)&v);
7231 if (hres != S_OK)
7233 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7234 SafeArrayDestroy(a);
7235 break;
7237 for (j = 0; j < bound.cElements; j++)
7238 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7239 hres = SafeArrayUnaccessData(a);
7240 if (hres != S_OK)
7242 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7243 SafeArrayDestroy(a);
7244 break;
7246 if (rgvt[i] & VT_BYREF)
7247 V_BYREF(&rgvarg[i]) = &a;
7248 else
7249 V_ARRAY(&rgvarg[i]) = a;
7250 V_VT(&rgvarg[i]) = rgvt[i];
7252 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7254 if (wParamFlags & PARAMFLAG_FIN)
7255 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7256 else
7257 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7258 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7259 V_VT(&rgvarg[i]) = rgvt[i];
7261 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7263 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7264 V_VT(&rgvarg[i]) = rgvt[i];
7266 else
7268 /* FIXME: this doesn't work for VT_BYREF arguments if
7269 * they are not the same type as in the paramdesc */
7270 V_VT(&rgvarg[i]) = V_VT(src_arg);
7271 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7272 V_VT(&rgvarg[i]) = rgvt[i];
7275 if (FAILED(hres))
7277 ERR("failed to convert param %d to %s from %s\n", i,
7278 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7279 break;
7281 prgpvarg[i] = &rgvarg[i];
7283 else
7285 prgpvarg[i] = src_arg;
7288 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->lptdesc->vt == VT_USERDEFINED))
7289 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7290 && V_UNKNOWN(prgpvarg[i])) {
7291 IUnknown *userdefined_iface;
7292 GUID guid;
7294 if (tdesc->vt == VT_PTR)
7295 tdesc = tdesc->lptdesc;
7297 hres = get_iface_guid((ITypeInfo*)iface, tdesc->hreftype, &guid);
7298 if(FAILED(hres))
7299 break;
7301 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7302 if(FAILED(hres)) {
7303 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7304 break;
7307 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7308 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7311 else if (wParamFlags & PARAMFLAG_FOPT)
7313 VARIANTARG *arg;
7314 arg = prgpvarg[i] = &rgvarg[i];
7315 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7317 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].paramdesc.pparamdescex->varDefaultValue);
7318 if (FAILED(hres))
7319 break;
7321 else
7323 /* if the function wants a pointer to a variant then
7324 * set that up, otherwise just pass the VT_ERROR in
7325 * the argument by value */
7326 if (rgvt[i] & VT_BYREF)
7328 V_VT(&missing_arg[i]) = VT_ERROR;
7329 V_ERROR(&missing_arg[i]) = DISP_E_PARAMNOTFOUND;
7331 V_VT(arg) = VT_VARIANT | VT_BYREF;
7332 V_VARIANTREF(arg) = &missing_arg[i];
7334 else
7336 V_VT(arg) = VT_ERROR;
7337 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
7341 else if (func_desc->cParamsOpt < 0 && ((rgvt[i] & ~VT_BYREF) == (VT_VARIANT | VT_ARRAY)))
7343 hres = SafeArrayAllocDescriptorEx( VT_EMPTY, 1, &a );
7344 if (FAILED(hres)) break;
7345 if (rgvt[i] & VT_BYREF)
7346 V_BYREF(&rgvarg[i]) = &a;
7347 else
7348 V_ARRAY(&rgvarg[i]) = a;
7349 V_VT(&rgvarg[i]) = rgvt[i];
7350 prgpvarg[i] = &rgvarg[i];
7352 else
7354 hres = DISP_E_BADPARAMCOUNT;
7355 break;
7358 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7360 /* VT_VOID is a special case for return types, so it is not
7361 * handled in the general function */
7362 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7363 V_VT(&varresult) = VT_EMPTY;
7364 else
7366 V_VT(&varresult) = 0;
7367 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7368 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7371 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7372 V_VT(&varresult), func_desc->cParams, rgvt,
7373 prgpvarg, &varresult);
7375 vargs_converted = 0;
7377 for (i = 0; i < func_desc->cParams; i++)
7379 USHORT wParamFlags = func_desc->lprgelemdescParam[i].paramdesc.wParamFlags;
7381 if (wParamFlags & PARAMFLAG_FLCID)
7382 continue;
7383 else if (wParamFlags & PARAMFLAG_FRETVAL)
7385 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7387 if (pVarResult)
7389 VariantInit(pVarResult);
7390 /* deref return value */
7391 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7394 VARIANT_ClearInd(prgpvarg[i]);
7396 else if (vargs_converted < pDispParams->cArgs)
7398 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7399 if (wParamFlags & PARAMFLAG_FOUT)
7401 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7403 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7405 if (FAILED(hres))
7407 ERR("failed to convert param %d to vt %d\n", i,
7408 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7409 break;
7413 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7414 func_desc->cParamsOpt < 0 &&
7415 i == func_desc->cParams-1)
7417 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7418 LONG ubound;
7419 VARIANT *v;
7420 hres = SafeArrayGetUBound(a, 1, &ubound);
7421 if (hres != S_OK)
7423 ERR("SafeArrayGetUBound failed with %#lx.\n", hres);
7424 break;
7426 hres = SafeArrayAccessData(a, (LPVOID)&v);
7427 if (hres != S_OK)
7429 ERR("SafeArrayAccessData failed with %#lx.\n", hres);
7430 break;
7432 for (j = 0; j <= ubound; j++)
7433 VariantClear(&v[j]);
7434 hres = SafeArrayUnaccessData(a);
7435 if (hres != S_OK)
7437 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres);
7438 break;
7441 VariantClear(&rgvarg[i]);
7442 vargs_converted++;
7444 else if (wParamFlags & PARAMFLAG_FOPT)
7446 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7447 VariantClear(&rgvarg[i]);
7450 VariantClear(&missing_arg[i]);
7453 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7455 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult));
7456 hres = DISP_E_EXCEPTION;
7457 if (pExcepInfo)
7459 IErrorInfo *pErrorInfo;
7460 pExcepInfo->scode = V_ERROR(&varresult);
7461 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7463 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7464 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7465 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7466 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7468 IErrorInfo_Release(pErrorInfo);
7472 if (V_VT(&varresult) != VT_ERROR)
7474 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7476 if (pVarResult)
7478 VariantClear(pVarResult);
7479 *pVarResult = varresult;
7481 else
7482 VariantClear(&varresult);
7485 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7486 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7487 (func_desc->lprgelemdescParam[0].paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7488 (pDispParams->cArgs != 0))
7490 if (V_VT(pVarResult) == VT_DISPATCH)
7492 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7493 /* Note: not VariantClear; we still need the dispatch
7494 * pointer to be valid */
7495 VariantInit(pVarResult);
7496 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7497 GetSystemDefaultLCID(), wFlags,
7498 pDispParams, pVarResult, pExcepInfo, pArgErr);
7499 IDispatch_Release(pDispatch);
7501 else
7503 VariantClear(pVarResult);
7504 hres = DISP_E_NOTACOLLECTION;
7508 func_fail:
7509 free(buffer);
7510 break;
7512 case FUNC_DISPATCH: {
7513 IDispatch *disp;
7515 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7516 if (SUCCEEDED(hres)) {
7517 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7518 hres = IDispatch_Invoke(
7519 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7520 pVarResult,pExcepInfo,pArgErr
7522 if (FAILED(hres))
7523 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres);
7524 IDispatch_Release(disp);
7525 } else
7526 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7527 break;
7529 default:
7530 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7531 hres = E_FAIL;
7532 break;
7535 TRACE("-- %#lx\n", hres);
7536 return hres;
7538 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7539 VARDESC *var_desc;
7541 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7542 if(FAILED(hres)) return hres;
7544 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7545 dump_VARDESC(var_desc);
7546 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7547 return E_NOTIMPL;
7550 /* not found, check for special error cases */
7551 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc)
7553 const FUNCDESC *func_desc = &This->funcdescs[fdc].funcdesc;
7554 if (memid == func_desc->memid)
7556 if ((wFlags & INVOKE_PROPERTYPUT) && (func_desc->invkind & INVOKE_PROPERTYGET))
7558 int count_inputs = 0;
7559 for (i = 0; i < func_desc->cParams; i++)
7561 USHORT wParamFlags = func_desc->lprgelemdescParam[i].paramdesc.wParamFlags;
7562 if (!(wParamFlags & PARAMFLAG_FRETVAL))
7563 count_inputs++;
7566 if (count_inputs == 0 || pDispParams->cArgs == count_inputs + 1)
7567 return DISP_E_BADPARAMCOUNT;
7572 /* not found, look for it in inherited interfaces */
7573 ITypeInfo2_GetTypeKind(iface, &type_kind);
7574 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7575 if(This->impltypes) {
7576 /* recursive search */
7577 ITypeInfo *pTInfo;
7578 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7579 if(SUCCEEDED(hres)){
7580 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7581 ITypeInfo_Release(pTInfo);
7582 return hres;
7584 WARN("Could not search inherited interface!\n");
7587 WARN("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
7588 return DISP_E_MEMBERNOTFOUND;
7591 /* ITypeInfo::GetDocumentation
7593 * Retrieves the documentation string, the complete Help file name and path,
7594 * and the context ID for the Help topic for a specified type description.
7596 * (Can be tested by the Visual Basic Editor in Word for instance.)
7598 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7599 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7600 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7602 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7603 const TLBFuncDesc *pFDesc;
7604 const TLBVarDesc *pVDesc;
7605 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7606 iface, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7607 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7608 if(pBstrName)
7609 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7610 if(pBstrDocString)
7611 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7612 if(pdwHelpContext)
7613 *pdwHelpContext=This->dwHelpContext;
7614 if(pBstrHelpFile)
7615 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7616 return S_OK;
7617 }else {/* for a member */
7618 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
7619 if(pFDesc){
7620 if(pBstrName)
7621 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7622 if(pBstrDocString)
7623 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7624 if(pdwHelpContext)
7625 *pdwHelpContext=pFDesc->helpcontext;
7626 if(pBstrHelpFile)
7627 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7628 return S_OK;
7630 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
7631 if(pVDesc){
7632 if(pBstrName)
7633 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7634 if(pBstrDocString)
7635 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7636 if(pdwHelpContext)
7637 *pdwHelpContext=pVDesc->HelpContext;
7638 if(pBstrHelpFile)
7639 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7640 return S_OK;
7644 if(This->impltypes &&
7645 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7646 /* recursive search */
7647 ITypeInfo *pTInfo;
7648 HRESULT result;
7649 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7650 if(SUCCEEDED(result)) {
7651 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7652 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7653 ITypeInfo_Release(pTInfo);
7654 return result;
7656 WARN("Could not search inherited interface!\n");
7659 WARN("member %ld not found\n", memid);
7660 return TYPE_E_ELEMENTNOTFOUND;
7663 /* ITypeInfo::GetDllEntry
7665 * Retrieves a description or specification of an entry point for a function
7666 * in a DLL.
7668 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7669 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7670 WORD *pwOrdinal)
7672 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7673 const TLBFuncDesc *pFDesc;
7675 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7677 if (pBstrDllName) *pBstrDllName = NULL;
7678 if (pBstrName) *pBstrName = NULL;
7679 if (pwOrdinal) *pwOrdinal = 0;
7681 if (This->typeattr.typekind != TKIND_MODULE)
7682 return TYPE_E_BADMODULEKIND;
7684 pFDesc = TLB_get_funcdesc_by_memberid_invkind(This, memid, invKind);
7685 if (!pFDesc) return TYPE_E_ELEMENTNOTFOUND;
7687 dump_TypeInfo(This);
7688 if (TRACE_ON(ole)) dump_TLBFuncDescOne(pFDesc);
7690 if (pBstrDllName) *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7692 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1))
7694 if (pBstrName) *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7695 if (pwOrdinal) *pwOrdinal = -1;
7697 else
7699 if (pBstrName) *pBstrName = NULL;
7700 if (pwOrdinal) *pwOrdinal = LOWORD(pFDesc->Entry);
7702 return S_OK;
7705 /* internal function to make the inherited interfaces' methods appear
7706 * part of the interface */
7707 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7708 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7710 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7711 HRESULT hr;
7713 TRACE("%p, %#lx.\n", iface, *hRefType);
7715 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7717 ITypeInfo *pSubTypeInfo;
7719 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7720 if (FAILED(hr))
7721 return hr;
7723 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7724 hRefType, ppTInfo);
7725 ITypeInfo_Release(pSubTypeInfo);
7726 if (SUCCEEDED(hr))
7727 return hr;
7729 *hRefType -= DISPATCH_HREF_OFFSET;
7731 if (!(*hRefType & DISPATCH_HREF_MASK))
7732 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7733 else
7734 return E_FAIL;
7737 /* ITypeInfo::GetRefTypeInfo
7739 * If a type description references other type descriptions, it retrieves
7740 * the referenced type descriptions.
7742 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7743 ITypeInfo2 *iface,
7744 HREFTYPE hRefType,
7745 ITypeInfo **ppTInfo)
7747 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7748 ITypeInfo *type_info = NULL;
7749 HRESULT result = E_FAIL;
7750 TLBRefType *ref_type;
7751 UINT i;
7753 if(!ppTInfo)
7754 return E_INVALIDARG;
7756 if ((INT)hRefType < 0) {
7757 ITypeInfoImpl *pTypeInfoImpl;
7759 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7760 !(This->typeattr.typekind == TKIND_INTERFACE ||
7761 This->typeattr.typekind == TKIND_DISPATCH))
7762 return TYPE_E_ELEMENTNOTFOUND;
7764 /* when we meet a DUAL typeinfo, we must create the alternate
7765 * version of it.
7767 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7769 *pTypeInfoImpl = *This;
7770 pTypeInfoImpl->ref = 0;
7771 list_init(&pTypeInfoImpl->custdata_list);
7773 if (This->typeattr.typekind == TKIND_INTERFACE)
7774 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7775 else
7776 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7778 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7779 /* the AddRef implicitly adds a reference to the parent typelib, which
7780 * stops the copied data from being destroyed until the new typeinfo's
7781 * refcount goes to zero, but we need to signal to the new instance to
7782 * not free its data structures when it is destroyed */
7783 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7784 ITypeInfo_AddRef(*ppTInfo);
7786 TRACE("got dual interface %p\n", *ppTInfo);
7787 return S_OK;
7790 if ((hRefType & DISPATCH_HREF_MASK) && (This->typeattr.typekind == TKIND_DISPATCH))
7791 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &hRefType, ppTInfo);
7793 if(!(hRefType & 0x1))
7795 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7797 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7799 result = S_OK;
7800 type_info = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7801 ITypeInfo_AddRef(type_info);
7802 break;
7807 if (!type_info)
7809 ITypeLib *pTLib = NULL;
7811 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7813 if(ref_type->reference == (hRefType & (~0x3)))
7814 break;
7816 if(&ref_type->entry == &This->pTypeLib->ref_list)
7818 FIXME("Can't find pRefType for ref %lx\n", hRefType);
7819 return E_FAIL;
7822 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7823 UINT Index;
7824 TRACE("internal reference\n");
7825 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7826 } else {
7827 if(ref_type->pImpTLInfo->pImpTypeLib) {
7828 TRACE("typeinfo in imported typelib that is already loaded\n");
7829 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7830 ITypeLib_AddRef(pTLib);
7831 result = S_OK;
7832 } else {
7833 /* Search in cached typelibs */
7834 ITypeLibImpl *entry;
7836 EnterCriticalSection(&cache_section);
7837 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
7839 if (entry->guid
7840 && IsEqualIID(&entry->guid->guid, TLB_get_guid_null(ref_type->pImpTLInfo->guid))
7841 && entry->ver_major == ref_type->pImpTLInfo->wVersionMajor
7842 && entry->ver_minor == ref_type->pImpTLInfo->wVersionMinor
7843 && entry->set_lcid == ref_type->pImpTLInfo->lcid)
7845 TRACE("got cached %p\n", entry);
7846 pTLib = (ITypeLib*)&entry->ITypeLib2_iface;
7847 ITypeLib_AddRef(pTLib);
7848 result = S_OK;
7849 break;
7852 LeaveCriticalSection(&cache_section);
7854 if (!pTLib)
7856 BSTR libnam;
7858 /* Search on disk */
7859 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7860 ref_type->pImpTLInfo->wVersionMajor,
7861 ref_type->pImpTLInfo->wVersionMinor,
7862 This->pTypeLib->syskind,
7863 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7864 if (FAILED(result))
7865 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7867 result = LoadTypeLib(libnam, &pTLib);
7868 SysFreeString(libnam);
7871 if(SUCCEEDED(result)) {
7872 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7873 ITypeLib_AddRef(pTLib);
7877 if(SUCCEEDED(result)) {
7878 if(ref_type->index == TLB_REF_USE_GUID)
7879 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), &type_info);
7880 else
7881 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, &type_info);
7883 if (pTLib != NULL)
7884 ITypeLib_Release(pTLib);
7885 if (FAILED(result))
7887 WARN("(%p) failed hreftype %#lx.\n", iface, hRefType);
7888 return result;
7892 if ((hRefType & 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info, -2, ppTInfo)))
7893 ITypeInfo_Release(type_info);
7894 else *ppTInfo = type_info;
7896 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface, hRefType,
7897 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7898 return result;
7901 /* ITypeInfo::AddressOfMember
7903 * Retrieves the addresses of static functions or variables, such as those
7904 * defined in a DLL.
7906 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7907 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7909 HRESULT hr;
7910 BSTR dll, entry;
7911 WORD ordinal;
7912 HMODULE module;
7914 TRACE("%p, %lx, %#x, %p.\n", iface, memid, invKind, ppv);
7916 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7917 if (FAILED(hr))
7918 return hr;
7920 module = LoadLibraryW(dll);
7921 if (!module)
7923 ERR("couldn't load %s\n", debugstr_w(dll));
7924 SysFreeString(dll);
7925 SysFreeString(entry);
7926 return STG_E_FILENOTFOUND;
7928 /* FIXME: store library somewhere where we can free it */
7930 if (entry)
7932 LPSTR entryA;
7933 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7934 entryA = malloc(len);
7935 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7937 *ppv = GetProcAddress(module, entryA);
7938 if (!*ppv)
7939 ERR("function not found %s\n", debugstr_a(entryA));
7941 free(entryA);
7943 else
7945 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7946 if (!*ppv)
7947 ERR("function not found %d\n", ordinal);
7950 SysFreeString(dll);
7951 SysFreeString(entry);
7953 if (!*ppv)
7954 return TYPE_E_DLLFUNCTIONNOTFOUND;
7956 return S_OK;
7959 /* ITypeInfo::CreateInstance
7961 * Creates a new instance of a type that describes a component object class
7962 * (coclass).
7964 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7965 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7967 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7968 HRESULT hr;
7969 TYPEATTR *pTA;
7971 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7973 *ppvObj = NULL;
7975 if(pOuterUnk)
7977 WARN("Not able to aggregate\n");
7978 return CLASS_E_NOAGGREGATION;
7981 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7982 if(FAILED(hr)) return hr;
7984 if(pTA->typekind != TKIND_COCLASS)
7986 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7987 hr = E_INVALIDARG;
7988 goto end;
7991 hr = S_FALSE;
7992 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7994 IUnknown *pUnk;
7995 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7996 TRACE("GetActiveObject rets %#lx.\n", hr);
7997 if(hr == S_OK)
7999 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8000 IUnknown_Release(pUnk);
8004 if(hr != S_OK)
8005 hr = CoCreateInstance(&pTA->guid, NULL,
8006 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8007 riid, ppvObj);
8009 end:
8010 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8011 return hr;
8014 /* ITypeInfo::GetMops
8016 * Retrieves marshalling information.
8018 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, BSTR *pBstrMops)
8020 FIXME("%p, %ld stub!\n", iface, memid);
8021 *pBstrMops = NULL;
8022 return S_OK;
8025 /* ITypeInfo::GetContainingTypeLib
8027 * Retrieves the containing type library and the index of the type description
8028 * within that type library.
8030 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8031 ITypeLib * *ppTLib, UINT *pIndex)
8033 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8035 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8036 if (pIndex) {
8037 *pIndex=This->index;
8038 TRACE("returning pIndex=%d\n", *pIndex);
8041 if (ppTLib) {
8042 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8043 ITypeLib_AddRef(*ppTLib);
8044 TRACE("returning ppTLib=%p\n", *ppTLib);
8047 return S_OK;
8050 /* ITypeInfo::ReleaseTypeAttr
8052 * Releases a TYPEATTR previously returned by Get
8055 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8056 TYPEATTR* pTypeAttr)
8058 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8059 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8060 free(pTypeAttr);
8063 /* ITypeInfo::ReleaseFuncDesc
8065 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8067 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8068 ITypeInfo2 *iface,
8069 FUNCDESC *pFuncDesc)
8071 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8072 SHORT i;
8074 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8076 for (i = 0; i < pFuncDesc->cParams; i++)
8077 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8078 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8080 SysFreeString((BSTR)pFuncDesc);
8083 /* ITypeInfo::ReleaseVarDesc
8085 * Releases a VARDESC previously returned by GetVarDesc.
8087 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8088 VARDESC *pVarDesc)
8090 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8091 TRACE("(%p)->(%p)\n", This, pVarDesc);
8093 TLB_FreeVarDesc(pVarDesc);
8096 /* ITypeInfo2::GetTypeKind
8098 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8101 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8102 TYPEKIND *pTypeKind)
8104 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8105 *pTypeKind = This->typeattr.typekind;
8106 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8107 return S_OK;
8110 /* ITypeInfo2::GetTypeFlags
8112 * Returns the type flags without any allocations. This returns a DWORD type
8113 * flag, which expands the type flags without growing the TYPEATTR (type
8114 * attribute).
8117 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8119 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8120 TRACE("%p, %p.\n", iface, pTypeFlags);
8121 *pTypeFlags=This->typeattr.wTypeFlags;
8122 return S_OK;
8125 /* ITypeInfo2::GetFuncIndexOfMemId
8126 * Binds to a specific member based on a known DISPID, where the member name
8127 * is not known (for example, when binding to a default member).
8130 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8131 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8133 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8134 UINT fdc;
8135 HRESULT result;
8137 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8138 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8139 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8140 break;
8142 if(fdc < This->typeattr.cFuncs) {
8143 *pFuncIndex = fdc;
8144 result = S_OK;
8145 } else
8146 result = TYPE_E_ELEMENTNOTFOUND;
8148 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface, memid, invKind, result);
8149 return result;
8152 /* TypeInfo2::GetVarIndexOfMemId
8154 * Binds to a specific member based on a known DISPID, where the member name
8155 * is not known (for example, when binding to a default member).
8158 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8159 MEMBERID memid, UINT *pVarIndex)
8161 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8162 TLBVarDesc *pVarInfo;
8164 TRACE("%p, %ld, %p.\n", iface, memid, pVarIndex);
8166 pVarInfo = TLB_get_vardesc_by_memberid(This, memid);
8167 if(!pVarInfo)
8168 return TYPE_E_ELEMENTNOTFOUND;
8170 *pVarIndex = (pVarInfo - This->vardescs);
8172 return S_OK;
8175 /* ITypeInfo2::GetCustData
8177 * Gets the custom data
8179 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8180 ITypeInfo2 * iface,
8181 REFGUID guid,
8182 VARIANT *pVarVal)
8184 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8185 TLBCustData *pCData;
8187 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8189 if(!guid || !pVarVal)
8190 return E_INVALIDARG;
8192 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8194 VariantInit( pVarVal);
8195 if (pCData)
8196 VariantCopy( pVarVal, &pCData->data);
8197 else
8198 VariantClear( pVarVal );
8199 return S_OK;
8202 /* ITypeInfo2::GetFuncCustData
8204 * Gets the custom data
8206 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8207 ITypeInfo2 * iface,
8208 UINT index,
8209 REFGUID guid,
8210 VARIANT *pVarVal)
8212 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8213 const TLBFuncDesc *desc;
8214 TLBCustData *data;
8215 UINT hrefoffset;
8216 HRESULT hr;
8218 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8220 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &desc, &hrefoffset);
8221 if (FAILED(hr))
8223 WARN("description for function %d not found\n", index);
8224 return hr;
8227 VariantInit(pVarVal);
8228 data = TLB_get_custdata_by_guid(&desc->custdata_list, guid);
8229 return data ? VariantCopy(pVarVal, &data->data) : S_OK;
8232 /* ITypeInfo2::GetParamCustData
8234 * Gets the custom data
8236 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8237 ITypeInfo2 * iface,
8238 UINT indexFunc,
8239 UINT indexParam,
8240 REFGUID guid,
8241 VARIANT *pVarVal)
8243 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8244 const TLBFuncDesc *pFDesc;
8245 TLBCustData *pCData;
8246 UINT hrefoffset;
8247 HRESULT hr;
8249 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8250 debugstr_guid(guid), pVarVal);
8252 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8253 if (FAILED(hr))
8254 return hr;
8256 if(indexParam >= pFDesc->funcdesc.cParams)
8257 return TYPE_E_ELEMENTNOTFOUND;
8259 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8260 if(!pCData)
8261 return TYPE_E_ELEMENTNOTFOUND;
8263 VariantInit(pVarVal);
8264 VariantCopy(pVarVal, &pCData->data);
8266 return S_OK;
8269 /* ITypeInfo2::GetVarCustData
8271 * Gets the custom data
8273 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8274 ITypeInfo2 * iface,
8275 UINT index,
8276 REFGUID guid,
8277 VARIANT *pVarVal)
8279 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8280 TLBCustData *pCData;
8281 TLBVarDesc *pVDesc = &This->vardescs[index];
8283 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8285 if(index >= This->typeattr.cVars)
8286 return TYPE_E_ELEMENTNOTFOUND;
8288 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8289 if(!pCData)
8290 return TYPE_E_ELEMENTNOTFOUND;
8292 VariantInit(pVarVal);
8293 VariantCopy(pVarVal, &pCData->data);
8295 return S_OK;
8298 /* ITypeInfo2::GetImplCustData
8300 * Gets the custom data
8302 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8303 ITypeInfo2 * iface,
8304 UINT index,
8305 REFGUID guid,
8306 VARIANT *pVarVal)
8308 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8309 TLBCustData *pCData;
8310 TLBImplType *pRDesc = &This->impltypes[index];
8312 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8314 if(index >= This->typeattr.cImplTypes)
8315 return TYPE_E_ELEMENTNOTFOUND;
8317 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8318 if(!pCData)
8319 return TYPE_E_ELEMENTNOTFOUND;
8321 VariantInit(pVarVal);
8322 VariantCopy(pVarVal, &pCData->data);
8324 return S_OK;
8327 /* ITypeInfo2::GetDocumentation2
8329 * Retrieves the documentation string, the complete Help file name and path,
8330 * the localization context to use, and the context ID for the library Help
8331 * topic in the Help file.
8334 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8335 ITypeInfo2 * iface,
8336 MEMBERID memid,
8337 LCID lcid,
8338 BSTR *pbstrHelpString,
8339 DWORD *pdwHelpStringContext,
8340 BSTR *pbstrHelpStringDll)
8342 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8343 const TLBFuncDesc *pFDesc;
8344 const TLBVarDesc *pVDesc;
8345 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8346 iface, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8347 pbstrHelpStringDll );
8348 /* the help string should be obtained from the helpstringdll,
8349 * using the _DLLGetDocumentation function, based on the supplied
8350 * lcid. Nice to do sometime...
8352 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8353 if(pbstrHelpString)
8354 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8355 if(pdwHelpStringContext)
8356 *pdwHelpStringContext=This->dwHelpStringContext;
8357 if(pbstrHelpStringDll)
8358 *pbstrHelpStringDll=
8359 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8360 return S_OK;
8361 }else {/* for a member */
8362 pFDesc = TLB_get_funcdesc_by_memberid(This, memid);
8363 if(pFDesc){
8364 if(pbstrHelpString)
8365 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8366 if(pdwHelpStringContext)
8367 *pdwHelpStringContext=pFDesc->HelpStringContext;
8368 if(pbstrHelpStringDll)
8369 *pbstrHelpStringDll=
8370 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8371 return S_OK;
8373 pVDesc = TLB_get_vardesc_by_memberid(This, memid);
8374 if(pVDesc){
8375 if(pbstrHelpString)
8376 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8377 if(pdwHelpStringContext)
8378 *pdwHelpStringContext=pVDesc->HelpStringContext;
8379 if(pbstrHelpStringDll)
8380 *pbstrHelpStringDll=
8381 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8382 return S_OK;
8385 return TYPE_E_ELEMENTNOTFOUND;
8388 /* ITypeInfo2::GetAllCustData
8390 * Gets all custom data items for the Type info.
8393 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8394 ITypeInfo2 * iface,
8395 CUSTDATA *pCustData)
8397 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8399 TRACE("%p %p\n", This, pCustData);
8401 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8404 /* ITypeInfo2::GetAllFuncCustData
8406 * Gets all custom data items for the specified Function
8409 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8410 ITypeInfo2 * iface,
8411 UINT index,
8412 CUSTDATA *pCustData)
8414 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8415 const TLBFuncDesc *pFDesc;
8416 UINT hrefoffset;
8417 HRESULT hr;
8419 TRACE("%p %u %p\n", This, index, pCustData);
8421 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &pFDesc, &hrefoffset);
8422 if (FAILED(hr))
8423 return hr;
8425 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8428 /* ITypeInfo2::GetAllParamCustData
8430 * Gets all custom data items for the Functions
8433 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8434 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8436 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8437 const TLBFuncDesc *pFDesc;
8438 UINT hrefoffset;
8439 HRESULT hr;
8441 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8443 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, indexFunc, &pFDesc, &hrefoffset);
8444 if (FAILED(hr))
8445 return hr;
8447 if(indexParam >= pFDesc->funcdesc.cParams)
8448 return TYPE_E_ELEMENTNOTFOUND;
8450 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8453 /* ITypeInfo2::GetAllVarCustData
8455 * Gets all custom data items for the specified Variable
8458 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8459 UINT index, CUSTDATA *pCustData)
8461 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8462 TLBVarDesc * pVDesc = &This->vardescs[index];
8464 TRACE("%p %u %p\n", This, index, pCustData);
8466 if(index >= This->typeattr.cVars)
8467 return TYPE_E_ELEMENTNOTFOUND;
8469 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8472 /* ITypeInfo2::GetAllImplCustData
8474 * Gets all custom data items for the specified implementation type
8477 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8478 ITypeInfo2 * iface,
8479 UINT index,
8480 CUSTDATA *pCustData)
8482 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8483 TLBImplType *pRDesc = &This->impltypes[index];
8485 TRACE("%p %u %p\n", This, index, pCustData);
8487 if(index >= This->typeattr.cImplTypes)
8488 return TYPE_E_ELEMENTNOTFOUND;
8490 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8493 static const ITypeInfo2Vtbl tinfvt =
8496 ITypeInfo_fnQueryInterface,
8497 ITypeInfo_fnAddRef,
8498 ITypeInfo_fnRelease,
8500 ITypeInfo_fnGetTypeAttr,
8501 ITypeInfo_fnGetTypeComp,
8502 ITypeInfo_fnGetFuncDesc,
8503 ITypeInfo_fnGetVarDesc,
8504 ITypeInfo_fnGetNames,
8505 ITypeInfo_fnGetRefTypeOfImplType,
8506 ITypeInfo_fnGetImplTypeFlags,
8507 ITypeInfo_fnGetIDsOfNames,
8508 ITypeInfo_fnInvoke,
8509 ITypeInfo_fnGetDocumentation,
8510 ITypeInfo_fnGetDllEntry,
8511 ITypeInfo_fnGetRefTypeInfo,
8512 ITypeInfo_fnAddressOfMember,
8513 ITypeInfo_fnCreateInstance,
8514 ITypeInfo_fnGetMops,
8515 ITypeInfo_fnGetContainingTypeLib,
8516 ITypeInfo_fnReleaseTypeAttr,
8517 ITypeInfo_fnReleaseFuncDesc,
8518 ITypeInfo_fnReleaseVarDesc,
8520 ITypeInfo2_fnGetTypeKind,
8521 ITypeInfo2_fnGetTypeFlags,
8522 ITypeInfo2_fnGetFuncIndexOfMemId,
8523 ITypeInfo2_fnGetVarIndexOfMemId,
8524 ITypeInfo2_fnGetCustData,
8525 ITypeInfo2_fnGetFuncCustData,
8526 ITypeInfo2_fnGetParamCustData,
8527 ITypeInfo2_fnGetVarCustData,
8528 ITypeInfo2_fnGetImplTypeCustData,
8529 ITypeInfo2_fnGetDocumentation2,
8530 ITypeInfo2_fnGetAllCustData,
8531 ITypeInfo2_fnGetAllFuncCustData,
8532 ITypeInfo2_fnGetAllParamCustData,
8533 ITypeInfo2_fnGetAllVarCustData,
8534 ITypeInfo2_fnGetAllImplTypeCustData,
8537 /******************************************************************************
8538 * CreateDispTypeInfo [OLEAUT32.31]
8540 * Build type information for an object so it can be called through an
8541 * IDispatch interface.
8543 * RETURNS
8544 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8545 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8547 * NOTES
8548 * This call allows an objects methods to be accessed through IDispatch, by
8549 * building an ITypeInfo object that IDispatch can use to call through.
8551 HRESULT WINAPI CreateDispTypeInfo(
8552 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8553 LCID lcid, /* [I] Locale Id */
8554 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8556 ITypeInfoImpl *pTIClass, *pTIIface;
8557 ITypeLibImpl *pTypeLibImpl;
8558 unsigned int param, func;
8559 TLBFuncDesc *pFuncDesc;
8560 TLBRefType *ref;
8562 TRACE("\n");
8563 pTypeLibImpl = TypeLibImpl_Constructor();
8564 if (!pTypeLibImpl) return E_FAIL;
8566 pTypeLibImpl->TypeInfoCount = 2;
8567 pTypeLibImpl->typeinfos = calloc(pTypeLibImpl->TypeInfoCount, sizeof(ITypeInfoImpl*));
8569 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8570 pTIIface->pTypeLib = pTypeLibImpl;
8571 pTIIface->index = 0;
8572 pTIIface->Name = NULL;
8573 pTIIface->dwHelpContext = -1;
8574 pTIIface->guid = NULL;
8575 pTIIface->typeattr.lcid = lcid;
8576 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8577 pTIIface->typeattr.wMajorVerNum = 0;
8578 pTIIface->typeattr.wMinorVerNum = 0;
8579 pTIIface->typeattr.cbAlignment = 2;
8580 pTIIface->typeattr.cbSizeInstance = -1;
8581 pTIIface->typeattr.cbSizeVft = -1;
8582 pTIIface->typeattr.cFuncs = 0;
8583 pTIIface->typeattr.cImplTypes = 0;
8584 pTIIface->typeattr.cVars = 0;
8585 pTIIface->typeattr.wTypeFlags = 0;
8586 pTIIface->hreftype = 0;
8588 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8589 pFuncDesc = pTIIface->funcdescs;
8590 for(func = 0; func < pidata->cMembers; func++) {
8591 METHODDATA *md = pidata->pmethdata + func;
8592 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8593 pFuncDesc->funcdesc.memid = md->dispid;
8594 pFuncDesc->funcdesc.lprgscode = NULL;
8595 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8596 pFuncDesc->funcdesc.invkind = md->wFlags;
8597 pFuncDesc->funcdesc.callconv = md->cc;
8598 pFuncDesc->funcdesc.cParams = md->cArgs;
8599 pFuncDesc->funcdesc.cParamsOpt = 0;
8600 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8601 pFuncDesc->funcdesc.cScodes = 0;
8602 pFuncDesc->funcdesc.wFuncFlags = 0;
8603 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8604 pFuncDesc->funcdesc.elemdescFunc.paramdesc.wParamFlags = PARAMFLAG_NONE;
8605 pFuncDesc->funcdesc.elemdescFunc.paramdesc.pparamdescex = NULL;
8606 pFuncDesc->funcdesc.lprgelemdescParam = calloc(md->cArgs, sizeof(ELEMDESC));
8607 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8608 for(param = 0; param < md->cArgs; param++) {
8609 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8610 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8612 pFuncDesc->helpcontext = 0;
8613 pFuncDesc->HelpStringContext = 0;
8614 pFuncDesc->HelpString = NULL;
8615 pFuncDesc->Entry = NULL;
8616 list_init(&pFuncDesc->custdata_list);
8617 pTIIface->typeattr.cFuncs++;
8618 ++pFuncDesc;
8621 dump_TypeInfo(pTIIface);
8623 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8624 pTIClass->pTypeLib = pTypeLibImpl;
8625 pTIClass->index = 1;
8626 pTIClass->Name = NULL;
8627 pTIClass->dwHelpContext = -1;
8628 pTIClass->guid = NULL;
8629 pTIClass->typeattr.lcid = lcid;
8630 pTIClass->typeattr.typekind = TKIND_COCLASS;
8631 pTIClass->typeattr.wMajorVerNum = 0;
8632 pTIClass->typeattr.wMinorVerNum = 0;
8633 pTIClass->typeattr.cbAlignment = 2;
8634 pTIClass->typeattr.cbSizeInstance = -1;
8635 pTIClass->typeattr.cbSizeVft = -1;
8636 pTIClass->typeattr.cFuncs = 0;
8637 pTIClass->typeattr.cImplTypes = 1;
8638 pTIClass->typeattr.cVars = 0;
8639 pTIClass->typeattr.wTypeFlags = 0;
8640 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8642 pTIClass->impltypes = TLBImplType_Alloc(1);
8644 ref = calloc(1, sizeof(*ref));
8645 ref->pImpTLInfo = TLB_REF_INTERNAL;
8646 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8648 dump_TypeInfo(pTIClass);
8650 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8652 ITypeInfo_AddRef(*pptinfo);
8653 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8655 return S_OK;
8659 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8661 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8663 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8666 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8668 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8670 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8673 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8675 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8677 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8680 static HRESULT WINAPI ITypeComp_fnBind(
8681 ITypeComp * iface,
8682 OLECHAR * szName,
8683 ULONG lHash,
8684 WORD wFlags,
8685 ITypeInfo ** ppTInfo,
8686 DESCKIND * pDescKind,
8687 BINDPTR * pBindPtr)
8689 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8690 const TLBFuncDesc *pFDesc;
8691 const TLBVarDesc *pVDesc;
8692 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8693 UINT fdc;
8695 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8697 *pDescKind = DESCKIND_NONE;
8698 pBindPtr->lpfuncdesc = NULL;
8699 *ppTInfo = NULL;
8701 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8702 pFDesc = &This->funcdescs[fdc];
8703 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8704 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8705 break;
8706 else
8707 /* name found, but wrong flags */
8708 hr = TYPE_E_TYPEMISMATCH;
8712 if (fdc < This->typeattr.cFuncs)
8714 HRESULT hr = TLB_AllocAndInitFuncDesc(
8715 &pFDesc->funcdesc,
8716 &pBindPtr->lpfuncdesc,
8717 This->typeattr.typekind == TKIND_DISPATCH);
8718 if (FAILED(hr))
8719 return hr;
8720 *pDescKind = DESCKIND_FUNCDESC;
8721 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8722 ITypeInfo_AddRef(*ppTInfo);
8723 return S_OK;
8724 } else {
8725 pVDesc = TLB_get_vardesc_by_name(This, szName);
8726 if(pVDesc){
8727 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8728 if (FAILED(hr))
8729 return hr;
8730 *pDescKind = DESCKIND_VARDESC;
8731 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8732 ITypeInfo_AddRef(*ppTInfo);
8733 return S_OK;
8737 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8738 /* recursive search */
8739 ITypeInfo *pTInfo;
8740 ITypeComp *pTComp;
8741 HRESULT hr;
8742 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8743 if (SUCCEEDED(hr))
8745 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8746 ITypeInfo_Release(pTInfo);
8748 if (SUCCEEDED(hr))
8750 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8751 ITypeComp_Release(pTComp);
8752 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8753 This->typeattr.typekind == TKIND_DISPATCH)
8755 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8756 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8757 SysFreeString((BSTR)tmp);
8759 return hr;
8761 WARN("Could not search inherited interface!\n");
8763 if (hr == DISP_E_MEMBERNOTFOUND)
8764 hr = S_OK;
8765 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8766 return hr;
8769 static HRESULT WINAPI ITypeComp_fnBindType(
8770 ITypeComp * iface,
8771 OLECHAR * szName,
8772 ULONG lHash,
8773 ITypeInfo ** ppTInfo,
8774 ITypeComp ** ppTComp)
8776 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8778 /* strange behaviour (does nothing) but like the
8779 * original */
8781 if (!ppTInfo || !ppTComp)
8782 return E_POINTER;
8784 *ppTInfo = NULL;
8785 *ppTComp = NULL;
8787 return S_OK;
8790 static const ITypeCompVtbl tcompvt =
8793 ITypeComp_fnQueryInterface,
8794 ITypeComp_fnAddRef,
8795 ITypeComp_fnRelease,
8797 ITypeComp_fnBind,
8798 ITypeComp_fnBindType
8801 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8802 ICreateTypeLib2** ppctlib)
8804 ITypeLibImpl *This;
8805 HRESULT hres;
8807 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8809 if (!szFile) return E_INVALIDARG;
8811 This = TypeLibImpl_Constructor();
8812 if (!This)
8813 return E_OUTOFMEMORY;
8815 This->lcid = GetSystemDefaultLCID();
8816 This->syskind = syskind;
8817 This->ptr_size = get_ptr_size(syskind);
8819 This->path = wcsdup(szFile);
8820 if (!This->path) {
8821 ITypeLib2_Release(&This->ITypeLib2_iface);
8822 return E_OUTOFMEMORY;
8825 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8826 ITypeLib2_Release(&This->ITypeLib2_iface);
8827 return hres;
8830 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8831 REFIID riid, void **object)
8833 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8835 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8838 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8840 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8842 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8845 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8847 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8849 return ITypeLib2_Release(&This->ITypeLib2_iface);
8852 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8853 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8855 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8856 ITypeInfoImpl *info;
8857 HRESULT hres;
8859 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8861 if (!ctinfo || !name)
8862 return E_INVALIDARG;
8864 info = TLB_get_typeinfo_by_name(This, name);
8865 if (info)
8866 return TYPE_E_NAMECONFLICT;
8868 This->typeinfos = realloc(This->typeinfos, sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8870 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8872 info->pTypeLib = This;
8873 info->Name = TLB_append_str(&This->name_list, name);
8874 info->index = This->TypeInfoCount;
8875 info->typeattr.typekind = kind;
8876 info->typeattr.cbAlignment = 4;
8878 switch (info->typeattr.typekind) {
8879 case TKIND_ENUM:
8880 case TKIND_INTERFACE:
8881 case TKIND_DISPATCH:
8882 case TKIND_COCLASS:
8883 info->typeattr.cbSizeInstance = This->ptr_size;
8884 break;
8885 case TKIND_RECORD:
8886 case TKIND_UNION:
8887 info->typeattr.cbSizeInstance = 0;
8888 break;
8889 case TKIND_MODULE:
8890 info->typeattr.cbSizeInstance = 2;
8891 break;
8892 case TKIND_ALIAS:
8893 info->typeattr.cbSizeInstance = -0x75;
8894 break;
8895 default:
8896 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8897 info->typeattr.cbSizeInstance = 0xdeadbeef;
8898 break;
8901 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8902 &IID_ICreateTypeInfo, (void **)ctinfo);
8903 if (FAILED(hres)) {
8904 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8905 return hres;
8908 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8910 ++This->TypeInfoCount;
8912 return S_OK;
8915 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8916 LPOLESTR name)
8918 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8920 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8922 if (!name)
8923 return E_INVALIDARG;
8925 This->Name = TLB_append_str(&This->name_list, name);
8927 return S_OK;
8930 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8931 WORD majorVerNum, WORD minorVerNum)
8933 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8935 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8937 This->ver_major = majorVerNum;
8938 This->ver_minor = minorVerNum;
8940 return S_OK;
8943 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8944 REFGUID guid)
8946 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8948 TRACE("%p %s\n", This, debugstr_guid(guid));
8950 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8952 return S_OK;
8955 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8956 LPOLESTR doc)
8958 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8960 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8962 if (!doc)
8963 return E_INVALIDARG;
8965 This->DocString = TLB_append_str(&This->string_list, doc);
8967 return S_OK;
8970 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8971 LPOLESTR helpFileName)
8973 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8975 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8977 if (!helpFileName)
8978 return E_INVALIDARG;
8980 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8982 return S_OK;
8985 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8986 DWORD helpContext)
8988 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8990 TRACE("%p, %ld.\n", iface, helpContext);
8992 This->dwHelpContext = helpContext;
8994 return S_OK;
8997 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8998 LCID lcid)
9000 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9002 TRACE("%p, %#lx.\n", iface, lcid);
9004 This->set_lcid = lcid;
9006 return S_OK;
9009 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9010 UINT libFlags)
9012 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9014 TRACE("%p %x\n", This, libFlags);
9016 This->libflags = libFlags;
9018 return S_OK;
9021 typedef struct tagWMSFT_SegContents {
9022 DWORD len;
9023 void *data;
9024 } WMSFT_SegContents;
9026 typedef struct tagWMSFT_TLBFile {
9027 MSFT_Header header;
9028 WMSFT_SegContents typeinfo_seg;
9029 WMSFT_SegContents impfile_seg;
9030 WMSFT_SegContents impinfo_seg;
9031 WMSFT_SegContents ref_seg;
9032 WMSFT_SegContents guidhash_seg;
9033 WMSFT_SegContents guid_seg;
9034 WMSFT_SegContents namehash_seg;
9035 WMSFT_SegContents name_seg;
9036 WMSFT_SegContents string_seg;
9037 WMSFT_SegContents typdesc_seg;
9038 WMSFT_SegContents arraydesc_seg;
9039 WMSFT_SegContents custdata_seg;
9040 WMSFT_SegContents cdguids_seg;
9041 MSFT_SegDir segdir;
9042 WMSFT_SegContents aux_seg;
9043 } WMSFT_TLBFile;
9045 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9046 WMSFT_TLBFile *file)
9048 TLBString *str;
9049 UINT last_offs;
9050 char *data;
9052 file->string_seg.len = 0;
9053 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9054 int size;
9056 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9057 if (size == 0)
9058 return E_UNEXPECTED;
9060 size += sizeof(INT16);
9061 if (size % 4)
9062 size = (size + 4) & ~0x3;
9063 if (size < 8)
9064 size = 8;
9066 file->string_seg.len += size;
9068 /* temporarily use str->offset to store the length of the aligned,
9069 * converted string */
9070 str->offset = size;
9073 file->string_seg.data = data = malloc(file->string_seg.len);
9075 last_offs = 0;
9076 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9077 int size;
9079 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9080 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9081 if (size == 0) {
9082 free(file->string_seg.data);
9083 return E_UNEXPECTED;
9086 *((INT16*)data) = size;
9088 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9090 size = str->offset;
9091 data += size;
9092 str->offset = last_offs;
9093 last_offs += size;
9096 return S_OK;
9099 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9100 WMSFT_TLBFile *file)
9102 TLBString *str;
9103 UINT last_offs;
9104 char *data;
9105 MSFT_NameIntro *last_intro = NULL;
9107 file->header.nametablecount = 0;
9108 file->header.nametablechars = 0;
9110 file->name_seg.len = 0;
9111 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9112 int size;
9114 size = lstrlenW(str->str);
9115 file->header.nametablechars += size;
9116 file->header.nametablecount++;
9118 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9119 if (size == 0)
9120 return E_UNEXPECTED;
9122 size += sizeof(MSFT_NameIntro);
9123 if (size % 4)
9124 size = (size + 4) & ~0x3;
9125 if (size < 8)
9126 size = 8;
9128 file->name_seg.len += size;
9130 /* temporarily use str->offset to store the length of the aligned,
9131 * converted string */
9132 str->offset = size;
9135 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9136 file->name_seg.data = data = malloc(file->name_seg.len + 1);
9138 last_offs = 0;
9139 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9140 int size, hash;
9141 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9143 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9144 data + sizeof(MSFT_NameIntro),
9145 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9146 if (size == 0) {
9147 free(file->name_seg.data);
9148 return E_UNEXPECTED;
9150 data[sizeof(MSFT_NameIntro) + size] = '\0';
9152 intro->hreftype = -1; /* TODO? */
9153 intro->namelen = size & 0xFF;
9154 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9155 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9156 intro->namelen |= hash << 16;
9157 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9158 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9160 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9161 str->offset - size - sizeof(MSFT_NameIntro));
9163 /* update str->offset to actual value to use in other
9164 * compilation functions that require positions within
9165 * the string table */
9166 last_intro = intro;
9167 size = str->offset;
9168 data += size;
9169 str->offset = last_offs;
9170 last_offs += size;
9173 if(last_intro)
9174 last_intro->hreftype = 0; /* last one is 0? */
9176 return S_OK;
9179 static inline int hash_guid(GUID *guid)
9181 int i, hash = 0;
9183 for (i = 0; i < 8; i ++)
9184 hash ^= ((const short *)guid)[i];
9186 return hash & 0x1f;
9189 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9191 TLBGuid *guid;
9192 MSFT_GuidEntry *entry;
9193 DWORD offs;
9194 int hash_key, *guidhashtab;
9196 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9197 file->guid_seg.data = malloc(file->guid_seg.len);
9199 entry = file->guid_seg.data;
9200 offs = 0;
9201 guidhashtab = file->guidhash_seg.data;
9202 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9203 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9204 entry->hreftype = guid->hreftype;
9206 hash_key = hash_guid(&guid->guid);
9207 entry->next_hash = guidhashtab[hash_key];
9208 guidhashtab[hash_key] = offs;
9210 guid->offset = offs;
9211 offs += sizeof(MSFT_GuidEntry);
9212 ++entry;
9215 return S_OK;
9218 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9220 VARIANT v = *value;
9221 VARTYPE arg_type = V_VT(value);
9222 int mask = 0;
9223 HRESULT hres;
9224 DWORD ret = file->custdata_seg.len;
9226 if(arg_type == VT_INT)
9227 arg_type = VT_I4;
9228 if(arg_type == VT_UINT)
9229 arg_type = VT_UI4;
9231 v = *value;
9232 if(V_VT(value) != arg_type) {
9233 hres = VariantChangeType(&v, value, 0, arg_type);
9234 if(FAILED(hres)){
9235 ERR("VariantChangeType failed: %#lx.\n", hres);
9236 return -1;
9240 /* Check if default value can be stored in-place */
9241 switch(arg_type){
9242 case VT_I4:
9243 case VT_UI4:
9244 mask = 0x3ffffff;
9245 if(V_UI4(&v) > 0x3ffffff)
9246 break;
9247 /* fall through */
9248 case VT_I1:
9249 case VT_UI1:
9250 case VT_BOOL:
9251 if(!mask)
9252 mask = 0xff;
9253 /* fall through */
9254 case VT_I2:
9255 case VT_UI2:
9256 if(!mask)
9257 mask = 0xffff;
9258 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9261 /* have to allocate space in custdata_seg */
9262 switch(arg_type) {
9263 case VT_I4:
9264 case VT_R4:
9265 case VT_UI4:
9266 case VT_INT:
9267 case VT_UINT:
9268 case VT_HRESULT:
9269 case VT_PTR: {
9270 /* Construct the data to be allocated */
9271 int *data;
9273 if(file->custdata_seg.data){
9274 file->custdata_seg.data = realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9275 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9276 file->custdata_seg.len += sizeof(int) * 2;
9277 }else{
9278 file->custdata_seg.len = sizeof(int) * 2;
9279 data = file->custdata_seg.data = malloc(file->custdata_seg.len);
9282 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9283 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9285 /* TODO: Check if the encoded data is already present in custdata_seg */
9287 return ret;
9290 case VT_BSTR: {
9291 int mb_len = WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), NULL, 0, NULL, NULL );
9292 int i, len = (6 + mb_len + 3) & ~0x3;
9293 char *data;
9295 if(file->custdata_seg.data){
9296 file->custdata_seg.data = realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9297 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9298 file->custdata_seg.len += len;
9299 }else{
9300 file->custdata_seg.len = len;
9301 data = file->custdata_seg.data = malloc(file->custdata_seg.len);
9304 *((unsigned short *)data) = V_VT(value);
9305 *((unsigned int *)(data+2)) = mb_len;
9306 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], mb_len, NULL, NULL);
9307 for (i = 6 + mb_len; i < len; i++)
9308 data[i] = 0x57;
9310 /* TODO: Check if the encoded data is already present in custdata_seg */
9312 return ret;
9314 default:
9315 FIXME("Argument type not yet handled\n");
9316 return -1;
9320 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9322 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9324 DWORD offs = file->arraydesc_seg.len;
9325 DWORD *encoded;
9326 USHORT i;
9328 /* TODO: we should check for duplicates, but that's harder because each
9329 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9330 * at the library-level) */
9332 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9333 file->arraydesc_seg.data = realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9334 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9336 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9337 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9338 for(i = 0; i < desc->cDims; ++i){
9339 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9340 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9343 return offs;
9346 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9348 DWORD junk;
9349 INT16 junk2;
9350 DWORD offs = 0;
9351 DWORD encoded[2];
9352 VARTYPE vt, subtype;
9353 char *data;
9355 if(!desc)
9356 return -1;
9358 if(!out_mix)
9359 out_mix = &junk;
9360 if(!out_size)
9361 out_size = &junk2;
9363 vt = desc->vt & VT_TYPEMASK;
9365 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9366 DWORD mix;
9367 encoded[1] = WMSFT_append_typedesc(desc->lptdesc, file, &mix, out_size);
9368 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9369 *out_mix = 0x7FFF;
9370 *out_size += 2 * sizeof(DWORD);
9371 }else if(vt == VT_CARRAY){
9372 encoded[0] = desc->vt | (0x7FFE << 16);
9373 encoded[1] = WMSFT_append_arraydesc(desc->lpadesc, file);
9374 *out_mix = 0x7FFE;
9375 }else if(vt == VT_USERDEFINED){
9376 encoded[0] = desc->vt | (0x7FFF << 16);
9377 encoded[1] = desc->hreftype;
9378 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9379 }else{
9380 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9382 switch(vt){
9383 case VT_INT:
9384 subtype = VT_I4;
9385 break;
9386 case VT_UINT:
9387 subtype = VT_UI4;
9388 break;
9389 case VT_VOID:
9390 subtype = VT_EMPTY;
9391 break;
9392 default:
9393 subtype = vt;
9394 break;
9397 *out_mix = subtype;
9398 return 0x80000000 | (subtype << 16) | desc->vt;
9401 data = file->typdesc_seg.data;
9402 while(offs < file->typdesc_seg.len){
9403 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9404 return offs;
9405 offs += sizeof(encoded);
9408 file->typdesc_seg.len += sizeof(encoded);
9409 data = file->typdesc_seg.data = realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9411 memcpy(&data[offs], encoded, sizeof(encoded));
9413 return offs;
9416 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9418 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9419 DWORD ret = cdguids_seg->len, offs;
9420 MSFT_CDGuid *cdguid;
9421 TLBCustData *cd;
9423 if(list_empty(custdata_list))
9424 return -1;
9426 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9427 cdguids_seg->data = realloc(cdguids_seg->data, cdguids_seg->len);
9428 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9430 offs = ret + sizeof(MSFT_CDGuid);
9431 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9432 cdguid->GuidOffset = cd->guid->offset;
9433 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9434 cdguid->next = offs;
9435 offs += sizeof(MSFT_CDGuid);
9436 ++cdguid;
9439 --cdguid;
9440 cdguid->next = -1;
9442 return ret;
9445 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9446 WMSFT_TLBFile *file)
9448 WMSFT_SegContents *aux_seg = &file->aux_seg;
9449 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9450 MSFT_VarRecord *varrecord;
9451 MSFT_FuncRecord *funcrecord;
9452 MEMBERID *memid;
9453 DWORD *name, *offsets, offs;
9455 for(i = 0; i < info->typeattr.cFuncs; ++i){
9456 TLBFuncDesc *desc = &info->funcdescs[i];
9458 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9460 /* optional fields */
9461 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9462 if(!list_empty(&desc->custdata_list))
9463 recorded_size += 7 * sizeof(INT);
9464 else if(desc->HelpStringContext != 0)
9465 recorded_size += 6 * sizeof(INT);
9466 /* res9? resA? */
9467 else if(desc->Entry)
9468 recorded_size += 3 * sizeof(INT);
9469 else if(desc->HelpString)
9470 recorded_size += 2 * sizeof(INT);
9471 else if(desc->helpcontext)
9472 recorded_size += sizeof(INT);
9474 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9476 for(j = 0; j < desc->funcdesc.cParams; ++j){
9477 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9478 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9479 break;
9483 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9486 for(i = 0; i < info->typeattr.cVars; ++i){
9487 TLBVarDesc *desc = &info->vardescs[i];
9489 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9491 /* optional fields */
9492 if(desc->HelpStringContext != 0)
9493 recorded_size += 5 * sizeof(INT);
9494 else if(!list_empty(&desc->custdata_list))
9495 recorded_size += 4 * sizeof(INT);
9496 /* res9? */
9497 else if(desc->HelpString)
9498 recorded_size += 2 * sizeof(INT);
9499 else if(desc->HelpContext != 0)
9500 recorded_size += sizeof(INT);
9502 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9505 if(!recorded_size && !extra_size)
9506 return ret;
9508 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9510 aux_seg->len += recorded_size + extra_size;
9512 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9514 aux_seg->data = realloc(aux_seg->data, aux_seg->len);
9516 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9518 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9519 offs = 0;
9521 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9522 for(i = 0; i < info->typeattr.cFuncs; ++i){
9523 TLBFuncDesc *desc = &info->funcdescs[i];
9524 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9526 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9527 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9528 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9529 funcrecord->VtableOffset = desc->funcdesc.oVft;
9531 /* FKCCIC:
9532 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9533 * ^^^funckind
9534 * ^^^ ^invkind
9535 * ^has_cust_data
9536 * ^^^^callconv
9537 * ^has_param_defaults
9538 * ^oEntry_is_intresource
9540 funcrecord->FKCCIC =
9541 desc->funcdesc.funckind |
9542 (desc->funcdesc.invkind << 3) |
9543 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9544 (desc->funcdesc.callconv << 8);
9546 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9547 funcrecord->FKCCIC |= 0x2000;
9549 for(j = 0; j < desc->funcdesc.cParams; ++j){
9550 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9551 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9552 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9555 if(paramdefault_size > 0)
9556 funcrecord->FKCCIC |= 0x1000;
9558 funcrecord->nrargs = desc->funcdesc.cParams;
9559 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9561 /* optional fields */
9562 /* res9? resA? */
9563 if(!list_empty(&desc->custdata_list)){
9564 size += 7 * sizeof(INT);
9565 funcrecord->HelpContext = desc->helpcontext;
9566 if(desc->HelpString)
9567 funcrecord->oHelpString = desc->HelpString->offset;
9568 else
9569 funcrecord->oHelpString = -1;
9570 if(!desc->Entry)
9571 funcrecord->oEntry = -1;
9572 else if(IS_INTRESOURCE(desc->Entry))
9573 funcrecord->oEntry = LOWORD(desc->Entry);
9574 else
9575 funcrecord->oEntry = desc->Entry->offset;
9576 funcrecord->res9 = -1;
9577 funcrecord->resA = -1;
9578 funcrecord->HelpStringContext = desc->HelpStringContext;
9579 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9580 }else if(desc->HelpStringContext != 0){
9581 size += 6 * sizeof(INT);
9582 funcrecord->HelpContext = desc->helpcontext;
9583 if(desc->HelpString)
9584 funcrecord->oHelpString = desc->HelpString->offset;
9585 else
9586 funcrecord->oHelpString = -1;
9587 if(!desc->Entry)
9588 funcrecord->oEntry = -1;
9589 else if(IS_INTRESOURCE(desc->Entry))
9590 funcrecord->oEntry = LOWORD(desc->Entry);
9591 else
9592 funcrecord->oEntry = desc->Entry->offset;
9593 funcrecord->res9 = -1;
9594 funcrecord->resA = -1;
9595 funcrecord->HelpStringContext = desc->HelpStringContext;
9596 }else if(desc->Entry){
9597 size += 3 * sizeof(INT);
9598 funcrecord->HelpContext = desc->helpcontext;
9599 if(desc->HelpString)
9600 funcrecord->oHelpString = desc->HelpString->offset;
9601 else
9602 funcrecord->oHelpString = -1;
9603 if(!desc->Entry)
9604 funcrecord->oEntry = -1;
9605 else if(IS_INTRESOURCE(desc->Entry))
9606 funcrecord->oEntry = LOWORD(desc->Entry);
9607 else
9608 funcrecord->oEntry = desc->Entry->offset;
9609 }else if(desc->HelpString){
9610 size += 2 * sizeof(INT);
9611 funcrecord->HelpContext = desc->helpcontext;
9612 funcrecord->oHelpString = desc->HelpString->offset;
9613 }else if(desc->helpcontext){
9614 size += sizeof(INT);
9615 funcrecord->HelpContext = desc->helpcontext;
9618 paramdefault = (DWORD*)((char *)funcrecord + size);
9619 size += paramdefault_size;
9621 for(j = 0; j < desc->funcdesc.cParams; ++j){
9622 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9624 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9625 if(desc->pParamDesc[j].Name)
9626 info->oName = desc->pParamDesc[j].Name->offset;
9627 else
9628 info->oName = -1;
9629 info->Flags = desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags;
9631 if(paramdefault_size){
9632 if(desc->funcdesc.lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9633 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].paramdesc.pparamdescex->varDefaultValue, file);
9634 else if(paramdefault_size)
9635 *paramdefault = -1;
9636 ++paramdefault;
9639 size += sizeof(MSFT_ParameterInfo);
9642 funcrecord->Info = size | (i << 16); /* is it just the index? */
9644 *offsets = offs;
9645 offs += size;
9646 ++offsets;
9648 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9651 varrecord = (MSFT_VarRecord*)funcrecord;
9652 for(i = 0; i < info->typeattr.cVars; ++i){
9653 TLBVarDesc *desc = &info->vardescs[i];
9654 DWORD size = 5 * sizeof(INT);
9656 varrecord->vardescsize = sizeof(desc->vardesc);
9657 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9658 varrecord->Flags = desc->vardesc.wVarFlags;
9659 varrecord->VarKind = desc->vardesc.varkind;
9661 if(desc->vardesc.varkind == VAR_CONST){
9662 varrecord->vardescsize += sizeof(VARIANT);
9663 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.lpvarValue, file);
9664 }else
9665 varrecord->OffsValue = desc->vardesc.oInst;
9667 /* res9? */
9668 if(desc->HelpStringContext != 0){
9669 size += 5 * sizeof(INT);
9670 varrecord->HelpContext = desc->HelpContext;
9671 if(desc->HelpString)
9672 varrecord->HelpString = desc->HelpString->offset;
9673 else
9674 varrecord->HelpString = -1;
9675 varrecord->res9 = -1;
9676 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9677 varrecord->HelpStringContext = desc->HelpStringContext;
9678 }else if(!list_empty(&desc->custdata_list)){
9679 size += 4 * sizeof(INT);
9680 varrecord->HelpContext = desc->HelpContext;
9681 if(desc->HelpString)
9682 varrecord->HelpString = desc->HelpString->offset;
9683 else
9684 varrecord->HelpString = -1;
9685 varrecord->res9 = -1;
9686 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9687 }else if(desc->HelpString){
9688 size += 2 * sizeof(INT);
9689 varrecord->HelpContext = desc->HelpContext;
9690 if(desc->HelpString)
9691 varrecord->HelpString = desc->HelpString->offset;
9692 else
9693 varrecord->HelpString = -1;
9694 }else if(desc->HelpContext != 0){
9695 size += sizeof(INT);
9696 varrecord->HelpContext = desc->HelpContext;
9699 varrecord->Info = size | (i << 16);
9701 *offsets = offs;
9702 offs += size;
9703 ++offsets;
9705 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9708 memid = (MEMBERID*)varrecord;
9709 for(i = 0; i < info->typeattr.cFuncs; ++i){
9710 TLBFuncDesc *desc = &info->funcdescs[i];
9711 *memid = desc->funcdesc.memid;
9712 ++memid;
9714 for(i = 0; i < info->typeattr.cVars; ++i){
9715 TLBVarDesc *desc = &info->vardescs[i];
9716 *memid = desc->vardesc.memid;
9717 ++memid;
9720 name = (DWORD*)memid;
9721 for(i = 0; i < info->typeattr.cFuncs; ++i){
9722 TLBFuncDesc *desc = &info->funcdescs[i];
9723 if(desc->Name)
9724 *name = desc->Name->offset;
9725 else
9726 *name = -1;
9727 ++name;
9729 for(i = 0; i < info->typeattr.cVars; ++i){
9730 TLBVarDesc *desc = &info->vardescs[i];
9731 if(desc->Name)
9732 *name = desc->Name->offset;
9733 else
9734 *name = -1;
9735 ++name;
9738 return ret;
9741 typedef struct tagWMSFT_RefChunk {
9742 DWORD href;
9743 DWORD res04;
9744 DWORD res08;
9745 DWORD next;
9746 } WMSFT_RefChunk;
9748 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9750 DWORD offs = file->ref_seg.len, i;
9751 WMSFT_RefChunk *chunk;
9753 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9754 file->ref_seg.data = realloc(file->ref_seg.data, file->ref_seg.len);
9756 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9758 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9759 chunk->href = info->impltypes[i].hRef;
9760 chunk->res04 = info->impltypes[i].implflags;
9761 chunk->res08 = -1;
9762 if(i < info->typeattr.cImplTypes - 1)
9763 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9764 else
9765 chunk->next = -1;
9766 ++chunk;
9769 return offs;
9772 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9774 DWORD size;
9776 size = sizeof(MSFT_TypeInfoBase);
9778 if(data){
9779 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9780 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9781 base->typekind = TKIND_DISPATCH;
9782 else
9783 base->typekind = info->typeattr.typekind;
9784 base->typekind |= index << 16; /* TODO: There are some other flags here */
9785 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9786 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9787 base->res2 = 0;
9788 base->res3 = 0;
9789 base->res4 = 3;
9790 base->res5 = 0;
9791 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9792 base->res7 = 0;
9793 base->res8 = 0;
9794 base->res9 = 0;
9795 base->resA = 0;
9796 if(info->guid)
9797 base->posguid = info->guid->offset;
9798 else
9799 base->posguid = -1;
9800 base->flags = info->typeattr.wTypeFlags;
9801 if(info->Name) {
9802 base->NameOffset = info->Name->offset;
9804 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9805 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9806 }else {
9807 base->NameOffset = -1;
9809 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9810 if(info->DocString)
9811 base->docstringoffs = info->DocString->offset;
9812 else
9813 base->docstringoffs = -1;
9814 base->helpstringcontext = info->dwHelpStringContext;
9815 base->helpcontext = info->dwHelpContext;
9816 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9817 base->cImplTypes = info->typeattr.cImplTypes;
9818 base->cbSizeVft = info->typeattr.cbSizeVft;
9819 base->size = info->typeattr.cbSizeInstance;
9820 if(info->typeattr.typekind == TKIND_COCLASS){
9821 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9822 }else if(info->typeattr.typekind == TKIND_ALIAS){
9823 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9824 }else if(info->typeattr.typekind == TKIND_MODULE){
9825 if(info->DllName)
9826 base->datatype1 = info->DllName->offset;
9827 else
9828 base->datatype1 = -1;
9829 }else{
9830 if(info->typeattr.cImplTypes > 0)
9831 base->datatype1 = info->impltypes[0].hRef;
9832 else
9833 base->datatype1 = -1;
9835 base->datatype2 = index; /* FIXME: i think there's more here */
9836 base->res18 = 0;
9837 base->res19 = -1;
9840 return size;
9843 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9845 UINT i;
9847 file->typeinfo_seg.len = 0;
9848 for(i = 0; i < This->TypeInfoCount; ++i){
9849 ITypeInfoImpl *info = This->typeinfos[i];
9850 *junk = file->typeinfo_seg.len;
9851 ++junk;
9852 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9855 file->typeinfo_seg.data = malloc(file->typeinfo_seg.len);
9856 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9858 file->aux_seg.len = 0;
9859 file->aux_seg.data = NULL;
9861 file->typeinfo_seg.len = 0;
9862 for(i = 0; i < This->TypeInfoCount; ++i){
9863 ITypeInfoImpl *info = This->typeinfos[i];
9864 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9865 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9869 typedef struct tagWMSFT_ImpFile {
9870 INT guid_offs;
9871 LCID lcid;
9872 DWORD version;
9873 } WMSFT_ImpFile;
9875 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9877 TLBImpLib *implib;
9878 WMSFT_ImpFile *impfile;
9879 char *data;
9880 DWORD last_offs = 0;
9882 file->impfile_seg.len = 0;
9883 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9884 int size = 0;
9886 if(implib->name){
9887 WCHAR *path = wcsrchr(implib->name, '\\');
9888 if(path)
9889 ++path;
9890 else
9891 path = implib->name;
9892 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
9893 if (size == 0)
9894 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9897 size += sizeof(INT16);
9898 if (size % 4)
9899 size = (size + 4) & ~0x3;
9900 if (size < 8)
9901 size = 8;
9903 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9906 data = file->impfile_seg.data = malloc(file->impfile_seg.len);
9908 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9909 int strlen = 0, size;
9911 impfile = (WMSFT_ImpFile*)data;
9912 impfile->guid_offs = implib->guid->offset;
9913 impfile->lcid = implib->lcid;
9914 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9916 data += sizeof(WMSFT_ImpFile);
9918 if(implib->name){
9919 WCHAR *path= wcsrchr(implib->name, '\\');
9920 if(path)
9921 ++path;
9922 else
9923 path = implib->name;
9924 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
9925 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9926 if (strlen == 0)
9927 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9930 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9932 size = strlen + sizeof(INT16);
9933 if (size % 4)
9934 size = (size + 4) & ~0x3;
9935 if (size < 8)
9936 size = 8;
9937 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9939 data += size;
9940 implib->offset = last_offs;
9941 last_offs += size + sizeof(WMSFT_ImpFile);
9945 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9947 MSFT_ImpInfo *info;
9948 TLBRefType *ref_type;
9949 UINT i = 0;
9951 WMSFT_compile_impfile(This, file);
9953 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9954 info = file->impinfo_seg.data = malloc(file->impinfo_seg.len);
9956 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9957 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9958 if(ref_type->index == TLB_REF_USE_GUID){
9959 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9960 info->oGuid = ref_type->guid->offset;
9961 }else
9962 info->oGuid = ref_type->index;
9963 info->oImpFile = ref_type->pImpTLInfo->offset;
9964 ++i;
9965 ++info;
9969 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9971 file->guidhash_seg.len = 0x80;
9972 file->guidhash_seg.data = malloc(file->guidhash_seg.len);
9973 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9976 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9978 file->namehash_seg.len = 0x200;
9979 file->namehash_seg.data = malloc(file->namehash_seg.len);
9980 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9983 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9985 if(contents && contents->len){
9986 segdir->offset = *running_offset;
9987 segdir->length = contents->len;
9988 *running_offset += segdir->length;
9989 }else{
9990 segdir->offset = -1;
9991 segdir->length = 0;
9994 /* TODO: do these ever change? */
9995 segdir->res08 = -1;
9996 segdir->res0c = 0xf;
9999 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10001 DWORD written;
10002 if(segment)
10003 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10006 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10007 DWORD file_len)
10009 DWORD i;
10010 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10012 for(i = 0; i < This->TypeInfoCount; ++i){
10013 base->memoffset += file_len;
10014 ++base;
10017 return S_OK;
10020 static void WMSFT_free_file(WMSFT_TLBFile *file)
10022 free(file->typeinfo_seg.data);
10023 free(file->guidhash_seg.data);
10024 free(file->guid_seg.data);
10025 free(file->ref_seg.data);
10026 free(file->impinfo_seg.data);
10027 free(file->impfile_seg.data);
10028 free(file->namehash_seg.data);
10029 free(file->name_seg.data);
10030 free(file->string_seg.data);
10031 free(file->typdesc_seg.data);
10032 free(file->arraydesc_seg.data);
10033 free(file->custdata_seg.data);
10034 free(file->cdguids_seg.data);
10035 free(file->aux_seg.data);
10038 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10040 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10041 WMSFT_TLBFile file;
10042 DWORD written, junk_size, junk_offs, running_offset;
10043 BOOL br;
10044 HANDLE outfile;
10045 HRESULT hres;
10046 DWORD *junk;
10047 UINT i;
10049 TRACE("%p\n", This);
10051 for(i = 0; i < This->TypeInfoCount; ++i)
10052 if(This->typeinfos[i]->needs_layout)
10053 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10055 memset(&file, 0, sizeof(file));
10057 file.header.magic1 = 0x5446534D;
10058 file.header.magic2 = 0x00010002;
10059 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10060 file.header.lcid2 = This->set_lcid;
10061 file.header.varflags = 0x40 | This->syskind;
10062 if (This->HelpFile)
10063 file.header.varflags |= 0x10;
10064 if (This->HelpStringDll)
10065 file.header.varflags |= HELPDLLFLAG;
10066 file.header.version = (This->ver_minor << 16) | This->ver_major;
10067 file.header.flags = This->libflags;
10068 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10069 file.header.helpcontext = This->dwHelpContext;
10070 file.header.res44 = 0x20;
10071 file.header.res48 = 0x80;
10072 file.header.dispatchpos = This->dispatch_href;
10074 WMSFT_compile_namehash(This, &file);
10075 /* do name and string compilation to get offsets for other compilations */
10076 hres = WMSFT_compile_names(This, &file);
10077 if (FAILED(hres)){
10078 WMSFT_free_file(&file);
10079 return hres;
10082 hres = WMSFT_compile_strings(This, &file);
10083 if (FAILED(hres)){
10084 WMSFT_free_file(&file);
10085 return hres;
10088 WMSFT_compile_guidhash(This, &file);
10089 hres = WMSFT_compile_guids(This, &file);
10090 if (FAILED(hres)){
10091 WMSFT_free_file(&file);
10092 return hres;
10095 if(This->HelpFile)
10096 file.header.helpfile = This->HelpFile->offset;
10097 else
10098 file.header.helpfile = -1;
10100 if(This->DocString)
10101 file.header.helpstring = This->DocString->offset;
10102 else
10103 file.header.helpstring = -1;
10105 /* do some more segment compilation */
10106 file.header.nimpinfos = list_count(&This->ref_list);
10107 file.header.nrtypeinfos = This->TypeInfoCount;
10109 if(This->Name)
10110 file.header.NameOffset = This->Name->offset;
10111 else
10112 file.header.NameOffset = -1;
10114 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10116 if(This->guid)
10117 file.header.posguid = This->guid->offset;
10118 else
10119 file.header.posguid = -1;
10121 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10122 if(file.header.varflags & HELPDLLFLAG)
10123 junk_size += sizeof(DWORD);
10124 if(junk_size){
10125 junk = calloc(1, junk_size);
10126 if(file.header.varflags & HELPDLLFLAG){
10127 *junk = This->HelpStringDll->offset;
10128 junk_offs = 1;
10129 }else
10130 junk_offs = 0;
10131 }else{
10132 junk = NULL;
10133 junk_offs = 0;
10136 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10137 WMSFT_compile_impinfo(This, &file);
10139 running_offset = 0;
10141 TRACE("header at: 0x%lx\n", running_offset);
10142 running_offset += sizeof(file.header);
10144 TRACE("junk at: 0x%lx\n", running_offset);
10145 running_offset += junk_size;
10147 TRACE("segdir at: 0x%lx\n", running_offset);
10148 running_offset += sizeof(file.segdir);
10150 TRACE("typeinfo at: 0x%lx\n", running_offset);
10151 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10153 TRACE("guidhashtab at: 0x%lx\n", running_offset);
10154 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10156 TRACE("guidtab at: 0x%lx\n", running_offset);
10157 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10159 TRACE("reftab at: 0x%lx\n", running_offset);
10160 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10162 TRACE("impinfo at: 0x%lx\n", running_offset);
10163 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10165 TRACE("impfiles at: 0x%lx\n", running_offset);
10166 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10168 TRACE("namehashtab at: 0x%lx\n", running_offset);
10169 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10171 TRACE("nametab at: 0x%lx\n", running_offset);
10172 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10174 TRACE("stringtab at: 0x%lx\n", running_offset);
10175 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10177 TRACE("typdesc at: 0x%lx\n", running_offset);
10178 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10180 TRACE("arraydescriptions at: 0x%lx\n", running_offset);
10181 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10183 TRACE("custdata at: 0x%lx\n", running_offset);
10184 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10186 TRACE("cdguids at: 0x%lx\n", running_offset);
10187 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10189 TRACE("res0e at: 0x%lx\n", running_offset);
10190 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10192 TRACE("res0f at: 0x%lx\n", running_offset);
10193 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10195 TRACE("aux_seg at: 0x%lx\n", running_offset);
10197 WMSFT_fixup_typeinfos(This, &file, running_offset);
10199 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10200 FILE_ATTRIBUTE_NORMAL, 0);
10201 if (outfile == INVALID_HANDLE_VALUE){
10202 WMSFT_free_file(&file);
10203 free(junk);
10204 return TYPE_E_IOERROR;
10207 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10208 if (!br) {
10209 WMSFT_free_file(&file);
10210 CloseHandle(outfile);
10211 free(junk);
10212 return TYPE_E_IOERROR;
10215 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10216 free(junk);
10217 if (!br) {
10218 WMSFT_free_file(&file);
10219 CloseHandle(outfile);
10220 return TYPE_E_IOERROR;
10223 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10224 if (!br) {
10225 WMSFT_free_file(&file);
10226 CloseHandle(outfile);
10227 return TYPE_E_IOERROR;
10230 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10231 WMSFT_write_segment(outfile, &file.guidhash_seg);
10232 WMSFT_write_segment(outfile, &file.guid_seg);
10233 WMSFT_write_segment(outfile, &file.ref_seg);
10234 WMSFT_write_segment(outfile, &file.impinfo_seg);
10235 WMSFT_write_segment(outfile, &file.impfile_seg);
10236 WMSFT_write_segment(outfile, &file.namehash_seg);
10237 WMSFT_write_segment(outfile, &file.name_seg);
10238 WMSFT_write_segment(outfile, &file.string_seg);
10239 WMSFT_write_segment(outfile, &file.typdesc_seg);
10240 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10241 WMSFT_write_segment(outfile, &file.custdata_seg);
10242 WMSFT_write_segment(outfile, &file.cdguids_seg);
10243 WMSFT_write_segment(outfile, &file.aux_seg);
10245 WMSFT_free_file(&file);
10247 CloseHandle(outfile);
10249 return S_OK;
10252 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10253 LPOLESTR name)
10255 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10256 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10257 return E_NOTIMPL;
10260 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10261 REFGUID guid, VARIANT *varVal)
10263 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10264 TLBGuid *tlbguid;
10266 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10268 if (!guid || !varVal)
10269 return E_INVALIDARG;
10271 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10273 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10276 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10277 ULONG helpStringContext)
10279 FIXME("%p, %lu - stub\n", iface, helpStringContext);
10280 return E_NOTIMPL;
10283 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10284 LPOLESTR filename)
10286 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10287 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10289 if (!filename)
10290 return E_INVALIDARG;
10292 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10294 return S_OK;
10297 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10298 ICreateTypeLib2_fnQueryInterface,
10299 ICreateTypeLib2_fnAddRef,
10300 ICreateTypeLib2_fnRelease,
10301 ICreateTypeLib2_fnCreateTypeInfo,
10302 ICreateTypeLib2_fnSetName,
10303 ICreateTypeLib2_fnSetVersion,
10304 ICreateTypeLib2_fnSetGuid,
10305 ICreateTypeLib2_fnSetDocString,
10306 ICreateTypeLib2_fnSetHelpFileName,
10307 ICreateTypeLib2_fnSetHelpContext,
10308 ICreateTypeLib2_fnSetLcid,
10309 ICreateTypeLib2_fnSetLibFlags,
10310 ICreateTypeLib2_fnSaveAllChanges,
10311 ICreateTypeLib2_fnDeleteTypeInfo,
10312 ICreateTypeLib2_fnSetCustData,
10313 ICreateTypeLib2_fnSetHelpStringContext,
10314 ICreateTypeLib2_fnSetHelpStringDll
10317 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10318 REFIID riid, void **object)
10320 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10322 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10325 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10327 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10329 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10332 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10334 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10336 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10339 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10340 REFGUID guid)
10342 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10344 TRACE("%p %s\n", This, debugstr_guid(guid));
10346 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10348 return S_OK;
10351 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10352 UINT typeFlags)
10354 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10355 WORD old_flags;
10356 HRESULT hres;
10358 TRACE("%p %x\n", This, typeFlags);
10360 if (typeFlags & TYPEFLAG_FDUAL) {
10361 ITypeLib *stdole;
10362 ITypeInfo *dispatch;
10363 HREFTYPE hreftype;
10364 HRESULT hres;
10366 hres = LoadTypeLib(L"stdole2.tlb", &stdole);
10367 if(FAILED(hres))
10368 return hres;
10370 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10371 ITypeLib_Release(stdole);
10372 if(FAILED(hres))
10373 return hres;
10375 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10376 ITypeInfo_Release(dispatch);
10377 if(FAILED(hres))
10378 return hres;
10381 old_flags = This->typeattr.wTypeFlags;
10382 This->typeattr.wTypeFlags = typeFlags;
10384 hres = ICreateTypeInfo2_LayOut(iface);
10385 if (FAILED(hres)) {
10386 This->typeattr.wTypeFlags = old_flags;
10387 return hres;
10390 return S_OK;
10393 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10394 LPOLESTR doc)
10396 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10398 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10400 if (!doc)
10401 return E_INVALIDARG;
10403 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10405 return S_OK;
10408 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10409 DWORD helpContext)
10411 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10413 TRACE("%p, %ld.\n", iface, helpContext);
10415 This->dwHelpContext = helpContext;
10417 return S_OK;
10420 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10421 WORD majorVerNum, WORD minorVerNum)
10423 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10425 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10427 This->typeattr.wMajorVerNum = majorVerNum;
10428 This->typeattr.wMinorVerNum = minorVerNum;
10430 return S_OK;
10433 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10434 ITypeInfo *typeInfo, HREFTYPE *refType)
10436 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10437 UINT index;
10438 ITypeLib *container;
10439 TLBRefType *ref_type;
10440 TLBImpLib *implib;
10441 TYPEATTR *typeattr;
10442 TLIBATTR *libattr;
10443 HRESULT hres;
10445 TRACE("%p %p %p\n", This, typeInfo, refType);
10447 if (!typeInfo || !refType)
10448 return E_INVALIDARG;
10450 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10451 if (FAILED(hres))
10452 return hres;
10454 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10455 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10457 ITypeLib_Release(container);
10459 *refType = target->hreftype;
10461 return S_OK;
10464 hres = ITypeLib_GetLibAttr(container, &libattr);
10465 if (FAILED(hres)) {
10466 ITypeLib_Release(container);
10467 return hres;
10470 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10471 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10472 implib->lcid == libattr->lcid &&
10473 implib->wVersionMajor == libattr->wMajorVerNum &&
10474 implib->wVersionMinor == libattr->wMinorVerNum)
10475 break;
10478 if(&implib->entry == &This->pTypeLib->implib_list){
10479 implib = calloc(1, sizeof(TLBImpLib));
10481 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10482 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10483 implib->name = SysAllocString(our_container->path);
10484 }else{
10485 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10486 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10487 if(FAILED(hres)){
10488 implib->name = NULL;
10489 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres);
10493 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10494 implib->lcid = libattr->lcid;
10495 implib->wVersionMajor = libattr->wMajorVerNum;
10496 implib->wVersionMinor = libattr->wMinorVerNum;
10498 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10501 ITypeLib_ReleaseTLibAttr(container, libattr);
10502 ITypeLib_Release(container);
10504 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10505 if (FAILED(hres))
10506 return hres;
10508 index = 0;
10509 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10510 if(ref_type->index == TLB_REF_USE_GUID &&
10511 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10512 ref_type->tkind == typeattr->typekind)
10513 break;
10514 ++index;
10517 if(&ref_type->entry == &This->pTypeLib->ref_list){
10518 ref_type = calloc(1, sizeof(TLBRefType));
10520 ref_type->tkind = typeattr->typekind;
10521 ref_type->pImpTLInfo = implib;
10522 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10524 ref_type->index = TLB_REF_USE_GUID;
10526 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10528 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10531 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10533 *refType = ref_type->reference | 0x1;
10535 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10536 This->pTypeLib->dispatch_href = *refType;
10538 return S_OK;
10541 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10542 UINT index, FUNCDESC *funcDesc)
10544 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10545 TLBFuncDesc tmp_func_desc, *func_desc;
10546 int buf_size, i;
10547 char *buffer;
10548 HRESULT hres;
10550 TRACE("%p %u %p\n", This, index, funcDesc);
10552 if (!funcDesc || funcDesc->oVft & 3)
10553 return E_INVALIDARG;
10555 switch (This->typeattr.typekind) {
10556 case TKIND_MODULE:
10557 if (funcDesc->funckind != FUNC_STATIC)
10558 return TYPE_E_BADMODULEKIND;
10559 break;
10560 case TKIND_DISPATCH:
10561 if (funcDesc->funckind != FUNC_DISPATCH)
10562 return TYPE_E_BADMODULEKIND;
10563 break;
10564 default:
10565 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10566 return TYPE_E_BADMODULEKIND;
10569 if (index > This->typeattr.cFuncs)
10570 return TYPE_E_ELEMENTNOTFOUND;
10572 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10573 !funcDesc->cParams)
10574 return TYPE_E_INCONSISTENTPROPFUNCS;
10576 if(This->pTypeLib->syskind == SYS_WIN64 &&
10577 funcDesc->oVft % 8 != 0)
10578 return E_INVALIDARG;
10580 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10581 TLBFuncDesc_Constructor(&tmp_func_desc);
10583 tmp_func_desc.funcdesc = *funcDesc;
10585 if (tmp_func_desc.funcdesc.oVft != 0)
10586 tmp_func_desc.funcdesc.oVft |= 1;
10588 if (funcDesc->cScodes && funcDesc->lprgscode) {
10589 tmp_func_desc.funcdesc.lprgscode = malloc(sizeof(SCODE) * funcDesc->cScodes);
10590 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10591 } else {
10592 tmp_func_desc.funcdesc.lprgscode = NULL;
10593 tmp_func_desc.funcdesc.cScodes = 0;
10596 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10597 for (i = 0; i < funcDesc->cParams; ++i) {
10598 buf_size += sizeof(ELEMDESC);
10599 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10601 tmp_func_desc.funcdesc.lprgelemdescParam = malloc(buf_size);
10602 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10604 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10605 if (FAILED(hres)) {
10606 free(tmp_func_desc.funcdesc.lprgelemdescParam);
10607 free(tmp_func_desc.funcdesc.lprgscode);
10608 return hres;
10611 for (i = 0; i < funcDesc->cParams; ++i) {
10612 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10613 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10614 if (FAILED(hres)) {
10615 free(tmp_func_desc.funcdesc.lprgelemdescParam);
10616 free(tmp_func_desc.funcdesc.lprgscode);
10617 return hres;
10619 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10620 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10621 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10622 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].paramdesc.pparamdescex->varDefaultValue);
10623 if (FAILED(hres)) {
10624 free(tmp_func_desc.funcdesc.lprgelemdescParam);
10625 free(tmp_func_desc.funcdesc.lprgscode);
10626 return hres;
10631 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10633 if (This->funcdescs) {
10634 This->funcdescs = realloc(This->funcdescs, sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10636 if (index < This->typeattr.cFuncs) {
10637 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10638 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10639 func_desc = This->funcdescs + index;
10640 } else
10641 func_desc = This->funcdescs + This->typeattr.cFuncs;
10643 /* move custdata lists to the new memory location */
10644 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10645 if(index != i)
10646 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
10648 } else
10649 func_desc = This->funcdescs = malloc(sizeof(TLBFuncDesc));
10651 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10652 list_init(&func_desc->custdata_list);
10654 ++This->typeattr.cFuncs;
10656 This->needs_layout = TRUE;
10658 return S_OK;
10661 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10662 UINT index, HREFTYPE refType)
10664 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10665 TLBImplType *impl_type;
10666 HRESULT hres;
10668 TRACE("%p, %u, %ld.\n", iface, index, refType);
10670 switch(This->typeattr.typekind){
10671 case TKIND_COCLASS: {
10672 if (index == -1) {
10673 FIXME("Unhandled index: -1\n");
10674 return E_NOTIMPL;
10677 if(index != This->typeattr.cImplTypes)
10678 return TYPE_E_ELEMENTNOTFOUND;
10680 break;
10682 case TKIND_INTERFACE:
10683 case TKIND_DISPATCH:
10684 if (index != 0 || This->typeattr.cImplTypes)
10685 return TYPE_E_ELEMENTNOTFOUND;
10686 break;
10687 default:
10688 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10689 return E_NOTIMPL;
10692 if (This->impltypes){
10693 UINT i;
10695 This->impltypes = realloc(This->impltypes, sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10697 if (index < This->typeattr.cImplTypes) {
10698 memmove(This->impltypes + index + 1, This->impltypes + index,
10699 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10700 impl_type = This->impltypes + index;
10701 } else
10702 impl_type = This->impltypes + This->typeattr.cImplTypes;
10704 /* move custdata lists to the new memory location */
10705 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10706 if(index != i)
10707 TLB_relink_custdata(&This->impltypes[i].custdata_list);
10709 } else
10710 impl_type = This->impltypes = malloc(sizeof(TLBImplType));
10712 memset(impl_type, 0, sizeof(TLBImplType));
10713 TLBImplType_Constructor(impl_type);
10714 impl_type->hRef = refType;
10716 ++This->typeattr.cImplTypes;
10718 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10719 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10721 hres = ICreateTypeInfo2_LayOut(iface);
10722 if (FAILED(hres))
10723 return hres;
10725 return S_OK;
10728 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10729 UINT index, INT implTypeFlags)
10731 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10732 TLBImplType *impl_type = &This->impltypes[index];
10734 TRACE("%p %u %x\n", This, index, implTypeFlags);
10736 if (This->typeattr.typekind != TKIND_COCLASS)
10737 return TYPE_E_BADMODULEKIND;
10739 if (index >= This->typeattr.cImplTypes)
10740 return TYPE_E_ELEMENTNOTFOUND;
10742 impl_type->implflags = implTypeFlags;
10744 return S_OK;
10747 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10748 WORD alignment)
10750 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10752 TRACE("%p %d\n", This, alignment);
10754 This->typeattr.cbAlignment = alignment;
10756 return S_OK;
10759 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10760 LPOLESTR schema)
10762 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10764 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10766 if (!schema)
10767 return E_INVALIDARG;
10769 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10771 This->typeattr.lpstrSchema = This->Schema->str;
10773 return S_OK;
10776 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10777 UINT index, VARDESC *varDesc)
10779 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10780 TLBVarDesc *var_desc;
10781 HRESULT hr;
10783 TRACE("%p %u %p\n", This, index, varDesc);
10785 if (This->vardescs){
10786 UINT i;
10788 This->vardescs = realloc(This->vardescs, sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10790 if (index < This->typeattr.cVars) {
10791 memmove(This->vardescs + index + 1, This->vardescs + index,
10792 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10793 var_desc = This->vardescs + index;
10794 } else {
10795 var_desc = This->vardescs + This->typeattr.cVars;
10796 memset(var_desc, 0, sizeof(TLBVarDesc));
10799 /* move custdata lists to the new memory location */
10800 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10801 if(index != i)
10802 TLB_relink_custdata(&This->vardescs[i].custdata_list);
10804 } else
10805 var_desc = This->vardescs = calloc(1, sizeof(TLBVarDesc));
10807 TLBVarDesc_Constructor(var_desc);
10808 hr = TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10809 if (FAILED(hr))
10810 return hr;
10811 var_desc->vardesc = *var_desc->vardesc_create;
10813 ++This->typeattr.cVars;
10815 This->needs_layout = TRUE;
10817 return S_OK;
10820 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10821 UINT index, LPOLESTR *names, UINT numNames)
10823 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10824 TLBFuncDesc *func_desc = &This->funcdescs[index];
10825 int i;
10827 TRACE("%p %u %p %u\n", This, index, names, numNames);
10829 if (!names)
10830 return E_INVALIDARG;
10832 if (index >= This->typeattr.cFuncs || numNames == 0)
10833 return TYPE_E_ELEMENTNOTFOUND;
10835 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10836 if(numNames > func_desc->funcdesc.cParams)
10837 return TYPE_E_ELEMENTNOTFOUND;
10838 } else
10839 if(numNames > func_desc->funcdesc.cParams + 1)
10840 return TYPE_E_ELEMENTNOTFOUND;
10842 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10843 TLBFuncDesc *iter = &This->funcdescs[i];
10844 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
10845 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10846 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10847 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10848 continue;
10849 return TYPE_E_AMBIGUOUSNAME;
10853 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10855 for (i = 1; i < numNames; ++i) {
10856 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10857 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10860 return S_OK;
10863 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10864 UINT index, LPOLESTR name)
10866 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10868 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10870 if(!name)
10871 return E_INVALIDARG;
10873 if(index >= This->typeattr.cVars)
10874 return TYPE_E_ELEMENTNOTFOUND;
10876 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10877 return S_OK;
10880 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10881 TYPEDESC *tdescAlias)
10883 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10884 HRESULT hr;
10886 TRACE("%p %p\n", This, tdescAlias);
10888 if(!tdescAlias)
10889 return E_INVALIDARG;
10891 if(This->typeattr.typekind != TKIND_ALIAS)
10892 return TYPE_E_BADMODULEKIND;
10894 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10895 if(FAILED(hr))
10896 return hr;
10898 free(This->tdescAlias);
10899 This->tdescAlias = malloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10900 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10902 return S_OK;
10905 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10906 UINT index, LPOLESTR dllName, LPOLESTR procName)
10908 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10909 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10910 return E_NOTIMPL;
10913 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10914 UINT index, LPOLESTR docString)
10916 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10917 TLBFuncDesc *func_desc = &This->funcdescs[index];
10919 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10921 if(!docString)
10922 return E_INVALIDARG;
10924 if(index >= This->typeattr.cFuncs)
10925 return TYPE_E_ELEMENTNOTFOUND;
10927 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10929 return S_OK;
10932 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10933 UINT index, LPOLESTR docString)
10935 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10936 TLBVarDesc *var_desc = &This->vardescs[index];
10938 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10940 if(!docString)
10941 return E_INVALIDARG;
10943 if(index >= This->typeattr.cVars)
10944 return TYPE_E_ELEMENTNOTFOUND;
10946 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10948 return S_OK;
10951 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10952 UINT index, DWORD helpContext)
10954 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10955 TLBFuncDesc *func_desc = &This->funcdescs[index];
10957 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
10959 if(index >= This->typeattr.cFuncs)
10960 return TYPE_E_ELEMENTNOTFOUND;
10962 func_desc->helpcontext = helpContext;
10964 return S_OK;
10967 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10968 UINT index, DWORD helpContext)
10970 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10971 TLBVarDesc *var_desc = &This->vardescs[index];
10973 TRACE("%p, %u, %ld.\n", iface, index, helpContext);
10975 if(index >= This->typeattr.cVars)
10976 return TYPE_E_ELEMENTNOTFOUND;
10978 var_desc->HelpContext = helpContext;
10980 return S_OK;
10983 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10984 UINT index, BSTR bstrMops)
10986 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10987 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10988 return E_NOTIMPL;
10991 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10992 IDLDESC *idlDesc)
10994 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10996 TRACE("%p %p\n", This, idlDesc);
10998 if (!idlDesc)
10999 return E_INVALIDARG;
11001 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11002 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11004 return S_OK;
11007 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11009 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11010 ITypeInfo2 *tinfo = &This->ITypeInfo2_iface;
11011 TLBFuncDesc *func_desc;
11012 UINT user_vft = 0, i, depth = 0;
11013 HRESULT hres = S_OK;
11015 TRACE("%p\n", This);
11017 This->needs_layout = FALSE;
11019 if (This->typeattr.typekind == TKIND_INTERFACE) {
11020 ITypeInfo *inh;
11021 TYPEATTR *attr;
11022 HREFTYPE inh_href;
11024 hres = ITypeInfo2_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11026 if (SUCCEEDED(hres)) {
11027 hres = ITypeInfo2_GetRefTypeInfo(tinfo, inh_href, &inh);
11029 if (SUCCEEDED(hres)) {
11030 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11031 if (FAILED(hres)) {
11032 ITypeInfo_Release(inh);
11033 return hres;
11035 This->typeattr.cbSizeVft = attr->cbSizeVft;
11036 ITypeInfo_ReleaseTypeAttr(inh, attr);
11039 ++depth;
11040 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11041 if(SUCCEEDED(hres)){
11042 ITypeInfo *next;
11043 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11044 if(SUCCEEDED(hres)){
11045 ITypeInfo_Release(inh);
11046 inh = next;
11049 }while(SUCCEEDED(hres));
11050 hres = S_OK;
11052 ITypeInfo_Release(inh);
11053 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11054 This->typeattr.cbSizeVft = 0;
11055 hres = S_OK;
11056 } else
11057 return hres;
11058 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11059 This->typeattr.cbSizeVft = 0;
11060 hres = S_OK;
11061 } else
11062 return hres;
11063 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11064 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11065 else
11066 This->typeattr.cbSizeVft = 0;
11068 func_desc = This->funcdescs;
11069 i = 0;
11070 while (i < This->typeattr.cFuncs) {
11071 if (!(func_desc->funcdesc.oVft & 0x1))
11072 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11074 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11075 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11077 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11079 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11080 TLBFuncDesc *iter;
11081 UINT j = 0;
11082 BOOL reset = FALSE;
11084 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11086 iter = This->funcdescs;
11087 while (j < This->typeattr.cFuncs) {
11088 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11089 if (!reset) {
11090 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11091 reset = TRUE;
11092 } else
11093 ++func_desc->funcdesc.memid;
11094 iter = This->funcdescs;
11095 j = 0;
11096 } else {
11097 ++iter;
11098 ++j;
11103 ++func_desc;
11104 ++i;
11107 if (user_vft > This->typeattr.cbSizeVft)
11108 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11110 for(i = 0; i < This->typeattr.cVars; ++i){
11111 TLBVarDesc *var_desc = &This->vardescs[i];
11112 if(var_desc->vardesc.memid == MEMBERID_NIL){
11113 UINT j = 0;
11114 BOOL reset = FALSE;
11115 TLBVarDesc *iter;
11117 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11119 iter = This->vardescs;
11120 while (j < This->typeattr.cVars) {
11121 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11122 if (!reset) {
11123 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11124 reset = TRUE;
11125 } else
11126 ++var_desc->vardesc.memid;
11127 iter = This->vardescs;
11128 j = 0;
11129 } else {
11130 ++iter;
11131 ++j;
11137 return hres;
11140 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11141 UINT index)
11143 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11144 unsigned int i;
11146 TRACE("%p %u\n", This, index);
11148 if (index >= This->typeattr.cFuncs)
11149 return TYPE_E_ELEMENTNOTFOUND;
11151 typeinfo_release_funcdesc(&This->funcdescs[index]);
11153 --This->typeattr.cFuncs;
11154 if (index != This->typeattr.cFuncs)
11156 memmove(This->funcdescs + index, This->funcdescs + index + 1,
11157 sizeof(*This->funcdescs) * (This->typeattr.cFuncs - index));
11158 for (i = index; i < This->typeattr.cFuncs; ++i)
11159 TLB_relink_custdata(&This->funcdescs[i].custdata_list);
11162 This->needs_layout = TRUE;
11164 return S_OK;
11167 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11168 MEMBERID memid, INVOKEKIND invKind)
11170 FIXME("%p, %#lx, %d - stub\n", iface, memid, invKind);
11171 return E_NOTIMPL;
11174 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11175 UINT index)
11177 FIXME("%p, %u - stub\n", iface, index);
11178 return E_NOTIMPL;
11181 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11182 MEMBERID memid)
11184 FIXME("%p, %#lx - stub\n", iface, memid);
11185 return E_NOTIMPL;
11188 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11189 UINT index)
11191 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11192 int i;
11194 TRACE("%p %u\n", This, index);
11196 if (index >= This->typeattr.cImplTypes)
11197 return TYPE_E_ELEMENTNOTFOUND;
11199 TLB_FreeCustData(&This->impltypes[index].custdata_list);
11200 --This->typeattr.cImplTypes;
11202 if (index < This->typeattr.cImplTypes)
11204 memmove(This->impltypes + index, This->impltypes + index + 1, (This->typeattr.cImplTypes - index) *
11205 sizeof(*This->impltypes));
11206 for (i = index; i < This->typeattr.cImplTypes; ++i)
11207 TLB_relink_custdata(&This->impltypes[i].custdata_list);
11210 return S_OK;
11213 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11214 REFGUID guid, VARIANT *varVal)
11216 TLBGuid *tlbguid;
11218 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11220 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11222 if (!guid || !varVal)
11223 return E_INVALIDARG;
11225 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11227 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11230 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11231 UINT index, REFGUID guid, VARIANT *varVal)
11233 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11234 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11235 return E_NOTIMPL;
11238 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11239 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11241 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11242 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11243 return E_NOTIMPL;
11246 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11247 UINT index, REFGUID guid, VARIANT *varVal)
11249 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11250 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11251 return E_NOTIMPL;
11254 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11255 UINT index, REFGUID guid, VARIANT *varVal)
11257 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11258 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11259 return E_NOTIMPL;
11262 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11263 ULONG helpStringContext)
11265 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11267 TRACE("%p, %lu.\n", iface, helpStringContext);
11269 This->dwHelpStringContext = helpStringContext;
11271 return S_OK;
11274 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11275 UINT index, ULONG helpStringContext)
11277 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11278 return E_NOTIMPL;
11281 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11282 UINT index, ULONG helpStringContext)
11284 FIXME("%p, %u, %lu - stub\n", iface, index, helpStringContext);
11285 return E_NOTIMPL;
11288 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11290 FIXME("%p - stub\n", iface);
11291 return E_NOTIMPL;
11294 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11295 LPOLESTR name)
11297 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11299 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11301 if (!name)
11302 return E_INVALIDARG;
11304 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11306 return S_OK;
11309 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11310 ICreateTypeInfo2_fnQueryInterface,
11311 ICreateTypeInfo2_fnAddRef,
11312 ICreateTypeInfo2_fnRelease,
11313 ICreateTypeInfo2_fnSetGuid,
11314 ICreateTypeInfo2_fnSetTypeFlags,
11315 ICreateTypeInfo2_fnSetDocString,
11316 ICreateTypeInfo2_fnSetHelpContext,
11317 ICreateTypeInfo2_fnSetVersion,
11318 ICreateTypeInfo2_fnAddRefTypeInfo,
11319 ICreateTypeInfo2_fnAddFuncDesc,
11320 ICreateTypeInfo2_fnAddImplType,
11321 ICreateTypeInfo2_fnSetImplTypeFlags,
11322 ICreateTypeInfo2_fnSetAlignment,
11323 ICreateTypeInfo2_fnSetSchema,
11324 ICreateTypeInfo2_fnAddVarDesc,
11325 ICreateTypeInfo2_fnSetFuncAndParamNames,
11326 ICreateTypeInfo2_fnSetVarName,
11327 ICreateTypeInfo2_fnSetTypeDescAlias,
11328 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11329 ICreateTypeInfo2_fnSetFuncDocString,
11330 ICreateTypeInfo2_fnSetVarDocString,
11331 ICreateTypeInfo2_fnSetFuncHelpContext,
11332 ICreateTypeInfo2_fnSetVarHelpContext,
11333 ICreateTypeInfo2_fnSetMops,
11334 ICreateTypeInfo2_fnSetTypeIdldesc,
11335 ICreateTypeInfo2_fnLayOut,
11336 ICreateTypeInfo2_fnDeleteFuncDesc,
11337 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11338 ICreateTypeInfo2_fnDeleteVarDesc,
11339 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11340 ICreateTypeInfo2_fnDeleteImplType,
11341 ICreateTypeInfo2_fnSetCustData,
11342 ICreateTypeInfo2_fnSetFuncCustData,
11343 ICreateTypeInfo2_fnSetParamCustData,
11344 ICreateTypeInfo2_fnSetVarCustData,
11345 ICreateTypeInfo2_fnSetImplTypeCustData,
11346 ICreateTypeInfo2_fnSetHelpStringContext,
11347 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11348 ICreateTypeInfo2_fnSetVarHelpStringContext,
11349 ICreateTypeInfo2_fnInvalidate,
11350 ICreateTypeInfo2_fnSetName
11353 /******************************************************************************
11354 * ClearCustData (OLEAUT32.171)
11356 * Clear a custom data type's data.
11358 * PARAMS
11359 * lpCust [I] The custom data type instance
11361 * RETURNS
11362 * Nothing.
11364 void WINAPI ClearCustData(CUSTDATA *lpCust)
11366 if (lpCust && lpCust->cCustData)
11368 if (lpCust->prgCustData)
11370 DWORD i;
11372 for (i = 0; i < lpCust->cCustData; i++)
11373 VariantClear(&lpCust->prgCustData[i].varValue);
11375 CoTaskMemFree(lpCust->prgCustData);
11376 lpCust->prgCustData = NULL;
11378 lpCust->cCustData = 0;