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