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