1 /*
2 * TYPELIB
3 *
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
11 *
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.
16 *
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.
21 *
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
25 *
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
28 *
29 * - Tested using OLEVIEW (Platform SDK tool) only.
30 *
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.
34 *
35 * - locale stuff is partially implemented but hasn't been tested.
36 *
37 * - typelib file is still read in its entirety, but it is released now.
38 *
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
41 *
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
47 *
48 */
49
50 #include <stdlib.h>
51 #include <string.h>
52 #include <stdarg.h>
53 #include <stdio.h>
54 #include <ctype.h>
55
56 #define COBJMACROS
57 #define NONAMELESSUNION
58
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"
67
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"
75
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78
79 typedef struct
80 {
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
88
89 typedef struct
90 {
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
94 /*
95 * Name info array.
96 */
97 } NE_TYPEINFO;
98
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*);
102
103 /****************************************************************************
104 * FromLExxx
105 *
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
108 */
109 #ifdef WORDS_BIGENDIAN
FromLEWord(WORD p_iVal)110 static WORD FromLEWord(WORD p_iVal)
111 {
112 return (((p_iVal & 0x00FF) << 8) |
113 ((p_iVal & 0xFF00) >> 8));
114 }
115
116
FromLEDWord(DWORD p_iVal)117 static DWORD FromLEDWord(DWORD p_iVal)
118 {
119 return (((p_iVal & 0x000000FF) << 24) |
120 ((p_iVal & 0x0000FF00) << 8) |
121 ((p_iVal & 0x00FF0000) >> 8) |
122 ((p_iVal & 0xFF000000) >> 24));
123 }
124 #else
125 #define FromLEWord(X) (X)
126 #define FromLEDWord(X) (X)
127 #endif
128
129 #define DISPATCH_HREF_OFFSET 0x01000000
130 #define DISPATCH_HREF_MASK 0xff000000
131
132 /****************************************************************************
133 * FromLExxx
134 *
135 * Fix byte order in any structure if necessary
136 */
137 #ifdef WORDS_BIGENDIAN
FromLEWords(void * p_Val,int p_iSize)138 static void FromLEWords(void *p_Val, int p_iSize)
139 {
140 WORD *Val = p_Val;
141
142 p_iSize /= sizeof(WORD);
143
144 while (p_iSize) {
145 *Val = FromLEWord(*Val);
146 Val++;
147 p_iSize--;
148 }
149 }
150
151
FromLEDWords(void * p_Val,int p_iSize)152 static void FromLEDWords(void *p_Val, int p_iSize)
153 {
154 DWORD *Val = p_Val;
155
156 p_iSize /= sizeof(DWORD);
157
158 while (p_iSize) {
159 *Val = FromLEDWord(*Val);
160 Val++;
161 p_iSize--;
162 }
163 }
164 #else
165 #define FromLEWords(X,Y) /*nothing*/
166 #define FromLEDWords(X,Y) /*nothing*/
167 #endif
168
169 /*
170 * Find a typelib key which matches a requested maj.min version.
171 */
find_typelib_key(REFGUID guid,WORD * wMaj,WORD * wMin)172 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 {
174 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
175 WCHAR buffer[60];
176 char key_name[16];
177 DWORD len, i;
178 INT best_maj = -1, best_min = -1;
179 HKEY hkey;
180
181 memcpy( buffer, typelibW, sizeof(typelibW) );
182 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
183
184 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
185 return FALSE;
186
187 len = sizeof(key_name);
188 i = 0;
189 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 {
191 INT v_maj, v_min;
192
193 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 {
195 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196
197 if (*wMaj == 0xffff && *wMin == 0xffff)
198 {
199 if (v_maj > best_maj) best_maj = v_maj;
200 if (v_min > best_min) best_min = v_min;
201 }
202 else if (*wMaj == v_maj)
203 {
204 best_maj = v_maj;
205
206 if (*wMin == v_min)
207 {
208 best_min = v_min;
209 break; /* exact match */
210 }
211 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
212 }
213 }
214 len = sizeof(key_name);
215 }
216 RegCloseKey( hkey );
217
218 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219
220 if (*wMaj == 0xffff && *wMin == 0xffff)
221 {
222 if (best_maj >= 0 && best_min >= 0)
223 {
224 *wMaj = best_maj;
225 *wMin = best_min;
226 return TRUE;
227 }
228 }
229
230 if (*wMaj == best_maj && best_min >= 0)
231 {
232 *wMin = best_min;
233 return TRUE;
234 }
235 return FALSE;
236 }
237
238 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
239 /* buffer must be at least 60 characters long */
get_typelib_key(REFGUID guid,WORD wMaj,WORD wMin,WCHAR * buffer)240 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 {
242 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
243 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244
245 memcpy( buffer, TypelibW, sizeof(TypelibW) );
246 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
247 swprintf( buffer + lstrlenW(buffer), VersionFormatW, wMaj, wMin );
248 return buffer;
249 }
250
251 /* get the path of an interface key, in the form "Interface\\<guid>" */
252 /* buffer must be at least 50 characters long */
get_interface_key(REFGUID guid,WCHAR * buffer)253 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 {
255 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256
257 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
258 StringFromGUID2( guid, buffer + lstrlenW(buffer), 40 );
259 return buffer;
260 }
261
262 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
263 /* buffer must be at least 16 characters long */
get_lcid_subkey(LCID lcid,SYSKIND syskind,WCHAR * buffer)264 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 {
266 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
267 static const WCHAR win16W[] = {'w','i','n','1','6',0};
268 static const WCHAR win32W[] = {'w','i','n','3','2',0};
269 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270
271 swprintf( buffer, LcidFormatW, lcid );
272 switch(syskind)
273 {
274 case SYS_WIN16: lstrcatW( buffer, win16W ); break;
275 case SYS_WIN32: lstrcatW( buffer, win32W ); break;
276 case SYS_WIN64: lstrcatW( buffer, win64W ); break;
277 default:
278 TRACE("Typelib is for unsupported syskind %i\n", syskind);
279 return NULL;
280 }
281 return buffer;
282 }
283
284 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
285
286 struct tlibredirect_data
287 {
288 ULONG size;
289 DWORD res;
290 ULONG name_len;
291 ULONG name_offset;
292 LANGID langid;
293 WORD flags;
294 ULONG help_len;
295 ULONG help_offset;
296 WORD major_version;
297 WORD minor_version;
298 };
299
300 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
query_typelib_path(REFGUID guid,WORD wMaj,WORD wMin,SYSKIND syskind,LCID lcid,BSTR * path,BOOL redir)301 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
302 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
303 {
304 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
305 LCID myLCID = lcid;
306 HKEY hkey;
307 WCHAR buffer[60];
308 WCHAR Path[MAX_PATH];
309 LONG res;
310
311 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
312
313 if (redir)
314 {
315 ACTCTX_SECTION_KEYED_DATA data;
316
317 data.cbSize = sizeof(data);
318 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
319 {
320 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
321 WCHAR *nameW;
322 DWORD len;
323
324 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
325 return TYPE_E_LIBNOTREGISTERED;
326
327 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
328 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
329 if (!len) return TYPE_E_LIBNOTREGISTERED;
330
331 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
332 *path = SysAllocString( Path );
333 return S_OK;
334 }
335 }
336
337 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
338 get_typelib_key( guid, wMaj, wMin, buffer );
339
340 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
341 if (res == ERROR_FILE_NOT_FOUND)
342 {
343 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
344 return TYPE_E_LIBNOTREGISTERED;
345 }
346 else if (res != ERROR_SUCCESS)
347 {
348 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
349 return TYPE_E_REGISTRYACCESS;
350 }
351
352 while (hr != S_OK)
353 {
354 LONG dwPathLen = sizeof(Path);
355
356 get_lcid_subkey( myLCID, syskind, buffer );
357
358 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
359 {
360 if (!lcid)
361 break;
362 else if (myLCID == lcid)
363 {
364 /* try with sub-langid */
365 myLCID = SUBLANGID(lcid);
366 }
367 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
368 {
369 /* try with system langid */
370 myLCID = 0;
371 }
372 else
373 {
374 break;
375 }
376 }
377 else
378 {
379 *path = SysAllocString( Path );
380 hr = S_OK;
381 }
382 }
383 RegCloseKey( hkey );
384 TRACE_(typelib)("-- 0x%08x\n", hr);
385 return hr;
386 }
387
388 /****************************************************************************
389 * QueryPathOfRegTypeLib [OLEAUT32.164]
390 *
391 * Gets the path to a registered type library.
392 *
393 * PARAMS
394 * guid [I] referenced guid
395 * wMaj [I] major version
396 * wMin [I] minor version
397 * lcid [I] locale id
398 * path [O] path of typelib
399 *
400 * RETURNS
401 * Success: S_OK.
402 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
403 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
404 * opened.
405 */
QueryPathOfRegTypeLib(REFGUID guid,WORD wMaj,WORD wMin,LCID lcid,LPBSTR path)406 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
407 {
408 BOOL redir = TRUE;
409 #ifdef _WIN64
410 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
411 if(SUCCEEDED(hres))
412 return hres;
413 redir = FALSE;
414 #endif
415 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
416 }
417
418 /******************************************************************************
419 * CreateTypeLib [OLEAUT32.160] creates a typelib
420 *
421 * RETURNS
422 * Success: S_OK
423 * Failure: Status
424 */
CreateTypeLib(SYSKIND syskind,LPCOLESTR file,ICreateTypeLib ** ctlib)425 HRESULT WINAPI CreateTypeLib(SYSKIND syskind, LPCOLESTR file, ICreateTypeLib **ctlib)
426 {
427 ICreateTypeLib2 *typelib2;
428 HRESULT hres;
429
430 FIXME("(%d, %s, %p): forwarding to CreateTypeLib2\n", syskind, debugstr_w(file), ctlib);
431
432 hres = CreateTypeLib2(syskind, file, &typelib2);
433 if(SUCCEEDED(hres))
434 {
435 hres = ICreateTypeLib2_QueryInterface(typelib2, &IID_ICreateTypeLib, (void **)&ctlib);
436 ICreateTypeLib2_Release(typelib2);
437 }
438
439 return hres;
440 }
441
442 /******************************************************************************
443 * LoadTypeLib [OLEAUT32.161]
444 *
445 * Loads a type library
446 *
447 * PARAMS
448 * szFile [I] Name of file to load from.
449 * pptLib [O] Pointer that receives ITypeLib object on success.
450 *
451 * RETURNS
452 * Success: S_OK
453 * Failure: Status
454 *
455 * SEE
456 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
457 */
LoadTypeLib(const OLECHAR * szFile,ITypeLib ** pptLib)458 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
459 {
460 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
461 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
462 }
463
464 /******************************************************************************
465 * LoadTypeLibEx [OLEAUT32.183]
466 *
467 * Loads and optionally registers a type library
468 *
469 * RETURNS
470 * Success: S_OK
471 * Failure: Status
472 */
LoadTypeLibEx(LPCOLESTR szFile,REGKIND regkind,ITypeLib ** pptLib)473 HRESULT WINAPI LoadTypeLibEx(
474 LPCOLESTR szFile, /* [in] Name of file to load from */
475 REGKIND regkind, /* [in] Specify kind of registration */
476 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
477 {
478 WCHAR szPath[MAX_PATH+1];
479 HRESULT res;
480
481 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
482
483 if (!szFile || !pptLib)
484 return E_INVALIDARG;
485
486 *pptLib = NULL;
487
488 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
489
490 if (SUCCEEDED(res))
491 switch(regkind)
492 {
493 case REGKIND_DEFAULT:
494 /* don't register typelibs supplied with full path. Experimentation confirms the following */
495 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
496 (szFile[0] && (szFile[1] == ':'))) break;
497 /* else fall-through */
498
499 case REGKIND_REGISTER:
500 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
501 {
502 ITypeLib_Release(*pptLib);
503 *pptLib = 0;
504 }
505 break;
506 case REGKIND_NONE:
507 break;
508 }
509
510 TRACE(" returns %08x\n",res);
511 return res;
512 }
513
514 /******************************************************************************
515 * LoadRegTypeLib [OLEAUT32.162]
516 *
517 * Loads a registered type library.
518 *
519 * PARAMS
520 * rguid [I] GUID of the registered type library.
521 * wVerMajor [I] major version.
522 * wVerMinor [I] minor version.
523 * lcid [I] locale ID.
524 * ppTLib [O] pointer that receives an ITypeLib object on success.
525 *
526 * RETURNS
527 * Success: S_OK.
528 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
529 * LoadTypeLib.
530 */
LoadRegTypeLib(REFGUID rguid,WORD wVerMajor,WORD wVerMinor,LCID lcid,ITypeLib ** ppTLib)531 HRESULT WINAPI LoadRegTypeLib(
532 REFGUID rguid,
533 WORD wVerMajor,
534 WORD wVerMinor,
535 LCID lcid,
536 ITypeLib **ppTLib)
537 {
538 BSTR bstr=NULL;
539 HRESULT res;
540
541 *ppTLib = NULL;
542
543 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
544
545 if(SUCCEEDED(res))
546 {
547 res= LoadTypeLib(bstr, ppTLib);
548 SysFreeString(bstr);
549
550 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
551 {
552 TLIBATTR *attr;
553
554 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
555 if (res == S_OK)
556 {
557 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
558 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
559
560 if (mismatch)
561 {
562 ITypeLib_Release(*ppTLib);
563 *ppTLib = NULL;
564 res = TYPE_E_LIBNOTREGISTERED;
565 }
566 }
567 }
568 }
569
570 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
571
572 return res;
573 }
574
575
576 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
577 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
578 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
579 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
580 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
581 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
582
TLB_register_interface(TLIBATTR * libattr,LPOLESTR name,TYPEATTR * tattr,DWORD flag)583 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
584 {
585 WCHAR keyName[60];
586 HKEY key, subKey;
587
588 static const WCHAR typelib_proxy_clsid[] = {'{','0','0','0','2','0','4','2','4','-',
589 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
590 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
591 static const WCHAR dispatch_proxy_clsid[] = {'{','0','0','0','2','0','4','2','0','-',
592 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
593 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
594
595 get_interface_key( &tattr->guid, keyName );
596 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
597 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
598 {
599 const WCHAR *proxy_clsid;
600
601 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
602 proxy_clsid = typelib_proxy_clsid;
603 else
604 proxy_clsid = dispatch_proxy_clsid;
605
606 if (name)
607 RegSetValueExW(key, NULL, 0, REG_SZ,
608 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR));
609
610 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
611 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
612 RegSetValueExW(subKey, NULL, 0, REG_SZ,
613 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
614 RegCloseKey(subKey);
615 }
616
617 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
618 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
619 RegSetValueExW(subKey, NULL, 0, REG_SZ,
620 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
621 RegCloseKey(subKey);
622 }
623
624 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
625 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
626 {
627 WCHAR buffer[40];
628 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
629 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
630
631 StringFromGUID2(&libattr->guid, buffer, 40);
632 RegSetValueExW(subKey, NULL, 0, REG_SZ,
633 (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
634 swprintf(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
635 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
636 (BYTE*)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
637 RegCloseKey(subKey);
638 }
639
640 RegCloseKey(key);
641 }
642 }
643
644 /******************************************************************************
645 * RegisterTypeLib [OLEAUT32.163]
646 * Adds information about a type library to the System Registry
647 * NOTES
648 * Docs: ITypeLib FAR * ptlib
649 * Docs: OLECHAR FAR* szFullPath
650 * Docs: OLECHAR FAR* szHelpDir
651 *
652 * RETURNS
653 * Success: S_OK
654 * Failure: Status
655 */
RegisterTypeLib(ITypeLib * ptlib,const WCHAR * szFullPath,const WCHAR * szHelpDir)656 HRESULT WINAPI RegisterTypeLib(ITypeLib *ptlib, const WCHAR *szFullPath, const WCHAR *szHelpDir)
657 {
658 HRESULT res;
659 TLIBATTR *attr;
660 WCHAR keyName[60];
661 WCHAR tmp[16];
662 HKEY key, subKey;
663 UINT types, tidx;
664 TYPEKIND kind;
665 DWORD disposition;
666
667 if (ptlib == NULL || szFullPath == NULL)
668 return E_INVALIDARG;
669
670 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
671 return E_FAIL;
672
673 #ifndef _WIN64
674 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
675 #endif
676
677 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
678
679 res = S_OK;
680 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
681 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
682 {
683 LPOLESTR doc;
684
685 /* Set the human-readable name of the typelib */
686 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
687 res = E_FAIL;
688 else if (doc)
689 {
690 if (RegSetValueExW(key, NULL, 0, REG_SZ,
691 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
692 res = E_FAIL;
693
694 SysFreeString(doc);
695 }
696
697 /* Make up the name of the typelib path subkey */
698 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
699
700 /* Create the typelib path subkey */
701 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
702 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
703 {
704 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
705 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
706 res = E_FAIL;
707
708 RegCloseKey(subKey);
709 }
710 else
711 res = E_FAIL;
712
713 /* Create the flags subkey */
714 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
715 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
716 {
717 /* FIXME: is %u correct? */
718 static const WCHAR formatW[] = {'%','u',0};
719 WCHAR buf[20];
720 swprintf(buf, formatW, attr->wLibFlags);
721 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
722 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
723 res = E_FAIL;
724
725 RegCloseKey(subKey);
726 }
727 else
728 res = E_FAIL;
729
730 /* create the helpdir subkey */
731 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
732 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
733 {
734 BSTR freeHelpDir = NULL;
735 OLECHAR* pIndexStr;
736
737 /* if we created a new key, and helpDir was null, set the helpdir
738 to the directory which contains the typelib. However,
739 if we just opened an existing key, we leave the helpdir alone */
740 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
741 szHelpDir = freeHelpDir = SysAllocString(szFullPath);
742 pIndexStr = wcsrchr(szHelpDir, '\\');
743 if (pIndexStr) {
744 *pIndexStr = 0;
745 }
746 }
747
748 /* if we have an szHelpDir, set it! */
749 if (szHelpDir != NULL) {
750 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
751 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
752 res = E_FAIL;
753 }
754 }
755
756 SysFreeString(freeHelpDir);
757 RegCloseKey(subKey);
758 } else {
759 res = E_FAIL;
760 }
761
762 RegCloseKey(key);
763 }
764 else
765 res = E_FAIL;
766
767 /* register OLE Automation-compatible interfaces for this typelib */
768 types = ITypeLib_GetTypeInfoCount(ptlib);
769 for (tidx=0; tidx<types; tidx++) {
770 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
771 LPOLESTR name = NULL;
772 ITypeInfo *tinfo = NULL;
773
774 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
775
776 switch (kind) {
777 case TKIND_INTERFACE:
778 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
779 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
780 break;
781
782 case TKIND_DISPATCH:
783 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
784 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
785 break;
786
787 default:
788 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
789 break;
790 }
791
792 if (tinfo) {
793 TYPEATTR *tattr = NULL;
794 ITypeInfo_GetTypeAttr(tinfo, &tattr);
795
796 if (tattr) {
797 TRACE_(typelib)("guid=%s, flags=%04x (",
798 debugstr_guid(&tattr->guid),
799 tattr->wTypeFlags);
800
801 if (TRACE_ON(typelib)) {
802 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
803 XX(FAPPOBJECT);
804 XX(FCANCREATE);
805 XX(FLICENSED);
806 XX(FPREDECLID);
807 XX(FHIDDEN);
808 XX(FCONTROL);
809 XX(FDUAL);
810 XX(FNONEXTENSIBLE);
811 XX(FOLEAUTOMATION);
812 XX(FRESTRICTED);
813 XX(FAGGREGATABLE);
814 XX(FREPLACEABLE);
815 XX(FDISPATCHABLE);
816 XX(FREVERSEBIND);
817 XX(FPROXY);
818 #undef XX
819 MESSAGE("\n");
820 }
821
822 /* Register all dispinterfaces (which includes dual interfaces) and
823 oleautomation interfaces */
824 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
825 kind == TKIND_DISPATCH)
826 {
827 BOOL is_wow64;
828 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
829
830 /* register interface<->typelib coupling */
831 TLB_register_interface(attr, name, tattr, 0);
832
833 /* register TLBs into the opposite registry view, too */
834 if(opposite == KEY_WOW64_32KEY ||
835 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
836 TLB_register_interface(attr, name, tattr, opposite);
837 }
838
839 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
840 }
841
842 ITypeInfo_Release(tinfo);
843 }
844
845 SysFreeString(name);
846 }
847 }
848
849 ITypeLib_ReleaseTLibAttr(ptlib, attr);
850
851 return res;
852 }
853
TLB_unregister_interface(GUID * guid,REGSAM flag)854 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
855 {
856 WCHAR subKeyName[50];
857 HKEY subKey;
858
859 /* the path to the type */
860 get_interface_key( guid, subKeyName );
861
862 /* Delete its bits */
863 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
864 return;
865
866 RegDeleteKeyW(subKey, ProxyStubClsidW);
867 RegDeleteKeyW(subKey, ProxyStubClsid32W);
868 RegDeleteKeyW(subKey, TypeLibW);
869 RegCloseKey(subKey);
870 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
871 }
872
873 /******************************************************************************
874 * UnRegisterTypeLib [OLEAUT32.186]
875 * Removes information about a type library from the System Registry
876 * NOTES
877 *
878 * RETURNS
879 * Success: S_OK
880 * Failure: Status
881 */
UnRegisterTypeLib(REFGUID libid,WORD wVerMajor,WORD wVerMinor,LCID lcid,SYSKIND syskind)882 HRESULT WINAPI UnRegisterTypeLib(
883 REFGUID libid, /* [in] Guid of the library */
884 WORD wVerMajor, /* [in] major version */
885 WORD wVerMinor, /* [in] minor version */
886 LCID lcid, /* [in] locale id */
887 SYSKIND syskind)
888 {
889 BSTR tlibPath = NULL;
890 DWORD tmpLength;
891 WCHAR keyName[60];
892 WCHAR subKeyName[50];
893 int result = S_OK;
894 DWORD i = 0;
895 BOOL deleteOtherStuff;
896 HKEY key = NULL;
897 TYPEATTR* typeAttr = NULL;
898 TYPEKIND kind;
899 ITypeInfo* typeInfo = NULL;
900 ITypeLib* typeLib = NULL;
901 int numTypes;
902
903 TRACE("(IID: %s)\n",debugstr_guid(libid));
904
905 /* Create the path to the key */
906 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
907
908 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
909 {
910 TRACE("Unsupported syskind %i\n", syskind);
911 result = E_INVALIDARG;
912 goto end;
913 }
914
915 /* get the path to the typelib on disk */
916 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
917 result = E_INVALIDARG;
918 goto end;
919 }
920
921 /* Try and open the key to the type library. */
922 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
923 result = E_INVALIDARG;
924 goto end;
925 }
926
927 /* Try and load the type library */
928 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
929 result = TYPE_E_INVALIDSTATE;
930 goto end;
931 }
932
933 /* remove any types registered with this typelib */
934 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
935 for (i=0; i<numTypes; i++) {
936 /* get the kind of type */
937 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
938 goto enddeleteloop;
939 }
940
941 /* skip non-interfaces, and get type info for the type */
942 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
943 goto enddeleteloop;
944 }
945 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
946 goto enddeleteloop;
947 }
948 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
949 goto enddeleteloop;
950 }
951
952 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
953 kind == TKIND_DISPATCH)
954 {
955 BOOL is_wow64;
956 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
957
958 TLB_unregister_interface(&typeAttr->guid, 0);
959
960 /* unregister TLBs into the opposite registry view, too */
961 if(opposite == KEY_WOW64_32KEY ||
962 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
963 TLB_unregister_interface(&typeAttr->guid, opposite);
964 }
965 }
966
967 enddeleteloop:
968 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
969 typeAttr = NULL;
970 if (typeInfo) ITypeInfo_Release(typeInfo);
971 typeInfo = NULL;
972 }
973
974 /* Now, delete the type library path subkey */
975 get_lcid_subkey( lcid, syskind, subKeyName );
976 RegDeleteKeyW(key, subKeyName);
977 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
978 RegDeleteKeyW(key, subKeyName);
979
980 /* check if there is anything besides the FLAGS/HELPDIR keys.
981 If there is, we don't delete them */
982 tmpLength = ARRAY_SIZE(subKeyName);
983 deleteOtherStuff = TRUE;
984 i = 0;
985 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
986 tmpLength = ARRAY_SIZE(subKeyName);
987
988 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
989 if (!wcscmp(subKeyName, FLAGSW)) continue;
990 if (!wcscmp(subKeyName, HELPDIRW)) continue;
991 deleteOtherStuff = FALSE;
992 break;
993 }
994
995 /* only delete the other parts of the key if we're absolutely sure */
996 if (deleteOtherStuff) {
997 RegDeleteKeyW(key, FLAGSW);
998 RegDeleteKeyW(key, HELPDIRW);
999 RegCloseKey(key);
1000 key = NULL;
1001
1002 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1003 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
1004 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1005 }
1006
1007 end:
1008 SysFreeString(tlibPath);
1009 if (typeLib) ITypeLib_Release(typeLib);
1010 if (key) RegCloseKey(key);
1011 return result;
1012 }
1013
1014 /******************************************************************************
1015 * RegisterTypeLibForUser [OLEAUT32.442]
1016 * Adds information about a type library to the user registry
1017 * NOTES
1018 * Docs: ITypeLib FAR * ptlib
1019 * Docs: OLECHAR FAR* szFullPath
1020 * Docs: OLECHAR FAR* szHelpDir
1021 *
1022 * RETURNS
1023 * Success: S_OK
1024 * Failure: Status
1025 */
RegisterTypeLibForUser(ITypeLib * ptlib,OLECHAR * szFullPath,OLECHAR * szHelpDir)1026 HRESULT WINAPI RegisterTypeLibForUser(
1027 ITypeLib * ptlib, /* [in] Pointer to the library*/
1028 OLECHAR * szFullPath, /* [in] full Path of the library*/
1029 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1030 may be NULL*/
1031 {
1032 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1033 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1034 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1035 }
1036
1037 /******************************************************************************
1038 * UnRegisterTypeLibForUser [OLEAUT32.443]
1039 * Removes information about a type library from the user registry
1040 *
1041 * RETURNS
1042 * Success: S_OK
1043 * Failure: Status
1044 */
UnRegisterTypeLibForUser(REFGUID libid,WORD wVerMajor,WORD wVerMinor,LCID lcid,SYSKIND syskind)1045 HRESULT WINAPI UnRegisterTypeLibForUser(
1046 REFGUID libid, /* [in] GUID of the library */
1047 WORD wVerMajor, /* [in] major version */
1048 WORD wVerMinor, /* [in] minor version */
1049 LCID lcid, /* [in] locale id */
1050 SYSKIND syskind)
1051 {
1052 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1053 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1054 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1055 }
1056
1057 /*======================= ITypeLib implementation =======================*/
1058
1059 typedef struct tagTLBGuid {
1060 GUID guid;
1061 INT hreftype;
1062 UINT offset;
1063 struct list entry;
1064 } TLBGuid;
1065
1066 typedef struct tagTLBCustData
1067 {
1068 TLBGuid *guid;
1069 VARIANT data;
1070 struct list entry;
1071 } TLBCustData;
1072
1073 /* data structure for import typelibs */
1074 typedef struct tagTLBImpLib
1075 {
1076 int offset; /* offset in the file (MSFT)
1077 offset in nametable (SLTG)
1078 just used to identify library while reading
1079 data from file */
1080 TLBGuid *guid; /* libid */
1081 BSTR name; /* name */
1082
1083 LCID lcid; /* lcid of imported typelib */
1084
1085 WORD wVersionMajor; /* major version number */
1086 WORD wVersionMinor; /* minor version number */
1087
1088 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1089 NULL if not yet loaded */
1090 struct list entry;
1091 } TLBImpLib;
1092
1093 typedef struct tagTLBString {
1094 BSTR str;
1095 UINT offset;
1096 struct list entry;
1097 } TLBString;
1098
1099 /* internal ITypeLib data */
1100 typedef struct tagITypeLibImpl
1101 {
1102 ITypeLib2 ITypeLib2_iface;
1103 ITypeComp ITypeComp_iface;
1104 ICreateTypeLib2 ICreateTypeLib2_iface;
1105 LONG ref;
1106 TLBGuid *guid;
1107 LCID lcid;
1108 SYSKIND syskind;
1109 int ptr_size;
1110 WORD ver_major;
1111 WORD ver_minor;
1112 WORD libflags;
1113 LCID set_lcid;
1114
1115 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1116 * exported to the application as a UNICODE string.
1117 */
1118 struct list string_list;
1119 struct list name_list;
1120 struct list guid_list;
1121
1122 const TLBString *Name;
1123 const TLBString *DocString;
1124 const TLBString *HelpFile;
1125 const TLBString *HelpStringDll;
1126 DWORD dwHelpContext;
1127 int TypeInfoCount; /* nr of typeinfo's in librarry */
1128 struct tagITypeInfoImpl **typeinfos;
1129 struct list custdata_list;
1130 struct list implib_list;
1131 int ctTypeDesc; /* number of items in type desc array */
1132 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1133 library. Only used while reading MSFT
1134 typelibs */
1135 struct list ref_list; /* list of ref types in this typelib */
1136 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1137
1138
1139 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1140 struct list entry;
1141 WCHAR *path;
1142 INT index;
1143 } ITypeLibImpl;
1144
1145 static const ITypeLib2Vtbl tlbvt;
1146 static const ITypeCompVtbl tlbtcvt;
1147 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1148
impl_from_ITypeLib2(ITypeLib2 * iface)1149 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1150 {
1151 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1152 }
1153
impl_from_ITypeLib(ITypeLib * iface)1154 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1155 {
1156 return impl_from_ITypeLib2((ITypeLib2*)iface);
1157 }
1158
impl_from_ITypeComp(ITypeComp * iface)1159 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1160 {
1161 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1162 }
1163
impl_from_ICreateTypeLib2(ICreateTypeLib2 * iface)1164 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1165 {
1166 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1167 }
1168
1169 /* ITypeLib methods */
1170 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1171 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1172
1173 /*======================= ITypeInfo implementation =======================*/
1174
1175 /* data for referenced types */
1176 typedef struct tagTLBRefType
1177 {
1178 INT index; /* Type index for internal ref or for external ref
1179 it the format is SLTG. -2 indicates to
1180 use guid */
1181
1182 TYPEKIND tkind;
1183 TLBGuid *guid; /* guid of the referenced type */
1184 /* if index == TLB_REF_USE_GUID */
1185
1186 HREFTYPE reference; /* The href of this ref */
1187 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1188 TLB_REF_INTERNAL for internal refs
1189 TLB_REF_NOT_FOUND for broken refs */
1190
1191 struct list entry;
1192 } TLBRefType;
1193
1194 #define TLB_REF_USE_GUID -2
1195
1196 #define TLB_REF_INTERNAL (void*)-2
1197 #define TLB_REF_NOT_FOUND (void*)-1
1198
1199 /* internal Parameter data */
1200 typedef struct tagTLBParDesc
1201 {
1202 const TLBString *Name;
1203 struct list custdata_list;
1204 } TLBParDesc;
1205
1206 /* internal Function data */
1207 typedef struct tagTLBFuncDesc
1208 {
1209 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1210 const TLBString *Name; /* the name of this function */
1211 TLBParDesc *pParamDesc; /* array with param names and custom data */
1212 int helpcontext;
1213 int HelpStringContext;
1214 const TLBString *HelpString;
1215 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1216 struct list custdata_list;
1217 } TLBFuncDesc;
1218
1219 /* internal Variable data */
1220 typedef struct tagTLBVarDesc
1221 {
1222 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1223 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1224 const TLBString *Name; /* the name of this variable */
1225 int HelpContext;
1226 int HelpStringContext;
1227 const TLBString *HelpString;
1228 struct list custdata_list;
1229 } TLBVarDesc;
1230
1231 /* internal implemented interface data */
1232 typedef struct tagTLBImplType
1233 {
1234 HREFTYPE hRef; /* hRef of interface */
1235 int implflags; /* IMPLFLAG_*s */
1236 struct list custdata_list;
1237 } TLBImplType;
1238
1239 /* internal TypeInfo data */
1240 typedef struct tagITypeInfoImpl
1241 {
1242 ITypeInfo2 ITypeInfo2_iface;
1243 ITypeComp ITypeComp_iface;
1244 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1245 LONG ref;
1246 BOOL not_attached_to_typelib;
1247 BOOL needs_layout;
1248
1249 TLBGuid *guid;
1250 TYPEATTR typeattr;
1251 TYPEDESC *tdescAlias;
1252
1253 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1254 int index; /* index in this typelib; */
1255 HREFTYPE hreftype; /* hreftype for app object binding */
1256 /* type libs seem to store the doc strings in ascii
1257 * so why should we do it in unicode?
1258 */
1259 const TLBString *Name;
1260 const TLBString *DocString;
1261 const TLBString *DllName;
1262 const TLBString *Schema;
1263 DWORD dwHelpContext;
1264 DWORD dwHelpStringContext;
1265
1266 /* functions */
1267 TLBFuncDesc *funcdescs;
1268
1269 /* variables */
1270 TLBVarDesc *vardescs;
1271
1272 /* Implemented Interfaces */
1273 TLBImplType *impltypes;
1274
1275 struct list *pcustdata_list;
1276 struct list custdata_list;
1277 } ITypeInfoImpl;
1278
info_impl_from_ITypeComp(ITypeComp * iface)1279 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1280 {
1281 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1282 }
1283
impl_from_ITypeInfo2(ITypeInfo2 * iface)1284 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1285 {
1286 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1287 }
1288
impl_from_ITypeInfo(ITypeInfo * iface)1289 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1290 {
1291 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1292 }
1293
info_impl_from_ICreateTypeInfo2(ICreateTypeInfo2 * iface)1294 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1295 {
1296 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1297 }
1298
1299 static const ITypeInfo2Vtbl tinfvt;
1300 static const ITypeCompVtbl tcompvt;
1301 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1302
1303 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1304 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1305
1306 typedef struct tagTLBContext
1307 {
1308 unsigned int oStart; /* start of TLB in file */
1309 unsigned int pos; /* current pos */
1310 unsigned int length; /* total length */
1311 void *mapping; /* memory mapping */
1312 MSFT_SegDir * pTblDir;
1313 ITypeLibImpl* pLibInfo;
1314 } TLBContext;
1315
1316
TLB_get_bstr(const TLBString * str)1317 static inline BSTR TLB_get_bstr(const TLBString *str)
1318 {
1319 return str != NULL ? str->str : NULL;
1320 }
1321
TLB_str_memcmp(void * left,const TLBString * str,DWORD len)1322 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1323 {
1324 if(!str)
1325 return 1;
1326 return memcmp(left, str->str, len);
1327 }
1328
TLB_get_guidref(const TLBGuid * guid)1329 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1330 {
1331 return guid != NULL ? &guid->guid : NULL;
1332 }
1333
TLB_get_guid_null(const TLBGuid * guid)1334 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1335 {
1336 return guid != NULL ? &guid->guid : &GUID_NULL;
1337 }
1338
get_ptr_size(SYSKIND syskind)1339 static int get_ptr_size(SYSKIND syskind)
1340 {
1341 switch(syskind){
1342 case SYS_WIN64:
1343 return 8;
1344 case SYS_WIN32:
1345 case SYS_MAC:
1346 case SYS_WIN16:
1347 return 4;
1348 }
1349 WARN("Unhandled syskind: 0x%x\n", syskind);
1350 return 4;
1351 }
1352
1353 /*
1354 debug
1355 */
dump_TypeDesc(const TYPEDESC * pTD,char * szVarType)1356 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1357 if (pTD->vt & VT_RESERVED)
1358 szVarType += strlen(strcpy(szVarType, "reserved | "));
1359 if (pTD->vt & VT_BYREF)
1360 szVarType += strlen(strcpy(szVarType, "ref to "));
1361 if (pTD->vt & VT_ARRAY)
1362 szVarType += strlen(strcpy(szVarType, "array of "));
1363 if (pTD->vt & VT_VECTOR)
1364 szVarType += strlen(strcpy(szVarType, "vector of "));
1365 switch(pTD->vt & VT_TYPEMASK) {
1366 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1367 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1368 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1369 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1370 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1371 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1372 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1373 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1374 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1375 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1376 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1377 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1378 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1379 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1380 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1381 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1382 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1383 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1384 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1385 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1386 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1387 pTD->u.hreftype); break;
1388 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1389 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1390 case VT_PTR: sprintf(szVarType, "ptr to ");
1391 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1392 break;
1393 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1394 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1395 break;
1396 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1397 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1398 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1399 break;
1400
1401 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1402 }
1403 }
1404
dump_ELEMDESC(const ELEMDESC * edesc)1405 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1406 char buf[200];
1407 USHORT flags = edesc->u.paramdesc.wParamFlags;
1408 dump_TypeDesc(&edesc->tdesc,buf);
1409 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1410 MESSAGE("\t\tu.paramdesc.wParamFlags");
1411 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1412 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1413 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1414 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1415 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1416 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1417 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1418 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1419 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1420 }
dump_FUNCDESC(const FUNCDESC * funcdesc)1421 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1422 int i;
1423 MESSAGE("memid is %08x\n",funcdesc->memid);
1424 for (i=0;i<funcdesc->cParams;i++) {
1425 MESSAGE("Param %d:\n",i);
1426 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1427 }
1428 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1429 switch (funcdesc->funckind) {
1430 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1431 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1432 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1433 case FUNC_STATIC: MESSAGE("static");break;
1434 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1435 default: MESSAGE("unknown");break;
1436 }
1437 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1438 switch (funcdesc->invkind) {
1439 case INVOKE_FUNC: MESSAGE("func");break;
1440 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1441 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1442 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1443 }
1444 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1445 switch (funcdesc->callconv) {
1446 case CC_CDECL: MESSAGE("cdecl");break;
1447 case CC_PASCAL: MESSAGE("pascal");break;
1448 case CC_STDCALL: MESSAGE("stdcall");break;
1449 case CC_SYSCALL: MESSAGE("syscall");break;
1450 default:break;
1451 }
1452 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1453 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1454 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1455
1456 MESSAGE("\telemdescFunc (return value type):\n");
1457 dump_ELEMDESC(&funcdesc->elemdescFunc);
1458 }
1459
1460 static const char * const typekind_desc[] =
1461 {
1462 "TKIND_ENUM",
1463 "TKIND_RECORD",
1464 "TKIND_MODULE",
1465 "TKIND_INTERFACE",
1466 "TKIND_DISPATCH",
1467 "TKIND_COCLASS",
1468 "TKIND_ALIAS",
1469 "TKIND_UNION",
1470 "TKIND_MAX"
1471 };
1472
dump_TLBFuncDescOne(const TLBFuncDesc * pfd)1473 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1474 {
1475 int i;
1476 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1477 for (i=0;i<pfd->funcdesc.cParams;i++)
1478 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1479
1480
1481 dump_FUNCDESC(&(pfd->funcdesc));
1482
1483 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1484 if(pfd->Entry == NULL)
1485 MESSAGE("\tentry: (null)\n");
1486 else if(pfd->Entry == (void*)-1)
1487 MESSAGE("\tentry: invalid\n");
1488 else if(IS_INTRESOURCE(pfd->Entry))
1489 MESSAGE("\tentry: %p\n", pfd->Entry);
1490 else
1491 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1492 }
dump_TLBFuncDesc(const TLBFuncDesc * pfd,UINT n)1493 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1494 {
1495 while (n)
1496 {
1497 dump_TLBFuncDescOne(pfd);
1498 ++pfd;
1499 --n;
1500 }
1501 }
dump_TLBVarDesc(const TLBVarDesc * pvd,UINT n)1502 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1503 {
1504 while (n)
1505 {
1506 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1507 ++pvd;
1508 --n;
1509 }
1510 }
1511
dump_TLBImpLib(const TLBImpLib * import)1512 static void dump_TLBImpLib(const TLBImpLib *import)
1513 {
1514 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1515 debugstr_w(import->name));
1516 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1517 import->wVersionMinor, import->lcid, import->offset);
1518 }
1519
dump_TLBRefType(const ITypeLibImpl * pTL)1520 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1521 {
1522 TLBRefType *ref;
1523
1524 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1525 {
1526 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1527 if(ref->index == -1)
1528 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1529 else
1530 TRACE_(typelib)("type no: %d\n", ref->index);
1531
1532 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1533 {
1534 TRACE_(typelib)("in lib\n");
1535 dump_TLBImpLib(ref->pImpTLInfo);
1536 }
1537 }
1538 }
1539
dump_TLBImplType(const TLBImplType * impl,UINT n)1540 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1541 {
1542 if(!impl)
1543 return;
1544 while (n) {
1545 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1546 impl->hRef, impl->implflags);
1547 ++impl;
1548 --n;
1549 }
1550 }
1551
dump_DispParms(const DISPPARAMS * pdp)1552 static void dump_DispParms(const DISPPARAMS * pdp)
1553 {
1554 unsigned int index;
1555
1556 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1557
1558 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1559 {
1560 TRACE("named args:\n");
1561 for (index = 0; index < pdp->cNamedArgs; index++)
1562 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1563 }
1564
1565 if (pdp->cArgs && pdp->rgvarg)
1566 {
1567 TRACE("args:\n");
1568 for (index = 0; index < pdp->cArgs; index++)
1569 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1570 }
1571 }
1572
dump_TypeInfo(const ITypeInfoImpl * pty)1573 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1574 {
1575 TRACE("%p ref=%u\n", pty, pty->ref);
1576 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1577 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1578 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1579 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1580 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1581 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1582 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1583 if (TRACE_ON(ole))
1584 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1585 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1586 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1587 }
1588
dump_VARDESC(const VARDESC * v)1589 static void dump_VARDESC(const VARDESC *v)
1590 {
1591 MESSAGE("memid %d\n",v->memid);
1592 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1593 MESSAGE("oInst %d\n",v->u.oInst);
1594 dump_ELEMDESC(&(v->elemdescVar));
1595 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1596 MESSAGE("varkind %d\n",v->varkind);
1597 }
1598
1599 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1600 {
1601 /* VT_LPWSTR is largest type that, may appear in type description */
1602 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1603 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1604 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1605 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1606 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1607 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1608 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1609 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1610 };
1611
TLB_abort(void)1612 static void TLB_abort(void)
1613 {
1614 DebugBreak();
1615 }
1616
1617 /* returns the size required for a deep copy of a typedesc into a
1618 * flat buffer */
TLB_SizeTypeDesc(const TYPEDESC * tdesc,BOOL alloc_initial_space)1619 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1620 {
1621 SIZE_T size = 0;
1622
1623 if (alloc_initial_space)
1624 size += sizeof(TYPEDESC);
1625
1626 switch (tdesc->vt)
1627 {
1628 case VT_PTR:
1629 case VT_SAFEARRAY:
1630 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1631 break;
1632 case VT_CARRAY:
1633 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1634 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1635 break;
1636 }
1637 return size;
1638 }
1639
1640 /* deep copy a typedesc into a flat buffer */
TLB_CopyTypeDesc(TYPEDESC * dest,const TYPEDESC * src,void * buffer)1641 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1642 {
1643 if (!dest)
1644 {
1645 dest = buffer;
1646 buffer = (char *)buffer + sizeof(TYPEDESC);
1647 }
1648
1649 *dest = *src;
1650
1651 switch (src->vt)
1652 {
1653 case VT_PTR:
1654 case VT_SAFEARRAY:
1655 dest->u.lptdesc = buffer;
1656 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1657 break;
1658 case VT_CARRAY:
1659 dest->u.lpadesc = buffer;
1660 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1661 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1662 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1663 break;
1664 }
1665 return buffer;
1666 }
1667
1668 /* free custom data allocated by MSFT_CustData */
TLB_FreeCustData(struct list * custdata_list)1669 static inline void TLB_FreeCustData(struct list *custdata_list)
1670 {
1671 TLBCustData *cd, *cdn;
1672 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1673 {
1674 list_remove(&cd->entry);
1675 VariantClear(&cd->data);
1676 heap_free(cd);
1677 }
1678 }
1679
TLB_MultiByteToBSTR(const char * ptr)1680 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1681 {
1682 DWORD len;
1683 BSTR ret;
1684
1685 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1686 ret = SysAllocStringLen(NULL, len - 1);
1687 if (!ret) return ret;
1688 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1689 return ret;
1690 }
1691
TLB_get_funcdesc_by_memberid(TLBFuncDesc * funcdescs,UINT n,MEMBERID memid)1692 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1693 UINT n, MEMBERID memid)
1694 {
1695 while(n){
1696 if(funcdescs->funcdesc.memid == memid)
1697 return funcdescs;
1698 ++funcdescs;
1699 --n;
1700 }
1701 return NULL;
1702 }
1703
TLB_get_vardesc_by_memberid(TLBVarDesc * vardescs,UINT n,MEMBERID memid)1704 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1705 UINT n, MEMBERID memid)
1706 {
1707 while(n){
1708 if(vardescs->vardesc.memid == memid)
1709 return vardescs;
1710 ++vardescs;
1711 --n;
1712 }
1713 return NULL;
1714 }
1715
TLB_get_vardesc_by_name(TLBVarDesc * vardescs,UINT n,const OLECHAR * name)1716 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1717 UINT n, const OLECHAR *name)
1718 {
1719 while(n){
1720 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1721 return vardescs;
1722 ++vardescs;
1723 --n;
1724 }
1725 return NULL;
1726 }
1727
TLB_get_custdata_by_guid(struct list * custdata_list,REFGUID guid)1728 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1729 {
1730 TLBCustData *cust_data;
1731 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1732 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1733 return cust_data;
1734 return NULL;
1735 }
1736
TLB_get_typeinfo_by_name(ITypeInfoImpl ** typeinfos,UINT n,const OLECHAR * name)1737 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1738 UINT n, const OLECHAR *name)
1739 {
1740 while(n){
1741 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1742 return *typeinfos;
1743 ++typeinfos;
1744 --n;
1745 }
1746 return NULL;
1747 }
1748
TLBVarDesc_Constructor(TLBVarDesc * var_desc)1749 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1750 {
1751 list_init(&var_desc->custdata_list);
1752 }
1753
TLBVarDesc_Alloc(UINT n)1754 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1755 {
1756 TLBVarDesc *ret;
1757
1758 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1759 if(!ret)
1760 return NULL;
1761
1762 while(n){
1763 TLBVarDesc_Constructor(&ret[n-1]);
1764 --n;
1765 }
1766
1767 return ret;
1768 }
1769
TLBParDesc_Constructor(UINT n)1770 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1771 {
1772 TLBParDesc *ret;
1773
1774 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1775 if(!ret)
1776 return NULL;
1777
1778 while(n){
1779 list_init(&ret[n-1].custdata_list);
1780 --n;
1781 }
1782
1783 return ret;
1784 }
1785
TLBFuncDesc_Constructor(TLBFuncDesc * func_desc)1786 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1787 {
1788 list_init(&func_desc->custdata_list);
1789 }
1790
TLBFuncDesc_Alloc(UINT n)1791 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1792 {
1793 TLBFuncDesc *ret;
1794
1795 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1796 if(!ret)
1797 return NULL;
1798
1799 while(n){
1800 TLBFuncDesc_Constructor(&ret[n-1]);
1801 --n;
1802 }
1803
1804 return ret;
1805 }
1806
TLBImplType_Constructor(TLBImplType * impl)1807 static void TLBImplType_Constructor(TLBImplType *impl)
1808 {
1809 list_init(&impl->custdata_list);
1810 }
1811
TLBImplType_Alloc(UINT n)1812 static TLBImplType *TLBImplType_Alloc(UINT n)
1813 {
1814 TLBImplType *ret;
1815
1816 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1817 if(!ret)
1818 return NULL;
1819
1820 while(n){
1821 TLBImplType_Constructor(&ret[n-1]);
1822 --n;
1823 }
1824
1825 return ret;
1826 }
1827
TLB_append_guid(struct list * guid_list,const GUID * new_guid,HREFTYPE hreftype)1828 static TLBGuid *TLB_append_guid(struct list *guid_list,
1829 const GUID *new_guid, HREFTYPE hreftype)
1830 {
1831 TLBGuid *guid;
1832
1833 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1834 if (IsEqualGUID(&guid->guid, new_guid))
1835 return guid;
1836 }
1837
1838 guid = heap_alloc(sizeof(TLBGuid));
1839 if (!guid)
1840 return NULL;
1841
1842 memcpy(&guid->guid, new_guid, sizeof(GUID));
1843 guid->hreftype = hreftype;
1844
1845 list_add_tail(guid_list, &guid->entry);
1846
1847 return guid;
1848 }
1849
TLB_set_custdata(struct list * custdata_list,TLBGuid * tlbguid,VARIANT * var)1850 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1851 {
1852 TLBCustData *cust_data;
1853
1854 switch(V_VT(var)){
1855 case VT_I4:
1856 case VT_R4:
1857 case VT_UI4:
1858 case VT_INT:
1859 case VT_UINT:
1860 case VT_HRESULT:
1861 case VT_BSTR:
1862 break;
1863 default:
1864 return DISP_E_BADVARTYPE;
1865 }
1866
1867 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1868
1869 if (!cust_data) {
1870 cust_data = heap_alloc(sizeof(TLBCustData));
1871 if (!cust_data)
1872 return E_OUTOFMEMORY;
1873
1874 cust_data->guid = tlbguid;
1875 VariantInit(&cust_data->data);
1876
1877 list_add_tail(custdata_list, &cust_data->entry);
1878 }else
1879 VariantClear(&cust_data->data);
1880
1881 return VariantCopy(&cust_data->data, var);
1882 }
1883
TLB_append_str(struct list * string_list,BSTR new_str)1884 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1885 {
1886 TLBString *str;
1887
1888 if(!new_str)
1889 return NULL;
1890
1891 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1892 if (wcscmp(str->str, new_str) == 0)
1893 return str;
1894 }
1895
1896 str = heap_alloc(sizeof(TLBString));
1897 if (!str)
1898 return NULL;
1899
1900 str->str = SysAllocString(new_str);
1901 if (!str->str) {
1902 heap_free(str);
1903 return NULL;
1904 }
1905
1906 list_add_tail(string_list, &str->entry);
1907
1908 return str;
1909 }
1910
TLB_get_size_from_hreftype(ITypeInfoImpl * info,HREFTYPE href,ULONG * size,WORD * align)1911 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1912 ULONG *size, WORD *align)
1913 {
1914 ITypeInfo *other;
1915 TYPEATTR *attr;
1916 HRESULT hr;
1917
1918 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1919 if(FAILED(hr))
1920 return hr;
1921
1922 hr = ITypeInfo_GetTypeAttr(other, &attr);
1923 if(FAILED(hr)){
1924 ITypeInfo_Release(other);
1925 return hr;
1926 }
1927
1928 if(size)
1929 *size = attr->cbSizeInstance;
1930 if(align)
1931 *align = attr->cbAlignment;
1932
1933 ITypeInfo_ReleaseTypeAttr(other, attr);
1934 ITypeInfo_Release(other);
1935
1936 return S_OK;
1937 }
1938
TLB_size_instance(ITypeInfoImpl * info,SYSKIND sys,TYPEDESC * tdesc,ULONG * size,WORD * align)1939 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1940 TYPEDESC *tdesc, ULONG *size, WORD *align)
1941 {
1942 ULONG i, sub, ptr_size;
1943 HRESULT hr;
1944
1945 ptr_size = get_ptr_size(sys);
1946
1947 switch(tdesc->vt){
1948 case VT_VOID:
1949 *size = 0;
1950 break;
1951 case VT_I1:
1952 case VT_UI1:
1953 *size = 1;
1954 break;
1955 case VT_I2:
1956 case VT_BOOL:
1957 case VT_UI2:
1958 *size = 2;
1959 break;
1960 case VT_I4:
1961 case VT_R4:
1962 case VT_ERROR:
1963 case VT_UI4:
1964 case VT_INT:
1965 case VT_UINT:
1966 case VT_HRESULT:
1967 *size = 4;
1968 break;
1969 case VT_R8:
1970 case VT_I8:
1971 case VT_UI8:
1972 *size = 8;
1973 break;
1974 case VT_BSTR:
1975 case VT_DISPATCH:
1976 case VT_UNKNOWN:
1977 case VT_PTR:
1978 case VT_SAFEARRAY:
1979 case VT_LPSTR:
1980 case VT_LPWSTR:
1981 *size = ptr_size;
1982 break;
1983 case VT_DATE:
1984 *size = sizeof(DATE);
1985 break;
1986 case VT_VARIANT:
1987 *size = sizeof(VARIANT);
1988 #ifdef _WIN64
1989 if(sys == SYS_WIN32)
1990 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1991 #endif
1992 break;
1993 case VT_DECIMAL:
1994 *size = sizeof(DECIMAL);
1995 break;
1996 case VT_CY:
1997 *size = sizeof(CY);
1998 break;
1999 case VT_CARRAY:
2000 *size = 0;
2001 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2002 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2003 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2004 if(FAILED(hr))
2005 return hr;
2006 *size *= sub;
2007 return S_OK;
2008 case VT_USERDEFINED:
2009 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2010 default:
2011 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2012 return E_FAIL;
2013 }
2014
2015 if(align){
2016 if(*size < 4)
2017 *align = *size;
2018 else
2019 *align = 4;
2020 }
2021
2022 return S_OK;
2023 }
2024
2025 /**********************************************************************
2026 *
2027 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2028 */
2029
MSFT_Seek(TLBContext * pcx,LONG where)2030 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2031 {
2032 if (where != DO_NOT_SEEK)
2033 {
2034 where += pcx->oStart;
2035 if (where > pcx->length)
2036 {
2037 /* FIXME */
2038 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2039 TLB_abort();
2040 }
2041 pcx->pos = where;
2042 }
2043 }
2044
2045 /* read function */
MSFT_Read(void * buffer,DWORD count,TLBContext * pcx,LONG where)2046 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2047 {
2048 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2049 pcx->pos, count, pcx->oStart, pcx->length, where);
2050
2051 MSFT_Seek(pcx, where);
2052 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2053 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2054 pcx->pos += count;
2055 return count;
2056 }
2057
MSFT_ReadLEDWords(void * buffer,DWORD count,TLBContext * pcx,LONG where)2058 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2059 LONG where )
2060 {
2061 DWORD ret;
2062
2063 ret = MSFT_Read(buffer, count, pcx, where);
2064 FromLEDWords(buffer, ret);
2065
2066 return ret;
2067 }
2068
MSFT_ReadLEWords(void * buffer,DWORD count,TLBContext * pcx,LONG where)2069 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2070 LONG where )
2071 {
2072 DWORD ret;
2073
2074 ret = MSFT_Read(buffer, count, pcx, where);
2075 FromLEWords(buffer, ret);
2076
2077 return ret;
2078 }
2079
MSFT_ReadAllGuids(TLBContext * pcx)2080 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2081 {
2082 TLBGuid *guid;
2083 MSFT_GuidEntry entry;
2084 int offs = 0;
2085
2086 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2087 while (1) {
2088 if (offs >= pcx->pTblDir->pGuidTab.length)
2089 return S_OK;
2090
2091 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2092
2093 guid = heap_alloc(sizeof(TLBGuid));
2094
2095 guid->offset = offs;
2096 guid->guid = entry.guid;
2097 guid->hreftype = entry.hreftype;
2098
2099 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2100
2101 offs += sizeof(MSFT_GuidEntry);
2102 }
2103 }
2104
MSFT_ReadGuid(int offset,TLBContext * pcx)2105 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2106 {
2107 TLBGuid *ret;
2108
2109 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2110 if(ret->offset == offset){
2111 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2112 return ret;
2113 }
2114 }
2115
2116 return NULL;
2117 }
2118
MSFT_ReadHreftype(TLBContext * pcx,int offset)2119 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2120 {
2121 MSFT_NameIntro niName;
2122
2123 if (offset < 0)
2124 {
2125 ERR_(typelib)("bad offset %d\n", offset);
2126 return -1;
2127 }
2128
2129 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2130 pcx->pTblDir->pNametab.offset+offset);
2131
2132 return niName.hreftype;
2133 }
2134
MSFT_ReadAllNames(TLBContext * pcx)2135 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2136 {
2137 char *string;
2138 MSFT_NameIntro intro;
2139 INT16 len_piece;
2140 int offs = 0, lengthInChars;
2141
2142 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2143 while (1) {
2144 TLBString *tlbstr;
2145
2146 if (offs >= pcx->pTblDir->pNametab.length)
2147 return S_OK;
2148
2149 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2150 intro.namelen &= 0xFF;
2151 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2152 if(len_piece % 4)
2153 len_piece = (len_piece + 4) & ~0x3;
2154 if(len_piece < 8)
2155 len_piece = 8;
2156
2157 string = heap_alloc(len_piece + 1);
2158 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2159 string[intro.namelen] = '\0';
2160
2161 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2162 string, -1, NULL, 0);
2163 if (!lengthInChars) {
2164 heap_free(string);
2165 return E_UNEXPECTED;
2166 }
2167
2168 tlbstr = heap_alloc(sizeof(TLBString));
2169
2170 tlbstr->offset = offs;
2171 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2172 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2173
2174 heap_free(string);
2175
2176 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2177
2178 offs += len_piece;
2179 }
2180 }
2181
MSFT_ReadName(TLBContext * pcx,int offset)2182 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2183 {
2184 TLBString *tlbstr;
2185
2186 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2187 if (tlbstr->offset == offset) {
2188 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2189 return tlbstr;
2190 }
2191 }
2192
2193 return NULL;
2194 }
2195
MSFT_ReadString(TLBContext * pcx,int offset)2196 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2197 {
2198 TLBString *tlbstr;
2199
2200 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2201 if (tlbstr->offset == offset) {
2202 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2203 return tlbstr;
2204 }
2205 }
2206
2207 return NULL;
2208 }
2209
2210 /*
2211 * read a value and fill a VARIANT structure
2212 */
MSFT_ReadValue(VARIANT * pVar,int offset,TLBContext * pcx)2213 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2214 {
2215 int size;
2216
2217 TRACE_(typelib)("\n");
2218
2219 if(offset <0) { /* data are packed in here */
2220 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2221 V_I4(pVar) = offset & 0x3ffffff;
2222 return;
2223 }
2224 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2225 pcx->pTblDir->pCustData.offset + offset );
2226 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2227 switch (V_VT(pVar)){
2228 case VT_EMPTY: /* FIXME: is this right? */
2229 case VT_NULL: /* FIXME: is this right? */
2230 case VT_I2 : /* this should not happen */
2231 case VT_I4 :
2232 case VT_R4 :
2233 case VT_ERROR :
2234 case VT_BOOL :
2235 case VT_I1 :
2236 case VT_UI1 :
2237 case VT_UI2 :
2238 case VT_UI4 :
2239 case VT_INT :
2240 case VT_UINT :
2241 case VT_VOID : /* FIXME: is this right? */
2242 case VT_HRESULT :
2243 size=4; break;
2244 case VT_R8 :
2245 case VT_CY :
2246 case VT_DATE :
2247 case VT_I8 :
2248 case VT_UI8 :
2249 case VT_DECIMAL : /* FIXME: is this right? */
2250 case VT_FILETIME :
2251 size=8;break;
2252 /* pointer types with known behaviour */
2253 case VT_BSTR :{
2254 char * ptr;
2255 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2256 if(size == -1){
2257 V_BSTR(pVar) = NULL;
2258 }else{
2259 ptr = heap_alloc_zero(size);
2260 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2261 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2262 /* FIXME: do we need a AtoW conversion here? */
2263 V_UNION(pVar, bstrVal[size])='\0';
2264 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2265 heap_free(ptr);
2266 }
2267 }
2268 size=-4; break;
2269 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2270 case VT_DISPATCH :
2271 case VT_VARIANT :
2272 case VT_UNKNOWN :
2273 case VT_PTR :
2274 case VT_SAFEARRAY :
2275 case VT_CARRAY :
2276 case VT_USERDEFINED :
2277 case VT_LPSTR :
2278 case VT_LPWSTR :
2279 case VT_BLOB :
2280 case VT_STREAM :
2281 case VT_STORAGE :
2282 case VT_STREAMED_OBJECT :
2283 case VT_STORED_OBJECT :
2284 case VT_BLOB_OBJECT :
2285 case VT_CF :
2286 case VT_CLSID :
2287 default:
2288 size=0;
2289 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2290 V_VT(pVar));
2291 }
2292
2293 if(size>0) /* (big|small) endian correct? */
2294 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2295 return;
2296 }
2297 /*
2298 * create a linked list with custom data
2299 */
MSFT_CustData(TLBContext * pcx,int offset,struct list * custdata_list)2300 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2301 {
2302 MSFT_CDGuid entry;
2303 TLBCustData* pNew;
2304 int count=0;
2305
2306 TRACE_(typelib)("\n");
2307
2308 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2309
2310 while(offset >=0){
2311 count++;
2312 pNew=heap_alloc_zero(sizeof(TLBCustData));
2313 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2314 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2315 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2316 list_add_head(custdata_list, &pNew->entry);
2317 offset = entry.next;
2318 }
2319 return count;
2320 }
2321
MSFT_GetTdesc(TLBContext * pcx,INT type,TYPEDESC * pTd)2322 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2323 {
2324 if(type <0)
2325 pTd->vt=type & VT_TYPEMASK;
2326 else
2327 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2328
2329 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2330 }
2331
TLB_is_propgetput(INVOKEKIND invkind)2332 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2333 {
2334 return (invkind == INVOKE_PROPERTYGET ||
2335 invkind == INVOKE_PROPERTYPUT ||
2336 invkind == INVOKE_PROPERTYPUTREF);
2337 }
2338
2339 static void
MSFT_DoFuncs(TLBContext * pcx,ITypeInfoImpl * pTI,int cFuncs,int cVars,int offset,TLBFuncDesc ** pptfd)2340 MSFT_DoFuncs(TLBContext* pcx,
2341 ITypeInfoImpl* pTI,
2342 int cFuncs,
2343 int cVars,
2344 int offset,
2345 TLBFuncDesc** pptfd)
2346 {
2347 /*
2348 * member information is stored in a data structure at offset
2349 * indicated by the memoffset field of the typeinfo structure
2350 * There are several distinctive parts.
2351 * The first part starts with a field that holds the total length
2352 * of this (first) part excluding this field. Then follow the records,
2353 * for each member there is one record.
2354 *
2355 * The first entry is always the length of the record (including this
2356 * length word).
2357 * The rest of the record depends on the type of the member. If there is
2358 * a field indicating the member type (function, variable, interface, etc)
2359 * I have not found it yet. At this time we depend on the information
2360 * in the type info and the usual order how things are stored.
2361 *
2362 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2363 * for each member;
2364 *
2365 * Third is an equal sized array with file offsets to the name entry
2366 * of each member.
2367 *
2368 * The fourth and last (?) part is an array with offsets to the records
2369 * in the first part of this file segment.
2370 */
2371
2372 int infolen, nameoffset, reclength, i;
2373 int recoffset = offset + sizeof(INT);
2374
2375 char *recbuf = heap_alloc(0xffff);
2376 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2377 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2378
2379 TRACE_(typelib)("\n");
2380
2381 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2382
2383 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2384 ptfd = *pptfd;
2385 for ( i = 0; i < cFuncs ; i++ )
2386 {
2387 int optional;
2388
2389 /* name, eventually add to a hash table */
2390 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2391 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2392
2393 /* read the function information record */
2394 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2395
2396 reclength &= 0xffff;
2397
2398 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2399
2400 /* size without argument data */
2401 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2402 if (pFuncRec->FKCCIC & 0x1000)
2403 optional -= pFuncRec->nrargs * sizeof(INT);
2404
2405 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2406 ptfd->helpcontext = pFuncRec->HelpContext;
2407
2408 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2409 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2410
2411 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2412 {
2413 if (pFuncRec->FKCCIC & 0x2000 )
2414 {
2415 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2416 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2417 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2418 }
2419 else
2420 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2421 }
2422 else
2423 ptfd->Entry = (TLBString*)-1;
2424
2425 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2426 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2427
2428 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2429 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2430
2431 /* fill the FuncDesc Structure */
2432 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2433 offset + infolen + ( i + 1) * sizeof(INT));
2434
2435 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2436 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2437 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2438 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2439 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2440 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2441 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2442
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);
2451
2452 MSFT_GetTdesc(pcx,
2453 pFuncRec->DataType,
2454 &ptfd->funcdesc.elemdescFunc.tdesc);
2455
2456 /* do the parameters/arguments */
2457 if(pFuncRec->nrargs)
2458 {
2459 int j = 0;
2460 MSFT_ParameterInfo paraminfo;
2461
2462 ptfd->funcdesc.lprgelemdescParam =
2463 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2464
2465 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2466
2467 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2468 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2469
2470 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2471 {
2472 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2473
2474 MSFT_GetTdesc(pcx,
2475 paraminfo.DataType,
2476 &elemdesc->tdesc);
2477
2478 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2479
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)));
2485
2486 /* default value */
2487 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2488 (pFuncRec->FKCCIC & 0x1000) )
2489 {
2490 INT* pInt = (INT *)((char *)pFuncRec +
2491 reclength -
2492 (pFuncRec->nrargs * 4) * sizeof(INT) );
2493
2494 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2495
2496 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2497 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2498
2499 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2500 pInt[j], pcx);
2501 }
2502 else
2503 elemdesc->u.paramdesc.pparamdescex = NULL;
2504
2505 /* custom info */
2506 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2507 j*sizeof(pFuncRec->oArgCustData[0])) &&
2508 pFuncRec->FKCCIC & 0x80 )
2509 {
2510 MSFT_CustData(pcx,
2511 pFuncRec->oArgCustData[j],
2512 &ptfd->pParamDesc[j].custdata_list);
2513 }
2514
2515 /* SEEK value = jump to offset,
2516 * from there jump to the end of record,
2517 * go back by (j-1) arguments
2518 */
2519 MSFT_ReadLEDWords( ¶minfo ,
2520 sizeof(MSFT_ParameterInfo), pcx,
2521 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2522 * sizeof(MSFT_ParameterInfo)));
2523 }
2524 }
2525
2526 /* scode is not used: archaic win16 stuff FIXME: right? */
2527 ptfd->funcdesc.cScodes = 0 ;
2528 ptfd->funcdesc.lprgscode = NULL ;
2529
2530 ptfd_prev = ptfd;
2531 ++ptfd;
2532 recoffset += reclength;
2533 }
2534 heap_free(recbuf);
2535 }
2536
MSFT_DoVars(TLBContext * pcx,ITypeInfoImpl * pTI,int cFuncs,int cVars,int offset,TLBVarDesc ** pptvd)2537 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2538 int cVars, int offset, TLBVarDesc ** pptvd)
2539 {
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;
2546
2547 TRACE_(typelib)("\n");
2548
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);
2563
2564 /* optional data */
2565 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2566 ptvd->HelpContext = pVarRec->HelpContext;
2567
2568 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2569 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2570
2571 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2572 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2573
2574 /* fill the VarDesc Structure */
2575 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2576 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2577 ptvd->vardesc.varkind = pVarRec->VarKind;
2578 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2579 MSFT_GetTdesc(pcx, pVarRec->DataType,
2580 &ptvd->vardesc.elemdescVar.tdesc);
2581 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2582 if(pVarRec->VarKind == VAR_CONST ){
2583 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2584 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2585 pVarRec->OffsValue, pcx);
2586 } else
2587 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2588 recoffset += reclength;
2589 }
2590 }
2591
2592 /* process Implemented Interfaces of a com class */
MSFT_DoImplTypes(TLBContext * pcx,ITypeInfoImpl * pTI,int count,int offset)2593 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2594 int offset)
2595 {
2596 int i;
2597 MSFT_RefRecord refrec;
2598 TLBImplType *pImpl;
2599
2600 TRACE_(typelib)("\n");
2601
2602 pTI->impltypes = TLBImplType_Alloc(count);
2603 pImpl = pTI->impltypes;
2604 for(i=0;i<count;i++){
2605 if(offset<0) break; /* paranoia */
2606 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2607 pImpl->hRef = refrec.reftype;
2608 pImpl->implflags=refrec.flags;
2609 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2610 offset=refrec.onext;
2611 ++pImpl;
2612 }
2613 }
2614
2615 #ifdef _WIN64
2616 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2617 * and some structures, and fix the alignment */
TLB_fix_32on64_typeinfo(ITypeInfoImpl * info)2618 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2619 {
2620 if(info->typeattr.typekind == TKIND_ALIAS){
2621 switch(info->tdescAlias->vt){
2622 case VT_BSTR:
2623 case VT_DISPATCH:
2624 case VT_UNKNOWN:
2625 case VT_PTR:
2626 case VT_SAFEARRAY:
2627 case VT_LPSTR:
2628 case VT_LPWSTR:
2629 info->typeattr.cbSizeInstance = sizeof(void*);
2630 info->typeattr.cbAlignment = sizeof(void*);
2631 break;
2632 case VT_CARRAY:
2633 case VT_USERDEFINED:
2634 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2635 break;
2636 case VT_VARIANT:
2637 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2638 info->typeattr.cbAlignment = 8;
2639 default:
2640 if(info->typeattr.cbSizeInstance < sizeof(void*))
2641 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2642 else
2643 info->typeattr.cbAlignment = sizeof(void*);
2644 break;
2645 }
2646 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2647 info->typeattr.typekind == TKIND_DISPATCH ||
2648 info->typeattr.typekind == TKIND_COCLASS){
2649 info->typeattr.cbSizeInstance = sizeof(void*);
2650 info->typeattr.cbAlignment = sizeof(void*);
2651 }
2652 }
2653 #endif
2654
2655 /*
2656 * process a typeinfo record
2657 */
MSFT_DoTypeInfo(TLBContext * pcx,int count,ITypeLibImpl * pLibInfo)2658 static ITypeInfoImpl * MSFT_DoTypeInfo(
2659 TLBContext *pcx,
2660 int count,
2661 ITypeLibImpl * pLibInfo)
2662 {
2663 MSFT_TypeInfoBase tiBase;
2664 ITypeInfoImpl *ptiRet;
2665
2666 TRACE_(typelib)("count=%u\n", count);
2667
2668 ptiRet = ITypeInfoImpl_Constructor();
2669 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2670 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2671
2672 /* this is where we are coming from */
2673 ptiRet->pTypeLib = pLibInfo;
2674 ptiRet->index=count;
2675
2676 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2677 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2678 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2679 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2680 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2681 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2682 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2683 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2684 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2685 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2686 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2687 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2688 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2689 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2690 TYPEDESC tmp;
2691 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2692 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2693 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2694 }
2695
2696 /* FIXME: */
2697 /* IDLDESC idldescType; *//* never saw this one != zero */
2698
2699 /* name, eventually add to a hash table */
2700 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2701 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2702 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2703 /* help info */
2704 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2705 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2706 ptiRet->dwHelpContext=tiBase.helpcontext;
2707
2708 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2709 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2710
2711 /* note: InfoType's Help file and HelpStringDll come from the containing
2712 * library. Further HelpString and Docstring appear to be the same thing :(
2713 */
2714 /* functions */
2715 if(ptiRet->typeattr.cFuncs >0 )
2716 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2717 ptiRet->typeattr.cVars,
2718 tiBase.memoffset, &ptiRet->funcdescs);
2719 /* variables */
2720 if(ptiRet->typeattr.cVars >0 )
2721 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2722 ptiRet->typeattr.cVars,
2723 tiBase.memoffset, &ptiRet->vardescs);
2724 if(ptiRet->typeattr.cImplTypes >0 ) {
2725 switch(ptiRet->typeattr.typekind)
2726 {
2727 case TKIND_COCLASS:
2728 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2729 tiBase.datatype1);
2730 break;
2731 case TKIND_DISPATCH:
2732 /* This is not -1 when the interface is a non-base dual interface or
2733 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2734 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2735 not this interface.
2736 */
2737
2738 if (tiBase.datatype1 != -1)
2739 {
2740 ptiRet->impltypes = TLBImplType_Alloc(1);
2741 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2742 }
2743 break;
2744 default:
2745 ptiRet->impltypes = TLBImplType_Alloc(1);
2746 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2747 break;
2748 }
2749 }
2750 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2751
2752 TRACE_(typelib)("%s guid: %s kind:%s\n",
2753 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2754 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2755 typekind_desc[ptiRet->typeattr.typekind]);
2756 if (TRACE_ON(typelib))
2757 dump_TypeInfo(ptiRet);
2758
2759 return ptiRet;
2760 }
2761
MSFT_ReadAllStrings(TLBContext * pcx)2762 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2763 {
2764 char *string;
2765 INT16 len_str, len_piece;
2766 int offs = 0, lengthInChars;
2767
2768 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2769 while (1) {
2770 TLBString *tlbstr;
2771
2772 if (offs >= pcx->pTblDir->pStringtab.length)
2773 return S_OK;
2774
2775 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2776 len_piece = len_str + sizeof(INT16);
2777 if(len_piece % 4)
2778 len_piece = (len_piece + 4) & ~0x3;
2779 if(len_piece < 8)
2780 len_piece = 8;
2781
2782 string = heap_alloc(len_piece + 1);
2783 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2784 string[len_str] = '\0';
2785
2786 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2787 string, -1, NULL, 0);
2788 if (!lengthInChars) {
2789 heap_free(string);
2790 return E_UNEXPECTED;
2791 }
2792
2793 tlbstr = heap_alloc(sizeof(TLBString));
2794
2795 tlbstr->offset = offs;
2796 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2797 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2798
2799 heap_free(string);
2800
2801 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2802
2803 offs += len_piece;
2804 }
2805 }
2806
MSFT_ReadAllRefs(TLBContext * pcx)2807 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2808 {
2809 TLBRefType *ref;
2810 int offs = 0;
2811
2812 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2813 while (offs < pcx->pTblDir->pImpInfo.length) {
2814 MSFT_ImpInfo impinfo;
2815 TLBImpLib *pImpLib;
2816
2817 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2818
2819 ref = heap_alloc_zero(sizeof(TLBRefType));
2820 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2821
2822 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2823 if(pImpLib->offset==impinfo.oImpFile)
2824 break;
2825
2826 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2827 ref->reference = offs;
2828 ref->pImpTLInfo = pImpLib;
2829 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2830 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2831 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2832 ref->index = TLB_REF_USE_GUID;
2833 } else
2834 ref->index = impinfo.oGuid;
2835 }else{
2836 ERR("Cannot find a reference\n");
2837 ref->reference = -1;
2838 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2839 }
2840
2841 offs += sizeof(impinfo);
2842 }
2843
2844 return S_OK;
2845 }
2846
2847 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2848 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2849 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2850 * tradeoff here.
2851 */
2852 static struct list tlb_cache = LIST_INIT(tlb_cache);
2853 static CRITICAL_SECTION cache_section;
2854 static CRITICAL_SECTION_DEBUG cache_section_debug =
2855 {
2856 0, 0, &cache_section,
2857 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2858 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2859 };
2860 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2861
2862
2863 typedef struct TLB_PEFile
2864 {
2865 IUnknown IUnknown_iface;
2866 LONG refs;
2867 HMODULE dll;
2868 HRSRC typelib_resource;
2869 HGLOBAL typelib_global;
2870 LPVOID typelib_base;
2871 } TLB_PEFile;
2872
pefile_impl_from_IUnknown(IUnknown * iface)2873 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2874 {
2875 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2876 }
2877
TLB_PEFile_QueryInterface(IUnknown * iface,REFIID riid,void ** ppv)2878 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2879 {
2880 if (IsEqualIID(riid, &IID_IUnknown))
2881 {
2882 *ppv = iface;
2883 IUnknown_AddRef(iface);
2884 return S_OK;
2885 }
2886 *ppv = NULL;
2887 return E_NOINTERFACE;
2888 }
2889
TLB_PEFile_AddRef(IUnknown * iface)2890 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2891 {
2892 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2893 return InterlockedIncrement(&This->refs);
2894 }
2895
TLB_PEFile_Release(IUnknown * iface)2896 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2897 {
2898 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2899 ULONG refs = InterlockedDecrement(&This->refs);
2900 if (!refs)
2901 {
2902 if (This->typelib_global)
2903 FreeResource(This->typelib_global);
2904 if (This->dll)
2905 FreeLibrary(This->dll);
2906 heap_free(This);
2907 }
2908 return refs;
2909 }
2910
2911 static const IUnknownVtbl TLB_PEFile_Vtable =
2912 {
2913 TLB_PEFile_QueryInterface,
2914 TLB_PEFile_AddRef,
2915 TLB_PEFile_Release
2916 };
2917
TLB_PEFile_Open(LPCWSTR path,INT index,LPVOID * ppBase,DWORD * pdwTLBLength,IUnknown ** ppFile)2918 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2919 {
2920 TLB_PEFile *This;
2921 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2922
2923 This = heap_alloc(sizeof(TLB_PEFile));
2924 if (!This)
2925 return E_OUTOFMEMORY;
2926
2927 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2928 This->refs = 1;
2929 This->dll = NULL;
2930 This->typelib_resource = NULL;
2931 This->typelib_global = NULL;
2932 This->typelib_base = NULL;
2933
2934 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2935 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2936
2937 if (This->dll)
2938 {
2939 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2940 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2941 if (This->typelib_resource)
2942 {
2943 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2944 if (This->typelib_global)
2945 {
2946 This->typelib_base = LockResource(This->typelib_global);
2947
2948 if (This->typelib_base)
2949 {
2950 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2951 *ppBase = This->typelib_base;
2952 *ppFile = &This->IUnknown_iface;
2953 return S_OK;
2954 }
2955 }
2956 }
2957
2958 TRACE("No TYPELIB resource found\n");
2959 hr = E_FAIL;
2960 }
2961
2962 TLB_PEFile_Release(&This->IUnknown_iface);
2963 return hr;
2964 }
2965
2966 typedef struct TLB_NEFile
2967 {
2968 IUnknown IUnknown_iface;
2969 LONG refs;
2970 LPVOID typelib_base;
2971 } TLB_NEFile;
2972
nefile_impl_from_IUnknown(IUnknown * iface)2973 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2974 {
2975 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2976 }
2977
TLB_NEFile_QueryInterface(IUnknown * iface,REFIID riid,void ** ppv)2978 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2979 {
2980 if (IsEqualIID(riid, &IID_IUnknown))
2981 {
2982 *ppv = iface;
2983 IUnknown_AddRef(iface);
2984 return S_OK;
2985 }
2986 *ppv = NULL;
2987 return E_NOINTERFACE;
2988 }
2989
TLB_NEFile_AddRef(IUnknown * iface)2990 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2991 {
2992 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2993 return InterlockedIncrement(&This->refs);
2994 }
2995
TLB_NEFile_Release(IUnknown * iface)2996 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2997 {
2998 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2999 ULONG refs = InterlockedDecrement(&This->refs);
3000 if (!refs)
3001 {
3002 heap_free(This->typelib_base);
3003 heap_free(This);
3004 }
3005 return refs;
3006 }
3007
3008 static const IUnknownVtbl TLB_NEFile_Vtable =
3009 {
3010 TLB_NEFile_QueryInterface,
3011 TLB_NEFile_AddRef,
3012 TLB_NEFile_Release
3013 };
3014
3015 /***********************************************************************
3016 * read_xx_header [internal]
3017 */
read_xx_header(HFILE lzfd)3018 static int read_xx_header( HFILE lzfd )
3019 {
3020 IMAGE_DOS_HEADER mzh;
3021 char magic[3];
3022
3023 LZSeek( lzfd, 0, SEEK_SET );
3024 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3025 return 0;
3026 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3027 return 0;
3028
3029 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3030 if ( 2 != LZRead( lzfd, magic, 2 ) )
3031 return 0;
3032
3033 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3034
3035 if ( magic[0] == 'N' && magic[1] == 'E' )
3036 return IMAGE_OS2_SIGNATURE;
3037 if ( magic[0] == 'P' && magic[1] == 'E' )
3038 return IMAGE_NT_SIGNATURE;
3039
3040 magic[2] = '\0';
3041 WARN("Can't handle %s files.\n", magic );
3042 return 0;
3043 }
3044
3045
3046 /***********************************************************************
3047 * find_ne_resource [internal]
3048 */
find_ne_resource(HFILE lzfd,LPCSTR typeid,LPCSTR resid,DWORD * resLen,DWORD * resOff)3049 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3050 DWORD *resLen, DWORD *resOff )
3051 {
3052 IMAGE_OS2_HEADER nehd;
3053 NE_TYPEINFO *typeInfo;
3054 NE_NAMEINFO *nameInfo;
3055 DWORD nehdoffset;
3056 LPBYTE resTab;
3057 DWORD resTabSize;
3058 int count;
3059
3060 /* Read in NE header */
3061 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3062 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3063
3064 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3065 if ( !resTabSize )
3066 {
3067 TRACE("No resources in NE dll\n" );
3068 return FALSE;
3069 }
3070
3071 /* Read in resource table */
3072 resTab = heap_alloc( resTabSize );
3073 if ( !resTab ) return FALSE;
3074
3075 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3076 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3077 {
3078 heap_free( resTab );
3079 return FALSE;
3080 }
3081
3082 /* Find resource */
3083 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3084
3085 if (!IS_INTRESOURCE(typeid)) /* named type */
3086 {
3087 BYTE len = strlen( typeid );
3088 while (typeInfo->type_id)
3089 {
3090 if (!(typeInfo->type_id & 0x8000))
3091 {
3092 BYTE *p = resTab + typeInfo->type_id;
3093 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3094 }
3095 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3096 typeInfo->count * sizeof(NE_NAMEINFO));
3097 }
3098 }
3099 else /* numeric type id */
3100 {
3101 WORD id = LOWORD(typeid) | 0x8000;
3102 while (typeInfo->type_id)
3103 {
3104 if (typeInfo->type_id == id) goto found_type;
3105 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3106 typeInfo->count * sizeof(NE_NAMEINFO));
3107 }
3108 }
3109 TRACE("No typeid entry found for %p\n", typeid );
3110 heap_free( resTab );
3111 return FALSE;
3112
3113 found_type:
3114 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3115
3116 if (!IS_INTRESOURCE(resid)) /* named resource */
3117 {
3118 BYTE len = strlen( resid );
3119 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3120 {
3121 BYTE *p = resTab + nameInfo->id;
3122 if (nameInfo->id & 0x8000) continue;
3123 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3124 }
3125 }
3126 else /* numeric resource id */
3127 {
3128 WORD id = LOWORD(resid) | 0x8000;
3129 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3130 if (nameInfo->id == id) goto found_name;
3131 }
3132 TRACE("No resid entry found for %p\n", typeid );
3133 heap_free( resTab );
3134 return FALSE;
3135
3136 found_name:
3137 /* Return resource data */
3138 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3139 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3140
3141 heap_free( resTab );
3142 return TRUE;
3143 }
3144
TLB_NEFile_Open(LPCWSTR path,INT index,LPVOID * ppBase,DWORD * pdwTLBLength,IUnknown ** ppFile)3145 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3146
3147 HFILE lzfd = -1;
3148 OFSTRUCT ofs;
3149 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3150 TLB_NEFile *This;
3151
3152 This = heap_alloc(sizeof(TLB_NEFile));
3153 if (!This) return E_OUTOFMEMORY;
3154
3155 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3156 This->refs = 1;
3157 This->typelib_base = NULL;
3158
3159 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3160 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3161 {
3162 DWORD reslen, offset;
3163 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3164 {
3165 This->typelib_base = heap_alloc(reslen);
3166 if( !This->typelib_base )
3167 hr = E_OUTOFMEMORY;
3168 else
3169 {
3170 LZSeek( lzfd, offset, SEEK_SET );
3171 reslen = LZRead( lzfd, This->typelib_base, reslen );
3172 LZClose( lzfd );
3173 *ppBase = This->typelib_base;
3174 *pdwTLBLength = reslen;
3175 *ppFile = &This->IUnknown_iface;
3176 return S_OK;
3177 }
3178 }
3179 }
3180
3181 if( lzfd >= 0) LZClose( lzfd );
3182 TLB_NEFile_Release(&This->IUnknown_iface);
3183 return hr;
3184 }
3185
3186 typedef struct TLB_Mapping
3187 {
3188 IUnknown IUnknown_iface;
3189 LONG refs;
3190 HANDLE file;
3191 HANDLE mapping;
3192 LPVOID typelib_base;
3193 } TLB_Mapping;
3194
mapping_impl_from_IUnknown(IUnknown * iface)3195 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3196 {
3197 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3198 }
3199
TLB_Mapping_QueryInterface(IUnknown * iface,REFIID riid,void ** ppv)3200 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3201 {
3202 if (IsEqualIID(riid, &IID_IUnknown))
3203 {
3204 *ppv = iface;
3205 IUnknown_AddRef(iface);
3206 return S_OK;
3207 }
3208 *ppv = NULL;
3209 return E_NOINTERFACE;
3210 }
3211
TLB_Mapping_AddRef(IUnknown * iface)3212 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3213 {
3214 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3215 return InterlockedIncrement(&This->refs);
3216 }
3217
TLB_Mapping_Release(IUnknown * iface)3218 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3219 {
3220 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3221 ULONG refs = InterlockedDecrement(&This->refs);
3222 if (!refs)
3223 {
3224 if (This->typelib_base)
3225 UnmapViewOfFile(This->typelib_base);
3226 if (This->mapping)
3227 CloseHandle(This->mapping);
3228 if (This->file != INVALID_HANDLE_VALUE)
3229 CloseHandle(This->file);
3230 heap_free(This);
3231 }
3232 return refs;
3233 }
3234
3235 static const IUnknownVtbl TLB_Mapping_Vtable =
3236 {
3237 TLB_Mapping_QueryInterface,
3238 TLB_Mapping_AddRef,
3239 TLB_Mapping_Release
3240 };
3241
TLB_Mapping_Open(LPCWSTR path,LPVOID * ppBase,DWORD * pdwTLBLength,IUnknown ** ppFile)3242 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3243 {
3244 TLB_Mapping *This;
3245
3246 This = heap_alloc(sizeof(TLB_Mapping));
3247 if (!This)
3248 return E_OUTOFMEMORY;
3249
3250 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3251 This->refs = 1;
3252 This->file = INVALID_HANDLE_VALUE;
3253 This->mapping = NULL;
3254 This->typelib_base = NULL;
3255
3256 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3257 if (INVALID_HANDLE_VALUE != This->file)
3258 {
3259 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3260 if (This->mapping)
3261 {
3262 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3263 if(This->typelib_base)
3264 {
3265 /* retrieve file size */
3266 *pdwTLBLength = GetFileSize(This->file, NULL);
3267 *ppBase = This->typelib_base;
3268 *ppFile = &This->IUnknown_iface;
3269 return S_OK;
3270 }
3271 }
3272 }
3273
3274 IUnknown_Release(&This->IUnknown_iface);
3275 return TYPE_E_CANTLOADLIBRARY;
3276 }
3277
3278 /****************************************************************************
3279 * TLB_ReadTypeLib
3280 *
3281 * find the type of the typelib file and map the typelib resource into
3282 * the memory
3283 */
3284
3285 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
TLB_ReadTypeLib(LPCWSTR pszFileName,LPWSTR pszPath,UINT cchPath,ITypeLib2 ** ppTypeLib)3286 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3287 {
3288 ITypeLibImpl *entry;
3289 HRESULT ret;
3290 INT index = 1;
3291 LPWSTR index_str, file = (LPWSTR)pszFileName;
3292 LPVOID pBase = NULL;
3293 DWORD dwTLBLength = 0;
3294 IUnknown *pFile = NULL;
3295 HANDLE h;
3296
3297 *ppTypeLib = NULL;
3298
3299 index_str = wcsrchr(pszFileName, '\\');
3300 if(index_str && *++index_str != '\0')
3301 {
3302 LPWSTR end_ptr;
3303 LONG idx = wcstol(index_str, &end_ptr, 10);
3304 if(*end_ptr == '\0')
3305 {
3306 int str_len = index_str - pszFileName - 1;
3307 index = idx;
3308 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3309 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3310 file[str_len] = 0;
3311 }
3312 }
3313
3314 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3315 {
3316 if(wcschr(file, '\\'))
3317 {
3318 lstrcpyW(pszPath, file);
3319 }
3320 else
3321 {
3322 int len = GetSystemDirectoryW(pszPath, cchPath);
3323 pszPath[len] = '\\';
3324 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3325 }
3326 }
3327
3328 if(file != pszFileName) heap_free(file);
3329
3330 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3331 if(h != INVALID_HANDLE_VALUE){
3332 FILE_NAME_INFORMATION size_info;
3333 BOOL br;
3334
3335 /* GetFileInformationByHandleEx returns the path of the file without
3336 * WOW64 redirection */
3337 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3338 if(br || GetLastError() == ERROR_MORE_DATA){
3339 FILE_NAME_INFORMATION *info;
3340 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3341
3342 info = HeapAlloc(GetProcessHeap(), 0, size);
3343
3344 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3345 if(br){
3346 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3347 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3348 }
3349
3350 HeapFree(GetProcessHeap(), 0, info);
3351 }
3352
3353 CloseHandle(h);
3354 }
3355
3356 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3357
3358 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3359 EnterCriticalSection(&cache_section);
3360 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3361 {
3362 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3363 {
3364 TRACE("cache hit\n");
3365 *ppTypeLib = &entry->ITypeLib2_iface;
3366 ITypeLib2_AddRef(*ppTypeLib);
3367 LeaveCriticalSection(&cache_section);
3368 return S_OK;
3369 }
3370 }
3371 LeaveCriticalSection(&cache_section);
3372
3373 /* now actually load and parse the typelib */
3374
3375 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3376 if (ret == TYPE_E_CANTLOADLIBRARY)
3377 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3378 if (ret == TYPE_E_CANTLOADLIBRARY)
3379 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3380 if (SUCCEEDED(ret))
3381 {
3382 if (dwTLBLength >= 4)
3383 {
3384 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3385 if (dwSignature == MSFT_SIGNATURE)
3386 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3387 else if (dwSignature == SLTG_SIGNATURE)
3388 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3389 else
3390 {
3391 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3392 ret = TYPE_E_CANTLOADLIBRARY;
3393 }
3394 }
3395 else
3396 ret = TYPE_E_CANTLOADLIBRARY;
3397 IUnknown_Release(pFile);
3398 }
3399
3400 if(*ppTypeLib) {
3401 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3402
3403 TRACE("adding to cache\n");
3404 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3405 lstrcpyW(impl->path, pszPath);
3406 /* We should really canonicalise the path here. */
3407 impl->index = index;
3408
3409 /* FIXME: check if it has added already in the meantime */
3410 EnterCriticalSection(&cache_section);
3411 list_add_head(&tlb_cache, &impl->entry);
3412 LeaveCriticalSection(&cache_section);
3413 ret = S_OK;
3414 }
3415 else
3416 {
3417 if(ret != E_FAIL)
3418 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3419
3420 ret = TYPE_E_CANTLOADLIBRARY;
3421 }
3422
3423
3424 return ret;
3425 }
3426
3427 /*================== ITypeLib(2) Methods ===================================*/
3428
TypeLibImpl_Constructor(void)3429 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3430 {
3431 ITypeLibImpl* pTypeLibImpl;
3432
3433 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3434 if (!pTypeLibImpl) return NULL;
3435
3436 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3437 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3438 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3439 pTypeLibImpl->ref = 1;
3440
3441 list_init(&pTypeLibImpl->implib_list);
3442 list_init(&pTypeLibImpl->custdata_list);
3443 list_init(&pTypeLibImpl->name_list);
3444 list_init(&pTypeLibImpl->string_list);
3445 list_init(&pTypeLibImpl->guid_list);
3446 list_init(&pTypeLibImpl->ref_list);
3447 pTypeLibImpl->dispatch_href = -1;
3448
3449 return pTypeLibImpl;
3450 }
3451
3452 /****************************************************************************
3453 * ITypeLib2_Constructor_MSFT
3454 *
3455 * loading an MSFT typelib from an in-memory image
3456 */
ITypeLib2_Constructor_MSFT(LPVOID pLib,DWORD dwTLBLength)3457 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3458 {
3459 TLBContext cx;
3460 LONG lPSegDir;
3461 MSFT_Header tlbHeader;
3462 MSFT_SegDir tlbSegDir;
3463 ITypeLibImpl * pTypeLibImpl;
3464 int i;
3465
3466 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3467
3468 pTypeLibImpl = TypeLibImpl_Constructor();
3469 if (!pTypeLibImpl) return NULL;
3470
3471 /* get pointer to beginning of typelib data */
3472 cx.pos = 0;
3473 cx.oStart=0;
3474 cx.mapping = pLib;
3475 cx.pLibInfo = pTypeLibImpl;
3476 cx.length = dwTLBLength;
3477
3478 /* read header */
3479 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3480 TRACE_(typelib)("header:\n");
3481 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3482 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3483 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3484 return NULL;
3485 }
3486 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3487
3488 /* there is a small amount of information here until the next important
3489 * part:
3490 * the segment directory . Try to calculate the amount of data */
3491 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3492
3493 /* now read the segment directory */
3494 TRACE("read segment directory (at %d)\n",lPSegDir);
3495 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3496 cx.pTblDir = &tlbSegDir;
3497
3498 /* just check two entries */
3499 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3500 {
3501 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3502 heap_free(pTypeLibImpl);
3503 return NULL;
3504 }
3505
3506 MSFT_ReadAllNames(&cx);
3507 MSFT_ReadAllStrings(&cx);
3508 MSFT_ReadAllGuids(&cx);
3509
3510 /* now fill our internal data */
3511 /* TLIBATTR fields */
3512 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3513
3514 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3515 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3516 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3517 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3518 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3519
3520 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3521 pTypeLibImpl->lcid = tlbHeader.lcid;
3522
3523 /* name, eventually add to a hash table */
3524 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3525
3526 /* help info */
3527 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3528 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3529
3530 if( tlbHeader.varflags & HELPDLLFLAG)
3531 {
3532 int offset;
3533 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3534 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3535 }
3536
3537 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3538
3539 /* custom data */
3540 if(tlbHeader.CustomDataOffset >= 0)
3541 {
3542 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3543 }
3544
3545 /* fill in type descriptions */
3546 if(tlbSegDir.pTypdescTab.length > 0)
3547 {
3548 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3549 INT16 td[4];
3550 pTypeLibImpl->ctTypeDesc = cTD;
3551 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3552 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3553 for(i=0; i<cTD; )
3554 {
3555 /* FIXME: add several sanity checks here */
3556 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3557 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3558 {
3559 /* FIXME: check safearray */
3560 if(td[3] < 0)
3561 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3562 else
3563 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3564 }
3565 else if(td[0] == VT_CARRAY)
3566 {
3567 /* array descr table here */
3568 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3569 }
3570 else if(td[0] == VT_USERDEFINED)
3571 {
3572 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3573 }
3574 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3575 }
3576
3577 /* second time around to fill the array subscript info */
3578 for(i=0;i<cTD;i++)
3579 {
3580 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3581 if(tlbSegDir.pArrayDescriptions.offset>0)
3582 {
3583 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3585
3586 if(td[1]<0)
3587 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3588 else
3589 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3590
3591 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3592
3593 for(j = 0; j<td[2]; j++)
3594 {
3595 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3596 sizeof(INT), &cx, DO_NOT_SEEK);
3597 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3598 sizeof(INT), &cx, DO_NOT_SEEK);
3599 }
3600 }
3601 else
3602 {
3603 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3604 ERR("didn't find array description data\n");
3605 }
3606 }
3607 }
3608
3609 /* imported type libs */
3610 if(tlbSegDir.pImpFiles.offset>0)
3611 {
3612 TLBImpLib *pImpLib;
3613 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3614 UINT16 size;
3615
3616 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3617 {
3618 char *name;
3619
3620 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3621 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3622 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3623
3624 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3625 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3626 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3627 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3628
3629 size >>= 2;
3630 name = heap_alloc_zero(size+1);
3631 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3632 pImpLib->name = TLB_MultiByteToBSTR(name);
3633 heap_free(name);
3634
3635 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3636 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3637
3638 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3639 }
3640 }
3641
3642 MSFT_ReadAllRefs(&cx);
3643
3644 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3645
3646 /* type infos */
3647 if(tlbHeader.nrtypeinfos >= 0 )
3648 {
3649 ITypeInfoImpl **ppTI;
3650
3651 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3652
3653 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3654 {
3655 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3656
3657 ++ppTI;
3658 (pTypeLibImpl->TypeInfoCount)++;
3659 }
3660 }
3661
3662 #ifdef _WIN64
3663 if(pTypeLibImpl->syskind == SYS_WIN32){
3664 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3665 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3666 }
3667 #endif
3668
3669 TRACE("(%p)\n", pTypeLibImpl);
3670 return &pTypeLibImpl->ITypeLib2_iface;
3671 }
3672
3673
TLB_GUIDFromString(const char * str,GUID * guid)3674 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3675 {
3676 char b[3];
3677 int i;
3678 short s;
3679
3680 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3681 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3682 return FALSE;
3683 }
3684
3685 guid->Data4[0] = s >> 8;
3686 guid->Data4[1] = s & 0xff;
3687
3688 b[2] = '\0';
3689 for(i = 0; i < 6; i++) {
3690 memcpy(b, str + 24 + 2 * i, 2);
3691 guid->Data4[i + 2] = strtol(b, NULL, 16);
3692 }
3693 return TRUE;
3694 }
3695
3696 struct bitstream
3697 {
3698 const BYTE *buffer;
3699 DWORD length;
3700 WORD current;
3701 };
3702
lookup_code(const BYTE * table,DWORD table_size,struct bitstream * bits)3703 static const char *lookup_code(const BYTE *table, DWORD table_size, struct bitstream *bits)
3704 {
3705 const BYTE *p = table;
3706
3707 while (p < table + table_size && *p == 0x80)
3708 {
3709 if (p + 2 >= table + table_size) return NULL;
3710
3711 if (!(bits->current & 0xff))
3712 {
3713 if (!bits->length) return NULL;
3714 bits->current = (*bits->buffer << 8) | 1;
3715 bits->buffer++;
3716 bits->length--;
3717 }
3718
3719 if (bits->current & 0x8000)
3720 {
3721 p += 3;
3722 }
3723 else
3724 {
3725 p = table + (*(p + 2) | (*(p + 1) << 8));
3726 }
3727
3728 bits->current <<= 1;
3729 }
3730
3731 if (p + 1 < table + table_size && *(p + 1))
3732 {
3733 /* FIXME: Whats the meaning of *p? */
3734 const BYTE *q = p + 1;
3735 while (q < table + table_size && *q) q++;
3736 return (q < table + table_size) ? (const char *)(p + 1) : NULL;
3737 }
3738
3739 return NULL;
3740 }
3741
decode_string(const BYTE * table,const char * stream,DWORD stream_length,ITypeLibImpl * lib)3742 static const TLBString *decode_string(const BYTE *table, const char *stream, DWORD stream_length, ITypeLibImpl *lib)
3743 {
3744 DWORD buf_size, table_size;
3745 const char *p;
3746 struct bitstream bits;
3747 BSTR buf;
3748 TLBString *tlbstr;
3749
3750 if (!stream_length) return NULL;
3751
3752 bits.buffer = (const BYTE *)stream;
3753 bits.length = stream_length;
3754 bits.current = 0;
3755
3756 buf_size = *(const WORD *)table;
3757 table += sizeof(WORD);
3758 table_size = *(const DWORD *)table;
3759 table += sizeof(DWORD);
3760
3761 buf = SysAllocStringLen(NULL, buf_size);
3762 buf[0] = 0;
3763
3764 while ((p = lookup_code(table, table_size, &bits)))
3765 {
3766 static const WCHAR spaceW[] = { ' ',0 };
3767 if (buf[0]) lstrcatW(buf, spaceW);
3768 MultiByteToWideChar(CP_ACP, 0, p, -1, buf + lstrlenW(buf), buf_size - lstrlenW(buf));
3769 }
3770
3771 tlbstr = TLB_append_str(&lib->string_list, buf);
3772 SysFreeString(buf);
3773
3774 return tlbstr;
3775 }
3776
SLTG_ReadString(const char * ptr,const TLBString ** pStr,ITypeLibImpl * lib)3777 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3778 {
3779 WORD bytelen;
3780 DWORD len;
3781 BSTR tmp_str;
3782
3783 *pStr = NULL;
3784 bytelen = *(const WORD*)ptr;
3785 if(bytelen == 0xffff) return 2;
3786
3787 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3788 tmp_str = SysAllocStringLen(NULL, len);
3789 if (tmp_str) {
3790 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3791 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3792 SysFreeString(tmp_str);
3793 }
3794 return bytelen + 2;
3795 }
3796
SLTG_ReadStringA(const char * ptr,char ** str)3797 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3798 {
3799 WORD bytelen;
3800
3801 *str = NULL;
3802 bytelen = *(const WORD*)ptr;
3803 if(bytelen == 0xffff) return 2;
3804 *str = heap_alloc(bytelen + 1);
3805 memcpy(*str, ptr + 2, bytelen);
3806 (*str)[bytelen] = '\0';
3807 return bytelen + 2;
3808 }
3809
SLTG_ReadName(const char * pNameTable,int offset,ITypeLibImpl * lib)3810 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3811 {
3812 BSTR tmp_str;
3813 TLBString *tlbstr;
3814
3815 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3816 if (tlbstr->offset == offset)
3817 return tlbstr;
3818 }
3819
3820 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3821 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3822 SysFreeString(tmp_str);
3823
3824 return tlbstr;
3825 }
3826
SLTG_ReadLibBlk(LPVOID pLibBlk,ITypeLibImpl * pTypeLibImpl)3827 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3828 {
3829 char *ptr = pLibBlk;
3830 WORD w;
3831
3832 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3833 FIXME("libblk magic = %04x\n", w);
3834 return 0;
3835 }
3836
3837 ptr += 6;
3838 if((w = *(WORD*)ptr) != 0xffff) {
3839 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3840 ptr += w;
3841 }
3842 ptr += 2;
3843
3844 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3845
3846 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3847
3848 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3849 ptr += 4;
3850
3851 pTypeLibImpl->syskind = *(WORD*)ptr;
3852 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3853 ptr += 2;
3854
3855 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3856 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3857 else
3858 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3859 ptr += 2;
3860
3861 ptr += 4; /* skip res12 */
3862
3863 pTypeLibImpl->libflags = *(WORD*)ptr;
3864 ptr += 2;
3865
3866 pTypeLibImpl->ver_major = *(WORD*)ptr;
3867 ptr += 2;
3868
3869 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3870 ptr += 2;
3871
3872 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3873 ptr += sizeof(GUID);
3874
3875 return ptr - (char*)pLibBlk;
3876 }
3877
3878 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3879 typedef struct
3880 {
3881 unsigned int num;
3882 HREFTYPE refs[1];
3883 } sltg_ref_lookup_t;
3884
sltg_get_typelib_ref(const sltg_ref_lookup_t * table,DWORD typeinfo_ref,HREFTYPE * typelib_ref)3885 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3886 HREFTYPE *typelib_ref)
3887 {
3888 if(table && typeinfo_ref < table->num)
3889 {
3890 *typelib_ref = table->refs[typeinfo_ref];
3891 return S_OK;
3892 }
3893
3894 ERR_(typelib)("Unable to find reference\n");
3895 *typelib_ref = -1;
3896 return E_FAIL;
3897 }
3898
SLTG_DoType(WORD * pType,char * pBlk,TYPEDESC * pTD,const sltg_ref_lookup_t * ref_lookup)3899 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3900 {
3901 BOOL done = FALSE;
3902
3903 while(!done) {
3904 if((*pType & 0xe00) == 0xe00) {
3905 pTD->vt = VT_PTR;
3906 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3907 pTD = pTD->u.lptdesc;
3908 }
3909 switch(*pType & 0x3f) {
3910 case VT_PTR:
3911 pTD->vt = VT_PTR;
3912 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3913 pTD = pTD->u.lptdesc;
3914 break;
3915
3916 case VT_USERDEFINED:
3917 pTD->vt = VT_USERDEFINED;
3918 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3919 done = TRUE;
3920 break;
3921
3922 case VT_CARRAY:
3923 {
3924 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3925 array */
3926
3927 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3928
3929 pTD->vt = VT_CARRAY;
3930 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3931 pTD->u.lpadesc->cDims = pSA->cDims;
3932 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3933 pSA->cDims * sizeof(SAFEARRAYBOUND));
3934
3935 pTD = &pTD->u.lpadesc->tdescElem;
3936 break;
3937 }
3938
3939 case VT_SAFEARRAY:
3940 {
3941 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3942 useful? */
3943
3944 pType++;
3945 pTD->vt = VT_SAFEARRAY;
3946 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3947 pTD = pTD->u.lptdesc;
3948 break;
3949 }
3950 default:
3951 pTD->vt = *pType & 0x3f;
3952 done = TRUE;
3953 break;
3954 }
3955 pType++;
3956 }
3957 return pType;
3958 }
3959
SLTG_DoElem(WORD * pType,char * pBlk,ELEMDESC * pElem,const sltg_ref_lookup_t * ref_lookup)3960 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3961 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3962 {
3963 /* Handle [in/out] first */
3964 if((*pType & 0xc000) == 0xc000)
3965 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3966 else if(*pType & 0x8000)
3967 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3968 else if(*pType & 0x4000)
3969 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3970 else
3971 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3972
3973 if(*pType & 0x2000)
3974 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3975
3976 if(*pType & 0x80)
3977 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3978
3979 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3980 }
3981
3982
SLTG_DoRefs(SLTG_RefInfo * pRef,ITypeLibImpl * pTL,char * pNameTable)3983 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3984 char *pNameTable)
3985 {
3986 unsigned int ref;
3987 char *name;
3988 TLBRefType *ref_type;
3989 sltg_ref_lookup_t *table;
3990 HREFTYPE typelib_ref;
3991
3992 if(pRef->magic != SLTG_REF_MAGIC) {
3993 FIXME("Ref magic = %x\n", pRef->magic);
3994 return NULL;
3995 }
3996 name = ( (char*)pRef->names + pRef->number);
3997
3998 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3999 table->num = pRef->number >> 3;
4000
4001 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
4002
4003 /* We don't want the first href to be 0 */
4004 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
4005
4006 for(ref = 0; ref < pRef->number >> 3; ref++) {
4007 char *refname;
4008 unsigned int lib_offs, type_num;
4009
4010 ref_type = heap_alloc_zero(sizeof(TLBRefType));
4011
4012 name += SLTG_ReadStringA(name, &refname);
4013 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
4014 FIXME_(typelib)("Can't sscanf ref\n");
4015 if(lib_offs != 0xffff) {
4016 TLBImpLib *import;
4017
4018 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
4019 if(import->offset == lib_offs)
4020 break;
4021
4022 if(&import->entry == &pTL->implib_list) {
4023 char fname[MAX_PATH+1];
4024 int len;
4025 GUID tmpguid;
4026
4027 import = heap_alloc_zero(sizeof(*import));
4028 import->offset = lib_offs;
4029 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
4030 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
4031 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
4032 &import->wVersionMajor,
4033 &import->wVersionMinor,
4034 &import->lcid, fname) != 4) {
4035 FIXME_(typelib)("can't sscanf ref %s\n",
4036 pNameTable + lib_offs + 40);
4037 }
4038 len = strlen(fname);
4039 if(fname[len-1] != '#')
4040 FIXME("fname = %s\n", fname);
4041 fname[len-1] = '\0';
4042 import->name = TLB_MultiByteToBSTR(fname);
4043 list_add_tail(&pTL->implib_list, &import->entry);
4044 }
4045 ref_type->pImpTLInfo = import;
4046
4047 /* Store a reference to IDispatch */
4048 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4049 pTL->dispatch_href = typelib_ref;
4050
4051 } else { /* internal ref */
4052 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4053 }
4054 ref_type->reference = typelib_ref;
4055 ref_type->index = type_num;
4056
4057 heap_free(refname);
4058 list_add_tail(&pTL->ref_list, &ref_type->entry);
4059
4060 table->refs[ref] = typelib_ref;
4061 typelib_ref += 4;
4062 }
4063 if((BYTE)*name != SLTG_REF_MAGIC)
4064 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4065 dump_TLBRefType(pTL);
4066 return table;
4067 }
4068
SLTG_DoImpls(char * pBlk,ITypeInfoImpl * pTI,BOOL OneOnly,const sltg_ref_lookup_t * ref_lookup)4069 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4070 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4071 {
4072 SLTG_ImplInfo *info;
4073 TLBImplType *pImplType;
4074 /* I don't really get this structure, usually it's 0x16 bytes
4075 long, but iuser.tlb contains some that are 0x18 bytes long.
4076 That's ok because we can use the next ptr to jump to the next
4077 one. But how do we know the length of the last one? The WORD
4078 at offs 0x8 might be the clue. For now I'm just assuming that
4079 the last one is the regular 0x16 bytes. */
4080
4081 info = (SLTG_ImplInfo*)pBlk;
4082 while(1){
4083 pTI->typeattr.cImplTypes++;
4084 if(info->next == 0xffff)
4085 break;
4086 info = (SLTG_ImplInfo*)(pBlk + info->next);
4087 }
4088
4089 info = (SLTG_ImplInfo*)pBlk;
4090 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4091 pImplType = pTI->impltypes;
4092 while(1) {
4093 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4094 pImplType->implflags = info->impltypeflags;
4095 ++pImplType;
4096
4097 if(info->next == 0xffff)
4098 break;
4099 if(OneOnly)
4100 FIXME_(typelib)("Interface inheriting more than one interface\n");
4101 info = (SLTG_ImplInfo*)(pBlk + info->next);
4102 }
4103 info++; /* see comment at top of function */
4104 return (char*)info;
4105 }
4106
SLTG_DoVars(char * pBlk,char * pFirstItem,ITypeInfoImpl * pTI,unsigned short cVars,const char * pNameTable,const sltg_ref_lookup_t * ref_lookup,const BYTE * hlp_strings)4107 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4108 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup, const BYTE *hlp_strings)
4109 {
4110 TLBVarDesc *pVarDesc;
4111 const TLBString *prevName = NULL;
4112 SLTG_Variable *pItem;
4113 unsigned short i;
4114 WORD *pType;
4115
4116 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4117
4118 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4119 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4120
4121 pVarDesc->vardesc.memid = pItem->memid;
4122
4123 if (pItem->magic != SLTG_VAR_MAGIC &&
4124 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4125 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4126 return;
4127 }
4128
4129 if (pItem->name == 0xfffe)
4130 pVarDesc->Name = prevName;
4131 else
4132 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4133
4134 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4135 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4136 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4137
4138 if (pItem->helpstring != 0xffff)
4139 {
4140 pVarDesc->HelpString = decode_string(hlp_strings, pBlk + pItem->helpstring, pNameTable - pBlk, pTI->pTypeLib);
4141 TRACE_(typelib)("helpstring = %s\n", debugstr_w(pVarDesc->HelpString->str));
4142 }
4143
4144 if(pItem->flags & 0x02)
4145 pType = &pItem->type;
4146 else
4147 pType = (WORD*)(pBlk + pItem->type);
4148
4149 if (pItem->flags & ~0xda)
4150 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4151
4152 SLTG_DoElem(pType, pBlk,
4153 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4154
4155 if (TRACE_ON(typelib)) {
4156 char buf[300];
4157 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4158 TRACE_(typelib)("elemdescVar: %s\n", buf);
4159 }
4160
4161 if (pItem->flags & 0x40) {
4162 TRACE_(typelib)("VAR_DISPATCH\n");
4163 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4164 }
4165 else if (pItem->flags & 0x10) {
4166 TRACE_(typelib)("VAR_CONST\n");
4167 pVarDesc->vardesc.varkind = VAR_CONST;
4168 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4169 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4170 if (pItem->flags & 0x08)
4171 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4172 else {
4173 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4174 {
4175 case VT_LPSTR:
4176 case VT_LPWSTR:
4177 case VT_BSTR:
4178 {
4179 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4180 BSTR str;
4181 TRACE_(typelib)("len = %u\n", len);
4182 if (len == 0xffff) {
4183 str = NULL;
4184 } else {
4185 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4186 str = SysAllocStringLen(NULL, alloc_len);
4187 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4188 }
4189 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4190 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4191 break;
4192 }
4193 case VT_I2:
4194 case VT_UI2:
4195 case VT_I4:
4196 case VT_UI4:
4197 case VT_INT:
4198 case VT_UINT:
4199 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4200 *(INT*)(pBlk + pItem->byte_offs);
4201 break;
4202 default:
4203 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4204 }
4205 }
4206 }
4207 else {
4208 TRACE_(typelib)("VAR_PERINSTANCE\n");
4209 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4210 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4211 }
4212
4213 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4214 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4215
4216 if (pItem->flags & 0x80)
4217 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4218
4219 prevName = pVarDesc->Name;
4220 }
4221 pTI->typeattr.cVars = cVars;
4222 }
4223
SLTG_DoFuncs(char * pBlk,char * pFirstItem,ITypeInfoImpl * pTI,unsigned short cFuncs,char * pNameTable,const sltg_ref_lookup_t * ref_lookup,const BYTE * hlp_strings)4224 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4225 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup,
4226 const BYTE *hlp_strings)
4227 {
4228 SLTG_Function *pFunc;
4229 unsigned short i;
4230 TLBFuncDesc *pFuncDesc;
4231
4232 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4233
4234 pFuncDesc = pTI->funcdescs;
4235 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4236 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4237
4238 int param;
4239 WORD *pType, *pArg;
4240
4241 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4242 case SLTG_FUNCTION_MAGIC:
4243 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4244 break;
4245 case SLTG_DISPATCH_FUNCTION_MAGIC:
4246 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4247 break;
4248 case SLTG_STATIC_FUNCTION_MAGIC:
4249 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4250 break;
4251 default:
4252 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4253 continue;
4254 }
4255 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4256
4257 pFuncDesc->funcdesc.memid = pFunc->dispid;
4258 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4259 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4260 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4261 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4262 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4263 if (pFunc->helpstring != 0xffff)
4264 pFuncDesc->HelpString = decode_string(hlp_strings, pBlk + pFunc->helpstring, pNameTable - pBlk, pTI->pTypeLib);
4265
4266 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4267 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4268
4269 if(pFunc->retnextopt & 0x80)
4270 pType = &pFunc->rettype;
4271 else
4272 pType = (WORD*)(pBlk + pFunc->rettype);
4273
4274 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4275
4276 pFuncDesc->funcdesc.lprgelemdescParam =
4277 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4278 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4279
4280 pArg = (WORD*)(pBlk + pFunc->arg_off);
4281
4282 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4283 char *paramName = pNameTable + (*pArg & ~1);
4284 BOOL HaveOffs;
4285 /* If arg type follows then paramName points to the 2nd
4286 letter of the name, else the next WORD is an offset to
4287 the arg type and paramName points to the first letter.
4288 So let's take one char off paramName and see if we're
4289 pointing at an alpha-numeric char. However if *pArg is
4290 0xffff or 0xfffe then the param has no name, the former
4291 meaning that the next WORD is the type, the latter
4292 meaning that the next WORD is an offset to the type. */
4293
4294 if(*pArg == 0xffff || *pArg == 0xfffe)
4295 paramName = NULL;
4296
4297 HaveOffs = !(*pArg & 1);
4298 pArg++;
4299
4300 TRACE_(typelib)("param %d: paramName %s, *pArg %#x\n",
4301 param, debugstr_a(paramName), *pArg);
4302
4303 if(HaveOffs) { /* the next word is an offset to type */
4304 pType = (WORD*)(pBlk + *pArg);
4305 SLTG_DoElem(pType, pBlk,
4306 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4307 pArg++;
4308 } else {
4309 pArg = SLTG_DoElem(pArg, pBlk,
4310 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4311 }
4312
4313 /* Are we an optional param ? */
4314 if(pFuncDesc->funcdesc.cParams - param <=
4315 pFuncDesc->funcdesc.cParamsOpt)
4316 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4317
4318 if(paramName) {
4319 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4320 paramName - pNameTable, pTI->pTypeLib);
4321 } else {
4322 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4323 }
4324 }
4325 }
4326 pTI->typeattr.cFuncs = cFuncs;
4327 }
4328
SLTG_ProcessCoClass(char * pBlk,ITypeInfoImpl * pTI,char * pNameTable,SLTG_TypeInfoHeader * pTIHeader,SLTG_TypeInfoTail * pTITail)4329 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4330 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4331 SLTG_TypeInfoTail *pTITail)
4332 {
4333 char *pFirstItem;
4334 sltg_ref_lookup_t *ref_lookup = NULL;
4335
4336 if(pTIHeader->href_table != 0xffffffff) {
4337 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4338 pNameTable);
4339 }
4340
4341 pFirstItem = pBlk;
4342
4343 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4344 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4345 }
4346 heap_free(ref_lookup);
4347 }
4348
4349
SLTG_ProcessInterface(char * pBlk,ITypeInfoImpl * pTI,char * pNameTable,SLTG_TypeInfoHeader * pTIHeader,const SLTG_TypeInfoTail * pTITail,const BYTE * hlp_strings)4350 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4351 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4352 const SLTG_TypeInfoTail *pTITail, const BYTE *hlp_strings)
4353 {
4354 char *pFirstItem;
4355 sltg_ref_lookup_t *ref_lookup = NULL;
4356
4357 if(pTIHeader->href_table != 0xffffffff) {
4358 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4359 pNameTable);
4360 }
4361
4362 pFirstItem = pBlk;
4363
4364 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4365 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4366 }
4367
4368 if (pTITail->funcs_off != 0xffff)
4369 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup, hlp_strings);
4370
4371 heap_free(ref_lookup);
4372
4373 if (TRACE_ON(typelib))
4374 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4375 }
4376
SLTG_ProcessRecord(char * pBlk,ITypeInfoImpl * pTI,const char * pNameTable,SLTG_TypeInfoHeader * pTIHeader,const SLTG_TypeInfoTail * pTITail,const BYTE * hlp_strings)4377 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4378 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4379 const SLTG_TypeInfoTail *pTITail, const BYTE *hlp_strings)
4380 {
4381 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL, hlp_strings);
4382 }
4383
SLTG_ProcessAlias(char * pBlk,ITypeInfoImpl * pTI,char * pNameTable,SLTG_TypeInfoHeader * pTIHeader,const SLTG_TypeInfoTail * pTITail)4384 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4385 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4386 const SLTG_TypeInfoTail *pTITail)
4387 {
4388 WORD *pType;
4389 sltg_ref_lookup_t *ref_lookup = NULL;
4390
4391 if (pTITail->simple_alias) {
4392 /* if simple alias, no more processing required */
4393 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4394 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4395 return;
4396 }
4397
4398 if(pTIHeader->href_table != 0xffffffff) {
4399 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4400 pNameTable);
4401 }
4402
4403 /* otherwise it is an offset to a type */
4404 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4405
4406 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4407 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4408
4409 heap_free(ref_lookup);
4410 }
4411
SLTG_ProcessDispatch(char * pBlk,ITypeInfoImpl * pTI,char * pNameTable,SLTG_TypeInfoHeader * pTIHeader,const SLTG_TypeInfoTail * pTITail,const BYTE * hlp_strings)4412 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4413 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4414 const SLTG_TypeInfoTail *pTITail, const BYTE *hlp_strings)
4415 {
4416 sltg_ref_lookup_t *ref_lookup = NULL;
4417 if (pTIHeader->href_table != 0xffffffff)
4418 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4419 pNameTable);
4420
4421 if (pTITail->vars_off != 0xffff)
4422 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup, hlp_strings);
4423
4424 if (pTITail->funcs_off != 0xffff)
4425 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup, hlp_strings);
4426
4427 if (pTITail->impls_off != 0xffff)
4428 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4429
4430 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4431 * of dispinterface functions including the IDispatch ones, so
4432 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4433 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4434
4435 heap_free(ref_lookup);
4436 if (TRACE_ON(typelib))
4437 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4438 }
4439
SLTG_ProcessEnum(char * pBlk,ITypeInfoImpl * pTI,const char * pNameTable,SLTG_TypeInfoHeader * pTIHeader,const SLTG_TypeInfoTail * pTITail,const BYTE * hlp_strings)4440 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4441 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4442 const SLTG_TypeInfoTail *pTITail, const BYTE *hlp_strings)
4443 {
4444 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL, hlp_strings);
4445 }
4446
SLTG_ProcessModule(char * pBlk,ITypeInfoImpl * pTI,char * pNameTable,SLTG_TypeInfoHeader * pTIHeader,const SLTG_TypeInfoTail * pTITail,const BYTE * hlp_strings)4447 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4448 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4449 const SLTG_TypeInfoTail *pTITail, const BYTE *hlp_strings)
4450 {
4451 sltg_ref_lookup_t *ref_lookup = NULL;
4452 if (pTIHeader->href_table != 0xffffffff)
4453 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4454 pNameTable);
4455
4456 if (pTITail->vars_off != 0xffff)
4457 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup, hlp_strings);
4458
4459 if (pTITail->funcs_off != 0xffff)
4460 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup, hlp_strings);
4461 heap_free(ref_lookup);
4462 if (TRACE_ON(typelib))
4463 dump_TypeInfo(pTI);
4464 }
4465
4466 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4467 manageable copy of it into this */
4468 typedef struct {
4469 char *index_name;
4470 char *other_name;
4471 WORD res1a;
4472 WORD name_offs;
4473 WORD hlpstr_len;
4474 char *extra;
4475 WORD res20;
4476 DWORD helpcontext;
4477 WORD res26;
4478 GUID uuid;
4479 WORD typekind;
4480 } SLTG_InternalOtherTypeInfo;
4481
4482 /****************************************************************************
4483 * ITypeLib2_Constructor_SLTG
4484 *
4485 * loading a SLTG typelib from an in-memory image
4486 */
ITypeLib2_Constructor_SLTG(LPVOID pLib,DWORD dwTLBLength)4487 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4488 {
4489 ITypeLibImpl *pTypeLibImpl;
4490 SLTG_Header *pHeader;
4491 SLTG_BlkEntry *pBlkEntry;
4492 SLTG_Magic *pMagic;
4493 SLTG_Index *pIndex;
4494 SLTG_Pad9 *pPad9;
4495 LPVOID pBlk, pFirstBlk;
4496 SLTG_LibBlk *pLibBlk;
4497 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4498 char *pNameTable, *ptr;
4499 const BYTE *hlp_strings;
4500 int i;
4501 DWORD len, order;
4502 ITypeInfoImpl **ppTypeInfoImpl;
4503
4504 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4505
4506
4507 pTypeLibImpl = TypeLibImpl_Constructor();
4508 if (!pTypeLibImpl) return NULL;
4509
4510 pHeader = pLib;
4511
4512 TRACE_(typelib)("header:\n");
4513 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4514 pHeader->nrOfFileBlks );
4515 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4516 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4517 pHeader->SLTG_magic);
4518 return NULL;
4519 }
4520
4521 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4522 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4523
4524 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4525 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4526
4527 /* Next we have a magic block */
4528 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4529
4530 /* Let's see if we're still in sync */
4531 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4532 sizeof(SLTG_COMPOBJ_MAGIC))) {
4533 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4534 return NULL;
4535 }
4536 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4537 sizeof(SLTG_DIR_MAGIC))) {
4538 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4539 return NULL;
4540 }
4541
4542 pIndex = (SLTG_Index*)(pMagic+1);
4543
4544 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4545
4546 pFirstBlk = pPad9 + 1;
4547
4548 /* We'll set up a ptr to the main library block, which is the last one. */
4549
4550 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4551 pBlkEntry[order].next != 0;
4552 order = pBlkEntry[order].next - 1) {
4553 pBlk = (char*)pBlk + pBlkEntry[order].len;
4554 }
4555 pLibBlk = pBlk;
4556
4557 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4558
4559 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4560 interspersed */
4561
4562 len += 0x40;
4563
4564 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4565 pTypeLibImpl->TypeInfoCount = *(WORD *)((char *)pLibBlk + len);
4566 len += sizeof(WORD);
4567
4568 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4569
4570 ptr = (char*)pLibBlk + len;
4571
4572 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4573 WORD w, extra;
4574 len = 0;
4575
4576 w = *(WORD*)ptr;
4577 if(w != 0xffff) {
4578 len += w;
4579 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4580 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 2, w);
4581 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4582 }
4583 w = *(WORD*)(ptr + 2 + len);
4584 if(w != 0xffff) {
4585 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 4 + len, w));
4586 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4587 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 4 + len, w);
4588 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4589 len += w;
4590 }
4591 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + 4 + len);
4592 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + 6 + len);
4593 extra = pOtherTypeInfoBlks[i].hlpstr_len = *(WORD*)(ptr + 8 + len);
4594 if(extra) {
4595 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4596 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 10 + len, extra);
4597 len += extra;
4598 }
4599 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 10 + len);
4600 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 12 + len);
4601 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 16 + len);
4602 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 18 + len, sizeof(GUID));
4603 pOtherTypeInfoBlks[i].typekind = *(WORD*)(ptr + 18 + sizeof(GUID) + len);
4604 len += sizeof(SLTG_OtherTypeInfo);
4605 ptr += len;
4606 }
4607
4608 /* Get the next DWORD */
4609 len = *(DWORD*)ptr;
4610
4611 hlp_strings = (const BYTE *)ptr + sizeof(DWORD);
4612 TRACE("max help string length %#x, help strings length %#x\n",
4613 *(WORD *)hlp_strings, *(DWORD *)(hlp_strings + 2));
4614
4615 /* Now add this to pLibBLk look at what we're pointing at and
4616 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4617 dust and we should be pointing at the beginning of the name
4618 table */
4619
4620 pNameTable = (char*)pLibBlk + len;
4621
4622 switch(*(WORD*)pNameTable) {
4623 case 0xffff:
4624 break;
4625 case 0x0200:
4626 pNameTable += 0x20;
4627 break;
4628 default:
4629 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4630 break;
4631 }
4632
4633 pNameTable += 0x216;
4634
4635 pNameTable += 2;
4636
4637 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4638
4639 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4640
4641
4642 /* Hopefully we now have enough ptrs set up to actually read in
4643 some TypeInfos. It's not clear which order to do them in, so
4644 I'll just follow the links along the BlkEntry chain and read
4645 them in the order in which they are in the file */
4646
4647 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4648 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4649
4650 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4651 pBlkEntry[order].next != 0;
4652 order = pBlkEntry[order].next - 1, i++) {
4653
4654 SLTG_TypeInfoHeader *pTIHeader;
4655 SLTG_TypeInfoTail *pTITail;
4656 SLTG_MemberHeader *pMemHeader;
4657
4658 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4659 FIXME_(typelib)("Index strings don't match\n");
4660 heap_free(pOtherTypeInfoBlks);
4661 return NULL;
4662 }
4663
4664 pTIHeader = pBlk;
4665 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4666 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4667 heap_free(pOtherTypeInfoBlks);
4668 return NULL;
4669 }
4670 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4671 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4672 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4673
4674 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4675 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4676 (*ppTypeInfoImpl)->index = i;
4677 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4678 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4679 (*ppTypeInfoImpl)->DocString = decode_string(hlp_strings, pOtherTypeInfoBlks[i].extra, pOtherTypeInfoBlks[i].hlpstr_len, pTypeLibImpl);
4680 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4681 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4682 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4683 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4684 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4685 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4686
4687 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4688 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4689
4690 if((pTIHeader->typeflags1 & 7) != 2)
4691 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4692 if(pTIHeader->typeflags3 != 2)
4693 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4694
4695 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4696 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4697 typekind_desc[pTIHeader->typekind],
4698 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4699 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4700
4701 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4702
4703 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4704
4705 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4706 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4707 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4708
4709 switch(pTIHeader->typekind) {
4710 case TKIND_ENUM:
4711 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4712 pTIHeader, pTITail, hlp_strings);
4713 break;
4714
4715 case TKIND_RECORD:
4716 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4717 pTIHeader, pTITail, hlp_strings);
4718 break;
4719
4720 case TKIND_INTERFACE:
4721 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4722 pTIHeader, pTITail, hlp_strings);
4723 break;
4724
4725 case TKIND_COCLASS:
4726 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4727 pTIHeader, pTITail);
4728 break;
4729
4730 case TKIND_ALIAS:
4731 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4732 pTIHeader, pTITail);
4733 break;
4734
4735 case TKIND_DISPATCH:
4736 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4737 pTIHeader, pTITail, hlp_strings);
4738 break;
4739
4740 case TKIND_MODULE:
4741 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4742 pTIHeader, pTITail, hlp_strings);
4743 break;
4744
4745 default:
4746 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4747 break;
4748
4749 }
4750
4751 /* could get cFuncs, cVars and cImplTypes from here
4752 but we've already set those */
4753 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4754 X(06);
4755 X(16);
4756 X(18);
4757 X(1a);
4758 X(1e);
4759 X(24);
4760 X(26);
4761 X(2a);
4762 X(2c);
4763 X(2e);
4764 X(30);
4765 X(32);
4766 X(34);
4767 #undef X
4768 ++ppTypeInfoImpl;
4769 pBlk = (char*)pBlk + pBlkEntry[order].len;
4770 }
4771
4772 if(i != pTypeLibImpl->TypeInfoCount) {
4773 FIXME("Somehow processed %d TypeInfos\n", i);
4774 heap_free(pOtherTypeInfoBlks);
4775 return NULL;
4776 }
4777
4778 heap_free(pOtherTypeInfoBlks);
4779 return &pTypeLibImpl->ITypeLib2_iface;
4780 }
4781
ITypeLib2_fnQueryInterface(ITypeLib2 * iface,REFIID riid,void ** ppv)4782 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4783 {
4784 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4785
4786 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4787
4788 if(IsEqualIID(riid, &IID_IUnknown) ||
4789 IsEqualIID(riid,&IID_ITypeLib)||
4790 IsEqualIID(riid,&IID_ITypeLib2))
4791 {
4792 *ppv = &This->ITypeLib2_iface;
4793 }
4794 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4795 IsEqualIID(riid, &IID_ICreateTypeLib2))
4796 {
4797 *ppv = &This->ICreateTypeLib2_iface;
4798 }
4799 else
4800 {
4801 *ppv = NULL;
4802 TRACE("-- Interface: E_NOINTERFACE\n");
4803 return E_NOINTERFACE;
4804 }
4805
4806 IUnknown_AddRef((IUnknown*)*ppv);
4807 return S_OK;
4808 }
4809
ITypeLib2_fnAddRef(ITypeLib2 * iface)4810 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4811 {
4812 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4813 ULONG ref = InterlockedIncrement(&This->ref);
4814
4815 TRACE("(%p) ref=%u\n", This, ref);
4816
4817 return ref;
4818 }
4819
ITypeLib2_fnRelease(ITypeLib2 * iface)4820 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4821 {
4822 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4823 ULONG ref = InterlockedDecrement(&This->ref);
4824
4825 TRACE("(%p) ref=%u\n",This, ref);
4826
4827 if (!ref)
4828 {
4829 TLBImpLib *pImpLib, *pImpLibNext;
4830 TLBRefType *ref_type, *ref_type_next;
4831 TLBString *tlbstr, *tlbstr_next;
4832 TLBGuid *tlbguid, *tlbguid_next;
4833 int i;
4834
4835 /* remove cache entry */
4836 if(This->path)
4837 {
4838 TRACE("removing from cache list\n");
4839 EnterCriticalSection(&cache_section);
4840 if(This->entry.next)
4841 list_remove(&This->entry);
4842 LeaveCriticalSection(&cache_section);
4843 heap_free(This->path);
4844 }
4845 TRACE(" destroying ITypeLib(%p)\n",This);
4846
4847 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4848 list_remove(&tlbstr->entry);
4849 SysFreeString(tlbstr->str);
4850 heap_free(tlbstr);
4851 }
4852
4853 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4854 list_remove(&tlbstr->entry);
4855 SysFreeString(tlbstr->str);
4856 heap_free(tlbstr);
4857 }
4858
4859 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4860 list_remove(&tlbguid->entry);
4861 heap_free(tlbguid);
4862 }
4863
4864 TLB_FreeCustData(&This->custdata_list);
4865
4866 for (i = 0; i < This->ctTypeDesc; i++)
4867 if (This->pTypeDesc[i].vt == VT_CARRAY)
4868 heap_free(This->pTypeDesc[i].u.lpadesc);
4869
4870 heap_free(This->pTypeDesc);
4871
4872 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4873 {
4874 if (pImpLib->pImpTypeLib)
4875 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4876 SysFreeString(pImpLib->name);
4877
4878 list_remove(&pImpLib->entry);
4879 heap_free(pImpLib);
4880 }
4881
4882 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4883 {
4884 list_remove(&ref_type->entry);
4885 heap_free(ref_type);
4886 }
4887
4888 for (i = 0; i < This->TypeInfoCount; ++i){
4889 heap_free(This->typeinfos[i]->tdescAlias);
4890 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4891 }
4892 heap_free(This->typeinfos);
4893 heap_free(This);
4894 return 0;
4895 }
4896
4897 return ref;
4898 }
4899
4900 /* ITypeLib::GetTypeInfoCount
4901 *
4902 * Returns the number of type descriptions in the type library
4903 */
ITypeLib2_fnGetTypeInfoCount(ITypeLib2 * iface)4904 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4905 {
4906 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4907 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4908 return This->TypeInfoCount;
4909 }
4910
4911 /* ITypeLib::GetTypeInfo
4912 *
4913 * retrieves the specified type description in the library.
4914 */
ITypeLib2_fnGetTypeInfo(ITypeLib2 * iface,UINT index,ITypeInfo ** ppTInfo)4915 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4916 ITypeLib2 *iface,
4917 UINT index,
4918 ITypeInfo **ppTInfo)
4919 {
4920 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4921
4922 TRACE("%p %u %p\n", This, index, ppTInfo);
4923
4924 if(!ppTInfo)
4925 return E_INVALIDARG;
4926
4927 if(index >= This->TypeInfoCount)
4928 return TYPE_E_ELEMENTNOTFOUND;
4929
4930 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4931 ITypeInfo_AddRef(*ppTInfo);
4932
4933 return S_OK;
4934 }
4935
4936
4937 /* ITypeLibs::GetTypeInfoType
4938 *
4939 * Retrieves the type of a type description.
4940 */
ITypeLib2_fnGetTypeInfoType(ITypeLib2 * iface,UINT index,TYPEKIND * pTKind)4941 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4942 ITypeLib2 *iface,
4943 UINT index,
4944 TYPEKIND *pTKind)
4945 {
4946 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4947
4948 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4949
4950 if(!pTKind)
4951 return E_INVALIDARG;
4952
4953 if(index >= This->TypeInfoCount)
4954 return TYPE_E_ELEMENTNOTFOUND;
4955
4956 *pTKind = This->typeinfos[index]->typeattr.typekind;
4957
4958 return S_OK;
4959 }
4960
4961 /* ITypeLib::GetTypeInfoOfGuid
4962 *
4963 * Retrieves the type description that corresponds to the specified GUID.
4964 *
4965 */
ITypeLib2_fnGetTypeInfoOfGuid(ITypeLib2 * iface,REFGUID guid,ITypeInfo ** ppTInfo)4966 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4967 ITypeLib2 *iface,
4968 REFGUID guid,
4969 ITypeInfo **ppTInfo)
4970 {
4971 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4972 int i;
4973
4974 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4975
4976 for(i = 0; i < This->TypeInfoCount; ++i){
4977 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4978 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4979 ITypeInfo_AddRef(*ppTInfo);
4980 return S_OK;
4981 }
4982 }
4983
4984 return TYPE_E_ELEMENTNOTFOUND;
4985 }
4986
4987 /* ITypeLib::GetLibAttr
4988 *
4989 * Retrieves the structure that contains the library's attributes.
4990 *
4991 */
ITypeLib2_fnGetLibAttr(ITypeLib2 * iface,LPTLIBATTR * attr)4992 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4993 ITypeLib2 *iface,
4994 LPTLIBATTR *attr)
4995 {
4996 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4997
4998 TRACE("(%p, %p)\n", This, attr);
4999
5000 if (!attr) return E_INVALIDARG;
5001
5002 *attr = heap_alloc(sizeof(**attr));
5003 if (!*attr) return E_OUTOFMEMORY;
5004
5005 (*attr)->guid = *TLB_get_guid_null(This->guid);
5006 (*attr)->lcid = This->set_lcid;
5007 (*attr)->syskind = This->syskind;
5008 (*attr)->wMajorVerNum = This->ver_major;
5009 (*attr)->wMinorVerNum = This->ver_minor;
5010 (*attr)->wLibFlags = This->libflags;
5011
5012 return S_OK;
5013 }
5014
5015 /* ITypeLib::GetTypeComp
5016 *
5017 * Enables a client compiler to bind to a library's types, variables,
5018 * constants, and global functions.
5019 *
5020 */
ITypeLib2_fnGetTypeComp(ITypeLib2 * iface,ITypeComp ** ppTComp)5021 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
5022 ITypeLib2 *iface,
5023 ITypeComp **ppTComp)
5024 {
5025 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5026
5027 TRACE("(%p)->(%p)\n",This,ppTComp);
5028 *ppTComp = &This->ITypeComp_iface;
5029 ITypeComp_AddRef(*ppTComp);
5030
5031 return S_OK;
5032 }
5033
5034 /* ITypeLib::GetDocumentation
5035 *
5036 * Retrieves the library's documentation string, the complete Help file name
5037 * and path, and the context identifier for the library Help topic in the Help
5038 * file.
5039 *
5040 * On a successful return all non-null BSTR pointers will have been set,
5041 * possibly to NULL.
5042 */
ITypeLib2_fnGetDocumentation(ITypeLib2 * iface,INT index,BSTR * pBstrName,BSTR * pBstrDocString,DWORD * pdwHelpContext,BSTR * pBstrHelpFile)5043 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
5044 ITypeLib2 *iface,
5045 INT index,
5046 BSTR *pBstrName,
5047 BSTR *pBstrDocString,
5048 DWORD *pdwHelpContext,
5049 BSTR *pBstrHelpFile)
5050 {
5051 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5052 HRESULT result = E_INVALIDARG;
5053 ITypeInfo *pTInfo;
5054
5055 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5056 This, index,
5057 pBstrName, pBstrDocString,
5058 pdwHelpContext, pBstrHelpFile);
5059
5060 if(index<0)
5061 {
5062 /* documentation for the typelib */
5063 if(pBstrName)
5064 {
5065 if (This->Name)
5066 {
5067 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5068 goto memerr1;
5069 }
5070 else
5071 *pBstrName = NULL;
5072 }
5073 if(pBstrDocString)
5074 {
5075 if (This->DocString)
5076 {
5077 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5078 goto memerr2;
5079 }
5080 else
5081 *pBstrDocString = NULL;
5082 }
5083 if(pdwHelpContext)
5084 {
5085 *pdwHelpContext = This->dwHelpContext;
5086 }
5087 if(pBstrHelpFile)
5088 {
5089 if (This->HelpFile)
5090 {
5091 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5092 goto memerr3;
5093 }
5094 else
5095 *pBstrHelpFile = NULL;
5096 }
5097
5098 result = S_OK;
5099 }
5100 else
5101 {
5102 /* for a typeinfo */
5103 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5104
5105 if(SUCCEEDED(result))
5106 {
5107 result = ITypeInfo_GetDocumentation(pTInfo,
5108 MEMBERID_NIL,
5109 pBstrName,
5110 pBstrDocString,
5111 pdwHelpContext, pBstrHelpFile);
5112
5113 ITypeInfo_Release(pTInfo);
5114 }
5115 }
5116 return result;
5117 memerr3:
5118 if (pBstrDocString) SysFreeString (*pBstrDocString);
5119 memerr2:
5120 if (pBstrName) SysFreeString (*pBstrName);
5121 memerr1:
5122 return STG_E_INSUFFICIENTMEMORY;
5123 }
5124
5125 /* ITypeLib::IsName
5126 *
5127 * Indicates whether a passed-in string contains the name of a type or member
5128 * described in the library.
5129 *
5130 */
ITypeLib2_fnIsName(ITypeLib2 * iface,LPOLESTR szNameBuf,ULONG lHashVal,BOOL * pfName)5131 static HRESULT WINAPI ITypeLib2_fnIsName(
5132 ITypeLib2 *iface,
5133 LPOLESTR szNameBuf,
5134 ULONG lHashVal,
5135 BOOL *pfName)
5136 {
5137 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5138 int tic;
5139 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5140
5141 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5142 pfName);
5143
5144 *pfName=TRUE;
5145 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5146 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5147 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5148 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5149 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5150 int pc;
5151 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5152 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5153 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5154 goto ITypeLib2_fnIsName_exit;
5155 }
5156 }
5157 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5158 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5159 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5160 }
5161
5162 }
5163 *pfName=FALSE;
5164
5165 ITypeLib2_fnIsName_exit:
5166 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5167 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5168
5169 return S_OK;
5170 }
5171
5172 /* ITypeLib::FindName
5173 *
5174 * Finds occurrences of a type description in a type library. This may be used
5175 * to quickly verify that a name exists in a type library.
5176 *
5177 */
ITypeLib2_fnFindName(ITypeLib2 * iface,LPOLESTR name,ULONG hash,ITypeInfo ** ppTInfo,MEMBERID * memid,UINT16 * found)5178 static HRESULT WINAPI ITypeLib2_fnFindName(
5179 ITypeLib2 *iface,
5180 LPOLESTR name,
5181 ULONG hash,
5182 ITypeInfo **ppTInfo,
5183 MEMBERID *memid,
5184 UINT16 *found)
5185 {
5186 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5187 int tic;
5188 UINT count = 0;
5189 UINT len;
5190
5191 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5192
5193 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5194 return E_INVALIDARG;
5195
5196 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5197 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5198 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5199 TLBVarDesc *var;
5200 UINT fdc;
5201
5202 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5203 memid[count] = MEMBERID_NIL;
5204 goto ITypeLib2_fnFindName_exit;
5205 }
5206
5207 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5208 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5209
5210 if(!TLB_str_memcmp(name, func->Name, len)) {
5211 memid[count] = func->funcdesc.memid;
5212 goto ITypeLib2_fnFindName_exit;
5213 }
5214 }
5215
5216 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5217 if (var) {
5218 memid[count] = var->vardesc.memid;
5219 goto ITypeLib2_fnFindName_exit;
5220 }
5221
5222 continue;
5223 ITypeLib2_fnFindName_exit:
5224 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5225 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5226 count++;
5227 }
5228 TRACE("found %d typeinfos\n", count);
5229
5230 *found = count;
5231
5232 return S_OK;
5233 }
5234
5235 /* ITypeLib::ReleaseTLibAttr
5236 *
5237 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5238 *
5239 */
ITypeLib2_fnReleaseTLibAttr(ITypeLib2 * iface,TLIBATTR * pTLibAttr)5240 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5241 ITypeLib2 *iface,
5242 TLIBATTR *pTLibAttr)
5243 {
5244 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5245 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5246 heap_free(pTLibAttr);
5247 }
5248
5249 /* ITypeLib2::GetCustData
5250 *
5251 * gets the custom data
5252 */
ITypeLib2_fnGetCustData(ITypeLib2 * iface,REFGUID guid,VARIANT * pVarVal)5253 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5254 ITypeLib2 * iface,
5255 REFGUID guid,
5256 VARIANT *pVarVal)
5257 {
5258 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5259 TLBCustData *pCData;
5260
5261 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5262
5263 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5264 if(!pCData)
5265 return TYPE_E_ELEMENTNOTFOUND;
5266
5267 VariantInit(pVarVal);
5268 VariantCopy(pVarVal, &pCData->data);
5269
5270 return S_OK;
5271 }
5272
5273 /* ITypeLib2::GetLibStatistics
5274 *
5275 * Returns statistics about a type library that are required for efficient
5276 * sizing of hash tables.
5277 *
5278 */
ITypeLib2_fnGetLibStatistics(ITypeLib2 * iface,ULONG * pcUniqueNames,ULONG * pcchUniqueNames)5279 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5280 ITypeLib2 * iface,
5281 ULONG *pcUniqueNames,
5282 ULONG *pcchUniqueNames)
5283 {
5284 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5285
5286 FIXME("(%p): stub!\n", This);
5287
5288 if(pcUniqueNames) *pcUniqueNames=1;
5289 if(pcchUniqueNames) *pcchUniqueNames=1;
5290 return S_OK;
5291 }
5292
5293 /* ITypeLib2::GetDocumentation2
5294 *
5295 * Retrieves the library's documentation string, the complete Help file name
5296 * and path, the localization context to use, and the context ID for the
5297 * library Help topic in the Help file.
5298 *
5299 */
ITypeLib2_fnGetDocumentation2(ITypeLib2 * iface,INT index,LCID lcid,BSTR * pbstrHelpString,DWORD * pdwHelpStringContext,BSTR * pbstrHelpStringDll)5300 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5301 ITypeLib2 * iface,
5302 INT index,
5303 LCID lcid,
5304 BSTR *pbstrHelpString,
5305 DWORD *pdwHelpStringContext,
5306 BSTR *pbstrHelpStringDll)
5307 {
5308 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5309 HRESULT result;
5310 ITypeInfo *pTInfo;
5311
5312 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5313
5314 /* the help string should be obtained from the helpstringdll,
5315 * using the _DLLGetDocumentation function, based on the supplied
5316 * lcid. Nice to do sometime...
5317 */
5318 if(index<0)
5319 {
5320 /* documentation for the typelib */
5321 if(pbstrHelpString)
5322 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5323 if(pdwHelpStringContext)
5324 *pdwHelpStringContext=This->dwHelpContext;
5325 if(pbstrHelpStringDll)
5326 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5327
5328 result = S_OK;
5329 }
5330 else
5331 {
5332 /* for a typeinfo */
5333 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5334
5335 if(SUCCEEDED(result))
5336 {
5337 ITypeInfo2 * pTInfo2;
5338 result = ITypeInfo_QueryInterface(pTInfo,
5339 &IID_ITypeInfo2,
5340 (LPVOID*) &pTInfo2);
5341
5342 if(SUCCEEDED(result))
5343 {
5344 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5345 MEMBERID_NIL,
5346 lcid,
5347 pbstrHelpString,
5348 pdwHelpStringContext,
5349 pbstrHelpStringDll);
5350
5351 ITypeInfo2_Release(pTInfo2);
5352 }
5353
5354 ITypeInfo_Release(pTInfo);
5355 }
5356 }
5357 return result;
5358 }
5359
TLB_copy_all_custdata(struct list * custdata_list,CUSTDATA * pCustData)5360 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5361 {
5362 TLBCustData *pCData;
5363 unsigned int ct;
5364 CUSTDATAITEM *cdi;
5365
5366 ct = list_count(custdata_list);
5367
5368 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5369 if(!pCustData->prgCustData)
5370 return E_OUTOFMEMORY;
5371
5372 pCustData->cCustData = ct;
5373
5374 cdi = pCustData->prgCustData;
5375 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5376 cdi->guid = *TLB_get_guid_null(pCData->guid);
5377 VariantCopy(&cdi->varValue, &pCData->data);
5378 ++cdi;
5379 }
5380
5381 return S_OK;
5382 }
5383
5384
5385 /* ITypeLib2::GetAllCustData
5386 *
5387 * Gets all custom data items for the library.
5388 *
5389 */
ITypeLib2_fnGetAllCustData(ITypeLib2 * iface,CUSTDATA * pCustData)5390 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5391 ITypeLib2 * iface,
5392 CUSTDATA *pCustData)
5393 {
5394 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5395 TRACE("(%p)->(%p)\n", This, pCustData);
5396 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5397 }
5398
5399 static const ITypeLib2Vtbl tlbvt = {
5400 ITypeLib2_fnQueryInterface,
5401 ITypeLib2_fnAddRef,
5402 ITypeLib2_fnRelease,
5403 ITypeLib2_fnGetTypeInfoCount,
5404 ITypeLib2_fnGetTypeInfo,
5405 ITypeLib2_fnGetTypeInfoType,
5406 ITypeLib2_fnGetTypeInfoOfGuid,
5407 ITypeLib2_fnGetLibAttr,
5408 ITypeLib2_fnGetTypeComp,
5409 ITypeLib2_fnGetDocumentation,
5410 ITypeLib2_fnIsName,
5411 ITypeLib2_fnFindName,
5412 ITypeLib2_fnReleaseTLibAttr,
5413
5414 ITypeLib2_fnGetCustData,
5415 ITypeLib2_fnGetLibStatistics,
5416 ITypeLib2_fnGetDocumentation2,
5417 ITypeLib2_fnGetAllCustData
5418 };
5419
5420
ITypeLibComp_fnQueryInterface(ITypeComp * iface,REFIID riid,LPVOID * ppv)5421 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5422 {
5423 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5424
5425 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5426 }
5427
ITypeLibComp_fnAddRef(ITypeComp * iface)5428 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5429 {
5430 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5431
5432 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5433 }
5434
ITypeLibComp_fnRelease(ITypeComp * iface)5435 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5436 {
5437 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5438
5439 return ITypeLib2_Release(&This->ITypeLib2_iface);
5440 }
5441
ITypeLibComp_fnBind(ITypeComp * iface,OLECHAR * szName,ULONG lHash,WORD wFlags,ITypeInfo ** ppTInfo,DESCKIND * pDescKind,BINDPTR * pBindPtr)5442 static HRESULT WINAPI ITypeLibComp_fnBind(
5443 ITypeComp * iface,
5444 OLECHAR * szName,
5445 ULONG lHash,
5446 WORD wFlags,
5447 ITypeInfo ** ppTInfo,
5448 DESCKIND * pDescKind,
5449 BINDPTR * pBindPtr)
5450 {
5451 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5452 BOOL typemismatch = FALSE;
5453 int i;
5454
5455 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5456
5457 *pDescKind = DESCKIND_NONE;
5458 pBindPtr->lptcomp = NULL;
5459 *ppTInfo = NULL;
5460
5461 for(i = 0; i < This->TypeInfoCount; ++i){
5462 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5463 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5464
5465 /* FIXME: check wFlags here? */
5466 /* FIXME: we should use a hash table to look this info up using lHash
5467 * instead of an O(n) search */
5468 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5469 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5470 {
5471 if (pTypeInfo->Name && !wcscmp(pTypeInfo->Name->str, szName))
5472 {
5473 *pDescKind = DESCKIND_TYPECOMP;
5474 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5475 ITypeComp_AddRef(pBindPtr->lptcomp);
5476 TRACE("module or enum: %s\n", debugstr_w(szName));
5477 return S_OK;
5478 }
5479 }
5480
5481 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5482 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5483 {
5484 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5485 HRESULT hr;
5486
5487 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5488 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5489 {
5490 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5491 return S_OK;
5492 }
5493 else if (hr == TYPE_E_TYPEMISMATCH)
5494 typemismatch = TRUE;
5495 }
5496
5497 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5498 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5499 {
5500 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5501 HRESULT hr;
5502 ITypeInfo *subtypeinfo;
5503 BINDPTR subbindptr;
5504 DESCKIND subdesckind;
5505
5506 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5507 &subtypeinfo, &subdesckind, &subbindptr);
5508 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5509 {
5510 TYPEDESC tdesc_appobject;
5511 const VARDESC vardesc_appobject =
5512 {
5513 -2, /* memid */
5514 NULL, /* lpstrSchema */
5515 {
5516 0 /* oInst */
5517 },
5518 {
5519 /* ELEMDESC */
5520 {
5521 /* TYPEDESC */
5522 {
5523 &tdesc_appobject
5524 },
5525 VT_PTR
5526 },
5527 },
5528 0, /* wVarFlags */
5529 VAR_STATIC /* varkind */
5530 };
5531
5532 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5533 tdesc_appobject.vt = VT_USERDEFINED;
5534
5535 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5536
5537 /* cleanup things filled in by Bind call so we can put our
5538 * application object data in there instead */
5539 switch (subdesckind)
5540 {
5541 case DESCKIND_FUNCDESC:
5542 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5543 break;
5544 case DESCKIND_VARDESC:
5545 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5546 break;
5547 default:
5548 break;
5549 }
5550 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5551
5552 if (pTypeInfo->hreftype == -1)
5553 FIXME("no hreftype for interface %p\n", pTypeInfo);
5554
5555 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5556 if (FAILED(hr))
5557 return hr;
5558
5559 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5560 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5561 ITypeInfo_AddRef(*ppTInfo);
5562 return S_OK;
5563 }
5564 else if (hr == TYPE_E_TYPEMISMATCH)
5565 typemismatch = TRUE;
5566 }
5567 }
5568
5569 if (typemismatch)
5570 {
5571 TRACE("type mismatch %s\n", debugstr_w(szName));
5572 return TYPE_E_TYPEMISMATCH;
5573 }
5574 else
5575 {
5576 TRACE("name not found %s\n", debugstr_w(szName));
5577 return S_OK;
5578 }
5579 }
5580
ITypeLibComp_fnBindType(ITypeComp * iface,OLECHAR * szName,ULONG lHash,ITypeInfo ** ppTInfo,ITypeComp ** ppTComp)5581 static HRESULT WINAPI ITypeLibComp_fnBindType(
5582 ITypeComp * iface,
5583 OLECHAR * szName,
5584 ULONG lHash,
5585 ITypeInfo ** ppTInfo,
5586 ITypeComp ** ppTComp)
5587 {
5588 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5589 ITypeInfoImpl *info;
5590
5591 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5592
5593 if(!szName || !ppTInfo || !ppTComp)
5594 return E_INVALIDARG;
5595
5596 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5597 if(!info){
5598 *ppTInfo = NULL;
5599 *ppTComp = NULL;
5600 return S_OK;
5601 }
5602
5603 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5604 ITypeInfo_AddRef(*ppTInfo);
5605 *ppTComp = &info->ITypeComp_iface;
5606 ITypeComp_AddRef(*ppTComp);
5607
5608 return S_OK;
5609 }
5610
5611 static const ITypeCompVtbl tlbtcvt =
5612 {
5613
5614 ITypeLibComp_fnQueryInterface,
5615 ITypeLibComp_fnAddRef,
5616 ITypeLibComp_fnRelease,
5617
5618 ITypeLibComp_fnBind,
5619 ITypeLibComp_fnBindType
5620 };
5621
5622 /*================== ITypeInfo(2) Methods ===================================*/
ITypeInfoImpl_Constructor(void)5623 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5624 {
5625 ITypeInfoImpl *pTypeInfoImpl;
5626
5627 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5628 if (pTypeInfoImpl)
5629 {
5630 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5631 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5632 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5633 pTypeInfoImpl->ref = 0;
5634 pTypeInfoImpl->hreftype = -1;
5635 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5636 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5637 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5638 list_init(pTypeInfoImpl->pcustdata_list);
5639 }
5640 TRACE("(%p)\n", pTypeInfoImpl);
5641 return pTypeInfoImpl;
5642 }
5643
5644 /* ITypeInfo::QueryInterface
5645 */
ITypeInfo_fnQueryInterface(ITypeInfo2 * iface,REFIID riid,VOID ** ppvObject)5646 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5647 ITypeInfo2 *iface,
5648 REFIID riid,
5649 VOID **ppvObject)
5650 {
5651 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5652
5653 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5654
5655 *ppvObject=NULL;
5656 if(IsEqualIID(riid, &IID_IUnknown) ||
5657 IsEqualIID(riid,&IID_ITypeInfo)||
5658 IsEqualIID(riid,&IID_ITypeInfo2))
5659 *ppvObject = &This->ITypeInfo2_iface;
5660 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5661 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5662 *ppvObject = &This->ICreateTypeInfo2_iface;
5663 else if(IsEqualIID(riid, &IID_ITypeComp))
5664 *ppvObject = &This->ITypeComp_iface;
5665
5666 if(*ppvObject){
5667 IUnknown_AddRef((IUnknown*)*ppvObject);
5668 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5669 return S_OK;
5670 }
5671 TRACE("-- Interface: E_NOINTERFACE\n");
5672 return E_NOINTERFACE;
5673 }
5674
5675 /* ITypeInfo::AddRef
5676 */
ITypeInfo_fnAddRef(ITypeInfo2 * iface)5677 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5678 {
5679 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5680 ULONG ref = InterlockedIncrement(&This->ref);
5681
5682 TRACE("(%p)->ref is %u\n",This, ref);
5683
5684 if (ref == 1 /* incremented from 0 */)
5685 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5686
5687 return ref;
5688 }
5689
ITypeInfoImpl_Destroy(ITypeInfoImpl * This)5690 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5691 {
5692 UINT i;
5693
5694 TRACE("destroying ITypeInfo(%p)\n",This);
5695
5696 for (i = 0; i < This->typeattr.cFuncs; ++i)
5697 {
5698 int j;
5699 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5700 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5701 {
5702 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5703 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5704 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5705 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5706 }
5707 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5708 heap_free(pFInfo->pParamDesc);
5709 TLB_FreeCustData(&pFInfo->custdata_list);
5710 }
5711 heap_free(This->funcdescs);
5712
5713 for(i = 0; i < This->typeattr.cVars; ++i)
5714 {
5715 TLBVarDesc *pVInfo = &This->vardescs[i];
5716 if (pVInfo->vardesc_create) {
5717 TLB_FreeVarDesc(pVInfo->vardesc_create);
5718 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5719 VariantClear(pVInfo->vardesc.u.lpvarValue);
5720 heap_free(pVInfo->vardesc.u.lpvarValue);
5721 }
5722 TLB_FreeCustData(&pVInfo->custdata_list);
5723 }
5724 heap_free(This->vardescs);
5725
5726 if(This->impltypes){
5727 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5728 TLBImplType *pImpl = &This->impltypes[i];
5729 TLB_FreeCustData(&pImpl->custdata_list);
5730 }
5731 heap_free(This->impltypes);
5732 }
5733
5734 TLB_FreeCustData(&This->custdata_list);
5735
5736 heap_free(This);
5737 }
5738
5739 /* ITypeInfo::Release
5740 */
ITypeInfo_fnRelease(ITypeInfo2 * iface)5741 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5742 {
5743 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5744 ULONG ref = InterlockedDecrement(&This->ref);
5745
5746 TRACE("(%p)->(%u)\n",This, ref);
5747
5748 if (!ref)
5749 {
5750 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5751 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5752 if (not_attached_to_typelib)
5753 heap_free(This);
5754 /* otherwise This will be freed when typelib is freed */
5755 }
5756
5757 return ref;
5758 }
5759
5760 /* ITypeInfo::GetTypeAttr
5761 *
5762 * Retrieves a TYPEATTR structure that contains the attributes of the type
5763 * description.
5764 *
5765 */
ITypeInfo_fnGetTypeAttr(ITypeInfo2 * iface,LPTYPEATTR * ppTypeAttr)5766 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5767 LPTYPEATTR *ppTypeAttr)
5768 {
5769 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5770 SIZE_T size;
5771
5772 TRACE("(%p)\n",This);
5773
5774 size = sizeof(**ppTypeAttr);
5775 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5776 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5777
5778 *ppTypeAttr = heap_alloc(size);
5779 if (!*ppTypeAttr)
5780 return E_OUTOFMEMORY;
5781
5782 **ppTypeAttr = This->typeattr;
5783 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5784
5785 if (This->tdescAlias)
5786 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5787
5788 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5789 /* This should include all the inherited funcs */
5790 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5791 /* This is always the size of IDispatch's vtbl */
5792 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5793 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5794 }
5795 return S_OK;
5796 }
5797
5798 /* ITypeInfo::GetTypeComp
5799 *
5800 * Retrieves the ITypeComp interface for the type description, which enables a
5801 * client compiler to bind to the type description's members.
5802 *
5803 */
ITypeInfo_fnGetTypeComp(ITypeInfo2 * iface,ITypeComp ** ppTComp)5804 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5805 ITypeComp * *ppTComp)
5806 {
5807 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5808
5809 TRACE("(%p)->(%p)\n", This, ppTComp);
5810
5811 *ppTComp = &This->ITypeComp_iface;
5812 ITypeComp_AddRef(*ppTComp);
5813 return S_OK;
5814 }
5815
TLB_SizeElemDesc(const ELEMDESC * elemdesc)5816 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5817 {
5818 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5819 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5820 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5821 return size;
5822 }
5823
TLB_CopyElemDesc(const ELEMDESC * src,ELEMDESC * dest,char ** buffer)5824 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5825 {
5826 *dest = *src;
5827 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5828 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5829 {
5830 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5831 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5832 *buffer += sizeof(PARAMDESCEX);
5833 *pparamdescex_dest = *pparamdescex_src;
5834 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5835 VariantInit(&pparamdescex_dest->varDefaultValue);
5836 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5837 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5838 }
5839 else
5840 dest->u.paramdesc.pparamdescex = NULL;
5841 return S_OK;
5842 }
5843
TLB_SanitizeBSTR(BSTR str)5844 static HRESULT TLB_SanitizeBSTR(BSTR str)
5845 {
5846 UINT len = SysStringLen(str), i;
5847 for (i = 0; i < len; ++i)
5848 if (str[i] > 0x7f)
5849 str[i] = '?';
5850 return S_OK;
5851 }
5852
TLB_SanitizeVariant(VARIANT * var)5853 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5854 {
5855 if (V_VT(var) == VT_INT)
5856 return VariantChangeType(var, var, 0, VT_I4);
5857 else if (V_VT(var) == VT_UINT)
5858 return VariantChangeType(var, var, 0, VT_UI4);
5859 else if (V_VT(var) == VT_BSTR)
5860 return TLB_SanitizeBSTR(V_BSTR(var));
5861
5862 return S_OK;
5863 }
5864
TLB_FreeElemDesc(ELEMDESC * elemdesc)5865 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5866 {
5867 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5868 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5869 }
5870
TLB_AllocAndInitFuncDesc(const FUNCDESC * src,FUNCDESC ** dest_ptr,BOOL dispinterface)5871 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5872 {
5873 FUNCDESC *dest;
5874 char *buffer;
5875 SIZE_T size = sizeof(*src);
5876 SHORT i;
5877 HRESULT hr;
5878
5879 size += sizeof(*src->lprgscode) * src->cScodes;
5880 size += TLB_SizeElemDesc(&src->elemdescFunc);
5881 for (i = 0; i < src->cParams; i++)
5882 {
5883 size += sizeof(ELEMDESC);
5884 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5885 }
5886
5887 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5888 if (!dest) return E_OUTOFMEMORY;
5889
5890 *dest = *src;
5891 if (dispinterface) /* overwrite funckind */
5892 dest->funckind = FUNC_DISPATCH;
5893 buffer = (char *)(dest + 1);
5894
5895 dest->oVft = dest->oVft & 0xFFFC;
5896
5897 if (dest->cScodes) {
5898 dest->lprgscode = (SCODE *)buffer;
5899 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5900 buffer += sizeof(*src->lprgscode) * src->cScodes;
5901 } else
5902 dest->lprgscode = NULL;
5903
5904 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5905 if (FAILED(hr))
5906 {
5907 SysFreeString((BSTR)dest);
5908 return hr;
5909 }
5910
5911 if (dest->cParams) {
5912 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5913 buffer += sizeof(ELEMDESC) * src->cParams;
5914 for (i = 0; i < src->cParams; i++)
5915 {
5916 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5917 if (FAILED(hr))
5918 break;
5919 }
5920 if (FAILED(hr))
5921 {
5922 /* undo the above actions */
5923 for (i = i - 1; i >= 0; i--)
5924 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5925 TLB_FreeElemDesc(&dest->elemdescFunc);
5926 SysFreeString((BSTR)dest);
5927 return hr;
5928 }
5929 } else
5930 dest->lprgelemdescParam = NULL;
5931
5932 /* special treatment for dispinterfaces: this makes functions appear
5933 * to return their [retval] value when it is really returning an
5934 * HRESULT */
5935 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5936 {
5937 if (dest->cParams &&
5938 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5939 {
5940 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5941 if (elemdesc->tdesc.vt != VT_PTR)
5942 {
5943 ERR("elemdesc should have started with VT_PTR instead of:\n");
5944 if (ERR_ON(ole))
5945 dump_ELEMDESC(elemdesc);
5946 return E_UNEXPECTED;
5947 }
5948
5949 /* copy last parameter to the return value. we are using a flat
5950 * buffer so there is no danger of leaking memory in
5951 * elemdescFunc */
5952 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5953
5954 /* remove the last parameter */
5955 dest->cParams--;
5956 }
5957 else
5958 /* otherwise this function is made to appear to have no return
5959 * value */
5960 dest->elemdescFunc.tdesc.vt = VT_VOID;
5961
5962 }
5963
5964 *dest_ptr = dest;
5965 return S_OK;
5966 }
5967
TLB_FreeVarDesc(VARDESC * var_desc)5968 static void TLB_FreeVarDesc(VARDESC *var_desc)
5969 {
5970 TLB_FreeElemDesc(&var_desc->elemdescVar);
5971 if (var_desc->varkind == VAR_CONST)
5972 VariantClear(var_desc->u.lpvarValue);
5973 SysFreeString((BSTR)var_desc);
5974 }
5975
ITypeInfoImpl_GetInternalFuncDesc(ITypeInfo * iface,UINT index,const FUNCDESC ** ppFuncDesc)5976 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5977 {
5978 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5979
5980 if (index >= This->typeattr.cFuncs)
5981 return TYPE_E_ELEMENTNOTFOUND;
5982
5983 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5984 return S_OK;
5985 }
5986
5987 /* internal function to make the inherited interfaces' methods appear
5988 * part of the interface */
ITypeInfoImpl_GetInternalDispatchFuncDesc(ITypeInfo * iface,UINT index,const FUNCDESC ** ppFuncDesc,UINT * funcs,UINT * hrefoffset)5989 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5990 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5991 {
5992 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5993 HRESULT hr;
5994 UINT implemented_funcs = 0;
5995
5996 if (funcs)
5997 *funcs = 0;
5998 else
5999 *hrefoffset = DISPATCH_HREF_OFFSET;
6000
6001 if(This->impltypes)
6002 {
6003 ITypeInfo *pSubTypeInfo;
6004 UINT sub_funcs;
6005
6006 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6007 if (FAILED(hr))
6008 return hr;
6009
6010 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
6011 index,
6012 ppFuncDesc,
6013 &sub_funcs, hrefoffset);
6014 implemented_funcs += sub_funcs;
6015 ITypeInfo_Release(pSubTypeInfo);
6016 if (SUCCEEDED(hr))
6017 return hr;
6018 *hrefoffset += DISPATCH_HREF_OFFSET;
6019 }
6020
6021 if (funcs)
6022 *funcs = implemented_funcs + This->typeattr.cFuncs;
6023 else
6024 *hrefoffset = 0;
6025
6026 if (index < implemented_funcs)
6027 return E_INVALIDARG;
6028 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
6029 ppFuncDesc);
6030 }
6031
ITypeInfoImpl_ElemDescAddHrefOffset(LPELEMDESC pElemDesc,UINT hrefoffset)6032 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
6033 {
6034 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
6035 while (TRUE)
6036 {
6037 switch (pTypeDesc->vt)
6038 {
6039 case VT_USERDEFINED:
6040 pTypeDesc->u.hreftype += hrefoffset;
6041 return;
6042 case VT_PTR:
6043 case VT_SAFEARRAY:
6044 pTypeDesc = pTypeDesc->u.lptdesc;
6045 break;
6046 case VT_CARRAY:
6047 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6048 break;
6049 default:
6050 return;
6051 }
6052 }
6053 }
6054
ITypeInfoImpl_FuncDescAddHrefOffset(LPFUNCDESC pFuncDesc,UINT hrefoffset)6055 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6056 {
6057 SHORT i;
6058 for (i = 0; i < pFuncDesc->cParams; i++)
6059 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6060 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6061 }
6062
6063 /* ITypeInfo::GetFuncDesc
6064 *
6065 * Retrieves the FUNCDESC structure that contains information about a
6066 * specified function.
6067 *
6068 */
ITypeInfo_fnGetFuncDesc(ITypeInfo2 * iface,UINT index,LPFUNCDESC * ppFuncDesc)6069 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6070 LPFUNCDESC *ppFuncDesc)
6071 {
6072 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6073 const FUNCDESC *internal_funcdesc;
6074 HRESULT hr;
6075 UINT hrefoffset = 0;
6076
6077 TRACE("(%p) index %d\n", This, index);
6078
6079 if (!ppFuncDesc)
6080 return E_INVALIDARG;
6081
6082 if (This->needs_layout)
6083 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6084
6085 if (This->typeattr.typekind == TKIND_DISPATCH)
6086 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6087 &internal_funcdesc, NULL,
6088 &hrefoffset);
6089 else
6090 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6091 &internal_funcdesc);
6092 if (FAILED(hr))
6093 {
6094 WARN("description for function %d not found\n", index);
6095 return hr;
6096 }
6097
6098 hr = TLB_AllocAndInitFuncDesc(
6099 internal_funcdesc,
6100 ppFuncDesc,
6101 This->typeattr.typekind == TKIND_DISPATCH);
6102
6103 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6104 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6105
6106 TRACE("-- 0x%08x\n", hr);
6107 return hr;
6108 }
6109
TLB_AllocAndInitVarDesc(const VARDESC * src,VARDESC ** dest_ptr)6110 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6111 {
6112 VARDESC *dest;
6113 char *buffer;
6114 SIZE_T size = sizeof(*src);
6115 HRESULT hr;
6116
6117 if (src->lpstrSchema) size += (lstrlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6118 if (src->varkind == VAR_CONST)
6119 size += sizeof(VARIANT);
6120 size += TLB_SizeElemDesc(&src->elemdescVar);
6121
6122 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6123 if (!dest) return E_OUTOFMEMORY;
6124
6125 *dest = *src;
6126 buffer = (char *)(dest + 1);
6127 if (src->lpstrSchema)
6128 {
6129 int len;
6130 dest->lpstrSchema = (LPOLESTR)buffer;
6131 len = lstrlenW(src->lpstrSchema);
6132 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6133 buffer += (len + 1) * sizeof(WCHAR);
6134 }
6135
6136 if (src->varkind == VAR_CONST)
6137 {
6138 HRESULT hr;
6139
6140 dest->u.lpvarValue = (VARIANT *)buffer;
6141 *dest->u.lpvarValue = *src->u.lpvarValue;
6142 buffer += sizeof(VARIANT);
6143 VariantInit(dest->u.lpvarValue);
6144 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6145 if (FAILED(hr))
6146 {
6147 SysFreeString((BSTR)dest);
6148 return hr;
6149 }
6150 }
6151 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6152 if (FAILED(hr))
6153 {
6154 if (src->varkind == VAR_CONST)
6155 VariantClear(dest->u.lpvarValue);
6156 SysFreeString((BSTR)dest);
6157 return hr;
6158 }
6159 *dest_ptr = dest;
6160 return S_OK;
6161 }
6162
6163 /* ITypeInfo::GetVarDesc
6164 *
6165 * Retrieves a VARDESC structure that describes the specified variable.
6166 *
6167 */
ITypeInfo_fnGetVarDesc(ITypeInfo2 * iface,UINT index,LPVARDESC * ppVarDesc)6168 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6169 LPVARDESC *ppVarDesc)
6170 {
6171 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6172 const TLBVarDesc *pVDesc = &This->vardescs[index];
6173
6174 TRACE("(%p) index %d\n", This, index);
6175
6176 if(index >= This->typeattr.cVars)
6177 return TYPE_E_ELEMENTNOTFOUND;
6178
6179 if (This->needs_layout)
6180 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6181
6182 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6183 }
6184
6185 /* ITypeInfo_GetNames
6186 *
6187 * Retrieves the variable with the specified member ID (or the name of the
6188 * property or method and its parameters) that correspond to the specified
6189 * function ID.
6190 */
ITypeInfo_fnGetNames(ITypeInfo2 * iface,MEMBERID memid,BSTR * rgBstrNames,UINT cMaxNames,UINT * pcNames)6191 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6192 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6193 {
6194 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6195 const TLBFuncDesc *pFDesc;
6196 const TLBVarDesc *pVDesc;
6197 int i;
6198 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6199
6200 if(!rgBstrNames)
6201 return E_INVALIDARG;
6202
6203 *pcNames = 0;
6204
6205 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6206 if(pFDesc)
6207 {
6208 if(!cMaxNames || !pFDesc->Name)
6209 return S_OK;
6210
6211 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6212 ++(*pcNames);
6213
6214 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6215 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6216 return S_OK;
6217 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6218 ++(*pcNames);
6219 }
6220 return S_OK;
6221 }
6222
6223 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6224 if(pVDesc)
6225 {
6226 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6227 *pcNames=1;
6228 }
6229 else
6230 {
6231 if(This->impltypes &&
6232 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6233 /* recursive search */
6234 ITypeInfo *pTInfo;
6235 HRESULT result;
6236 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6237 if(SUCCEEDED(result))
6238 {
6239 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6240 ITypeInfo_Release(pTInfo);
6241 return result;
6242 }
6243 WARN("Could not search inherited interface!\n");
6244 }
6245 else
6246 {
6247 WARN("no names found\n");
6248 }
6249 *pcNames=0;
6250 return TYPE_E_ELEMENTNOTFOUND;
6251 }
6252 return S_OK;
6253 }
6254
6255
6256 /* ITypeInfo::GetRefTypeOfImplType
6257 *
6258 * If a type description describes a COM class, it retrieves the type
6259 * description of the implemented interface types. For an interface,
6260 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6261 * if any exist.
6262 *
6263 */
ITypeInfo_fnGetRefTypeOfImplType(ITypeInfo2 * iface,UINT index,HREFTYPE * pRefType)6264 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6265 ITypeInfo2 *iface,
6266 UINT index,
6267 HREFTYPE *pRefType)
6268 {
6269 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6270 HRESULT hr = S_OK;
6271
6272 TRACE("(%p) index %d\n", This, index);
6273 if (TRACE_ON(ole)) dump_TypeInfo(This);
6274
6275 if(index==(UINT)-1)
6276 {
6277 /* only valid on dual interfaces;
6278 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6279 */
6280
6281 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6282 {
6283 *pRefType = -2;
6284 }
6285 else
6286 {
6287 hr = TYPE_E_ELEMENTNOTFOUND;
6288 }
6289 }
6290 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6291 {
6292 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6293 *pRefType = This->pTypeLib->dispatch_href;
6294 }
6295 else
6296 {
6297 if(index >= This->typeattr.cImplTypes)
6298 hr = TYPE_E_ELEMENTNOTFOUND;
6299 else{
6300 *pRefType = This->impltypes[index].hRef;
6301 if (This->typeattr.typekind == TKIND_INTERFACE)
6302 *pRefType |= 0x2;
6303 }
6304 }
6305
6306 if(TRACE_ON(ole))
6307 {
6308 if(SUCCEEDED(hr))
6309 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6310 else
6311 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6312 }
6313
6314 return hr;
6315 }
6316
6317 /* ITypeInfo::GetImplTypeFlags
6318 *
6319 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6320 * or base interface in a type description.
6321 */
ITypeInfo_fnGetImplTypeFlags(ITypeInfo2 * iface,UINT index,INT * pImplTypeFlags)6322 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6323 UINT index, INT *pImplTypeFlags)
6324 {
6325 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6326
6327 TRACE("(%p) index %d\n", This, index);
6328
6329 if(!pImplTypeFlags)
6330 return E_INVALIDARG;
6331
6332 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6333 *pImplTypeFlags = 0;
6334 return S_OK;
6335 }
6336
6337 if(index >= This->typeattr.cImplTypes)
6338 return TYPE_E_ELEMENTNOTFOUND;
6339
6340 *pImplTypeFlags = This->impltypes[index].implflags;
6341
6342 return S_OK;
6343 }
6344
6345 /* GetIDsOfNames
6346 * Maps between member names and member IDs, and parameter names and
6347 * parameter IDs.
6348 */
ITypeInfo_fnGetIDsOfNames(ITypeInfo2 * iface,LPOLESTR * rgszNames,UINT cNames,MEMBERID * pMemId)6349 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6350 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6351 {
6352 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6353 const TLBVarDesc *pVDesc;
6354 HRESULT ret=S_OK;
6355 UINT i, fdc;
6356
6357 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6358 cNames);
6359
6360 /* init out parameters in case of failure */
6361 for (i = 0; i < cNames; i++)
6362 pMemId[i] = MEMBERID_NIL;
6363
6364 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6365 int j;
6366 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6367 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6368 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6369 for(i=1; i < cNames; i++){
6370 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6371 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6372 break;
6373 if( j<pFDesc->funcdesc.cParams)
6374 pMemId[i]=j;
6375 else
6376 ret=DISP_E_UNKNOWNNAME;
6377 };
6378 TRACE("-- 0x%08x\n", ret);
6379 return ret;
6380 }
6381 }
6382 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6383 if(pVDesc){
6384 if(cNames)
6385 *pMemId = pVDesc->vardesc.memid;
6386 return ret;
6387 }
6388 /* not found, see if it can be found in an inherited interface */
6389 if(This->impltypes) {
6390 /* recursive search */
6391 ITypeInfo *pTInfo;
6392 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6393 if(SUCCEEDED(ret)){
6394 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6395 ITypeInfo_Release(pTInfo);
6396 return ret;
6397 }
6398 WARN("Could not search inherited interface!\n");
6399 } else
6400 WARN("no names found\n");
6401 return DISP_E_UNKNOWNNAME;
6402 }
6403
6404
6405 #ifdef __i386__
6406
6407 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6408 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6409 __ASM_GLOBAL_FUNC( call_method,
6410 "pushl %ebp\n\t"
6411 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6412 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6413 "movl %esp,%ebp\n\t"
6414 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6415 "pushl %esi\n\t"
6416 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6417 "pushl %edi\n\t"
6418 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6419 "movl 12(%ebp),%edx\n\t"
6420 "movl %esp,%edi\n\t"
6421 "shll $2,%edx\n\t"
6422 "jz 1f\n\t"
6423 "subl %edx,%edi\n\t"
6424 "andl $~15,%edi\n\t"
6425 "movl %edi,%esp\n\t"
6426 "movl 12(%ebp),%ecx\n\t"
6427 "movl 16(%ebp),%esi\n\t"
6428 "cld\n\t"
6429 "rep; movsl\n"
6430 "1:\tcall *8(%ebp)\n\t"
6431 "subl %esp,%edi\n\t"
6432 "movl 20(%ebp),%ecx\n\t"
6433 "movl %edi,(%ecx)\n\t"
6434 "leal -8(%ebp),%esp\n\t"
6435 "popl %edi\n\t"
6436 __ASM_CFI(".cfi_same_value %edi\n\t")
6437 "popl %esi\n\t"
6438 __ASM_CFI(".cfi_same_value %esi\n\t")
6439 "popl %ebp\n\t"
6440 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6441 __ASM_CFI(".cfi_same_value %ebp\n\t")
6442 "ret" )
6443 __ASM_GLOBAL_FUNC( call_double_method,
6444 "jmp " __ASM_NAME("call_method") )
6445
DispCallFunc(void * pvInstance,ULONG_PTR oVft,CALLCONV cc,VARTYPE vtReturn,UINT cActuals,VARTYPE * prgvt,VARIANTARG ** prgpvarg,VARIANT * pvargResult)6446 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6447 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6448 {
6449 int argspos = 0, stack_offset;
6450 void *func;
6451 UINT i;
6452 DWORD *args;
6453
6454 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6455 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6456 pvargResult, V_VT(pvargResult));
6457
6458 if (cc != CC_STDCALL && cc != CC_CDECL)
6459 {
6460 FIXME("unsupported calling convention %d\n",cc);
6461 return E_INVALIDARG;
6462 }
6463
6464 /* maximum size for an argument is sizeof(VARIANT) */
6465 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6466
6467 if (pvInstance)
6468 {
6469 const FARPROC *vtable = *(FARPROC **)pvInstance;
6470 func = vtable[oVft/sizeof(void *)];
6471 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6472 }
6473 else func = (void *)oVft;
6474
6475 switch (vtReturn)
6476 {
6477 case VT_DECIMAL:
6478 case VT_VARIANT:
6479 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6480 break;
6481 case VT_HRESULT:
6482 WARN("invalid return type %u\n", vtReturn);
6483 heap_free( args );
6484 return E_INVALIDARG;
6485 default:
6486 break;
6487 }
6488
6489 for (i = 0; i < cActuals; i++)
6490 {
6491 VARIANT *arg = prgpvarg[i];
6492
6493 switch (prgvt[i])
6494 {
6495 case VT_EMPTY:
6496 break;
6497 case VT_I8:
6498 case VT_UI8:
6499 case VT_R8:
6500 case VT_DATE:
6501 case VT_CY:
6502 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6503 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6504 break;
6505 case VT_DECIMAL:
6506 case VT_VARIANT:
6507 memcpy( &args[argspos], arg, sizeof(*arg) );
6508 argspos += sizeof(*arg) / sizeof(DWORD);
6509 break;
6510 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6511 args[argspos++] = V_BOOL(arg);
6512 break;
6513 default:
6514 args[argspos++] = V_UI4(arg);
6515 break;
6516 }
6517 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6518 }
6519
6520 switch (vtReturn)
6521 {
6522 case VT_EMPTY:
6523 case VT_DECIMAL:
6524 case VT_VARIANT:
6525 call_method( func, argspos, args, &stack_offset );
6526 break;
6527 case VT_R4:
6528 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6529 break;
6530 case VT_R8:
6531 case VT_DATE:
6532 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6533 break;
6534 case VT_I8:
6535 case VT_UI8:
6536 case VT_CY:
6537 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6538 break;
6539 default:
6540 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6541 break;
6542 }
6543 heap_free( args );
6544 if (stack_offset && cc == CC_STDCALL)
6545 {
6546 WARN( "stack pointer off by %d\n", stack_offset );
6547 return DISP_E_BADCALLEE;
6548 }
6549 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6550 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6551 return S_OK;
6552 }
6553
6554 #elif defined(__x86_64__)
6555
6556 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6557 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6558 __ASM_GLOBAL_FUNC( call_method,
6559 "pushq %rbp\n\t"
6560 __ASM_SEH(".seh_pushreg %rbp\n\t")
6561 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6562 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6563 "movq %rsp,%rbp\n\t"
6564 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6565 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6566 "pushq %rsi\n\t"
6567 __ASM_SEH(".seh_pushreg %rsi\n\t")
6568 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6569 "pushq %rdi\n\t"
6570 __ASM_SEH(".seh_pushreg %rdi\n\t")
6571 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6572 __ASM_SEH(".seh_endprologue\n\t")
6573 "movq %rcx,%rax\n\t"
6574 "movq $4,%rcx\n\t"
6575 "cmp %rcx,%rdx\n\t"
6576 "cmovgq %rdx,%rcx\n\t"
6577 "leaq 0(,%rcx,8),%rdx\n\t"
6578 "subq %rdx,%rsp\n\t"
6579 "andq $~15,%rsp\n\t"
6580 "movq %rsp,%rdi\n\t"
6581 "movq %r8,%rsi\n\t"
6582 "rep; movsq\n\t"
6583 "movq 0(%rsp),%rcx\n\t"
6584 "movq 8(%rsp),%rdx\n\t"
6585 "movq 16(%rsp),%r8\n\t"
6586 "movq 24(%rsp),%r9\n\t"
6587 "movq 0(%rsp),%xmm0\n\t"
6588 "movq 8(%rsp),%xmm1\n\t"
6589 "movq 16(%rsp),%xmm2\n\t"
6590 "movq 24(%rsp),%xmm3\n\t"
6591 "callq *%rax\n\t"
6592 "leaq -16(%rbp),%rsp\n\t"
6593 "popq %rdi\n\t"
6594 __ASM_CFI(".cfi_same_value %rdi\n\t")
6595 "popq %rsi\n\t"
6596 __ASM_CFI(".cfi_same_value %rsi\n\t")
6597 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6598 "popq %rbp\n\t"
6599 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6600 __ASM_CFI(".cfi_same_value %rbp\n\t")
6601 "ret")
6602 __ASM_GLOBAL_FUNC( call_double_method,
6603 "jmp " __ASM_NAME("call_method") )
6604
DispCallFunc(void * pvInstance,ULONG_PTR oVft,CALLCONV cc,VARTYPE vtReturn,UINT cActuals,VARTYPE * prgvt,VARIANTARG ** prgpvarg,VARIANT * pvargResult)6605 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6606 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6607 {
6608 int argspos = 0;
6609 UINT i;
6610 DWORD_PTR *args;
6611 void *func;
6612
6613 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6614 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6615 pvargResult, V_VT(pvargResult));
6616
6617 if (cc != CC_STDCALL && cc != CC_CDECL)
6618 {
6619 FIXME("unsupported calling convention %d\n",cc);
6620 return E_INVALIDARG;
6621 }
6622
6623 /* maximum size for an argument is sizeof(DWORD_PTR) */
6624 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6625
6626 if (pvInstance)
6627 {
6628 const FARPROC *vtable = *(FARPROC **)pvInstance;
6629 func = vtable[oVft/sizeof(void *)];
6630 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6631 }
6632 else func = (void *)oVft;
6633
6634 switch (vtReturn)
6635 {
6636 case VT_DECIMAL:
6637 case VT_VARIANT:
6638 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6639 break;
6640 case VT_HRESULT:
6641 WARN("invalid return type %u\n", vtReturn);
6642 heap_free( args );
6643 return E_INVALIDARG;
6644 default:
6645 break;
6646 }
6647
6648 for (i = 0; i < cActuals; i++)
6649 {
6650 VARIANT *arg = prgpvarg[i];
6651
6652 switch (prgvt[i])
6653 {
6654 case VT_DECIMAL:
6655 case VT_VARIANT:
6656 args[argspos++] = (ULONG_PTR)arg;
6657 break;
6658 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6659 args[argspos++] = V_BOOL(arg);
6660 break;
6661 default:
6662 args[argspos++] = V_UI8(arg);
6663 break;
6664 }
6665 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6666 }
6667
6668 switch (vtReturn)
6669 {
6670 case VT_R4:
6671 V_R4(pvargResult) = call_double_method( func, argspos, args );
6672 break;
6673 case VT_R8:
6674 case VT_DATE:
6675 V_R8(pvargResult) = call_double_method( func, argspos, args );
6676 break;
6677 case VT_DECIMAL:
6678 case VT_VARIANT:
6679 call_method( func, argspos, args );
6680 break;
6681 default:
6682 V_UI8(pvargResult) = call_method( func, argspos, args );
6683 break;
6684 }
6685 heap_free( args );
6686 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6687 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6688 return S_OK;
6689 }
6690
6691 #elif defined(__arm__)
6692
6693 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6694 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6695 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6696 __ASM_GLOBAL_FUNC( call_method,
6697 /* r0 = *func
6698 * r1 = nb_stk_args
6699 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6700 * 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)
6701 */
6702
6703 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6704 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6705
6706 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6707 "beq 1f\n\t" /* Skip allocation if no stack args */
6708 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6709 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6710 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6711 "subs r1, r1, #4\n\t" /* Decrement count */
6712 "bgt 2b\n\t" /* Loop till done */
6713
6714 "1:\n\t"
6715 #ifndef __SOFTFP__
6716 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6717 #endif
6718 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6719 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6720
6721 "blx ip\n\t" /* Call the target function */
6722
6723 "mov sp, fp\n\t" /* Clean the stack using fp */
6724 "pop {fp, pc}\n\t" /* Restore fp and return */
6725 )
6726 __ASM_GLOBAL_FUNC( call_float_method,
6727 "b " __ASM_NAME("call_method") )
6728 __ASM_GLOBAL_FUNC( call_double_method,
6729 "b " __ASM_NAME("call_method") )
6730
DispCallFunc(void * pvInstance,ULONG_PTR oVft,CALLCONV cc,VARTYPE vtReturn,UINT cActuals,VARTYPE * prgvt,VARIANTARG ** prgpvarg,VARIANT * pvargResult)6731 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
6732 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
6733 {
6734 int argspos;
6735 void *func;
6736 UINT i;
6737 DWORD *args;
6738 struct {
6739 #ifndef __SOFTFP__
6740 union {
6741 float s[16];
6742 double d[8];
6743 } sd;
6744 #endif
6745 DWORD r[4];
6746 } regs;
6747 int rcount; /* 32-bit register index count */
6748 #ifndef __SOFTFP__
6749 int scount = 0; /* single-precision float register index count */
6750 int dcount = 0; /* double-precision float register index count */
6751 #endif
6752
6753 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6754 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6755
6756 if (cc != CC_STDCALL && cc != CC_CDECL)
6757 {
6758 FIXME("unsupported calling convention %d\n",cc);
6759 return E_INVALIDARG;
6760 }
6761
6762 argspos = 0;
6763 rcount = 0;
6764
6765 if (pvInstance)
6766 {
6767 const FARPROC *vtable = *(FARPROC **)pvInstance;
6768 func = vtable[oVft/sizeof(void *)];
6769 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6770 }
6771 else func = (void *)oVft;
6772
6773 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6774 /* first as it will need to be in the 'r' registers: */
6775 switch (vtReturn)
6776 {
6777 case VT_DECIMAL:
6778 case VT_VARIANT:
6779 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6780 break;
6781 case VT_HRESULT:
6782 WARN("invalid return type %u\n", vtReturn);
6783 return E_INVALIDARG;
6784 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6785 break;
6786 }
6787
6788 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6789 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6790
6791 for (i = 0; i < cActuals; i++)
6792 {
6793 VARIANT *arg = prgpvarg[i];
6794 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6795 int ntemp; /* Used for counting words split between registers and stack */
6796
6797 switch (prgvt[i])
6798 {
6799 case VT_EMPTY:
6800 break;
6801 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6802 case VT_DATE:
6803 #ifndef __SOFTFP__
6804 dcount = max( (scount + 1) / 2, dcount );
6805 if (dcount < 8)
6806 {
6807 regs.sd.d[dcount++] = V_R8(arg);
6808 }
6809 else
6810 {
6811 argspos += (argspos % 2); /* align argspos to 8-bytes */
6812 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6813 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6814 }
6815 break;
6816 #endif
6817 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6818 case VT_UI8:
6819 case VT_CY:
6820 if (rcount < 3)
6821 {
6822 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6823 memcpy( ®s.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6824 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6825 }
6826 else
6827 {
6828 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6829 argspos += (argspos % 2); /* align argspos to 8-bytes */
6830 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6831 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6832 }
6833 break;
6834 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6835 case VT_VARIANT:
6836 /* 8-byte align 'r' and/or stack: */
6837 if (rcount < 3)
6838 rcount += (rcount % 2);
6839 else
6840 {
6841 rcount = 4;
6842 argspos += (argspos % 2);
6843 }
6844 ntemp = sizeof(*arg) / sizeof(DWORD);
6845 while (ntemp > 0)
6846 {
6847 if (rcount < 4)
6848 regs.r[rcount++] = *pdwarg++;
6849 else
6850 args[argspos++] = *pdwarg++;
6851 --ntemp;
6852 }
6853 break;
6854 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6855 if (rcount < 4)
6856 regs.r[rcount++] = V_BOOL(arg);
6857 else
6858 args[argspos++] = V_BOOL(arg);
6859 break;
6860 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6861 #ifndef __SOFTFP__
6862 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6863 if (scount < 16)
6864 regs.sd.s[scount++] = V_R4(arg);
6865 else
6866 args[argspos++] = V_UI4(arg);
6867 break;
6868 #endif
6869 default:
6870 if (rcount < 4)
6871 regs.r[rcount++] = V_UI4(arg);
6872 else
6873 args[argspos++] = V_UI4(arg);
6874 break;
6875 }
6876 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6877 }
6878
6879 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
6880
6881 switch (vtReturn)
6882 {
6883 case VT_EMPTY: /* EMPTY = no return value */
6884 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6885 case VT_VARIANT:
6886 call_method( func, argspos, args, (DWORD*)®s );
6887 break;
6888 case VT_R4:
6889 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)®s );
6890 break;
6891 case VT_R8:
6892 case VT_DATE:
6893 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)®s );
6894 break;
6895 case VT_I8:
6896 case VT_UI8:
6897 case VT_CY:
6898 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)®s );
6899 break;
6900 default:
6901 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)®s );
6902 break;
6903 }
6904 heap_free( args );
6905 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6906 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6907 return S_OK;
6908 }
6909
6910 #elif defined(__aarch64__)
6911
6912 extern DWORD_PTR CDECL call_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6913 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6914 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD_PTR *stk_args, const DWORD_PTR *reg_args );
6915 __ASM_GLOBAL_FUNC( call_method,
6916 "stp x29, x30, [sp, #-16]!\n\t"
6917 "mov x29, sp\n\t"
6918 "sub sp, sp, x1, lsl #3\n\t"
6919 "cbz x1, 2f\n"
6920 "1:\tsub x1, x1, #1\n\t"
6921 "ldr x4, [x2, x1, lsl #3]\n\t"
6922 "str x4, [sp, x1, lsl #3]\n\t"
6923 "cbnz x1, 1b\n"
6924 "2:\tmov x16, x0\n\t"
6925 "mov x9, x3\n\t"
6926 "ldp d0, d1, [x9]\n\t"
6927 "ldp d2, d3, [x9, #0x10]\n\t"
6928 "ldp d4, d5, [x9, #0x20]\n\t"
6929 "ldp d6, d7, [x9, #0x30]\n\t"
6930 "ldp x0, x1, [x9, #0x40]\n\t"
6931 "ldp x2, x3, [x9, #0x50]\n\t"
6932 "ldp x4, x5, [x9, #0x60]\n\t"
6933 "ldp x6, x7, [x9, #0x70]\n\t"
6934 "ldr x8, [x9, #0x80]\n\t"
6935 "blr x16\n\t"
6936 "mov sp, x29\n\t"
6937 "ldp x29, x30, [sp], #16\n\t"
6938 "ret" )
6939 __ASM_GLOBAL_FUNC( call_float_method,
6940 "b " __ASM_NAME("call_method") )
6941 __ASM_GLOBAL_FUNC( call_double_method,
6942 "b " __ASM_NAME("call_method") )
6943
DispCallFunc(void * instance,ULONG_PTR offset,CALLCONV cc,VARTYPE ret_type,UINT count,VARTYPE * types,VARIANTARG ** vargs,VARIANT * result)6944 HRESULT WINAPI DispCallFunc( void *instance, ULONG_PTR offset, CALLCONV cc, VARTYPE ret_type, UINT count,
6945 VARTYPE *types, VARIANTARG **vargs, VARIANT *result )
6946 {
6947 int argspos;
6948 void *func;
6949 UINT i;
6950 DWORD_PTR *args;
6951 struct
6952 {
6953 union
6954 {
6955 float f;
6956 double d;
6957 } fp[8];
6958 DWORD_PTR x[9];
6959 } regs;
6960 int rcount; /* 64-bit register index count */
6961 int fpcount = 0; /* float register index count */
6962
6963 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6964 instance, offset, cc, ret_type, count, types, vargs, result, V_VT(result));
6965
6966 if (cc != CC_STDCALL && cc != CC_CDECL)
6967 {
6968 FIXME("unsupported calling convention %d\n",cc);
6969 return E_INVALIDARG;
6970 }
6971
6972 argspos = 0;
6973 rcount = 0;
6974
6975 if (instance)
6976 {
6977 const FARPROC *vtable = *(FARPROC **)instance;
6978 func = vtable[offset/sizeof(void *)];
6979 regs.x[rcount++] = (DWORD_PTR)instance; /* the This pointer is always the first parameter */
6980 }
6981 else func = (void *)offset;
6982
6983 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6984 /* first as it will need to be in the 'x' registers: */
6985 switch (ret_type)
6986 {
6987 case VT_DECIMAL:
6988 case VT_VARIANT:
6989 regs.x[8] = (DWORD_PTR)result; /* x8 is a pointer to the result */
6990 break;
6991 case VT_HRESULT:
6992 WARN("invalid return type %u\n", ret_type);
6993 return E_INVALIDARG;
6994 default:
6995 break;
6996 }
6997
6998 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6999 args = heap_alloc( sizeof(VARIANT) * count + sizeof(DWORD_PTR) * 4 );
7000
7001 for (i = 0; i < count; i++)
7002 {
7003 VARIANT *arg = vargs[i];
7004
7005 switch (types[i])
7006 {
7007 case VT_EMPTY:
7008 break;
7009 case VT_R4:
7010 if (fpcount < 8) regs.fp[fpcount++].f = V_R4(arg);
7011 else *(float *)&args[argspos++] = V_R4(arg);
7012 break;
7013 case VT_R8:
7014 case VT_DATE:
7015 if (fpcount < 8) regs.fp[fpcount++].d = V_R8(arg);
7016 else *(double *)&args[argspos++] = V_R8(arg);
7017 break;
7018 case VT_DECIMAL:
7019 case VT_VARIANT:
7020 if (rcount < 7)
7021 {
7022 memcpy( ®s.x[rcount], arg, sizeof(*arg) );
7023 rcount += 2;
7024 }
7025 else
7026 {
7027 memcpy( &args[argspos], arg, sizeof(*arg) );
7028 argspos += 2;
7029 }
7030 break;
7031 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
7032 if (rcount < 8) regs.x[rcount++] = V_BOOL(arg);
7033 else args[argspos++] = V_BOOL(arg);
7034 break;
7035 default:
7036 if (rcount < 8) regs.x[rcount++] = V_UI8(arg);
7037 else args[argspos++] = V_UI8(arg);
7038 break;
7039 }
7040 TRACE("arg %u: type %s %s\n", i, debugstr_vt(types[i]), debugstr_variant(arg));
7041 }
7042
7043 argspos += (argspos % 2); /* Make sure stack function alignment is 16-byte */
7044
7045 switch (ret_type)
7046 {
7047 case VT_EMPTY: /* EMPTY = no return value */
7048 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7049 case VT_VARIANT:
7050 call_method( func, argspos, args, (DWORD_PTR *)®s );
7051 break;
7052 case VT_R4:
7053 V_R4(result) = call_float_method( func, argspos, args, (DWORD_PTR *)®s );
7054 break;
7055 case VT_R8:
7056 case VT_DATE:
7057 V_R8(result) = call_double_method( func, argspos, args, (DWORD_PTR *)®s );
7058 break;
7059 default:
7060 V_UI8(result) = call_method( func, argspos, args, (DWORD_PTR *)®s );
7061 break;
7062 }
7063 heap_free( args );
7064 if (ret_type != VT_VARIANT) V_VT(result) = ret_type;
7065 TRACE("retval: %s\n", debugstr_variant(result));
7066 return S_OK;
7067 }
7068
7069 #else /* __aarch64__ */
7070
DispCallFunc(void * pvInstance,ULONG_PTR oVft,CALLCONV cc,VARTYPE vtReturn,UINT cActuals,VARTYPE * prgvt,VARIANTARG ** prgpvarg,VARIANT * pvargResult)7071 HRESULT WINAPI DispCallFunc( void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn,
7072 UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult )
7073 {
7074 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7075 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
7076 return E_NOTIMPL;
7077 }
7078
7079 #endif
7080
userdefined_to_variantvt(ITypeInfo * tinfo,const TYPEDESC * tdesc,VARTYPE * vt)7081 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7082 {
7083 HRESULT hr = S_OK;
7084 ITypeInfo *tinfo2 = NULL;
7085 TYPEATTR *tattr = NULL;
7086
7087 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
7088 if (hr)
7089 {
7090 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
7091 "hr = 0x%08x\n",
7092 tdesc->u.hreftype, hr);
7093 return hr;
7094 }
7095 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7096 if (hr)
7097 {
7098 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
7099 ITypeInfo_Release(tinfo2);
7100 return hr;
7101 }
7102
7103 switch (tattr->typekind)
7104 {
7105 case TKIND_ENUM:
7106 *vt |= VT_I4;
7107 break;
7108
7109 case TKIND_ALIAS:
7110 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
7111 break;
7112
7113 case TKIND_INTERFACE:
7114 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
7115 *vt |= VT_DISPATCH;
7116 else
7117 *vt |= VT_UNKNOWN;
7118 break;
7119
7120 case TKIND_DISPATCH:
7121 *vt |= VT_DISPATCH;
7122 break;
7123
7124 case TKIND_COCLASS:
7125 *vt |= VT_DISPATCH;
7126 break;
7127
7128 case TKIND_RECORD:
7129 FIXME("TKIND_RECORD unhandled.\n");
7130 hr = E_NOTIMPL;
7131 break;
7132
7133 case TKIND_UNION:
7134 FIXME("TKIND_UNION unhandled.\n");
7135 hr = E_NOTIMPL;
7136 break;
7137
7138 default:
7139 FIXME("TKIND %d unhandled.\n",tattr->typekind);
7140 hr = E_NOTIMPL;
7141 break;
7142 }
7143 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7144 ITypeInfo_Release(tinfo2);
7145 return hr;
7146 }
7147
typedescvt_to_variantvt(ITypeInfo * tinfo,const TYPEDESC * tdesc,VARTYPE * vt)7148 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
7149 {
7150 HRESULT hr = S_OK;
7151
7152 /* enforce only one level of pointer indirection */
7153 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
7154 {
7155 tdesc = tdesc->u.lptdesc;
7156
7157 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7158 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7159 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7160 if ((tdesc->vt == VT_USERDEFINED) ||
7161 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
7162 {
7163 VARTYPE vt_userdefined = 0;
7164 const TYPEDESC *tdesc_userdefined = tdesc;
7165 if (tdesc->vt == VT_PTR)
7166 {
7167 vt_userdefined = VT_BYREF;
7168 tdesc_userdefined = tdesc->u.lptdesc;
7169 }
7170 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
7171 if ((hr == S_OK) &&
7172 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
7173 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
7174 {
7175 *vt |= vt_userdefined;
7176 return S_OK;
7177 }
7178 }
7179 *vt = VT_BYREF;
7180 }
7181
7182 switch (tdesc->vt)
7183 {
7184 case VT_HRESULT:
7185 *vt |= VT_ERROR;
7186 break;
7187 case VT_USERDEFINED:
7188 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
7189 break;
7190 case VT_VOID:
7191 case VT_CARRAY:
7192 case VT_PTR:
7193 case VT_LPSTR:
7194 case VT_LPWSTR:
7195 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
7196 hr = DISP_E_BADVARTYPE;
7197 break;
7198 case VT_SAFEARRAY:
7199 *vt |= VT_ARRAY;
7200 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
7201 break;
7202 case VT_INT:
7203 *vt |= VT_I4;
7204 break;
7205 case VT_UINT:
7206 *vt |= VT_UI4;
7207 break;
7208 default:
7209 *vt |= tdesc->vt;
7210 break;
7211 }
7212 return hr;
7213 }
7214
get_iface_guid(ITypeInfo * tinfo,HREFTYPE href,GUID * guid)7215 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
7216 {
7217 ITypeInfo *tinfo2;
7218 TYPEATTR *tattr;
7219 HRESULT hres;
7220 int flags, i;
7221
7222 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
7223 if(FAILED(hres))
7224 return hres;
7225
7226 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
7227 if(FAILED(hres)) {
7228 ITypeInfo_Release(tinfo2);
7229 return hres;
7230 }
7231
7232 switch(tattr->typekind) {
7233 case TKIND_ALIAS:
7234 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
7235 break;
7236
7237 case TKIND_INTERFACE:
7238 case TKIND_DISPATCH:
7239 *guid = tattr->guid;
7240 break;
7241
7242 case TKIND_COCLASS:
7243 for (i = 0; i < tattr->cImplTypes; i++)
7244 {
7245 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
7246 if (flags & IMPLTYPEFLAG_FDEFAULT)
7247 break;
7248 }
7249
7250 if (i == tattr->cImplTypes)
7251 i = 0;
7252
7253 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
7254 if (SUCCEEDED(hres))
7255 hres = get_iface_guid(tinfo2, href, guid);
7256 break;
7257
7258 default:
7259 ERR("Unexpected typekind %d\n", tattr->typekind);
7260 hres = E_UNEXPECTED;
7261 }
7262
7263 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
7264 ITypeInfo_Release(tinfo2);
7265 return hres;
7266 }
7267
func_restricted(const FUNCDESC * desc)7268 static inline BOOL func_restricted( const FUNCDESC *desc )
7269 {
7270 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7271 }
7272
7273 #define INVBUF_ELEMENT_SIZE \
7274 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7275 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7276 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7277 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7278 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7279 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7280 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7281 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7282
ITypeInfo_fnInvoke(ITypeInfo2 * iface,VOID * pIUnk,MEMBERID memid,UINT16 wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * pArgErr)7283 static HRESULT WINAPI ITypeInfo_fnInvoke(
7284 ITypeInfo2 *iface,
7285 VOID *pIUnk,
7286 MEMBERID memid,
7287 UINT16 wFlags,
7288 DISPPARAMS *pDispParams,
7289 VARIANT *pVarResult,
7290 EXCEPINFO *pExcepInfo,
7291 UINT *pArgErr)
7292 {
7293 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7294 int i;
7295 unsigned int var_index;
7296 TYPEKIND type_kind;
7297 HRESULT hres;
7298 const TLBFuncDesc *pFuncInfo;
7299 UINT fdc;
7300
7301 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7302 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7303 );
7304
7305 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7306 return DISP_E_MEMBERNOTFOUND;
7307
7308 if (!pDispParams)
7309 {
7310 ERR("NULL pDispParams not allowed\n");
7311 return E_INVALIDARG;
7312 }
7313
7314 dump_DispParms(pDispParams);
7315
7316 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7317 {
7318 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7319 pDispParams->cNamedArgs, pDispParams->cArgs);
7320 return E_INVALIDARG;
7321 }
7322
7323 /* we do this instead of using GetFuncDesc since it will return a fake
7324 * FUNCDESC for dispinterfaces and we want the real function description */
7325 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7326 pFuncInfo = &This->funcdescs[fdc];
7327 if ((memid == pFuncInfo->funcdesc.memid) &&
7328 (wFlags & pFuncInfo->funcdesc.invkind) &&
7329 !func_restricted( &pFuncInfo->funcdesc ))
7330 break;
7331 }
7332
7333 if (fdc < This->typeattr.cFuncs) {
7334 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7335
7336 if (TRACE_ON(ole))
7337 {
7338 TRACE("invoking:\n");
7339 dump_TLBFuncDescOne(pFuncInfo);
7340 }
7341
7342 switch (func_desc->funckind) {
7343 case FUNC_PUREVIRTUAL:
7344 case FUNC_VIRTUAL: {
7345 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7346 VARIANT varresult;
7347 VARIANT retval; /* pointer for storing byref retvals in */
7348 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7349 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7350 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7351 UINT cNamedArgs = pDispParams->cNamedArgs;
7352 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7353 UINT vargs_converted=0;
7354
7355 hres = S_OK;
7356
7357 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7358 {
7359 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7360 {
7361 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7362 hres = DISP_E_PARAMNOTFOUND;
7363 goto func_fail;
7364 }
7365 }
7366
7367 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7368 {
7369 ERR("functions with the vararg attribute do not support named arguments\n");
7370 hres = DISP_E_NONAMEDARGS;
7371 goto func_fail;
7372 }
7373
7374 for (i = 0; i < func_desc->cParams; i++)
7375 {
7376 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7377 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7378 if (FAILED(hres))
7379 goto func_fail;
7380 }
7381
7382 TRACE("changing args\n");
7383 for (i = 0; i < func_desc->cParams; i++)
7384 {
7385 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7386 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7387 VARIANTARG *src_arg;
7388
7389 if (wParamFlags & PARAMFLAG_FLCID)
7390 {
7391 VARIANTARG *arg;
7392 arg = prgpvarg[i] = &rgvarg[i];
7393 V_VT(arg) = VT_I4;
7394 V_I4(arg) = This->pTypeLib->lcid;
7395 continue;
7396 }
7397
7398 src_arg = NULL;
7399
7400 if (cNamedArgs)
7401 {
7402 USHORT j;
7403 for (j = 0; j < cNamedArgs; j++)
7404 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7405 {
7406 src_arg = &pDispParams->rgvarg[j];
7407 break;
7408 }
7409 }
7410
7411 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7412 {
7413 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7414 vargs_converted++;
7415 }
7416
7417 if (wParamFlags & PARAMFLAG_FRETVAL)
7418 {
7419 /* under most conditions the caller is not allowed to
7420 * pass in a dispparam arg in the index of what would be
7421 * the retval parameter. however, there is an exception
7422 * where the extra parameter is used in an extra
7423 * IDispatch::Invoke below */
7424 if ((i < pDispParams->cArgs) &&
7425 ((func_desc->cParams != 1) || !pVarResult ||
7426 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7427 {
7428 hres = DISP_E_BADPARAMCOUNT;
7429 break;
7430 }
7431
7432 /* note: this check is placed so that if the caller passes
7433 * in a VARIANTARG for the retval we just ignore it, like
7434 * native does */
7435 if (i == func_desc->cParams - 1)
7436 {
7437 VARIANTARG *arg;
7438 arg = prgpvarg[i] = &rgvarg[i];
7439 memset(arg, 0, sizeof(*arg));
7440 V_VT(arg) = rgvt[i];
7441 memset(&retval, 0, sizeof(retval));
7442 V_BYREF(arg) = &retval;
7443 }
7444 else
7445 {
7446 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7447 hres = E_UNEXPECTED;
7448 break;
7449 }
7450 }
7451 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7452 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7453 {
7454 TRACE("%s\n", debugstr_variant(src_arg));
7455
7456 if(rgvt[i]!=V_VT(src_arg))
7457 {
7458 if (rgvt[i] == VT_VARIANT)
7459 hres = VariantCopy(&rgvarg[i], src_arg);
7460 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7461 {
7462 if (rgvt[i] == V_VT(src_arg))
7463 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7464 else
7465 {
7466 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7467 if (wParamFlags & PARAMFLAG_FIN)
7468 hres = VariantCopy(&missing_arg[i], src_arg);
7469 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7470 }
7471 V_VT(&rgvarg[i]) = rgvt[i];
7472 }
7473 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7474 {
7475 SAFEARRAY *a;
7476 SAFEARRAYBOUND bound;
7477 VARIANT *v;
7478 LONG j;
7479 bound.lLbound = 0;
7480 bound.cElements = pDispParams->cArgs-i;
7481 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7482 {
7483 ERR("SafeArrayCreate failed\n");
7484 break;
7485 }
7486 hres = SafeArrayAccessData(a, (LPVOID)&v);
7487 if (hres != S_OK)
7488 {
7489 ERR("SafeArrayAccessData failed with %x\n", hres);
7490 SafeArrayDestroy(a);
7491 break;
7492 }
7493 for (j = 0; j < bound.cElements; j++)
7494 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7495 hres = SafeArrayUnaccessData(a);
7496 if (hres != S_OK)
7497 {
7498 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7499 SafeArrayDestroy(a);
7500 break;
7501 }
7502 if (rgvt[i] & VT_BYREF)
7503 V_BYREF(&rgvarg[i]) = &a;
7504 else
7505 V_ARRAY(&rgvarg[i]) = a;
7506 V_VT(&rgvarg[i]) = rgvt[i];
7507 }
7508 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7509 {
7510 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7511 if (wParamFlags & PARAMFLAG_FIN)
7512 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7513 else
7514 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7515 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7516 V_VT(&rgvarg[i]) = rgvt[i];
7517 }
7518 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7519 {
7520 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7521 V_VT(&rgvarg[i]) = rgvt[i];
7522 }
7523 else
7524 {
7525 /* FIXME: this doesn't work for VT_BYREF arguments if
7526 * they are not the same type as in the paramdesc */
7527 V_VT(&rgvarg[i]) = V_VT(src_arg);
7528 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7529 V_VT(&rgvarg[i]) = rgvt[i];
7530 }
7531
7532 if (FAILED(hres))
7533 {
7534 ERR("failed to convert param %d to %s from %s\n", i,
7535 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7536 break;
7537 }
7538 prgpvarg[i] = &rgvarg[i];
7539 }
7540 else
7541 {
7542 prgpvarg[i] = src_arg;
7543 }
7544
7545 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7546 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7547 && V_UNKNOWN(prgpvarg[i])) {
7548 IUnknown *userdefined_iface;
7549 GUID guid;
7550
7551 if (tdesc->vt == VT_PTR)
7552 tdesc = tdesc->u.lptdesc;
7553
7554 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7555 if(FAILED(hres))
7556 break;
7557
7558 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7559 if(FAILED(hres)) {
7560 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7561 break;
7562 }
7563
7564 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7565 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7566 }
7567 }
7568 else if (wParamFlags & PARAMFLAG_FOPT)
7569 {
7570 VARIANTARG *arg;
7571 arg = prgpvarg[i] = &rgvarg[i];
7572 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7573 {
7574 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7575 if (FAILED(hres))
7576 break;
7577 }
7578 else
7579 {
7580 VARIANTARG *missing_arg;
7581 /* if the function wants a pointer to a variant then
7582 * set that up, otherwise just pass the VT_ERROR in
7583 * the argument by value */
7584 if (rgvt[i] & VT_BYREF)
7585 {
7586 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7587 V_VT(arg) = VT_VARIANT | VT_BYREF;
7588 V_VARIANTREF(arg) = missing_arg;
7589 }
7590 else
7591 missing_arg = arg;
7592 V_VT(missing_arg) = VT_ERROR;
7593 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7594 }
7595 }
7596 else
7597 {
7598 hres = DISP_E_BADPARAMCOUNT;
7599 break;
7600 }
7601 }
7602 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7603
7604 /* VT_VOID is a special case for return types, so it is not
7605 * handled in the general function */
7606 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7607 V_VT(&varresult) = VT_EMPTY;
7608 else
7609 {
7610 V_VT(&varresult) = 0;
7611 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7612 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7613 }
7614
7615 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7616 V_VT(&varresult), func_desc->cParams, rgvt,
7617 prgpvarg, &varresult);
7618
7619 vargs_converted = 0;
7620
7621 for (i = 0; i < func_desc->cParams; i++)
7622 {
7623 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7624 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7625
7626 if (wParamFlags & PARAMFLAG_FLCID)
7627 continue;
7628 else if (wParamFlags & PARAMFLAG_FRETVAL)
7629 {
7630 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7631
7632 if (pVarResult)
7633 {
7634 VariantInit(pVarResult);
7635 /* deref return value */
7636 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7637 }
7638
7639 VARIANT_ClearInd(prgpvarg[i]);
7640 }
7641 else if (vargs_converted < pDispParams->cArgs)
7642 {
7643 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7644 if (wParamFlags & PARAMFLAG_FOUT)
7645 {
7646 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7647 {
7648 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7649
7650 if (FAILED(hres))
7651 {
7652 ERR("failed to convert param %d to vt %d\n", i,
7653 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7654 break;
7655 }
7656 }
7657 }
7658 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7659 func_desc->cParamsOpt < 0 &&
7660 i == func_desc->cParams-1)
7661 {
7662 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7663 LONG j, ubound;
7664 VARIANT *v;
7665 hres = SafeArrayGetUBound(a, 1, &ubound);
7666 if (hres != S_OK)
7667 {
7668 ERR("SafeArrayGetUBound failed with %x\n", hres);
7669 break;
7670 }
7671 hres = SafeArrayAccessData(a, (LPVOID)&v);
7672 if (hres != S_OK)
7673 {
7674 ERR("SafeArrayAccessData failed with %x\n", hres);
7675 break;
7676 }
7677 for (j = 0; j <= ubound; j++)
7678 VariantClear(&v[j]);
7679 hres = SafeArrayUnaccessData(a);
7680 if (hres != S_OK)
7681 {
7682 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7683 break;
7684 }
7685 }
7686 VariantClear(&rgvarg[i]);
7687 vargs_converted++;
7688 }
7689 else if (wParamFlags & PARAMFLAG_FOPT)
7690 {
7691 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7692 VariantClear(&rgvarg[i]);
7693 }
7694
7695 VariantClear(&missing_arg[i]);
7696 }
7697
7698 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7699 {
7700 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7701 hres = DISP_E_EXCEPTION;
7702 if (pExcepInfo)
7703 {
7704 IErrorInfo *pErrorInfo;
7705 pExcepInfo->scode = V_ERROR(&varresult);
7706 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7707 {
7708 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7709 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7710 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7711 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7712
7713 IErrorInfo_Release(pErrorInfo);
7714 }
7715 }
7716 }
7717 if (V_VT(&varresult) != VT_ERROR)
7718 {
7719 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7720
7721 if (pVarResult)
7722 {
7723 VariantClear(pVarResult);
7724 *pVarResult = varresult;
7725 }
7726 else
7727 VariantClear(&varresult);
7728 }
7729
7730 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7731 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7732 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7733 (pDispParams->cArgs != 0))
7734 {
7735 if (V_VT(pVarResult) == VT_DISPATCH)
7736 {
7737 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7738 /* Note: not VariantClear; we still need the dispatch
7739 * pointer to be valid */
7740 VariantInit(pVarResult);
7741 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7742 GetSystemDefaultLCID(), wFlags,
7743 pDispParams, pVarResult, pExcepInfo, pArgErr);
7744 IDispatch_Release(pDispatch);
7745 }
7746 else
7747 {
7748 VariantClear(pVarResult);
7749 hres = DISP_E_NOTACOLLECTION;
7750 }
7751 }
7752
7753 func_fail:
7754 heap_free(buffer);
7755 break;
7756 }
7757 case FUNC_DISPATCH: {
7758 IDispatch *disp;
7759
7760 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7761 if (SUCCEEDED(hres)) {
7762 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7763 hres = IDispatch_Invoke(
7764 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7765 pVarResult,pExcepInfo,pArgErr
7766 );
7767 if (FAILED(hres))
7768 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7769 IDispatch_Release(disp);
7770 } else
7771 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7772 break;
7773 }
7774 default:
7775 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7776 hres = E_FAIL;
7777 break;
7778 }
7779
7780 TRACE("-- 0x%08x\n", hres);
7781 return hres;
7782
7783 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7784 VARDESC *var_desc;
7785
7786 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7787 if(FAILED(hres)) return hres;
7788
7789 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7790 dump_VARDESC(var_desc);
7791 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7792 return E_NOTIMPL;
7793 }
7794
7795 /* not found, look for it in inherited interfaces */
7796 ITypeInfo2_GetTypeKind(iface, &type_kind);
7797 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7798 if(This->impltypes) {
7799 /* recursive search */
7800 ITypeInfo *pTInfo;
7801 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7802 if(SUCCEEDED(hres)){
7803 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7804 ITypeInfo_Release(pTInfo);
7805 return hres;
7806 }
7807 WARN("Could not search inherited interface!\n");
7808 }
7809 }
7810 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7811 return DISP_E_MEMBERNOTFOUND;
7812 }
7813
7814 /* ITypeInfo::GetDocumentation
7815 *
7816 * Retrieves the documentation string, the complete Help file name and path,
7817 * and the context ID for the Help topic for a specified type description.
7818 *
7819 * (Can be tested by the Visual Basic Editor in Word for instance.)
7820 */
ITypeInfo_fnGetDocumentation(ITypeInfo2 * iface,MEMBERID memid,BSTR * pBstrName,BSTR * pBstrDocString,DWORD * pdwHelpContext,BSTR * pBstrHelpFile)7821 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7822 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7823 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7824 {
7825 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7826 const TLBFuncDesc *pFDesc;
7827 const TLBVarDesc *pVDesc;
7828 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7829 " HelpContext(%p) HelpFile(%p)\n",
7830 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7831 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7832 if(pBstrName)
7833 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7834 if(pBstrDocString)
7835 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7836 if(pdwHelpContext)
7837 *pdwHelpContext=This->dwHelpContext;
7838 if(pBstrHelpFile)
7839 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7840 return S_OK;
7841 }else {/* for a member */
7842 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7843 if(pFDesc){
7844 if(pBstrName)
7845 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7846 if(pBstrDocString)
7847 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7848 if(pdwHelpContext)
7849 *pdwHelpContext=pFDesc->helpcontext;
7850 if(pBstrHelpFile)
7851 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7852 return S_OK;
7853 }
7854 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7855 if(pVDesc){
7856 if(pBstrName)
7857 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7858 if(pBstrDocString)
7859 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7860 if(pdwHelpContext)
7861 *pdwHelpContext=pVDesc->HelpContext;
7862 if(pBstrHelpFile)
7863 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7864 return S_OK;
7865 }
7866 }
7867
7868 if(This->impltypes &&
7869 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7870 /* recursive search */
7871 ITypeInfo *pTInfo;
7872 HRESULT result;
7873 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7874 if(SUCCEEDED(result)) {
7875 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7876 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7877 ITypeInfo_Release(pTInfo);
7878 return result;
7879 }
7880 WARN("Could not search inherited interface!\n");
7881 }
7882
7883 WARN("member %d not found\n", memid);
7884 return TYPE_E_ELEMENTNOTFOUND;
7885 }
7886
7887 /* ITypeInfo::GetDllEntry
7888 *
7889 * Retrieves a description or specification of an entry point for a function
7890 * in a DLL.
7891 */
ITypeInfo_fnGetDllEntry(ITypeInfo2 * iface,MEMBERID memid,INVOKEKIND invKind,BSTR * pBstrDllName,BSTR * pBstrName,WORD * pwOrdinal)7892 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7893 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7894 WORD *pwOrdinal)
7895 {
7896 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7897 const TLBFuncDesc *pFDesc;
7898
7899 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7900
7901 if (pBstrDllName) *pBstrDllName = NULL;
7902 if (pBstrName) *pBstrName = NULL;
7903 if (pwOrdinal) *pwOrdinal = 0;
7904
7905 if (This->typeattr.typekind != TKIND_MODULE)
7906 return TYPE_E_BADMODULEKIND;
7907
7908 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7909 if(pFDesc){
7910 dump_TypeInfo(This);
7911 if (TRACE_ON(ole))
7912 dump_TLBFuncDescOne(pFDesc);
7913
7914 if (pBstrDllName)
7915 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7916
7917 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7918 if (pBstrName)
7919 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7920 if (pwOrdinal)
7921 *pwOrdinal = -1;
7922 return S_OK;
7923 }
7924 if (pBstrName)
7925 *pBstrName = NULL;
7926 if (pwOrdinal)
7927 *pwOrdinal = LOWORD(pFDesc->Entry);
7928 return S_OK;
7929 }
7930 return TYPE_E_ELEMENTNOTFOUND;
7931 }
7932
7933 /* internal function to make the inherited interfaces' methods appear
7934 * part of the interface */
ITypeInfoImpl_GetDispatchRefTypeInfo(ITypeInfo * iface,HREFTYPE * hRefType,ITypeInfo ** ppTInfo)7935 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7936 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7937 {
7938 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7939 HRESULT hr;
7940
7941 TRACE("%p, 0x%x\n", iface, *hRefType);
7942
7943 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7944 {
7945 ITypeInfo *pSubTypeInfo;
7946
7947 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7948 if (FAILED(hr))
7949 return hr;
7950
7951 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7952 hRefType, ppTInfo);
7953 ITypeInfo_Release(pSubTypeInfo);
7954 if (SUCCEEDED(hr))
7955 return hr;
7956 }
7957 *hRefType -= DISPATCH_HREF_OFFSET;
7958
7959 if (!(*hRefType & DISPATCH_HREF_MASK))
7960 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7961 else
7962 return E_FAIL;
7963 }
7964
7965 struct search_res_tlb_params
7966 {
7967 const GUID *guid;
7968 ITypeLib *pTLib;
7969 };
7970
search_res_tlb(HMODULE hModule,LPCWSTR lpszType,LPWSTR lpszName,LONG_PTR lParam)7971 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7972 {
7973 struct search_res_tlb_params *params = (LPVOID)lParam;
7974 static const WCHAR formatW[] = {'\\','%','d',0};
7975 WCHAR szPath[MAX_PATH+1];
7976 ITypeLib *pTLib = NULL;
7977 HRESULT ret;
7978 DWORD len;
7979
7980 if (IS_INTRESOURCE(lpszName) == FALSE)
7981 return TRUE;
7982
7983 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7984 return TRUE;
7985
7986 if (swprintf(szPath + len, formatW, LOWORD(lpszName)) < 0)
7987 return TRUE;
7988
7989 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7990 if (SUCCEEDED(ret))
7991 {
7992 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7993 if (IsEqualGUID(params->guid, impl->guid))
7994 {
7995 params->pTLib = pTLib;
7996 return FALSE; /* stop enumeration */
7997 }
7998 ITypeLib_Release(pTLib);
7999 }
8000
8001 return TRUE;
8002 }
8003
8004 /* ITypeInfo::GetRefTypeInfo
8005 *
8006 * If a type description references other type descriptions, it retrieves
8007 * the referenced type descriptions.
8008 */
ITypeInfo_fnGetRefTypeInfo(ITypeInfo2 * iface,HREFTYPE hRefType,ITypeInfo ** ppTInfo)8009 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
8010 ITypeInfo2 *iface,
8011 HREFTYPE hRefType,
8012 ITypeInfo **ppTInfo)
8013 {
8014 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8015 HRESULT result = E_FAIL;
8016
8017 if(!ppTInfo)
8018 return E_INVALIDARG;
8019
8020 if ((INT)hRefType < 0) {
8021 ITypeInfoImpl *pTypeInfoImpl;
8022
8023 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
8024 !(This->typeattr.typekind == TKIND_INTERFACE ||
8025 This->typeattr.typekind == TKIND_DISPATCH))
8026 return TYPE_E_ELEMENTNOTFOUND;
8027
8028 /* when we meet a DUAL typeinfo, we must create the alternate
8029 * version of it.
8030 */
8031 pTypeInfoImpl = ITypeInfoImpl_Constructor();
8032
8033 *pTypeInfoImpl = *This;
8034 pTypeInfoImpl->ref = 0;
8035 list_init(&pTypeInfoImpl->custdata_list);
8036
8037 if (This->typeattr.typekind == TKIND_INTERFACE)
8038 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
8039 else
8040 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
8041
8042 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
8043 /* the AddRef implicitly adds a reference to the parent typelib, which
8044 * stops the copied data from being destroyed until the new typeinfo's
8045 * refcount goes to zero, but we need to signal to the new instance to
8046 * not free its data structures when it is destroyed */
8047 pTypeInfoImpl->not_attached_to_typelib = TRUE;
8048
8049 ITypeInfo_AddRef(*ppTInfo);
8050
8051 result = S_OK;
8052 } else if ((hRefType & DISPATCH_HREF_MASK) &&
8053 (This->typeattr.typekind == TKIND_DISPATCH))
8054 {
8055 HREFTYPE href_dispatch = hRefType;
8056 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
8057 } else {
8058 TLBRefType *ref_type;
8059 ITypeLib *pTLib = NULL;
8060 UINT i;
8061
8062 if(!(hRefType & 0x1)){
8063 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
8064 {
8065 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
8066 {
8067 result = S_OK;
8068 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
8069 ITypeInfo_AddRef(*ppTInfo);
8070 goto end;
8071 }
8072 }
8073 }
8074
8075 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
8076 {
8077 if(ref_type->reference == (hRefType & (~0x3)))
8078 break;
8079 }
8080 if(&ref_type->entry == &This->pTypeLib->ref_list)
8081 {
8082 FIXME("Can't find pRefType for ref %x\n", hRefType);
8083 goto end;
8084 }
8085
8086 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
8087 UINT Index;
8088 TRACE("internal reference\n");
8089 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
8090 } else {
8091 if(ref_type->pImpTLInfo->pImpTypeLib) {
8092 TRACE("typeinfo in imported typelib that is already loaded\n");
8093 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
8094 ITypeLib_AddRef(pTLib);
8095 result = S_OK;
8096 } else {
8097 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
8098 struct search_res_tlb_params params;
8099 BSTR libnam;
8100
8101 TRACE("typeinfo in imported typelib that isn't already loaded\n");
8102
8103 /* Search in resource table */
8104 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
8105 params.pTLib = NULL;
8106 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)¶ms);
8107 pTLib = params.pTLib;
8108 result = S_OK;
8109
8110 if (!pTLib)
8111 {
8112 /* Search on disk */
8113 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
8114 ref_type->pImpTLInfo->wVersionMajor,
8115 ref_type->pImpTLInfo->wVersionMinor,
8116 This->pTypeLib->syskind,
8117 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
8118 if (FAILED(result))
8119 libnam = SysAllocString(ref_type->pImpTLInfo->name);
8120
8121 result = LoadTypeLib(libnam, &pTLib);
8122 SysFreeString(libnam);
8123 }
8124
8125 if(SUCCEEDED(result)) {
8126 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
8127 ITypeLib_AddRef(pTLib);
8128 }
8129 }
8130 }
8131 if(SUCCEEDED(result)) {
8132 if(ref_type->index == TLB_REF_USE_GUID)
8133 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
8134 else
8135 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
8136 }
8137 if (pTLib != NULL)
8138 ITypeLib_Release(pTLib);
8139 }
8140
8141 end:
8142 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
8143 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
8144 return result;
8145 }
8146
8147 /* ITypeInfo::AddressOfMember
8148 *
8149 * Retrieves the addresses of static functions or variables, such as those
8150 * defined in a DLL.
8151 */
ITypeInfo_fnAddressOfMember(ITypeInfo2 * iface,MEMBERID memid,INVOKEKIND invKind,PVOID * ppv)8152 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
8153 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
8154 {
8155 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8156 HRESULT hr;
8157 BSTR dll, entry;
8158 WORD ordinal;
8159 HMODULE module;
8160
8161 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
8162
8163 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
8164 if (FAILED(hr))
8165 return hr;
8166
8167 module = LoadLibraryW(dll);
8168 if (!module)
8169 {
8170 ERR("couldn't load %s\n", debugstr_w(dll));
8171 SysFreeString(dll);
8172 SysFreeString(entry);
8173 return STG_E_FILENOTFOUND;
8174 }
8175 /* FIXME: store library somewhere where we can free it */
8176
8177 if (entry)
8178 {
8179 LPSTR entryA;
8180 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
8181 entryA = heap_alloc(len);
8182 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
8183
8184 *ppv = GetProcAddress(module, entryA);
8185 if (!*ppv)
8186 ERR("function not found %s\n", debugstr_a(entryA));
8187
8188 heap_free(entryA);
8189 }
8190 else
8191 {
8192 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
8193 if (!*ppv)
8194 ERR("function not found %d\n", ordinal);
8195 }
8196
8197 SysFreeString(dll);
8198 SysFreeString(entry);
8199
8200 if (!*ppv)
8201 return TYPE_E_DLLFUNCTIONNOTFOUND;
8202
8203 return S_OK;
8204 }
8205
8206 /* ITypeInfo::CreateInstance
8207 *
8208 * Creates a new instance of a type that describes a component object class
8209 * (coclass).
8210 */
ITypeInfo_fnCreateInstance(ITypeInfo2 * iface,IUnknown * pOuterUnk,REFIID riid,VOID ** ppvObj)8211 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
8212 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
8213 {
8214 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8215 HRESULT hr;
8216 TYPEATTR *pTA;
8217
8218 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8219
8220 *ppvObj = NULL;
8221
8222 if(pOuterUnk)
8223 {
8224 WARN("Not able to aggregate\n");
8225 return CLASS_E_NOAGGREGATION;
8226 }
8227
8228 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8229 if(FAILED(hr)) return hr;
8230
8231 if(pTA->typekind != TKIND_COCLASS)
8232 {
8233 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8234 hr = E_INVALIDARG;
8235 goto end;
8236 }
8237
8238 hr = S_FALSE;
8239 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8240 {
8241 IUnknown *pUnk;
8242 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8243 TRACE("GetActiveObject rets %08x\n", hr);
8244 if(hr == S_OK)
8245 {
8246 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8247 IUnknown_Release(pUnk);
8248 }
8249 }
8250
8251 if(hr != S_OK)
8252 hr = CoCreateInstance(&pTA->guid, NULL,
8253 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8254 riid, ppvObj);
8255
8256 end:
8257 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8258 return hr;
8259 }
8260
8261 /* ITypeInfo::GetMops
8262 *
8263 * Retrieves marshalling information.
8264 */
ITypeInfo_fnGetMops(ITypeInfo2 * iface,MEMBERID memid,BSTR * pBstrMops)8265 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8266 BSTR *pBstrMops)
8267 {
8268 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8269 FIXME("(%p %d) stub!\n", This, memid);
8270 *pBstrMops = NULL;
8271 return S_OK;
8272 }
8273
8274 /* ITypeInfo::GetContainingTypeLib
8275 *
8276 * Retrieves the containing type library and the index of the type description
8277 * within that type library.
8278 */
ITypeInfo_fnGetContainingTypeLib(ITypeInfo2 * iface,ITypeLib ** ppTLib,UINT * pIndex)8279 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8280 ITypeLib * *ppTLib, UINT *pIndex)
8281 {
8282 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8283
8284 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8285 if (pIndex) {
8286 *pIndex=This->index;
8287 TRACE("returning pIndex=%d\n", *pIndex);
8288 }
8289
8290 if (ppTLib) {
8291 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8292 ITypeLib_AddRef(*ppTLib);
8293 TRACE("returning ppTLib=%p\n", *ppTLib);
8294 }
8295
8296 return S_OK;
8297 }
8298
8299 /* ITypeInfo::ReleaseTypeAttr
8300 *
8301 * Releases a TYPEATTR previously returned by Get
8302 *
8303 */
ITypeInfo_fnReleaseTypeAttr(ITypeInfo2 * iface,TYPEATTR * pTypeAttr)8304 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8305 TYPEATTR* pTypeAttr)
8306 {
8307 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8308 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8309 heap_free(pTypeAttr);
8310 }
8311
8312 /* ITypeInfo::ReleaseFuncDesc
8313 *
8314 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8315 */
ITypeInfo_fnReleaseFuncDesc(ITypeInfo2 * iface,FUNCDESC * pFuncDesc)8316 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8317 ITypeInfo2 *iface,
8318 FUNCDESC *pFuncDesc)
8319 {
8320 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8321 SHORT i;
8322
8323 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8324
8325 for (i = 0; i < pFuncDesc->cParams; i++)
8326 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8327 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8328
8329 SysFreeString((BSTR)pFuncDesc);
8330 }
8331
8332 /* ITypeInfo::ReleaseVarDesc
8333 *
8334 * Releases a VARDESC previously returned by GetVarDesc.
8335 */
ITypeInfo_fnReleaseVarDesc(ITypeInfo2 * iface,VARDESC * pVarDesc)8336 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8337 VARDESC *pVarDesc)
8338 {
8339 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8340 TRACE("(%p)->(%p)\n", This, pVarDesc);
8341
8342 TLB_FreeVarDesc(pVarDesc);
8343 }
8344
8345 /* ITypeInfo2::GetTypeKind
8346 *
8347 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8348 *
8349 */
ITypeInfo2_fnGetTypeKind(ITypeInfo2 * iface,TYPEKIND * pTypeKind)8350 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8351 TYPEKIND *pTypeKind)
8352 {
8353 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8354 *pTypeKind = This->typeattr.typekind;
8355 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8356 return S_OK;
8357 }
8358
8359 /* ITypeInfo2::GetTypeFlags
8360 *
8361 * Returns the type flags without any allocations. This returns a DWORD type
8362 * flag, which expands the type flags without growing the TYPEATTR (type
8363 * attribute).
8364 *
8365 */
ITypeInfo2_fnGetTypeFlags(ITypeInfo2 * iface,ULONG * pTypeFlags)8366 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8367 {
8368 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8369 *pTypeFlags=This->typeattr.wTypeFlags;
8370 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8371 return S_OK;
8372 }
8373
8374 /* ITypeInfo2::GetFuncIndexOfMemId
8375 * Binds to a specific member based on a known DISPID, where the member name
8376 * is not known (for example, when binding to a default member).
8377 *
8378 */
ITypeInfo2_fnGetFuncIndexOfMemId(ITypeInfo2 * iface,MEMBERID memid,INVOKEKIND invKind,UINT * pFuncIndex)8379 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8380 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8381 {
8382 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8383 UINT fdc;
8384 HRESULT result;
8385
8386 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8387 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8388 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8389 break;
8390 }
8391 if(fdc < This->typeattr.cFuncs) {
8392 *pFuncIndex = fdc;
8393 result = S_OK;
8394 } else
8395 result = TYPE_E_ELEMENTNOTFOUND;
8396
8397 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8398 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8399 return result;
8400 }
8401
8402 /* TypeInfo2::GetVarIndexOfMemId
8403 *
8404 * Binds to a specific member based on a known DISPID, where the member name
8405 * is not known (for example, when binding to a default member).
8406 *
8407 */
ITypeInfo2_fnGetVarIndexOfMemId(ITypeInfo2 * iface,MEMBERID memid,UINT * pVarIndex)8408 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8409 MEMBERID memid, UINT *pVarIndex)
8410 {
8411 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8412 TLBVarDesc *pVarInfo;
8413
8414 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8415
8416 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8417 if(!pVarInfo)
8418 return TYPE_E_ELEMENTNOTFOUND;
8419
8420 *pVarIndex = (pVarInfo - This->vardescs);
8421
8422 return S_OK;
8423 }
8424
8425 /* ITypeInfo2::GetCustData
8426 *
8427 * Gets the custom data
8428 */
ITypeInfo2_fnGetCustData(ITypeInfo2 * iface,REFGUID guid,VARIANT * pVarVal)8429 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8430 ITypeInfo2 * iface,
8431 REFGUID guid,
8432 VARIANT *pVarVal)
8433 {
8434 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8435 TLBCustData *pCData;
8436
8437 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8438
8439 if(!guid || !pVarVal)
8440 return E_INVALIDARG;
8441
8442 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8443
8444 VariantInit( pVarVal);
8445 if (pCData)
8446 VariantCopy( pVarVal, &pCData->data);
8447 else
8448 VariantClear( pVarVal );
8449 return S_OK;
8450 }
8451
8452 /* ITypeInfo2::GetFuncCustData
8453 *
8454 * Gets the custom data
8455 */
ITypeInfo2_fnGetFuncCustData(ITypeInfo2 * iface,UINT index,REFGUID guid,VARIANT * pVarVal)8456 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8457 ITypeInfo2 * iface,
8458 UINT index,
8459 REFGUID guid,
8460 VARIANT *pVarVal)
8461 {
8462 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8463 TLBCustData *pCData;
8464 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8465
8466 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8467
8468 if(index >= This->typeattr.cFuncs)
8469 return TYPE_E_ELEMENTNOTFOUND;
8470
8471 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8472 if(!pCData)
8473 return TYPE_E_ELEMENTNOTFOUND;
8474
8475 VariantInit(pVarVal);
8476 VariantCopy(pVarVal, &pCData->data);
8477
8478 return S_OK;
8479 }
8480
8481 /* ITypeInfo2::GetParamCustData
8482 *
8483 * Gets the custom data
8484 */
ITypeInfo2_fnGetParamCustData(ITypeInfo2 * iface,UINT indexFunc,UINT indexParam,REFGUID guid,VARIANT * pVarVal)8485 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8486 ITypeInfo2 * iface,
8487 UINT indexFunc,
8488 UINT indexParam,
8489 REFGUID guid,
8490 VARIANT *pVarVal)
8491 {
8492 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8493 TLBCustData *pCData;
8494 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8495
8496 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8497 debugstr_guid(guid), pVarVal);
8498
8499 if(indexFunc >= This->typeattr.cFuncs)
8500 return TYPE_E_ELEMENTNOTFOUND;
8501
8502 if(indexParam >= pFDesc->funcdesc.cParams)
8503 return TYPE_E_ELEMENTNOTFOUND;
8504
8505 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8506 if(!pCData)
8507 return TYPE_E_ELEMENTNOTFOUND;
8508
8509 VariantInit(pVarVal);
8510 VariantCopy(pVarVal, &pCData->data);
8511
8512 return S_OK;
8513 }
8514
8515 /* ITypeInfo2::GetVarCustData
8516 *
8517 * Gets the custom data
8518 */
ITypeInfo2_fnGetVarCustData(ITypeInfo2 * iface,UINT index,REFGUID guid,VARIANT * pVarVal)8519 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8520 ITypeInfo2 * iface,
8521 UINT index,
8522 REFGUID guid,
8523 VARIANT *pVarVal)
8524 {
8525 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8526 TLBCustData *pCData;
8527 TLBVarDesc *pVDesc = &This->vardescs[index];
8528
8529 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8530
8531 if(index >= This->typeattr.cVars)
8532 return TYPE_E_ELEMENTNOTFOUND;
8533
8534 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8535 if(!pCData)
8536 return TYPE_E_ELEMENTNOTFOUND;
8537
8538 VariantInit(pVarVal);
8539 VariantCopy(pVarVal, &pCData->data);
8540
8541 return S_OK;
8542 }
8543
8544 /* ITypeInfo2::GetImplCustData
8545 *
8546 * Gets the custom data
8547 */
ITypeInfo2_fnGetImplTypeCustData(ITypeInfo2 * iface,UINT index,REFGUID guid,VARIANT * pVarVal)8548 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8549 ITypeInfo2 * iface,
8550 UINT index,
8551 REFGUID guid,
8552 VARIANT *pVarVal)
8553 {
8554 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8555 TLBCustData *pCData;
8556 TLBImplType *pRDesc = &This->impltypes[index];
8557
8558 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8559
8560 if(index >= This->typeattr.cImplTypes)
8561 return TYPE_E_ELEMENTNOTFOUND;
8562
8563 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8564 if(!pCData)
8565 return TYPE_E_ELEMENTNOTFOUND;
8566
8567 VariantInit(pVarVal);
8568 VariantCopy(pVarVal, &pCData->data);
8569
8570 return S_OK;
8571 }
8572
8573 /* ITypeInfo2::GetDocumentation2
8574 *
8575 * Retrieves the documentation string, the complete Help file name and path,
8576 * the localization context to use, and the context ID for the library Help
8577 * topic in the Help file.
8578 *
8579 */
ITypeInfo2_fnGetDocumentation2(ITypeInfo2 * iface,MEMBERID memid,LCID lcid,BSTR * pbstrHelpString,DWORD * pdwHelpStringContext,BSTR * pbstrHelpStringDll)8580 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8581 ITypeInfo2 * iface,
8582 MEMBERID memid,
8583 LCID lcid,
8584 BSTR *pbstrHelpString,
8585 DWORD *pdwHelpStringContext,
8586 BSTR *pbstrHelpStringDll)
8587 {
8588 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8589 const TLBFuncDesc *pFDesc;
8590 const TLBVarDesc *pVDesc;
8591 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8592 "HelpStringContext(%p) HelpStringDll(%p)\n",
8593 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8594 pbstrHelpStringDll );
8595 /* the help string should be obtained from the helpstringdll,
8596 * using the _DLLGetDocumentation function, based on the supplied
8597 * lcid. Nice to do sometime...
8598 */
8599 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8600 if(pbstrHelpString)
8601 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8602 if(pdwHelpStringContext)
8603 *pdwHelpStringContext=This->dwHelpStringContext;
8604 if(pbstrHelpStringDll)
8605 *pbstrHelpStringDll=
8606 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8607 return S_OK;
8608 }else {/* for a member */
8609 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8610 if(pFDesc){
8611 if(pbstrHelpString)
8612 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8613 if(pdwHelpStringContext)
8614 *pdwHelpStringContext=pFDesc->HelpStringContext;
8615 if(pbstrHelpStringDll)
8616 *pbstrHelpStringDll=
8617 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8618 return S_OK;
8619 }
8620 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8621 if(pVDesc){
8622 if(pbstrHelpString)
8623 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8624 if(pdwHelpStringContext)
8625 *pdwHelpStringContext=pVDesc->HelpStringContext;
8626 if(pbstrHelpStringDll)
8627 *pbstrHelpStringDll=
8628 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8629 return S_OK;
8630 }
8631 }
8632 return TYPE_E_ELEMENTNOTFOUND;
8633 }
8634
8635 /* ITypeInfo2::GetAllCustData
8636 *
8637 * Gets all custom data items for the Type info.
8638 *
8639 */
ITypeInfo2_fnGetAllCustData(ITypeInfo2 * iface,CUSTDATA * pCustData)8640 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8641 ITypeInfo2 * iface,
8642 CUSTDATA *pCustData)
8643 {
8644 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8645
8646 TRACE("%p %p\n", This, pCustData);
8647
8648 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8649 }
8650
8651 /* ITypeInfo2::GetAllFuncCustData
8652 *
8653 * Gets all custom data items for the specified Function
8654 *
8655 */
ITypeInfo2_fnGetAllFuncCustData(ITypeInfo2 * iface,UINT index,CUSTDATA * pCustData)8656 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8657 ITypeInfo2 * iface,
8658 UINT index,
8659 CUSTDATA *pCustData)
8660 {
8661 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8662 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8663
8664 TRACE("%p %u %p\n", This, index, pCustData);
8665
8666 if(index >= This->typeattr.cFuncs)
8667 return TYPE_E_ELEMENTNOTFOUND;
8668
8669 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8670 }
8671
8672 /* ITypeInfo2::GetAllParamCustData
8673 *
8674 * Gets all custom data items for the Functions
8675 *
8676 */
ITypeInfo2_fnGetAllParamCustData(ITypeInfo2 * iface,UINT indexFunc,UINT indexParam,CUSTDATA * pCustData)8677 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8678 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8679 {
8680 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8681 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8682
8683 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8684
8685 if(indexFunc >= This->typeattr.cFuncs)
8686 return TYPE_E_ELEMENTNOTFOUND;
8687
8688 if(indexParam >= pFDesc->funcdesc.cParams)
8689 return TYPE_E_ELEMENTNOTFOUND;
8690
8691 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8692 }
8693
8694 /* ITypeInfo2::GetAllVarCustData
8695 *
8696 * Gets all custom data items for the specified Variable
8697 *
8698 */
ITypeInfo2_fnGetAllVarCustData(ITypeInfo2 * iface,UINT index,CUSTDATA * pCustData)8699 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8700 UINT index, CUSTDATA *pCustData)
8701 {
8702 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8703 TLBVarDesc * pVDesc = &This->vardescs[index];
8704
8705 TRACE("%p %u %p\n", This, index, pCustData);
8706
8707 if(index >= This->typeattr.cVars)
8708 return TYPE_E_ELEMENTNOTFOUND;
8709
8710 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8711 }
8712
8713 /* ITypeInfo2::GetAllImplCustData
8714 *
8715 * Gets all custom data items for the specified implementation type
8716 *
8717 */
ITypeInfo2_fnGetAllImplTypeCustData(ITypeInfo2 * iface,UINT index,CUSTDATA * pCustData)8718 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8719 ITypeInfo2 * iface,
8720 UINT index,
8721 CUSTDATA *pCustData)
8722 {
8723 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8724 TLBImplType *pRDesc = &This->impltypes[index];
8725
8726 TRACE("%p %u %p\n", This, index, pCustData);
8727
8728 if(index >= This->typeattr.cImplTypes)
8729 return TYPE_E_ELEMENTNOTFOUND;
8730
8731 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8732 }
8733
8734 static const ITypeInfo2Vtbl tinfvt =
8735 {
8736
8737 ITypeInfo_fnQueryInterface,
8738 ITypeInfo_fnAddRef,
8739 ITypeInfo_fnRelease,
8740
8741 ITypeInfo_fnGetTypeAttr,
8742 ITypeInfo_fnGetTypeComp,
8743 ITypeInfo_fnGetFuncDesc,
8744 ITypeInfo_fnGetVarDesc,
8745 ITypeInfo_fnGetNames,
8746 ITypeInfo_fnGetRefTypeOfImplType,
8747 ITypeInfo_fnGetImplTypeFlags,
8748 ITypeInfo_fnGetIDsOfNames,
8749 ITypeInfo_fnInvoke,
8750 ITypeInfo_fnGetDocumentation,
8751 ITypeInfo_fnGetDllEntry,
8752 ITypeInfo_fnGetRefTypeInfo,
8753 ITypeInfo_fnAddressOfMember,
8754 ITypeInfo_fnCreateInstance,
8755 ITypeInfo_fnGetMops,
8756 ITypeInfo_fnGetContainingTypeLib,
8757 ITypeInfo_fnReleaseTypeAttr,
8758 ITypeInfo_fnReleaseFuncDesc,
8759 ITypeInfo_fnReleaseVarDesc,
8760
8761 ITypeInfo2_fnGetTypeKind,
8762 ITypeInfo2_fnGetTypeFlags,
8763 ITypeInfo2_fnGetFuncIndexOfMemId,
8764 ITypeInfo2_fnGetVarIndexOfMemId,
8765 ITypeInfo2_fnGetCustData,
8766 ITypeInfo2_fnGetFuncCustData,
8767 ITypeInfo2_fnGetParamCustData,
8768 ITypeInfo2_fnGetVarCustData,
8769 ITypeInfo2_fnGetImplTypeCustData,
8770 ITypeInfo2_fnGetDocumentation2,
8771 ITypeInfo2_fnGetAllCustData,
8772 ITypeInfo2_fnGetAllFuncCustData,
8773 ITypeInfo2_fnGetAllParamCustData,
8774 ITypeInfo2_fnGetAllVarCustData,
8775 ITypeInfo2_fnGetAllImplTypeCustData,
8776 };
8777
8778 /******************************************************************************
8779 * CreateDispTypeInfo [OLEAUT32.31]
8780 *
8781 * Build type information for an object so it can be called through an
8782 * IDispatch interface.
8783 *
8784 * RETURNS
8785 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8786 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8787 *
8788 * NOTES
8789 * This call allows an objects methods to be accessed through IDispatch, by
8790 * building an ITypeInfo object that IDispatch can use to call through.
8791 */
CreateDispTypeInfo(INTERFACEDATA * pidata,LCID lcid,ITypeInfo ** pptinfo)8792 HRESULT WINAPI CreateDispTypeInfo(
8793 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8794 LCID lcid, /* [I] Locale Id */
8795 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8796 {
8797 ITypeInfoImpl *pTIClass, *pTIIface;
8798 ITypeLibImpl *pTypeLibImpl;
8799 unsigned int param, func;
8800 TLBFuncDesc *pFuncDesc;
8801 TLBRefType *ref;
8802
8803 TRACE("\n");
8804 pTypeLibImpl = TypeLibImpl_Constructor();
8805 if (!pTypeLibImpl) return E_FAIL;
8806
8807 pTypeLibImpl->TypeInfoCount = 2;
8808 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8809
8810 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8811 pTIIface->pTypeLib = pTypeLibImpl;
8812 pTIIface->index = 0;
8813 pTIIface->Name = NULL;
8814 pTIIface->dwHelpContext = -1;
8815 pTIIface->guid = NULL;
8816 pTIIface->typeattr.lcid = lcid;
8817 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8818 pTIIface->typeattr.wMajorVerNum = 0;
8819 pTIIface->typeattr.wMinorVerNum = 0;
8820 pTIIface->typeattr.cbAlignment = 2;
8821 pTIIface->typeattr.cbSizeInstance = -1;
8822 pTIIface->typeattr.cbSizeVft = -1;
8823 pTIIface->typeattr.cFuncs = 0;
8824 pTIIface->typeattr.cImplTypes = 0;
8825 pTIIface->typeattr.cVars = 0;
8826 pTIIface->typeattr.wTypeFlags = 0;
8827 pTIIface->hreftype = 0;
8828
8829 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8830 pFuncDesc = pTIIface->funcdescs;
8831 for(func = 0; func < pidata->cMembers; func++) {
8832 METHODDATA *md = pidata->pmethdata + func;
8833 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8834 pFuncDesc->funcdesc.memid = md->dispid;
8835 pFuncDesc->funcdesc.lprgscode = NULL;
8836 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8837 pFuncDesc->funcdesc.invkind = md->wFlags;
8838 pFuncDesc->funcdesc.callconv = md->cc;
8839 pFuncDesc->funcdesc.cParams = md->cArgs;
8840 pFuncDesc->funcdesc.cParamsOpt = 0;
8841 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8842 pFuncDesc->funcdesc.cScodes = 0;
8843 pFuncDesc->funcdesc.wFuncFlags = 0;
8844 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8845 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8846 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8847 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8848 md->cArgs * sizeof(ELEMDESC));
8849 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8850 for(param = 0; param < md->cArgs; param++) {
8851 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8852 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8853 }
8854 pFuncDesc->helpcontext = 0;
8855 pFuncDesc->HelpStringContext = 0;
8856 pFuncDesc->HelpString = NULL;
8857 pFuncDesc->Entry = NULL;
8858 list_init(&pFuncDesc->custdata_list);
8859 pTIIface->typeattr.cFuncs++;
8860 ++pFuncDesc;
8861 }
8862
8863 dump_TypeInfo(pTIIface);
8864
8865 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8866 pTIClass->pTypeLib = pTypeLibImpl;
8867 pTIClass->index = 1;
8868 pTIClass->Name = NULL;
8869 pTIClass->dwHelpContext = -1;
8870 pTIClass->guid = NULL;
8871 pTIClass->typeattr.lcid = lcid;
8872 pTIClass->typeattr.typekind = TKIND_COCLASS;
8873 pTIClass->typeattr.wMajorVerNum = 0;
8874 pTIClass->typeattr.wMinorVerNum = 0;
8875 pTIClass->typeattr.cbAlignment = 2;
8876 pTIClass->typeattr.cbSizeInstance = -1;
8877 pTIClass->typeattr.cbSizeVft = -1;
8878 pTIClass->typeattr.cFuncs = 0;
8879 pTIClass->typeattr.cImplTypes = 1;
8880 pTIClass->typeattr.cVars = 0;
8881 pTIClass->typeattr.wTypeFlags = 0;
8882 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8883
8884 pTIClass->impltypes = TLBImplType_Alloc(1);
8885
8886 ref = heap_alloc_zero(sizeof(*ref));
8887 ref->pImpTLInfo = TLB_REF_INTERNAL;
8888 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8889
8890 dump_TypeInfo(pTIClass);
8891
8892 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8893
8894 ITypeInfo_AddRef(*pptinfo);
8895 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8896
8897 return S_OK;
8898
8899 }
8900
ITypeComp_fnQueryInterface(ITypeComp * iface,REFIID riid,LPVOID * ppv)8901 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8902 {
8903 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8904
8905 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8906 }
8907
ITypeComp_fnAddRef(ITypeComp * iface)8908 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8909 {
8910 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8911
8912 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8913 }
8914
ITypeComp_fnRelease(ITypeComp * iface)8915 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8916 {
8917 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8918
8919 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8920 }
8921
ITypeComp_fnBind(ITypeComp * iface,OLECHAR * szName,ULONG lHash,WORD wFlags,ITypeInfo ** ppTInfo,DESCKIND * pDescKind,BINDPTR * pBindPtr)8922 static HRESULT WINAPI ITypeComp_fnBind(
8923 ITypeComp * iface,
8924 OLECHAR * szName,
8925 ULONG lHash,
8926 WORD wFlags,
8927 ITypeInfo ** ppTInfo,
8928 DESCKIND * pDescKind,
8929 BINDPTR * pBindPtr)
8930 {
8931 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8932 const TLBFuncDesc *pFDesc;
8933 const TLBVarDesc *pVDesc;
8934 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8935 UINT fdc;
8936
8937 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8938
8939 *pDescKind = DESCKIND_NONE;
8940 pBindPtr->lpfuncdesc = NULL;
8941 *ppTInfo = NULL;
8942
8943 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8944 pFDesc = &This->funcdescs[fdc];
8945 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8946 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8947 break;
8948 else
8949 /* name found, but wrong flags */
8950 hr = TYPE_E_TYPEMISMATCH;
8951 }
8952 }
8953
8954 if (fdc < This->typeattr.cFuncs)
8955 {
8956 HRESULT hr = TLB_AllocAndInitFuncDesc(
8957 &pFDesc->funcdesc,
8958 &pBindPtr->lpfuncdesc,
8959 This->typeattr.typekind == TKIND_DISPATCH);
8960 if (FAILED(hr))
8961 return hr;
8962 *pDescKind = DESCKIND_FUNCDESC;
8963 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8964 ITypeInfo_AddRef(*ppTInfo);
8965 return S_OK;
8966 } else {
8967 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8968 if(pVDesc){
8969 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8970 if (FAILED(hr))
8971 return hr;
8972 *pDescKind = DESCKIND_VARDESC;
8973 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8974 ITypeInfo_AddRef(*ppTInfo);
8975 return S_OK;
8976 }
8977 }
8978
8979 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8980 /* recursive search */
8981 ITypeInfo *pTInfo;
8982 ITypeComp *pTComp;
8983 HRESULT hr;
8984 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8985 if (SUCCEEDED(hr))
8986 {
8987 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8988 ITypeInfo_Release(pTInfo);
8989 }
8990 if (SUCCEEDED(hr))
8991 {
8992 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8993 ITypeComp_Release(pTComp);
8994 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8995 This->typeattr.typekind == TKIND_DISPATCH)
8996 {
8997 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8998 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8999 SysFreeString((BSTR)tmp);
9000 }
9001 return hr;
9002 }
9003 WARN("Could not search inherited interface!\n");
9004 }
9005 if (hr == DISP_E_MEMBERNOTFOUND)
9006 hr = S_OK;
9007 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
9008 return hr;
9009 }
9010
ITypeComp_fnBindType(ITypeComp * iface,OLECHAR * szName,ULONG lHash,ITypeInfo ** ppTInfo,ITypeComp ** ppTComp)9011 static HRESULT WINAPI ITypeComp_fnBindType(
9012 ITypeComp * iface,
9013 OLECHAR * szName,
9014 ULONG lHash,
9015 ITypeInfo ** ppTInfo,
9016 ITypeComp ** ppTComp)
9017 {
9018 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
9019
9020 /* strange behaviour (does nothing) but like the
9021 * original */
9022
9023 if (!ppTInfo || !ppTComp)
9024 return E_POINTER;
9025
9026 *ppTInfo = NULL;
9027 *ppTComp = NULL;
9028
9029 return S_OK;
9030 }
9031
9032 static const ITypeCompVtbl tcompvt =
9033 {
9034
9035 ITypeComp_fnQueryInterface,
9036 ITypeComp_fnAddRef,
9037 ITypeComp_fnRelease,
9038
9039 ITypeComp_fnBind,
9040 ITypeComp_fnBindType
9041 };
9042
CreateTypeLib2(SYSKIND syskind,LPCOLESTR szFile,ICreateTypeLib2 ** ppctlib)9043 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
9044 ICreateTypeLib2** ppctlib)
9045 {
9046 ITypeLibImpl *This;
9047 HRESULT hres;
9048
9049 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
9050
9051 if (!szFile) return E_INVALIDARG;
9052
9053 This = TypeLibImpl_Constructor();
9054 if (!This)
9055 return E_OUTOFMEMORY;
9056
9057 This->lcid = GetSystemDefaultLCID();
9058 This->syskind = syskind;
9059 This->ptr_size = get_ptr_size(syskind);
9060
9061 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
9062 if (!This->path) {
9063 ITypeLib2_Release(&This->ITypeLib2_iface);
9064 return E_OUTOFMEMORY;
9065 }
9066 lstrcpyW(This->path, szFile);
9067
9068 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
9069 ITypeLib2_Release(&This->ITypeLib2_iface);
9070 return hres;
9071 }
9072
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 * iface,REFIID riid,void ** object)9073 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
9074 REFIID riid, void **object)
9075 {
9076 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9077
9078 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
9079 }
9080
ICreateTypeLib2_fnAddRef(ICreateTypeLib2 * iface)9081 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
9082 {
9083 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9084
9085 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
9086 }
9087
ICreateTypeLib2_fnRelease(ICreateTypeLib2 * iface)9088 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
9089 {
9090 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9091
9092 return ITypeLib2_Release(&This->ITypeLib2_iface);
9093 }
9094
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 * iface,LPOLESTR name,TYPEKIND kind,ICreateTypeInfo ** ctinfo)9095 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
9096 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
9097 {
9098 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9099 ITypeInfoImpl *info;
9100 HRESULT hres;
9101
9102 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
9103
9104 if (!ctinfo || !name)
9105 return E_INVALIDARG;
9106
9107 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
9108 if (info)
9109 return TYPE_E_NAMECONFLICT;
9110
9111 if (This->typeinfos)
9112 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
9113 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
9114 else
9115 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
9116
9117 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
9118
9119 info->pTypeLib = This;
9120 info->Name = TLB_append_str(&This->name_list, name);
9121 info->index = This->TypeInfoCount;
9122 info->typeattr.typekind = kind;
9123 info->typeattr.cbAlignment = 4;
9124
9125 switch (info->typeattr.typekind) {
9126 case TKIND_ENUM:
9127 case TKIND_INTERFACE:
9128 case TKIND_DISPATCH:
9129 case TKIND_COCLASS:
9130 info->typeattr.cbSizeInstance = This->ptr_size;
9131 break;
9132 case TKIND_RECORD:
9133 case TKIND_UNION:
9134 info->typeattr.cbSizeInstance = 0;
9135 break;
9136 case TKIND_MODULE:
9137 info->typeattr.cbSizeInstance = 2;
9138 break;
9139 case TKIND_ALIAS:
9140 info->typeattr.cbSizeInstance = -0x75;
9141 break;
9142 default:
9143 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
9144 info->typeattr.cbSizeInstance = 0xdeadbeef;
9145 break;
9146 }
9147
9148 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
9149 &IID_ICreateTypeInfo, (void **)ctinfo);
9150 if (FAILED(hres)) {
9151 ITypeInfo2_Release(&info->ITypeInfo2_iface);
9152 return hres;
9153 }
9154
9155 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
9156
9157 ++This->TypeInfoCount;
9158
9159 return S_OK;
9160 }
9161
ICreateTypeLib2_fnSetName(ICreateTypeLib2 * iface,LPOLESTR name)9162 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
9163 LPOLESTR name)
9164 {
9165 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9166
9167 TRACE("%p %s\n", This, wine_dbgstr_w(name));
9168
9169 if (!name)
9170 return E_INVALIDARG;
9171
9172 This->Name = TLB_append_str(&This->name_list, name);
9173
9174 return S_OK;
9175 }
9176
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 * iface,WORD majorVerNum,WORD minorVerNum)9177 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
9178 WORD majorVerNum, WORD minorVerNum)
9179 {
9180 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9181
9182 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
9183
9184 This->ver_major = majorVerNum;
9185 This->ver_minor = minorVerNum;
9186
9187 return S_OK;
9188 }
9189
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 * iface,REFGUID guid)9190 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
9191 REFGUID guid)
9192 {
9193 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9194
9195 TRACE("%p %s\n", This, debugstr_guid(guid));
9196
9197 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
9198
9199 return S_OK;
9200 }
9201
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 * iface,LPOLESTR doc)9202 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
9203 LPOLESTR doc)
9204 {
9205 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9206
9207 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
9208
9209 if (!doc)
9210 return E_INVALIDARG;
9211
9212 This->DocString = TLB_append_str(&This->string_list, doc);
9213
9214 return S_OK;
9215 }
9216
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 * iface,LPOLESTR helpFileName)9217 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
9218 LPOLESTR helpFileName)
9219 {
9220 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9221
9222 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9223
9224 if (!helpFileName)
9225 return E_INVALIDARG;
9226
9227 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9228
9229 return S_OK;
9230 }
9231
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 * iface,DWORD helpContext)9232 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9233 DWORD helpContext)
9234 {
9235 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9236
9237 TRACE("%p %d\n", This, helpContext);
9238
9239 This->dwHelpContext = helpContext;
9240
9241 return S_OK;
9242 }
9243
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 * iface,LCID lcid)9244 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9245 LCID lcid)
9246 {
9247 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9248
9249 TRACE("%p %x\n", This, lcid);
9250
9251 This->set_lcid = lcid;
9252
9253 return S_OK;
9254 }
9255
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 * iface,UINT libFlags)9256 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9257 UINT libFlags)
9258 {
9259 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9260
9261 TRACE("%p %x\n", This, libFlags);
9262
9263 This->libflags = libFlags;
9264
9265 return S_OK;
9266 }
9267
9268 typedef struct tagWMSFT_SegContents {
9269 DWORD len;
9270 void *data;
9271 } WMSFT_SegContents;
9272
9273 typedef struct tagWMSFT_TLBFile {
9274 MSFT_Header header;
9275 WMSFT_SegContents typeinfo_seg;
9276 WMSFT_SegContents impfile_seg;
9277 WMSFT_SegContents impinfo_seg;
9278 WMSFT_SegContents ref_seg;
9279 WMSFT_SegContents guidhash_seg;
9280 WMSFT_SegContents guid_seg;
9281 WMSFT_SegContents namehash_seg;
9282 WMSFT_SegContents name_seg;
9283 WMSFT_SegContents string_seg;
9284 WMSFT_SegContents typdesc_seg;
9285 WMSFT_SegContents arraydesc_seg;
9286 WMSFT_SegContents custdata_seg;
9287 WMSFT_SegContents cdguids_seg;
9288 MSFT_SegDir segdir;
9289 WMSFT_SegContents aux_seg;
9290 } WMSFT_TLBFile;
9291
WMSFT_compile_strings(ITypeLibImpl * This,WMSFT_TLBFile * file)9292 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9293 WMSFT_TLBFile *file)
9294 {
9295 TLBString *str;
9296 UINT last_offs;
9297 char *data;
9298
9299 file->string_seg.len = 0;
9300 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9301 int size;
9302
9303 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str), NULL, 0, NULL, NULL);
9304 if (size == 0)
9305 return E_UNEXPECTED;
9306
9307 size += sizeof(INT16);
9308 if (size % 4)
9309 size = (size + 4) & ~0x3;
9310 if (size < 8)
9311 size = 8;
9312
9313 file->string_seg.len += size;
9314
9315 /* temporarily use str->offset to store the length of the aligned,
9316 * converted string */
9317 str->offset = size;
9318 }
9319
9320 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9321
9322 last_offs = 0;
9323 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9324 int size;
9325
9326 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9327 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9328 if (size == 0) {
9329 heap_free(file->string_seg.data);
9330 return E_UNEXPECTED;
9331 }
9332
9333 *((INT16*)data) = size;
9334
9335 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9336
9337 size = str->offset;
9338 data += size;
9339 str->offset = last_offs;
9340 last_offs += size;
9341 }
9342
9343 return S_OK;
9344 }
9345
WMSFT_compile_names(ITypeLibImpl * This,WMSFT_TLBFile * file)9346 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9347 WMSFT_TLBFile *file)
9348 {
9349 TLBString *str;
9350 UINT last_offs;
9351 char *data;
9352 MSFT_NameIntro *last_intro = NULL;
9353
9354 file->header.nametablecount = 0;
9355 file->header.nametablechars = 0;
9356
9357 file->name_seg.len = 0;
9358 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9359 int size;
9360
9361 size = lstrlenW(str->str);
9362 file->header.nametablechars += size;
9363 file->header.nametablecount++;
9364
9365 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9366 if (size == 0)
9367 return E_UNEXPECTED;
9368
9369 size += sizeof(MSFT_NameIntro);
9370 if (size % 4)
9371 size = (size + 4) & ~0x3;
9372 if (size < 8)
9373 size = 8;
9374
9375 file->name_seg.len += size;
9376
9377 /* temporarily use str->offset to store the length of the aligned,
9378 * converted string */
9379 str->offset = size;
9380 }
9381
9382 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9383 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9384
9385 last_offs = 0;
9386 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9387 int size, hash;
9388 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9389
9390 size = WideCharToMultiByte(CP_ACP, 0, str->str, lstrlenW(str->str),
9391 data + sizeof(MSFT_NameIntro),
9392 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9393 if (size == 0) {
9394 heap_free(file->name_seg.data);
9395 return E_UNEXPECTED;
9396 }
9397 data[sizeof(MSFT_NameIntro) + size] = '\0';
9398
9399 intro->hreftype = -1; /* TODO? */
9400 intro->namelen = size & 0xFF;
9401 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9402 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9403 intro->namelen |= hash << 16;
9404 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9405 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9406
9407 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9408 str->offset - size - sizeof(MSFT_NameIntro));
9409
9410 /* update str->offset to actual value to use in other
9411 * compilation functions that require positions within
9412 * the string table */
9413 last_intro = intro;
9414 size = str->offset;
9415 data += size;
9416 str->offset = last_offs;
9417 last_offs += size;
9418 }
9419
9420 if(last_intro)
9421 last_intro->hreftype = 0; /* last one is 0? */
9422
9423 return S_OK;
9424 }
9425
hash_guid(GUID * guid)9426 static inline int hash_guid(GUID *guid)
9427 {
9428 int i, hash = 0;
9429
9430 for (i = 0; i < 8; i ++)
9431 hash ^= ((const short *)guid)[i];
9432
9433 return hash & 0x1f;
9434 }
9435
WMSFT_compile_guids(ITypeLibImpl * This,WMSFT_TLBFile * file)9436 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9437 {
9438 TLBGuid *guid;
9439 MSFT_GuidEntry *entry;
9440 DWORD offs;
9441 int hash_key, *guidhashtab;
9442
9443 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9444 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9445
9446 entry = file->guid_seg.data;
9447 offs = 0;
9448 guidhashtab = file->guidhash_seg.data;
9449 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9450 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9451 entry->hreftype = guid->hreftype;
9452
9453 hash_key = hash_guid(&guid->guid);
9454 entry->next_hash = guidhashtab[hash_key];
9455 guidhashtab[hash_key] = offs;
9456
9457 guid->offset = offs;
9458 offs += sizeof(MSFT_GuidEntry);
9459 ++entry;
9460 }
9461
9462 return S_OK;
9463 }
9464
WMSFT_encode_variant(VARIANT * value,WMSFT_TLBFile * file)9465 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9466 {
9467 VARIANT v = *value;
9468 VARTYPE arg_type = V_VT(value);
9469 int mask = 0;
9470 HRESULT hres;
9471 DWORD ret = file->custdata_seg.len;
9472
9473 if(arg_type == VT_INT)
9474 arg_type = VT_I4;
9475 if(arg_type == VT_UINT)
9476 arg_type = VT_UI4;
9477
9478 v = *value;
9479 if(V_VT(value) != arg_type) {
9480 hres = VariantChangeType(&v, value, 0, arg_type);
9481 if(FAILED(hres)){
9482 ERR("VariantChangeType failed: %08x\n", hres);
9483 return -1;
9484 }
9485 }
9486
9487 /* Check if default value can be stored in-place */
9488 switch(arg_type){
9489 case VT_I4:
9490 case VT_UI4:
9491 mask = 0x3ffffff;
9492 if(V_UI4(&v) > 0x3ffffff)
9493 break;
9494 /* fall through */
9495 case VT_I1:
9496 case VT_UI1:
9497 case VT_BOOL:
9498 if(!mask)
9499 mask = 0xff;
9500 /* fall through */
9501 case VT_I2:
9502 case VT_UI2:
9503 if(!mask)
9504 mask = 0xffff;
9505 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9506 }
9507
9508 /* have to allocate space in custdata_seg */
9509 switch(arg_type) {
9510 case VT_I4:
9511 case VT_R4:
9512 case VT_UI4:
9513 case VT_INT:
9514 case VT_UINT:
9515 case VT_HRESULT:
9516 case VT_PTR: {
9517 /* Construct the data to be allocated */
9518 int *data;
9519
9520 if(file->custdata_seg.data){
9521 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9522 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9523 file->custdata_seg.len += sizeof(int) * 2;
9524 }else{
9525 file->custdata_seg.len = sizeof(int) * 2;
9526 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9527 }
9528
9529 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9530 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9531
9532 /* TODO: Check if the encoded data is already present in custdata_seg */
9533
9534 return ret;
9535 }
9536
9537 case VT_BSTR: {
9538 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9539 char *data;
9540
9541 if(file->custdata_seg.data){
9542 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9543 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9544 file->custdata_seg.len += len;
9545 }else{
9546 file->custdata_seg.len = len;
9547 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9548 }
9549
9550 *((unsigned short *)data) = V_VT(value);
9551 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9552 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9553 if(V_BSTR(&v)[i] <= 0x7f)
9554 data[i+6] = V_BSTR(&v)[i];
9555 else
9556 data[i+6] = '?';
9557 }
9558 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9559 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9560 data[i] = 0x57;
9561
9562 /* TODO: Check if the encoded data is already present in custdata_seg */
9563
9564 return ret;
9565 }
9566 default:
9567 FIXME("Argument type not yet handled\n");
9568 return -1;
9569 }
9570 }
9571
9572 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9573
WMSFT_append_arraydesc(ARRAYDESC * desc,WMSFT_TLBFile * file)9574 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9575 {
9576 DWORD offs = file->arraydesc_seg.len;
9577 DWORD *encoded;
9578 USHORT i;
9579
9580 /* TODO: we should check for duplicates, but that's harder because each
9581 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9582 * at the library-level) */
9583
9584 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9585 if(!file->arraydesc_seg.data)
9586 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9587 else
9588 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9589 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9590
9591 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9592 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9593 for(i = 0; i < desc->cDims; ++i){
9594 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9595 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9596 }
9597
9598 return offs;
9599 }
9600
WMSFT_append_typedesc(TYPEDESC * desc,WMSFT_TLBFile * file,DWORD * out_mix,INT16 * out_size)9601 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9602 {
9603 DWORD junk;
9604 INT16 junk2;
9605 DWORD offs = 0;
9606 DWORD encoded[2];
9607 VARTYPE vt, subtype;
9608 char *data;
9609
9610 if(!desc)
9611 return -1;
9612
9613 if(!out_mix)
9614 out_mix = &junk;
9615 if(!out_size)
9616 out_size = &junk2;
9617
9618 vt = desc->vt & VT_TYPEMASK;
9619
9620 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9621 DWORD mix;
9622 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9623 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9624 *out_mix = 0x7FFF;
9625 *out_size += 2 * sizeof(DWORD);
9626 }else if(vt == VT_CARRAY){
9627 encoded[0] = desc->vt | (0x7FFE << 16);
9628 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9629 *out_mix = 0x7FFE;
9630 }else if(vt == VT_USERDEFINED){
9631 encoded[0] = desc->vt | (0x7FFF << 16);
9632 encoded[1] = desc->u.hreftype;
9633 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9634 }else{
9635 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9636
9637 switch(vt){
9638 case VT_INT:
9639 subtype = VT_I4;
9640 break;
9641 case VT_UINT:
9642 subtype = VT_UI4;
9643 break;
9644 case VT_VOID:
9645 subtype = VT_EMPTY;
9646 break;
9647 default:
9648 subtype = vt;
9649 break;
9650 }
9651
9652 *out_mix = subtype;
9653 return 0x80000000 | (subtype << 16) | desc->vt;
9654 }
9655
9656 data = file->typdesc_seg.data;
9657 while(offs < file->typdesc_seg.len){
9658 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9659 return offs;
9660 offs += sizeof(encoded);
9661 }
9662
9663 file->typdesc_seg.len += sizeof(encoded);
9664 if(!file->typdesc_seg.data)
9665 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9666 else
9667 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9668
9669 memcpy(&data[offs], encoded, sizeof(encoded));
9670
9671 return offs;
9672 }
9673
WMSFT_compile_custdata(struct list * custdata_list,WMSFT_TLBFile * file)9674 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9675 {
9676 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9677 DWORD ret = cdguids_seg->len, offs;
9678 MSFT_CDGuid *cdguid;
9679 TLBCustData *cd;
9680
9681 if(list_empty(custdata_list))
9682 return -1;
9683
9684 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9685 if(!cdguids_seg->data){
9686 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9687 }else {
9688 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9689 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9690 }
9691
9692 offs = ret + sizeof(MSFT_CDGuid);
9693 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9694 cdguid->GuidOffset = cd->guid->offset;
9695 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9696 cdguid->next = offs;
9697 offs += sizeof(MSFT_CDGuid);
9698 ++cdguid;
9699 }
9700
9701 --cdguid;
9702 cdguid->next = -1;
9703
9704 return ret;
9705 }
9706
WMSFT_compile_typeinfo_aux(ITypeInfoImpl * info,WMSFT_TLBFile * file)9707 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9708 WMSFT_TLBFile *file)
9709 {
9710 WMSFT_SegContents *aux_seg = &file->aux_seg;
9711 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9712 MSFT_VarRecord *varrecord;
9713 MSFT_FuncRecord *funcrecord;
9714 MEMBERID *memid;
9715 DWORD *name, *offsets, offs;
9716
9717 for(i = 0; i < info->typeattr.cFuncs; ++i){
9718 TLBFuncDesc *desc = &info->funcdescs[i];
9719
9720 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9721
9722 /* optional fields */
9723 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9724 if(!list_empty(&desc->custdata_list))
9725 recorded_size += 7 * sizeof(INT);
9726 else if(desc->HelpStringContext != 0)
9727 recorded_size += 6 * sizeof(INT);
9728 /* res9? resA? */
9729 else if(desc->Entry)
9730 recorded_size += 3 * sizeof(INT);
9731 else if(desc->HelpString)
9732 recorded_size += 2 * sizeof(INT);
9733 else if(desc->helpcontext)
9734 recorded_size += sizeof(INT);
9735
9736 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9737
9738 for(j = 0; j < desc->funcdesc.cParams; ++j){
9739 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9740 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9741 break;
9742 }
9743 }
9744
9745 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9746 }
9747
9748 for(i = 0; i < info->typeattr.cVars; ++i){
9749 TLBVarDesc *desc = &info->vardescs[i];
9750
9751 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9752
9753 /* optional fields */
9754 if(desc->HelpStringContext != 0)
9755 recorded_size += 5 * sizeof(INT);
9756 else if(!list_empty(&desc->custdata_list))
9757 recorded_size += 4 * sizeof(INT);
9758 /* res9? */
9759 else if(desc->HelpString)
9760 recorded_size += 2 * sizeof(INT);
9761 else if(desc->HelpContext != 0)
9762 recorded_size += sizeof(INT);
9763
9764 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9765 }
9766
9767 if(!recorded_size && !extra_size)
9768 return ret;
9769
9770 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9771
9772 aux_seg->len += recorded_size + extra_size;
9773
9774 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9775
9776 if(aux_seg->data)
9777 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9778 else
9779 aux_seg->data = heap_alloc(aux_seg->len);
9780
9781 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9782
9783 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9784 offs = 0;
9785
9786 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9787 for(i = 0; i < info->typeattr.cFuncs; ++i){
9788 TLBFuncDesc *desc = &info->funcdescs[i];
9789 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9790
9791 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9792 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9793 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9794 funcrecord->VtableOffset = desc->funcdesc.oVft;
9795
9796 /* FKCCIC:
9797 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9798 * ^^^funckind
9799 * ^^^ ^invkind
9800 * ^has_cust_data
9801 * ^^^^callconv
9802 * ^has_param_defaults
9803 * ^oEntry_is_intresource
9804 */
9805 funcrecord->FKCCIC =
9806 desc->funcdesc.funckind |
9807 (desc->funcdesc.invkind << 3) |
9808 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9809 (desc->funcdesc.callconv << 8);
9810
9811 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9812 funcrecord->FKCCIC |= 0x2000;
9813
9814 for(j = 0; j < desc->funcdesc.cParams; ++j){
9815 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9816 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9817 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9818 }
9819 }
9820 if(paramdefault_size > 0)
9821 funcrecord->FKCCIC |= 0x1000;
9822
9823 funcrecord->nrargs = desc->funcdesc.cParams;
9824 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9825
9826 /* optional fields */
9827 /* res9? resA? */
9828 if(!list_empty(&desc->custdata_list)){
9829 size += 7 * sizeof(INT);
9830 funcrecord->HelpContext = desc->helpcontext;
9831 if(desc->HelpString)
9832 funcrecord->oHelpString = desc->HelpString->offset;
9833 else
9834 funcrecord->oHelpString = -1;
9835 if(!desc->Entry)
9836 funcrecord->oEntry = -1;
9837 else if(IS_INTRESOURCE(desc->Entry))
9838 funcrecord->oEntry = LOWORD(desc->Entry);
9839 else
9840 funcrecord->oEntry = desc->Entry->offset;
9841 funcrecord->res9 = -1;
9842 funcrecord->resA = -1;
9843 funcrecord->HelpStringContext = desc->HelpStringContext;
9844 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9845 }else if(desc->HelpStringContext != 0){
9846 size += 6 * sizeof(INT);
9847 funcrecord->HelpContext = desc->helpcontext;
9848 if(desc->HelpString)
9849 funcrecord->oHelpString = desc->HelpString->offset;
9850 else
9851 funcrecord->oHelpString = -1;
9852 if(!desc->Entry)
9853 funcrecord->oEntry = -1;
9854 else if(IS_INTRESOURCE(desc->Entry))
9855 funcrecord->oEntry = LOWORD(desc->Entry);
9856 else
9857 funcrecord->oEntry = desc->Entry->offset;
9858 funcrecord->res9 = -1;
9859 funcrecord->resA = -1;
9860 funcrecord->HelpStringContext = desc->HelpStringContext;
9861 }else if(desc->Entry){
9862 size += 3 * sizeof(INT);
9863 funcrecord->HelpContext = desc->helpcontext;
9864 if(desc->HelpString)
9865 funcrecord->oHelpString = desc->HelpString->offset;
9866 else
9867 funcrecord->oHelpString = -1;
9868 if(!desc->Entry)
9869 funcrecord->oEntry = -1;
9870 else if(IS_INTRESOURCE(desc->Entry))
9871 funcrecord->oEntry = LOWORD(desc->Entry);
9872 else
9873 funcrecord->oEntry = desc->Entry->offset;
9874 }else if(desc->HelpString){
9875 size += 2 * sizeof(INT);
9876 funcrecord->HelpContext = desc->helpcontext;
9877 funcrecord->oHelpString = desc->HelpString->offset;
9878 }else if(desc->helpcontext){
9879 size += sizeof(INT);
9880 funcrecord->HelpContext = desc->helpcontext;
9881 }
9882
9883 paramdefault = (DWORD*)((char *)funcrecord + size);
9884 size += paramdefault_size;
9885
9886 for(j = 0; j < desc->funcdesc.cParams; ++j){
9887 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9888
9889 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9890 if(desc->pParamDesc[j].Name)
9891 info->oName = desc->pParamDesc[j].Name->offset;
9892 else
9893 info->oName = -1;
9894 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9895
9896 if(paramdefault_size){
9897 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9898 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9899 else if(paramdefault_size)
9900 *paramdefault = -1;
9901 ++paramdefault;
9902 }
9903
9904 size += sizeof(MSFT_ParameterInfo);
9905 }
9906
9907 funcrecord->Info = size | (i << 16); /* is it just the index? */
9908
9909 *offsets = offs;
9910 offs += size;
9911 ++offsets;
9912
9913 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9914 }
9915
9916 varrecord = (MSFT_VarRecord*)funcrecord;
9917 for(i = 0; i < info->typeattr.cVars; ++i){
9918 TLBVarDesc *desc = &info->vardescs[i];
9919 DWORD size = 5 * sizeof(INT);
9920
9921 varrecord->vardescsize = sizeof(desc->vardesc);
9922 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9923 varrecord->Flags = desc->vardesc.wVarFlags;
9924 varrecord->VarKind = desc->vardesc.varkind;
9925
9926 if(desc->vardesc.varkind == VAR_CONST){
9927 varrecord->vardescsize += sizeof(VARIANT);
9928 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9929 }else
9930 varrecord->OffsValue = desc->vardesc.u.oInst;
9931
9932 /* res9? */
9933 if(desc->HelpStringContext != 0){
9934 size += 5 * sizeof(INT);
9935 varrecord->HelpContext = desc->HelpContext;
9936 if(desc->HelpString)
9937 varrecord->HelpString = desc->HelpString->offset;
9938 else
9939 varrecord->HelpString = -1;
9940 varrecord->res9 = -1;
9941 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9942 varrecord->HelpStringContext = desc->HelpStringContext;
9943 }else if(!list_empty(&desc->custdata_list)){
9944 size += 4 * sizeof(INT);
9945 varrecord->HelpContext = desc->HelpContext;
9946 if(desc->HelpString)
9947 varrecord->HelpString = desc->HelpString->offset;
9948 else
9949 varrecord->HelpString = -1;
9950 varrecord->res9 = -1;
9951 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9952 }else if(desc->HelpString){
9953 size += 2 * sizeof(INT);
9954 varrecord->HelpContext = desc->HelpContext;
9955 if(desc->HelpString)
9956 varrecord->HelpString = desc->HelpString->offset;
9957 else
9958 varrecord->HelpString = -1;
9959 }else if(desc->HelpContext != 0){
9960 size += sizeof(INT);
9961 varrecord->HelpContext = desc->HelpContext;
9962 }
9963
9964 varrecord->Info = size | (i << 16);
9965
9966 *offsets = offs;
9967 offs += size;
9968 ++offsets;
9969
9970 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9971 }
9972
9973 memid = (MEMBERID*)varrecord;
9974 for(i = 0; i < info->typeattr.cFuncs; ++i){
9975 TLBFuncDesc *desc = &info->funcdescs[i];
9976 *memid = desc->funcdesc.memid;
9977 ++memid;
9978 }
9979 for(i = 0; i < info->typeattr.cVars; ++i){
9980 TLBVarDesc *desc = &info->vardescs[i];
9981 *memid = desc->vardesc.memid;
9982 ++memid;
9983 }
9984
9985 name = (UINT*)memid;
9986 for(i = 0; i < info->typeattr.cFuncs; ++i){
9987 TLBFuncDesc *desc = &info->funcdescs[i];
9988 if(desc->Name)
9989 *name = desc->Name->offset;
9990 else
9991 *name = -1;
9992 ++name;
9993 }
9994 for(i = 0; i < info->typeattr.cVars; ++i){
9995 TLBVarDesc *desc = &info->vardescs[i];
9996 if(desc->Name)
9997 *name = desc->Name->offset;
9998 else
9999 *name = -1;
10000 ++name;
10001 }
10002
10003 return ret;
10004 }
10005
10006 typedef struct tagWMSFT_RefChunk {
10007 DWORD href;
10008 DWORD res04;
10009 DWORD res08;
10010 DWORD next;
10011 } WMSFT_RefChunk;
10012
WMSFT_compile_typeinfo_ref(ITypeInfoImpl * info,WMSFT_TLBFile * file)10013 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
10014 {
10015 DWORD offs = file->ref_seg.len, i;
10016 WMSFT_RefChunk *chunk;
10017
10018 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
10019 if(!file->ref_seg.data)
10020 file->ref_seg.data = heap_alloc(file->ref_seg.len);
10021 else
10022 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
10023
10024 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
10025
10026 for(i = 0; i < info->typeattr.cImplTypes; ++i){
10027 chunk->href = info->impltypes[i].hRef;
10028 chunk->res04 = info->impltypes[i].implflags;
10029 chunk->res08 = -1;
10030 if(i < info->typeattr.cImplTypes - 1)
10031 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
10032 else
10033 chunk->next = -1;
10034 ++chunk;
10035 }
10036
10037 return offs;
10038 }
10039
WMSFT_compile_typeinfo(ITypeInfoImpl * info,INT16 index,WMSFT_TLBFile * file,char * data)10040 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
10041 {
10042 DWORD size;
10043
10044 size = sizeof(MSFT_TypeInfoBase);
10045
10046 if(data){
10047 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
10048 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
10049 base->typekind = TKIND_DISPATCH;
10050 else
10051 base->typekind = info->typeattr.typekind;
10052 base->typekind |= index << 16; /* TODO: There are some other flags here */
10053 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
10054 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
10055 base->res2 = 0;
10056 base->res3 = 0;
10057 base->res4 = 3;
10058 base->res5 = 0;
10059 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
10060 base->res7 = 0;
10061 base->res8 = 0;
10062 base->res9 = 0;
10063 base->resA = 0;
10064 if(info->guid)
10065 base->posguid = info->guid->offset;
10066 else
10067 base->posguid = -1;
10068 base->flags = info->typeattr.wTypeFlags;
10069 if(info->Name) {
10070 base->NameOffset = info->Name->offset;
10071
10072 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
10073 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
10074 }else {
10075 base->NameOffset = -1;
10076 }
10077 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
10078 if(info->DocString)
10079 base->docstringoffs = info->DocString->offset;
10080 else
10081 base->docstringoffs = -1;
10082 base->helpstringcontext = info->dwHelpStringContext;
10083 base->helpcontext = info->dwHelpContext;
10084 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
10085 base->cImplTypes = info->typeattr.cImplTypes;
10086 base->cbSizeVft = info->typeattr.cbSizeVft;
10087 base->size = info->typeattr.cbSizeInstance;
10088 if(info->typeattr.typekind == TKIND_COCLASS){
10089 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
10090 }else if(info->typeattr.typekind == TKIND_ALIAS){
10091 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
10092 }else if(info->typeattr.typekind == TKIND_MODULE){
10093 if(info->DllName)
10094 base->datatype1 = info->DllName->offset;
10095 else
10096 base->datatype1 = -1;
10097 }else{
10098 if(info->typeattr.cImplTypes > 0)
10099 base->datatype1 = info->impltypes[0].hRef;
10100 else
10101 base->datatype1 = -1;
10102 }
10103 base->datatype2 = index; /* FIXME: i think there's more here */
10104 base->res18 = 0;
10105 base->res19 = -1;
10106 }
10107
10108 return size;
10109 }
10110
WMSFT_compile_typeinfo_seg(ITypeLibImpl * This,WMSFT_TLBFile * file,DWORD * junk)10111 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
10112 {
10113 UINT i;
10114
10115 file->typeinfo_seg.len = 0;
10116 for(i = 0; i < This->TypeInfoCount; ++i){
10117 ITypeInfoImpl *info = This->typeinfos[i];
10118 *junk = file->typeinfo_seg.len;
10119 ++junk;
10120 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
10121 }
10122
10123 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
10124 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
10125
10126 file->aux_seg.len = 0;
10127 file->aux_seg.data = NULL;
10128
10129 file->typeinfo_seg.len = 0;
10130 for(i = 0; i < This->TypeInfoCount; ++i){
10131 ITypeInfoImpl *info = This->typeinfos[i];
10132 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
10133 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
10134 }
10135 }
10136
10137 typedef struct tagWMSFT_ImpFile {
10138 INT guid_offs;
10139 LCID lcid;
10140 DWORD version;
10141 } WMSFT_ImpFile;
10142
WMSFT_compile_impfile(ITypeLibImpl * This,WMSFT_TLBFile * file)10143 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
10144 {
10145 TLBImpLib *implib;
10146 WMSFT_ImpFile *impfile;
10147 char *data;
10148 DWORD last_offs = 0;
10149
10150 file->impfile_seg.len = 0;
10151 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10152 int size = 0;
10153
10154 if(implib->name){
10155 WCHAR *path = wcsrchr(implib->name, '\\');
10156 if(path)
10157 ++path;
10158 else
10159 path = implib->name;
10160 size = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path), NULL, 0, NULL, NULL);
10161 if (size == 0)
10162 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10163 }
10164
10165 size += sizeof(INT16);
10166 if (size % 4)
10167 size = (size + 4) & ~0x3;
10168 if (size < 8)
10169 size = 8;
10170
10171 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
10172 }
10173
10174 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
10175
10176 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
10177 int strlen = 0, size;
10178
10179 impfile = (WMSFT_ImpFile*)data;
10180 impfile->guid_offs = implib->guid->offset;
10181 impfile->lcid = implib->lcid;
10182 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
10183
10184 data += sizeof(WMSFT_ImpFile);
10185
10186 if(implib->name){
10187 WCHAR *path= wcsrchr(implib->name, '\\');
10188 if(path)
10189 ++path;
10190 else
10191 path = implib->name;
10192 strlen = WideCharToMultiByte(CP_ACP, 0, path, lstrlenW(path),
10193 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
10194 if (strlen == 0)
10195 ERR("failed to convert wide string: %s\n", debugstr_w(path));
10196 }
10197
10198 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
10199
10200 size = strlen + sizeof(INT16);
10201 if (size % 4)
10202 size = (size + 4) & ~0x3;
10203 if (size < 8)
10204 size = 8;
10205 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
10206
10207 data += size;
10208 implib->offset = last_offs;
10209 last_offs += size + sizeof(WMSFT_ImpFile);
10210 }
10211 }
10212
WMSFT_compile_impinfo(ITypeLibImpl * This,WMSFT_TLBFile * file)10213 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
10214 {
10215 MSFT_ImpInfo *info;
10216 TLBRefType *ref_type;
10217 UINT i = 0;
10218
10219 WMSFT_compile_impfile(This, file);
10220
10221 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10222 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10223
10224 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10225 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10226 if(ref_type->index == TLB_REF_USE_GUID){
10227 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10228 info->oGuid = ref_type->guid->offset;
10229 }else
10230 info->oGuid = ref_type->index;
10231 info->oImpFile = ref_type->pImpTLInfo->offset;
10232 ++i;
10233 ++info;
10234 }
10235 }
10236
WMSFT_compile_guidhash(ITypeLibImpl * This,WMSFT_TLBFile * file)10237 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10238 {
10239 file->guidhash_seg.len = 0x80;
10240 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10241 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10242 }
10243
WMSFT_compile_namehash(ITypeLibImpl * This,WMSFT_TLBFile * file)10244 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10245 {
10246 file->namehash_seg.len = 0x200;
10247 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10248 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10249 }
10250
tmp_fill_segdir_seg(MSFT_pSeg * segdir,WMSFT_SegContents * contents,DWORD * running_offset)10251 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10252 {
10253 if(contents && contents->len){
10254 segdir->offset = *running_offset;
10255 segdir->length = contents->len;
10256 *running_offset += segdir->length;
10257 }else{
10258 segdir->offset = -1;
10259 segdir->length = 0;
10260 }
10261
10262 /* TODO: do these ever change? */
10263 segdir->res08 = -1;
10264 segdir->res0c = 0xf;
10265 }
10266
WMSFT_write_segment(HANDLE outfile,WMSFT_SegContents * segment)10267 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10268 {
10269 DWORD written;
10270 if(segment)
10271 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10272 }
10273
WMSFT_fixup_typeinfos(ITypeLibImpl * This,WMSFT_TLBFile * file,DWORD file_len)10274 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10275 DWORD file_len)
10276 {
10277 DWORD i;
10278 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10279
10280 for(i = 0; i < This->TypeInfoCount; ++i){
10281 base->memoffset += file_len;
10282 ++base;
10283 }
10284
10285 return S_OK;
10286 }
10287
WMSFT_free_file(WMSFT_TLBFile * file)10288 static void WMSFT_free_file(WMSFT_TLBFile *file)
10289 {
10290 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10291 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10292 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10293 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10294 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10295 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10296 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10297 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10298 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10299 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10300 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10301 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10302 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10303 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10304 }
10305
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 * iface)10306 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10307 {
10308 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10309 WMSFT_TLBFile file;
10310 DWORD written, junk_size, junk_offs, running_offset;
10311 BOOL br;
10312 HANDLE outfile;
10313 HRESULT hres;
10314 DWORD *junk;
10315 UINT i;
10316
10317 TRACE("%p\n", This);
10318
10319 for(i = 0; i < This->TypeInfoCount; ++i)
10320 if(This->typeinfos[i]->needs_layout)
10321 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10322
10323 memset(&file, 0, sizeof(file));
10324
10325 file.header.magic1 = 0x5446534D;
10326 file.header.magic2 = 0x00010002;
10327 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10328 file.header.lcid2 = This->set_lcid;
10329 file.header.varflags = 0x40 | This->syskind;
10330 if (This->HelpFile)
10331 file.header.varflags |= 0x10;
10332 if (This->HelpStringDll)
10333 file.header.varflags |= HELPDLLFLAG;
10334 file.header.version = (This->ver_minor << 16) | This->ver_major;
10335 file.header.flags = This->libflags;
10336 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10337 file.header.helpcontext = This->dwHelpContext;
10338 file.header.res44 = 0x20;
10339 file.header.res48 = 0x80;
10340 file.header.dispatchpos = This->dispatch_href;
10341
10342 WMSFT_compile_namehash(This, &file);
10343 /* do name and string compilation to get offsets for other compilations */
10344 hres = WMSFT_compile_names(This, &file);
10345 if (FAILED(hres)){
10346 WMSFT_free_file(&file);
10347 return hres;
10348 }
10349
10350 hres = WMSFT_compile_strings(This, &file);
10351 if (FAILED(hres)){
10352 WMSFT_free_file(&file);
10353 return hres;
10354 }
10355
10356 WMSFT_compile_guidhash(This, &file);
10357 hres = WMSFT_compile_guids(This, &file);
10358 if (FAILED(hres)){
10359 WMSFT_free_file(&file);
10360 return hres;
10361 }
10362
10363 if(This->HelpFile)
10364 file.header.helpfile = This->HelpFile->offset;
10365 else
10366 file.header.helpfile = -1;
10367
10368 if(This->DocString)
10369 file.header.helpstring = This->DocString->offset;
10370 else
10371 file.header.helpstring = -1;
10372
10373 /* do some more segment compilation */
10374 file.header.nimpinfos = list_count(&This->ref_list);
10375 file.header.nrtypeinfos = This->TypeInfoCount;
10376
10377 if(This->Name)
10378 file.header.NameOffset = This->Name->offset;
10379 else
10380 file.header.NameOffset = -1;
10381
10382 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10383
10384 if(This->guid)
10385 file.header.posguid = This->guid->offset;
10386 else
10387 file.header.posguid = -1;
10388
10389 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10390 if(file.header.varflags & HELPDLLFLAG)
10391 junk_size += sizeof(DWORD);
10392 if(junk_size){
10393 junk = heap_alloc_zero(junk_size);
10394 if(file.header.varflags & HELPDLLFLAG){
10395 *junk = This->HelpStringDll->offset;
10396 junk_offs = 1;
10397 }else
10398 junk_offs = 0;
10399 }else{
10400 junk = NULL;
10401 junk_offs = 0;
10402 }
10403
10404 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10405 WMSFT_compile_impinfo(This, &file);
10406
10407 running_offset = 0;
10408
10409 TRACE("header at: 0x%x\n", running_offset);
10410 running_offset += sizeof(file.header);
10411
10412 TRACE("junk at: 0x%x\n", running_offset);
10413 running_offset += junk_size;
10414
10415 TRACE("segdir at: 0x%x\n", running_offset);
10416 running_offset += sizeof(file.segdir);
10417
10418 TRACE("typeinfo at: 0x%x\n", running_offset);
10419 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10420
10421 TRACE("guidhashtab at: 0x%x\n", running_offset);
10422 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10423
10424 TRACE("guidtab at: 0x%x\n", running_offset);
10425 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10426
10427 TRACE("reftab at: 0x%x\n", running_offset);
10428 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10429
10430 TRACE("impinfo at: 0x%x\n", running_offset);
10431 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10432
10433 TRACE("impfiles at: 0x%x\n", running_offset);
10434 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10435
10436 TRACE("namehashtab at: 0x%x\n", running_offset);
10437 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10438
10439 TRACE("nametab at: 0x%x\n", running_offset);
10440 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10441
10442 TRACE("stringtab at: 0x%x\n", running_offset);
10443 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10444
10445 TRACE("typdesc at: 0x%x\n", running_offset);
10446 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10447
10448 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10449 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10450
10451 TRACE("custdata at: 0x%x\n", running_offset);
10452 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10453
10454 TRACE("cdguids at: 0x%x\n", running_offset);
10455 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10456
10457 TRACE("res0e at: 0x%x\n", running_offset);
10458 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10459
10460 TRACE("res0f at: 0x%x\n", running_offset);
10461 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10462
10463 TRACE("aux_seg at: 0x%x\n", running_offset);
10464
10465 WMSFT_fixup_typeinfos(This, &file, running_offset);
10466
10467 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10468 FILE_ATTRIBUTE_NORMAL, 0);
10469 if (outfile == INVALID_HANDLE_VALUE){
10470 WMSFT_free_file(&file);
10471 heap_free(junk);
10472 return TYPE_E_IOERROR;
10473 }
10474
10475 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10476 if (!br) {
10477 WMSFT_free_file(&file);
10478 CloseHandle(outfile);
10479 heap_free(junk);
10480 return TYPE_E_IOERROR;
10481 }
10482
10483 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10484 heap_free(junk);
10485 if (!br) {
10486 WMSFT_free_file(&file);
10487 CloseHandle(outfile);
10488 return TYPE_E_IOERROR;
10489 }
10490
10491 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10492 if (!br) {
10493 WMSFT_free_file(&file);
10494 CloseHandle(outfile);
10495 return TYPE_E_IOERROR;
10496 }
10497
10498 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10499 WMSFT_write_segment(outfile, &file.guidhash_seg);
10500 WMSFT_write_segment(outfile, &file.guid_seg);
10501 WMSFT_write_segment(outfile, &file.ref_seg);
10502 WMSFT_write_segment(outfile, &file.impinfo_seg);
10503 WMSFT_write_segment(outfile, &file.impfile_seg);
10504 WMSFT_write_segment(outfile, &file.namehash_seg);
10505 WMSFT_write_segment(outfile, &file.name_seg);
10506 WMSFT_write_segment(outfile, &file.string_seg);
10507 WMSFT_write_segment(outfile, &file.typdesc_seg);
10508 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10509 WMSFT_write_segment(outfile, &file.custdata_seg);
10510 WMSFT_write_segment(outfile, &file.cdguids_seg);
10511 WMSFT_write_segment(outfile, &file.aux_seg);
10512
10513 WMSFT_free_file(&file);
10514
10515 CloseHandle(outfile);
10516
10517 return S_OK;
10518 }
10519
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 * iface,LPOLESTR name)10520 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10521 LPOLESTR name)
10522 {
10523 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10524 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10525 return E_NOTIMPL;
10526 }
10527
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 * iface,REFGUID guid,VARIANT * varVal)10528 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10529 REFGUID guid, VARIANT *varVal)
10530 {
10531 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10532 TLBGuid *tlbguid;
10533
10534 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10535
10536 if (!guid || !varVal)
10537 return E_INVALIDARG;
10538
10539 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10540
10541 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10542 }
10543
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 * iface,ULONG helpStringContext)10544 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10545 ULONG helpStringContext)
10546 {
10547 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10548 FIXME("%p %u - stub\n", This, helpStringContext);
10549 return E_NOTIMPL;
10550 }
10551
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 * iface,LPOLESTR filename)10552 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10553 LPOLESTR filename)
10554 {
10555 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10556 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10557
10558 if (!filename)
10559 return E_INVALIDARG;
10560
10561 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10562
10563 return S_OK;
10564 }
10565
10566 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10567 ICreateTypeLib2_fnQueryInterface,
10568 ICreateTypeLib2_fnAddRef,
10569 ICreateTypeLib2_fnRelease,
10570 ICreateTypeLib2_fnCreateTypeInfo,
10571 ICreateTypeLib2_fnSetName,
10572 ICreateTypeLib2_fnSetVersion,
10573 ICreateTypeLib2_fnSetGuid,
10574 ICreateTypeLib2_fnSetDocString,
10575 ICreateTypeLib2_fnSetHelpFileName,
10576 ICreateTypeLib2_fnSetHelpContext,
10577 ICreateTypeLib2_fnSetLcid,
10578 ICreateTypeLib2_fnSetLibFlags,
10579 ICreateTypeLib2_fnSaveAllChanges,
10580 ICreateTypeLib2_fnDeleteTypeInfo,
10581 ICreateTypeLib2_fnSetCustData,
10582 ICreateTypeLib2_fnSetHelpStringContext,
10583 ICreateTypeLib2_fnSetHelpStringDll
10584 };
10585
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 * iface,REFIID riid,void ** object)10586 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10587 REFIID riid, void **object)
10588 {
10589 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10590
10591 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10592 }
10593
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 * iface)10594 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10595 {
10596 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10597
10598 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10599 }
10600
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 * iface)10601 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10602 {
10603 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10604
10605 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10606 }
10607
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 * iface,REFGUID guid)10608 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10609 REFGUID guid)
10610 {
10611 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10612
10613 TRACE("%p %s\n", This, debugstr_guid(guid));
10614
10615 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10616
10617 return S_OK;
10618 }
10619
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 * iface,UINT typeFlags)10620 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10621 UINT typeFlags)
10622 {
10623 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10624 WORD old_flags;
10625 HRESULT hres;
10626
10627 TRACE("%p %x\n", This, typeFlags);
10628
10629 if (typeFlags & TYPEFLAG_FDUAL) {
10630 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10631 ITypeLib *stdole;
10632 ITypeInfo *dispatch;
10633 HREFTYPE hreftype;
10634 HRESULT hres;
10635
10636 hres = LoadTypeLib(stdole2tlb, &stdole);
10637 if(FAILED(hres))
10638 return hres;
10639
10640 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10641 ITypeLib_Release(stdole);
10642 if(FAILED(hres))
10643 return hres;
10644
10645 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10646 ITypeInfo_Release(dispatch);
10647 if(FAILED(hres))
10648 return hres;
10649 }
10650
10651 old_flags = This->typeattr.wTypeFlags;
10652 This->typeattr.wTypeFlags = typeFlags;
10653
10654 hres = ICreateTypeInfo2_LayOut(iface);
10655 if (FAILED(hres)) {
10656 This->typeattr.wTypeFlags = old_flags;
10657 return hres;
10658 }
10659
10660 return S_OK;
10661 }
10662
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 * iface,LPOLESTR doc)10663 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10664 LPOLESTR doc)
10665 {
10666 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10667
10668 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10669
10670 if (!doc)
10671 return E_INVALIDARG;
10672
10673 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10674
10675 return S_OK;
10676 }
10677
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 * iface,DWORD helpContext)10678 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10679 DWORD helpContext)
10680 {
10681 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10682
10683 TRACE("%p %d\n", This, helpContext);
10684
10685 This->dwHelpContext = helpContext;
10686
10687 return S_OK;
10688 }
10689
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 * iface,WORD majorVerNum,WORD minorVerNum)10690 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10691 WORD majorVerNum, WORD minorVerNum)
10692 {
10693 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10694
10695 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10696
10697 This->typeattr.wMajorVerNum = majorVerNum;
10698 This->typeattr.wMinorVerNum = minorVerNum;
10699
10700 return S_OK;
10701 }
10702
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 * iface,ITypeInfo * typeInfo,HREFTYPE * refType)10703 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10704 ITypeInfo *typeInfo, HREFTYPE *refType)
10705 {
10706 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10707 UINT index;
10708 ITypeLib *container;
10709 TLBRefType *ref_type;
10710 TLBImpLib *implib;
10711 TYPEATTR *typeattr;
10712 TLIBATTR *libattr;
10713 HRESULT hres;
10714
10715 TRACE("%p %p %p\n", This, typeInfo, refType);
10716
10717 if (!typeInfo || !refType)
10718 return E_INVALIDARG;
10719
10720 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10721 if (FAILED(hres))
10722 return hres;
10723
10724 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10725 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10726
10727 ITypeLib_Release(container);
10728
10729 *refType = target->hreftype;
10730
10731 return S_OK;
10732 }
10733
10734 hres = ITypeLib_GetLibAttr(container, &libattr);
10735 if (FAILED(hres)) {
10736 ITypeLib_Release(container);
10737 return hres;
10738 }
10739
10740 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10741 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10742 implib->lcid == libattr->lcid &&
10743 implib->wVersionMajor == libattr->wMajorVerNum &&
10744 implib->wVersionMinor == libattr->wMinorVerNum)
10745 break;
10746 }
10747
10748 if(&implib->entry == &This->pTypeLib->implib_list){
10749 implib = heap_alloc_zero(sizeof(TLBImpLib));
10750
10751 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10752 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10753 implib->name = SysAllocString(our_container->path);
10754 }else{
10755 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10756 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10757 if(FAILED(hres)){
10758 implib->name = NULL;
10759 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10760 }
10761 }
10762
10763 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10764 implib->lcid = libattr->lcid;
10765 implib->wVersionMajor = libattr->wMajorVerNum;
10766 implib->wVersionMinor = libattr->wMinorVerNum;
10767
10768 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10769 }
10770
10771 ITypeLib_ReleaseTLibAttr(container, libattr);
10772 ITypeLib_Release(container);
10773
10774 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10775 if (FAILED(hres))
10776 return hres;
10777
10778 index = 0;
10779 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10780 if(ref_type->index == TLB_REF_USE_GUID &&
10781 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10782 ref_type->tkind == typeattr->typekind)
10783 break;
10784 ++index;
10785 }
10786
10787 if(&ref_type->entry == &This->pTypeLib->ref_list){
10788 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10789
10790 ref_type->tkind = typeattr->typekind;
10791 ref_type->pImpTLInfo = implib;
10792 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10793
10794 ref_type->index = TLB_REF_USE_GUID;
10795
10796 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10797
10798 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10799 }
10800
10801 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10802
10803 *refType = ref_type->reference | 0x1;
10804
10805 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10806 This->pTypeLib->dispatch_href = *refType;
10807
10808 return S_OK;
10809 }
10810
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 * iface,UINT index,FUNCDESC * funcDesc)10811 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10812 UINT index, FUNCDESC *funcDesc)
10813 {
10814 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10815 TLBFuncDesc tmp_func_desc, *func_desc;
10816 int buf_size, i;
10817 char *buffer;
10818 HRESULT hres;
10819
10820 TRACE("%p %u %p\n", This, index, funcDesc);
10821
10822 if (!funcDesc || funcDesc->oVft & 3)
10823 return E_INVALIDARG;
10824
10825 switch (This->typeattr.typekind) {
10826 case TKIND_MODULE:
10827 if (funcDesc->funckind != FUNC_STATIC)
10828 return TYPE_E_BADMODULEKIND;
10829 break;
10830 case TKIND_DISPATCH:
10831 if (funcDesc->funckind != FUNC_DISPATCH)
10832 return TYPE_E_BADMODULEKIND;
10833 break;
10834 default:
10835 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10836 return TYPE_E_BADMODULEKIND;
10837 }
10838
10839 if (index > This->typeattr.cFuncs)
10840 return TYPE_E_ELEMENTNOTFOUND;
10841
10842 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10843 !funcDesc->cParams)
10844 return TYPE_E_INCONSISTENTPROPFUNCS;
10845
10846 #ifdef _WIN64
10847 if(This->pTypeLib->syskind == SYS_WIN64 &&
10848 funcDesc->oVft % 8 != 0)
10849 return E_INVALIDARG;
10850 #endif
10851
10852 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10853 TLBFuncDesc_Constructor(&tmp_func_desc);
10854
10855 tmp_func_desc.funcdesc = *funcDesc;
10856
10857 if (tmp_func_desc.funcdesc.oVft != 0)
10858 tmp_func_desc.funcdesc.oVft |= 1;
10859
10860 if (funcDesc->cScodes && funcDesc->lprgscode) {
10861 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10862 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10863 } else {
10864 tmp_func_desc.funcdesc.lprgscode = NULL;
10865 tmp_func_desc.funcdesc.cScodes = 0;
10866 }
10867
10868 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10869 for (i = 0; i < funcDesc->cParams; ++i) {
10870 buf_size += sizeof(ELEMDESC);
10871 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10872 }
10873 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10874 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10875
10876 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10877 if (FAILED(hres)) {
10878 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10879 heap_free(tmp_func_desc.funcdesc.lprgscode);
10880 return hres;
10881 }
10882
10883 for (i = 0; i < funcDesc->cParams; ++i) {
10884 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10885 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10886 if (FAILED(hres)) {
10887 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10888 heap_free(tmp_func_desc.funcdesc.lprgscode);
10889 return hres;
10890 }
10891 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10892 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10893 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10894 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10895 if (FAILED(hres)) {
10896 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10897 heap_free(tmp_func_desc.funcdesc.lprgscode);
10898 return hres;
10899 }
10900 }
10901 }
10902
10903 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10904
10905 if (This->funcdescs) {
10906 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10907 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10908
10909 if (index < This->typeattr.cFuncs) {
10910 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10911 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10912 func_desc = This->funcdescs + index;
10913 } else
10914 func_desc = This->funcdescs + This->typeattr.cFuncs;
10915
10916 /* move custdata lists to the new memory location */
10917 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10918 if(index != i){
10919 TLBFuncDesc *fd = &This->funcdescs[i];
10920 if(fd->custdata_list.prev == fd->custdata_list.next)
10921 list_init(&fd->custdata_list);
10922 else{
10923 fd->custdata_list.prev->next = &fd->custdata_list;
10924 fd->custdata_list.next->prev = &fd->custdata_list;
10925 }
10926 }
10927 }
10928 } else
10929 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10930
10931 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10932 list_init(&func_desc->custdata_list);
10933
10934 ++This->typeattr.cFuncs;
10935
10936 This->needs_layout = TRUE;
10937
10938 return S_OK;
10939 }
10940
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 * iface,UINT index,HREFTYPE refType)10941 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10942 UINT index, HREFTYPE refType)
10943 {
10944 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10945 TLBImplType *impl_type;
10946 HRESULT hres;
10947
10948 TRACE("%p %u %d\n", This, index, refType);
10949
10950 switch(This->typeattr.typekind){
10951 case TKIND_COCLASS: {
10952 if (index == -1) {
10953 FIXME("Unhandled index: -1\n");
10954 return E_NOTIMPL;
10955 }
10956
10957 if(index != This->typeattr.cImplTypes)
10958 return TYPE_E_ELEMENTNOTFOUND;
10959
10960 break;
10961 }
10962 case TKIND_INTERFACE:
10963 case TKIND_DISPATCH:
10964 if (index != 0 || This->typeattr.cImplTypes)
10965 return TYPE_E_ELEMENTNOTFOUND;
10966 break;
10967 default:
10968 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10969 return E_NOTIMPL;
10970 }
10971
10972 if (This->impltypes){
10973 UINT i;
10974
10975 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10976 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10977
10978 if (index < This->typeattr.cImplTypes) {
10979 memmove(This->impltypes + index + 1, This->impltypes + index,
10980 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10981 impl_type = This->impltypes + index;
10982 } else
10983 impl_type = This->impltypes + This->typeattr.cImplTypes;
10984
10985 /* move custdata lists to the new memory location */
10986 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10987 if(index != i){
10988 TLBImplType *it = &This->impltypes[i];
10989 if(it->custdata_list.prev == it->custdata_list.next)
10990 list_init(&it->custdata_list);
10991 else{
10992 it->custdata_list.prev->next = &it->custdata_list;
10993 it->custdata_list.next->prev = &it->custdata_list;
10994 }
10995 }
10996 }
10997 } else
10998 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10999
11000 memset(impl_type, 0, sizeof(TLBImplType));
11001 TLBImplType_Constructor(impl_type);
11002 impl_type->hRef = refType;
11003
11004 ++This->typeattr.cImplTypes;
11005
11006 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
11007 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
11008
11009 hres = ICreateTypeInfo2_LayOut(iface);
11010 if (FAILED(hres))
11011 return hres;
11012
11013 return S_OK;
11014 }
11015
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 * iface,UINT index,INT implTypeFlags)11016 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
11017 UINT index, INT implTypeFlags)
11018 {
11019 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11020 TLBImplType *impl_type = &This->impltypes[index];
11021
11022 TRACE("%p %u %x\n", This, index, implTypeFlags);
11023
11024 if (This->typeattr.typekind != TKIND_COCLASS)
11025 return TYPE_E_BADMODULEKIND;
11026
11027 if (index >= This->typeattr.cImplTypes)
11028 return TYPE_E_ELEMENTNOTFOUND;
11029
11030 impl_type->implflags = implTypeFlags;
11031
11032 return S_OK;
11033 }
11034
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 * iface,WORD alignment)11035 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
11036 WORD alignment)
11037 {
11038 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11039
11040 TRACE("%p %d\n", This, alignment);
11041
11042 This->typeattr.cbAlignment = alignment;
11043
11044 return S_OK;
11045 }
11046
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 * iface,LPOLESTR schema)11047 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
11048 LPOLESTR schema)
11049 {
11050 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11051
11052 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
11053
11054 if (!schema)
11055 return E_INVALIDARG;
11056
11057 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
11058
11059 This->typeattr.lpstrSchema = This->Schema->str;
11060
11061 return S_OK;
11062 }
11063
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 * iface,UINT index,VARDESC * varDesc)11064 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
11065 UINT index, VARDESC *varDesc)
11066 {
11067 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11068 TLBVarDesc *var_desc;
11069
11070 TRACE("%p %u %p\n", This, index, varDesc);
11071
11072 if (This->vardescs){
11073 UINT i;
11074
11075 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
11076 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
11077
11078 if (index < This->typeattr.cVars) {
11079 memmove(This->vardescs + index + 1, This->vardescs + index,
11080 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
11081 var_desc = This->vardescs + index;
11082 } else
11083 var_desc = This->vardescs + This->typeattr.cVars;
11084
11085 /* move custdata lists to the new memory location */
11086 for(i = 0; i < This->typeattr.cVars + 1; ++i){
11087 if(index != i){
11088 TLBVarDesc *var = &This->vardescs[i];
11089 if(var->custdata_list.prev == var->custdata_list.next)
11090 list_init(&var->custdata_list);
11091 else{
11092 var->custdata_list.prev->next = &var->custdata_list;
11093 var->custdata_list.next->prev = &var->custdata_list;
11094 }
11095 }
11096 }
11097 } else
11098 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
11099
11100 TLBVarDesc_Constructor(var_desc);
11101 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
11102 var_desc->vardesc = *var_desc->vardesc_create;
11103
11104 ++This->typeattr.cVars;
11105
11106 This->needs_layout = TRUE;
11107
11108 return S_OK;
11109 }
11110
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 * iface,UINT index,LPOLESTR * names,UINT numNames)11111 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
11112 UINT index, LPOLESTR *names, UINT numNames)
11113 {
11114 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11115 TLBFuncDesc *func_desc = &This->funcdescs[index];
11116 int i;
11117
11118 TRACE("%p %u %p %u\n", This, index, names, numNames);
11119
11120 if (!names)
11121 return E_INVALIDARG;
11122
11123 if (index >= This->typeattr.cFuncs || numNames == 0)
11124 return TYPE_E_ELEMENTNOTFOUND;
11125
11126 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
11127 if(numNames > func_desc->funcdesc.cParams)
11128 return TYPE_E_ELEMENTNOTFOUND;
11129 } else
11130 if(numNames > func_desc->funcdesc.cParams + 1)
11131 return TYPE_E_ELEMENTNOTFOUND;
11132
11133 for(i = 0; i < This->typeattr.cFuncs; ++i) {
11134 TLBFuncDesc *iter = &This->funcdescs[i];
11135 if (iter->Name && !wcscmp(TLB_get_bstr(iter->Name), *names)) {
11136 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11137 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
11138 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
11139 continue;
11140 return TYPE_E_AMBIGUOUSNAME;
11141 }
11142 }
11143
11144 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
11145
11146 for (i = 1; i < numNames; ++i) {
11147 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
11148 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
11149 }
11150
11151 return S_OK;
11152 }
11153
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 * iface,UINT index,LPOLESTR name)11154 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
11155 UINT index, LPOLESTR name)
11156 {
11157 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11158
11159 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
11160
11161 if(!name)
11162 return E_INVALIDARG;
11163
11164 if(index >= This->typeattr.cVars)
11165 return TYPE_E_ELEMENTNOTFOUND;
11166
11167 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
11168 return S_OK;
11169 }
11170
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 * iface,TYPEDESC * tdescAlias)11171 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
11172 TYPEDESC *tdescAlias)
11173 {
11174 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11175 HRESULT hr;
11176
11177 TRACE("%p %p\n", This, tdescAlias);
11178
11179 if(!tdescAlias)
11180 return E_INVALIDARG;
11181
11182 if(This->typeattr.typekind != TKIND_ALIAS)
11183 return TYPE_E_BADMODULEKIND;
11184
11185 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
11186 if(FAILED(hr))
11187 return hr;
11188
11189 heap_free(This->tdescAlias);
11190 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
11191 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
11192
11193 return S_OK;
11194 }
11195
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 * iface,UINT index,LPOLESTR dllName,LPOLESTR procName)11196 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
11197 UINT index, LPOLESTR dllName, LPOLESTR procName)
11198 {
11199 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11200 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
11201 return E_NOTIMPL;
11202 }
11203
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 * iface,UINT index,LPOLESTR docString)11204 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
11205 UINT index, LPOLESTR docString)
11206 {
11207 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11208 TLBFuncDesc *func_desc = &This->funcdescs[index];
11209
11210 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11211
11212 if(!docString)
11213 return E_INVALIDARG;
11214
11215 if(index >= This->typeattr.cFuncs)
11216 return TYPE_E_ELEMENTNOTFOUND;
11217
11218 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11219
11220 return S_OK;
11221 }
11222
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 * iface,UINT index,LPOLESTR docString)11223 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11224 UINT index, LPOLESTR docString)
11225 {
11226 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11227 TLBVarDesc *var_desc = &This->vardescs[index];
11228
11229 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11230
11231 if(!docString)
11232 return E_INVALIDARG;
11233
11234 if(index >= This->typeattr.cVars)
11235 return TYPE_E_ELEMENTNOTFOUND;
11236
11237 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11238
11239 return S_OK;
11240 }
11241
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 * iface,UINT index,DWORD helpContext)11242 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11243 UINT index, DWORD helpContext)
11244 {
11245 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11246 TLBFuncDesc *func_desc = &This->funcdescs[index];
11247
11248 TRACE("%p %u %d\n", This, index, helpContext);
11249
11250 if(index >= This->typeattr.cFuncs)
11251 return TYPE_E_ELEMENTNOTFOUND;
11252
11253 func_desc->helpcontext = helpContext;
11254
11255 return S_OK;
11256 }
11257
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 * iface,UINT index,DWORD helpContext)11258 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11259 UINT index, DWORD helpContext)
11260 {
11261 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11262 TLBVarDesc *var_desc = &This->vardescs[index];
11263
11264 TRACE("%p %u %d\n", This, index, helpContext);
11265
11266 if(index >= This->typeattr.cVars)
11267 return TYPE_E_ELEMENTNOTFOUND;
11268
11269 var_desc->HelpContext = helpContext;
11270
11271 return S_OK;
11272 }
11273
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 * iface,UINT index,BSTR bstrMops)11274 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11275 UINT index, BSTR bstrMops)
11276 {
11277 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11278 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11279 return E_NOTIMPL;
11280 }
11281
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 * iface,IDLDESC * idlDesc)11282 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11283 IDLDESC *idlDesc)
11284 {
11285 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11286
11287 TRACE("%p %p\n", This, idlDesc);
11288
11289 if (!idlDesc)
11290 return E_INVALIDARG;
11291
11292 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11293 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11294
11295 return S_OK;
11296 }
11297
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 * iface)11298 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11299 {
11300 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11301 ITypeInfo *tinfo;
11302 TLBFuncDesc *func_desc;
11303 UINT user_vft = 0, i, depth = 0;
11304 HRESULT hres = S_OK;
11305
11306 TRACE("%p\n", This);
11307
11308 This->needs_layout = FALSE;
11309
11310 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
11311 if (FAILED(hres))
11312 return hres;
11313
11314 if (This->typeattr.typekind == TKIND_INTERFACE) {
11315 ITypeInfo *inh;
11316 TYPEATTR *attr;
11317 HREFTYPE inh_href;
11318
11319 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11320
11321 if (SUCCEEDED(hres)) {
11322 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
11323
11324 if (SUCCEEDED(hres)) {
11325 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11326 if (FAILED(hres)) {
11327 ITypeInfo_Release(inh);
11328 ITypeInfo_Release(tinfo);
11329 return hres;
11330 }
11331 This->typeattr.cbSizeVft = attr->cbSizeVft;
11332 ITypeInfo_ReleaseTypeAttr(inh, attr);
11333
11334 do{
11335 ++depth;
11336 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11337 if(SUCCEEDED(hres)){
11338 ITypeInfo *next;
11339 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11340 if(SUCCEEDED(hres)){
11341 ITypeInfo_Release(inh);
11342 inh = next;
11343 }
11344 }
11345 }while(SUCCEEDED(hres));
11346 hres = S_OK;
11347
11348 ITypeInfo_Release(inh);
11349 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11350 This->typeattr.cbSizeVft = 0;
11351 hres = S_OK;
11352 } else {
11353 ITypeInfo_Release(tinfo);
11354 return hres;
11355 }
11356 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11357 This->typeattr.cbSizeVft = 0;
11358 hres = S_OK;
11359 } else {
11360 ITypeInfo_Release(tinfo);
11361 return hres;
11362 }
11363 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11364 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11365 else
11366 This->typeattr.cbSizeVft = 0;
11367
11368 func_desc = This->funcdescs;
11369 i = 0;
11370 while (i < This->typeattr.cFuncs) {
11371 if (!(func_desc->funcdesc.oVft & 0x1))
11372 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11373
11374 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11375 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11376
11377 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11378
11379 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11380 TLBFuncDesc *iter;
11381 UINT j = 0;
11382 BOOL reset = FALSE;
11383
11384 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11385
11386 iter = This->funcdescs;
11387 while (j < This->typeattr.cFuncs) {
11388 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11389 if (!reset) {
11390 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11391 reset = TRUE;
11392 } else
11393 ++func_desc->funcdesc.memid;
11394 iter = This->funcdescs;
11395 j = 0;
11396 } else {
11397 ++iter;
11398 ++j;
11399 }
11400 }
11401 }
11402
11403 ++func_desc;
11404 ++i;
11405 }
11406
11407 if (user_vft > This->typeattr.cbSizeVft)
11408 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11409
11410 for(i = 0; i < This->typeattr.cVars; ++i){
11411 TLBVarDesc *var_desc = &This->vardescs[i];
11412 if(var_desc->vardesc.memid == MEMBERID_NIL){
11413 UINT j = 0;
11414 BOOL reset = FALSE;
11415 TLBVarDesc *iter;
11416
11417 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11418
11419 iter = This->vardescs;
11420 while (j < This->typeattr.cVars) {
11421 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11422 if (!reset) {
11423 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11424 reset = TRUE;
11425 } else
11426 ++var_desc->vardesc.memid;
11427 iter = This->vardescs;
11428 j = 0;
11429 } else {
11430 ++iter;
11431 ++j;
11432 }
11433 }
11434 }
11435 }
11436
11437 ITypeInfo_Release(tinfo);
11438 return hres;
11439 }
11440
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 * iface,UINT index)11441 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11442 UINT index)
11443 {
11444 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11445 FIXME("%p %u - stub\n", This, index);
11446 return E_NOTIMPL;
11447 }
11448
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 * iface,MEMBERID memid,INVOKEKIND invKind)11449 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11450 MEMBERID memid, INVOKEKIND invKind)
11451 {
11452 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11453 FIXME("%p %x %d - stub\n", This, memid, invKind);
11454 return E_NOTIMPL;
11455 }
11456
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 * iface,UINT index)11457 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11458 UINT index)
11459 {
11460 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11461 FIXME("%p %u - stub\n", This, index);
11462 return E_NOTIMPL;
11463 }
11464
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 * iface,MEMBERID memid)11465 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11466 MEMBERID memid)
11467 {
11468 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11469 FIXME("%p %x - stub\n", This, memid);
11470 return E_NOTIMPL;
11471 }
11472
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 * iface,UINT index)11473 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11474 UINT index)
11475 {
11476 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11477 FIXME("%p %u - stub\n", This, index);
11478 return E_NOTIMPL;
11479 }
11480
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 * iface,REFGUID guid,VARIANT * varVal)11481 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11482 REFGUID guid, VARIANT *varVal)
11483 {
11484 TLBGuid *tlbguid;
11485
11486 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11487
11488 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11489
11490 if (!guid || !varVal)
11491 return E_INVALIDARG;
11492
11493 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11494
11495 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11496 }
11497
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 * iface,UINT index,REFGUID guid,VARIANT * varVal)11498 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11499 UINT index, REFGUID guid, VARIANT *varVal)
11500 {
11501 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11502 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11503 return E_NOTIMPL;
11504 }
11505
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 * iface,UINT funcIndex,UINT paramIndex,REFGUID guid,VARIANT * varVal)11506 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11507 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11508 {
11509 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11510 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11511 return E_NOTIMPL;
11512 }
11513
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 * iface,UINT index,REFGUID guid,VARIANT * varVal)11514 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11515 UINT index, REFGUID guid, VARIANT *varVal)
11516 {
11517 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11518 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11519 return E_NOTIMPL;
11520 }
11521
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 * iface,UINT index,REFGUID guid,VARIANT * varVal)11522 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11523 UINT index, REFGUID guid, VARIANT *varVal)
11524 {
11525 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11526 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11527 return E_NOTIMPL;
11528 }
11529
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 * iface,ULONG helpStringContext)11530 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11531 ULONG helpStringContext)
11532 {
11533 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11534
11535 TRACE("%p %u\n", This, helpStringContext);
11536
11537 This->dwHelpStringContext = helpStringContext;
11538
11539 return S_OK;
11540 }
11541
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 * iface,UINT index,ULONG helpStringContext)11542 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11543 UINT index, ULONG helpStringContext)
11544 {
11545 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11546 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11547 return E_NOTIMPL;
11548 }
11549
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 * iface,UINT index,ULONG helpStringContext)11550 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11551 UINT index, ULONG helpStringContext)
11552 {
11553 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11554 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11555 return E_NOTIMPL;
11556 }
11557
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 * iface)11558 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11559 {
11560 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11561 FIXME("%p - stub\n", This);
11562 return E_NOTIMPL;
11563 }
11564
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 * iface,LPOLESTR name)11565 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11566 LPOLESTR name)
11567 {
11568 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11569
11570 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11571
11572 if (!name)
11573 return E_INVALIDARG;
11574
11575 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11576
11577 return S_OK;
11578 }
11579
11580 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11581 ICreateTypeInfo2_fnQueryInterface,
11582 ICreateTypeInfo2_fnAddRef,
11583 ICreateTypeInfo2_fnRelease,
11584 ICreateTypeInfo2_fnSetGuid,
11585 ICreateTypeInfo2_fnSetTypeFlags,
11586 ICreateTypeInfo2_fnSetDocString,
11587 ICreateTypeInfo2_fnSetHelpContext,
11588 ICreateTypeInfo2_fnSetVersion,
11589 ICreateTypeInfo2_fnAddRefTypeInfo,
11590 ICreateTypeInfo2_fnAddFuncDesc,
11591 ICreateTypeInfo2_fnAddImplType,
11592 ICreateTypeInfo2_fnSetImplTypeFlags,
11593 ICreateTypeInfo2_fnSetAlignment,
11594 ICreateTypeInfo2_fnSetSchema,
11595 ICreateTypeInfo2_fnAddVarDesc,
11596 ICreateTypeInfo2_fnSetFuncAndParamNames,
11597 ICreateTypeInfo2_fnSetVarName,
11598 ICreateTypeInfo2_fnSetTypeDescAlias,
11599 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11600 ICreateTypeInfo2_fnSetFuncDocString,
11601 ICreateTypeInfo2_fnSetVarDocString,
11602 ICreateTypeInfo2_fnSetFuncHelpContext,
11603 ICreateTypeInfo2_fnSetVarHelpContext,
11604 ICreateTypeInfo2_fnSetMops,
11605 ICreateTypeInfo2_fnSetTypeIdldesc,
11606 ICreateTypeInfo2_fnLayOut,
11607 ICreateTypeInfo2_fnDeleteFuncDesc,
11608 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11609 ICreateTypeInfo2_fnDeleteVarDesc,
11610 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11611 ICreateTypeInfo2_fnDeleteImplType,
11612 ICreateTypeInfo2_fnSetCustData,
11613 ICreateTypeInfo2_fnSetFuncCustData,
11614 ICreateTypeInfo2_fnSetParamCustData,
11615 ICreateTypeInfo2_fnSetVarCustData,
11616 ICreateTypeInfo2_fnSetImplTypeCustData,
11617 ICreateTypeInfo2_fnSetHelpStringContext,
11618 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11619 ICreateTypeInfo2_fnSetVarHelpStringContext,
11620 ICreateTypeInfo2_fnInvalidate,
11621 ICreateTypeInfo2_fnSetName
11622 };
11623
11624 /******************************************************************************
11625 * ClearCustData (OLEAUT32.171)
11626 *
11627 * Clear a custom data type's data.
11628 *
11629 * PARAMS
11630 * lpCust [I] The custom data type instance
11631 *
11632 * RETURNS
11633 * Nothing.
11634 */
ClearCustData(CUSTDATA * lpCust)11635 void WINAPI ClearCustData(CUSTDATA *lpCust)
11636 {
11637 if (lpCust && lpCust->cCustData)
11638 {
11639 if (lpCust->prgCustData)
11640 {
11641 DWORD i;
11642
11643 for (i = 0; i < lpCust->cCustData; i++)
11644 VariantClear(&lpCust->prgCustData[i].varValue);
11645
11646 CoTaskMemFree(lpCust->prgCustData);
11647 lpCust->prgCustData = NULL;
11648 }
11649 lpCust->cCustData = 0;
11650 }
11651 }
11652