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 * 2005 Robert Shearman, for CodeWeavers
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 *
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
26 *
27 * - Tested using OLEVIEW (Platform SDK tool) only.
28 *
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
32 *
33 * - locale stuff is partially implemented but hasn't been tested.
34 *
35 * - typelib file is still read in its entirety, but it is released now.
36 *
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
39 *
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
45 *
46 */
47
48 #include "config.h"
49 #include "wine/port.h"
50
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
56
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
60
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
68
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
75
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78
79 typedef struct
80 {
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
88
89 typedef struct
90 {
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
94 /*
95 * Name info array.
96 */
97 } NE_TYPEINFO;
98
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
101
102 /****************************************************************************
103 * FromLExxx
104 *
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
107 */
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
110 {
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
113 }
114
115
116 static DWORD FromLEDWord(DWORD p_iVal)
117 {
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
122 }
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
127
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
130
131 /****************************************************************************
132 * FromLExxx
133 *
134 * Fix byte order in any structure if necessary
135 */
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
138 {
139 WORD *Val = p_Val;
140
141 p_iSize /= sizeof(WORD);
142
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
147 }
148 }
149
150
151 static void FromLEDWords(void *p_Val, int p_iSize)
152 {
153 DWORD *Val = p_Val;
154
155 p_iSize /= sizeof(DWORD);
156
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
161 }
162 }
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
167
168 /*
169 * Find a typelib key which matches a requested maj.min version.
170 */
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
172 {
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
179
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
182
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
185
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
189 {
190 INT v_maj, v_min;
191
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
193 {
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
195
196 if (*wMaj == 0xffff && *wMin == 0xffff)
197 {
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
200 }
201 else if (*wMaj == v_maj)
202 {
203 best_maj = v_maj;
204
205 if (*wMin == v_min)
206 {
207 best_min = v_min;
208 break; /* exact match */
209 }
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
211 }
212 }
213 len = sizeof(key_name);
214 }
215 RegCloseKey( hkey );
216
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
218
219 if (*wMaj == 0xffff && *wMin == 0xffff)
220 {
221 if (best_maj >= 0 && best_min >= 0)
222 {
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
226 }
227 }
228
229 if (*wMaj == best_maj && best_min >= 0)
230 {
231 *wMin = best_min;
232 return TRUE;
233 }
234 return FALSE;
235 }
236
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
240 {
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
243
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
248 }
249
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
253 {
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
255
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
259 }
260
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
264 {
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
269
270 sprintfW( buffer, LcidFormatW, lcid );
271 switch(syskind)
272 {
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
276 default:
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
278 return NULL;
279 }
280 return buffer;
281 }
282
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
284
285
286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
288 SYSKIND syskind, LCID lcid, LPBSTR path )
289 {
290 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
291 LCID myLCID = lcid;
292 HKEY hkey;
293 WCHAR buffer[60];
294 WCHAR Path[MAX_PATH];
295 LONG res;
296
297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
298
299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
300 get_typelib_key( guid, wMaj, wMin, buffer );
301
302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
303 if (res == ERROR_FILE_NOT_FOUND)
304 {
305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
306 return TYPE_E_LIBNOTREGISTERED;
307 }
308 else if (res != ERROR_SUCCESS)
309 {
310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
311 return TYPE_E_REGISTRYACCESS;
312 }
313
314 while (hr != S_OK)
315 {
316 LONG dwPathLen = sizeof(Path);
317
318 get_lcid_subkey( myLCID, syskind, buffer );
319
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
321 {
322 if (!lcid)
323 break;
324 else if (myLCID == lcid)
325 {
326 /* try with sub-langid */
327 myLCID = SUBLANGID(lcid);
328 }
329 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
330 {
331 /* try with system langid */
332 myLCID = 0;
333 }
334 else
335 {
336 break;
337 }
338 }
339 else
340 {
341 *path = SysAllocString( Path );
342 hr = S_OK;
343 }
344 }
345 RegCloseKey( hkey );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
347 return hr;
348 }
349
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
352 *
353 * Gets the path to a registered type library.
354 *
355 * PARAMS
356 * guid [I] referenced guid
357 * wMaj [I] major version
358 * wMin [I] minor version
359 * lcid [I] locale id
360 * path [O] path of typelib
361 *
362 * RETURNS
363 * Success: S_OK.
364 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
365 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
366 * opened.
367 */
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
369 {
370 #ifdef _WIN64
371 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
372 if(SUCCEEDED(hres))
373 return hres;
374 #endif
375 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
376 }
377
378 /******************************************************************************
379 * CreateTypeLib [OLEAUT32.160] creates a typelib
380 *
381 * RETURNS
382 * Success: S_OK
383 * Failure: Status
384 */
385 HRESULT WINAPI CreateTypeLib(
386 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
387 ) {
388 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
389 return E_FAIL;
390 }
391
392 /******************************************************************************
393 * LoadTypeLib [OLEAUT32.161]
394 *
395 * Loads a type library
396 *
397 * PARAMS
398 * szFile [I] Name of file to load from.
399 * pptLib [O] Pointer that receives ITypeLib object on success.
400 *
401 * RETURNS
402 * Success: S_OK
403 * Failure: Status
404 *
405 * SEE
406 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
407 */
408 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
409 {
410 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
411 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
412 }
413
414 /******************************************************************************
415 * LoadTypeLibEx [OLEAUT32.183]
416 *
417 * Loads and optionally registers a type library
418 *
419 * RETURNS
420 * Success: S_OK
421 * Failure: Status
422 */
423 HRESULT WINAPI LoadTypeLibEx(
424 LPCOLESTR szFile, /* [in] Name of file to load from */
425 REGKIND regkind, /* [in] Specify kind of registration */
426 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
427 {
428 WCHAR szPath[MAX_PATH+1];
429 HRESULT res;
430
431 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
432
433 *pptLib = NULL;
434
435 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
436
437 if (SUCCEEDED(res))
438 switch(regkind)
439 {
440 case REGKIND_DEFAULT:
441 /* don't register typelibs supplied with full path. Experimentation confirms the following */
442 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
443 (szFile[0] && (szFile[1] == ':'))) break;
444 /* else fall-through */
445
446 case REGKIND_REGISTER:
447 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
448 {
449 IUnknown_Release(*pptLib);
450 *pptLib = 0;
451 }
452 break;
453 case REGKIND_NONE:
454 break;
455 }
456
457 TRACE(" returns %08x\n",res);
458 return res;
459 }
460
461 /******************************************************************************
462 * LoadRegTypeLib [OLEAUT32.162]
463 *
464 * Loads a registered type library.
465 *
466 * PARAMS
467 * rguid [I] GUID of the registered type library.
468 * wVerMajor [I] major version.
469 * wVerMinor [I] minor version.
470 * lcid [I] locale ID.
471 * ppTLib [O] pointer that receives an ITypeLib object on success.
472 *
473 * RETURNS
474 * Success: S_OK.
475 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
476 * LoadTypeLib.
477 */
478 HRESULT WINAPI LoadRegTypeLib(
479 REFGUID rguid,
480 WORD wVerMajor,
481 WORD wVerMinor,
482 LCID lcid,
483 ITypeLib **ppTLib)
484 {
485 BSTR bstr=NULL;
486 HRESULT res;
487
488 *ppTLib = NULL;
489
490 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
491
492 if(SUCCEEDED(res))
493 {
494 res= LoadTypeLib(bstr, ppTLib);
495 SysFreeString(bstr);
496 }
497
498 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
499
500 return res;
501 }
502
503
504 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
505 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
506 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
507 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
508 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
509 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
510
511 /******************************************************************************
512 * RegisterTypeLib [OLEAUT32.163]
513 * Adds information about a type library to the System Registry
514 * NOTES
515 * Docs: ITypeLib FAR * ptlib
516 * Docs: OLECHAR FAR* szFullPath
517 * Docs: OLECHAR FAR* szHelpDir
518 *
519 * RETURNS
520 * Success: S_OK
521 * Failure: Status
522 */
523 HRESULT WINAPI RegisterTypeLib(
524 ITypeLib * ptlib, /* [in] Pointer to the library*/
525 OLECHAR * szFullPath, /* [in] full Path of the library*/
526 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
527 may be NULL*/
528 {
529 static const WCHAR PSOA[] = {'{','','','','2','','4','2','4','-',
530 '','','','','-','','','','','-','C','','','','-',
531 '','','','','','','','','','','4','6','}',0};
532 HRESULT res;
533 TLIBATTR *attr;
534 WCHAR keyName[60];
535 WCHAR tmp[16];
536 HKEY key, subKey;
537 UINT types, tidx;
538 TYPEKIND kind;
539 DWORD disposition;
540
541 if (ptlib == NULL || szFullPath == NULL)
542 return E_INVALIDARG;
543
544 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
545 return E_FAIL;
546
547 #ifdef _WIN64
548 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
549 #else
550 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
551 #endif
552
553 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
554
555 res = S_OK;
556 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
557 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
558 {
559 LPOLESTR doc;
560
561 /* Set the human-readable name of the typelib */
562 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
563 res = E_FAIL;
564 else if (doc)
565 {
566 if (RegSetValueExW(key, NULL, 0, REG_SZ,
567 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
568 res = E_FAIL;
569
570 SysFreeString(doc);
571 }
572
573 /* Make up the name of the typelib path subkey */
574 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
575
576 /* Create the typelib path subkey */
577 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
578 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
579 {
580 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
581 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
582 res = E_FAIL;
583
584 RegCloseKey(subKey);
585 }
586 else
587 res = E_FAIL;
588
589 /* Create the flags subkey */
590 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
591 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
592 {
593 /* FIXME: is %u correct? */
594 static const WCHAR formatW[] = {'%','u',0};
595 WCHAR buf[20];
596 sprintfW(buf, formatW, attr->wLibFlags);
597 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
598 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
599 res = E_FAIL;
600
601 RegCloseKey(subKey);
602 }
603 else
604 res = E_FAIL;
605
606 /* create the helpdir subkey */
607 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
608 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
609 {
610 BOOL freeHelpDir = FALSE;
611 OLECHAR* pIndexStr;
612
613 /* if we created a new key, and helpDir was null, set the helpdir
614 to the directory which contains the typelib. However,
615 if we just opened an existing key, we leave the helpdir alone */
616 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
617 szHelpDir = SysAllocString(szFullPath);
618 pIndexStr = strrchrW(szHelpDir, '\\');
619 if (pIndexStr) {
620 *pIndexStr = 0;
621 }
622 freeHelpDir = TRUE;
623 }
624
625 /* if we have an szHelpDir, set it! */
626 if (szHelpDir != NULL) {
627 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
628 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
629 res = E_FAIL;
630 }
631 }
632
633 /* tidy up */
634 if (freeHelpDir) SysFreeString(szHelpDir);
635 RegCloseKey(subKey);
636
637 } else {
638 res = E_FAIL;
639 }
640
641 RegCloseKey(key);
642 }
643 else
644 res = E_FAIL;
645
646 /* register OLE Automation-compatible interfaces for this typelib */
647 types = ITypeLib_GetTypeInfoCount(ptlib);
648 for (tidx=0; tidx<types; tidx++) {
649 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
650 LPOLESTR name = NULL;
651 ITypeInfo *tinfo = NULL;
652
653 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
654
655 switch (kind) {
656 case TKIND_INTERFACE:
657 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
659 break;
660
661 case TKIND_DISPATCH:
662 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
663 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
664 break;
665
666 default:
667 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
668 break;
669 }
670
671 if (tinfo) {
672 TYPEATTR *tattr = NULL;
673 ITypeInfo_GetTypeAttr(tinfo, &tattr);
674
675 if (tattr) {
676 TRACE_(typelib)("guid=%s, flags=%04x (",
677 debugstr_guid(&tattr->guid),
678 tattr->wTypeFlags);
679
680 if (TRACE_ON(typelib)) {
681 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
682 XX(FAPPOBJECT);
683 XX(FCANCREATE);
684 XX(FLICENSED);
685 XX(FPREDECLID);
686 XX(FHIDDEN);
687 XX(FCONTROL);
688 XX(FDUAL);
689 XX(FNONEXTENSIBLE);
690 XX(FOLEAUTOMATION);
691 XX(FRESTRICTED);
692 XX(FAGGREGATABLE);
693 XX(FREPLACEABLE);
694 XX(FDISPATCHABLE);
695 XX(FREVERSEBIND);
696 XX(FPROXY);
697 #undef XX
698 MESSAGE("\n");
699 }
700
701 /* Register all dispinterfaces (which includes dual interfaces) and
702 oleautomation interfaces */
703 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
704 kind == TKIND_DISPATCH)
705 {
706 /* register interface<->typelib coupling */
707 get_interface_key( &tattr->guid, keyName );
708 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
709 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
710 {
711 if (name)
712 RegSetValueExW(key, NULL, 0, REG_SZ,
713 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
714
715 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
716 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
717 RegSetValueExW(subKey, NULL, 0, REG_SZ,
718 (const BYTE *)PSOA, sizeof PSOA);
719 RegCloseKey(subKey);
720 }
721
722 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
723 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
724 RegSetValueExW(subKey, NULL, 0, REG_SZ,
725 (const BYTE *)PSOA, sizeof PSOA);
726 RegCloseKey(subKey);
727 }
728
729 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
730 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
731 {
732 WCHAR buffer[40];
733 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
734 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
735
736 StringFromGUID2(&attr->guid, buffer, 40);
737 RegSetValueExW(subKey, NULL, 0, REG_SZ,
738 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
739 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
740 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
741 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
742 RegCloseKey(subKey);
743 }
744
745 RegCloseKey(key);
746 }
747 }
748
749 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
750 }
751
752 ITypeInfo_Release(tinfo);
753 }
754
755 SysFreeString(name);
756 }
757 }
758
759 ITypeLib_ReleaseTLibAttr(ptlib, attr);
760
761 return res;
762 }
763
764
765 /******************************************************************************
766 * UnRegisterTypeLib [OLEAUT32.186]
767 * Removes information about a type library from the System Registry
768 * NOTES
769 *
770 * RETURNS
771 * Success: S_OK
772 * Failure: Status
773 */
774 HRESULT WINAPI UnRegisterTypeLib(
775 REFGUID libid, /* [in] Guid of the library */
776 WORD wVerMajor, /* [in] major version */
777 WORD wVerMinor, /* [in] minor version */
778 LCID lcid, /* [in] locale id */
779 SYSKIND syskind)
780 {
781 BSTR tlibPath = NULL;
782 DWORD tmpLength;
783 WCHAR keyName[60];
784 WCHAR subKeyName[50];
785 int result = S_OK;
786 DWORD i = 0;
787 BOOL deleteOtherStuff;
788 HKEY key = NULL;
789 HKEY subKey = NULL;
790 TYPEATTR* typeAttr = NULL;
791 TYPEKIND kind;
792 ITypeInfo* typeInfo = NULL;
793 ITypeLib* typeLib = NULL;
794 int numTypes;
795
796 TRACE("(IID: %s)\n",debugstr_guid(libid));
797
798 /* Create the path to the key */
799 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
800
801 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
802 {
803 TRACE("Unsupported syskind %i\n", syskind);
804 result = E_INVALIDARG;
805 goto end;
806 }
807
808 /* get the path to the typelib on disk */
809 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
810 result = E_INVALIDARG;
811 goto end;
812 }
813
814 /* Try and open the key to the type library. */
815 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
816 result = E_INVALIDARG;
817 goto end;
818 }
819
820 /* Try and load the type library */
821 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
822 result = TYPE_E_INVALIDSTATE;
823 goto end;
824 }
825
826 /* remove any types registered with this typelib */
827 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
828 for (i=0; i<numTypes; i++) {
829 /* get the kind of type */
830 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
831 goto enddeleteloop;
832 }
833
834 /* skip non-interfaces, and get type info for the type */
835 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
836 goto enddeleteloop;
837 }
838 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
839 goto enddeleteloop;
840 }
841 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
842 goto enddeleteloop;
843 }
844
845 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
846 kind == TKIND_DISPATCH)
847 {
848 /* the path to the type */
849 get_interface_key( &typeAttr->guid, subKeyName );
850
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
853 goto enddeleteloop;
854
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
858 RegCloseKey(subKey);
859 subKey = NULL;
860 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
861 }
862
863 enddeleteloop:
864 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
865 typeAttr = NULL;
866 if (typeInfo) ITypeInfo_Release(typeInfo);
867 typeInfo = NULL;
868 }
869
870 /* Now, delete the type library path subkey */
871 get_lcid_subkey( lcid, syskind, subKeyName );
872 RegDeleteKeyW(key, subKeyName);
873 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
874 RegDeleteKeyW(key, subKeyName);
875
876 /* check if there is anything besides the FLAGS/HELPDIR keys.
877 If there is, we don't delete them */
878 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 deleteOtherStuff = TRUE;
880 i = 0;
881 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
882 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
883
884 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
885 if (!strcmpW(subKeyName, FLAGSW)) continue;
886 if (!strcmpW(subKeyName, HELPDIRW)) continue;
887 deleteOtherStuff = FALSE;
888 break;
889 }
890
891 /* only delete the other parts of the key if we're absolutely sure */
892 if (deleteOtherStuff) {
893 RegDeleteKeyW(key, FLAGSW);
894 RegDeleteKeyW(key, HELPDIRW);
895 RegCloseKey(key);
896 key = NULL;
897
898 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
901 }
902
903 end:
904 SysFreeString(tlibPath);
905 if (typeLib) ITypeLib_Release(typeLib);
906 if (subKey) RegCloseKey(subKey);
907 if (key) RegCloseKey(key);
908 return result;
909 }
910
911 /******************************************************************************
912 * RegisterTypeLibForUser [OLEAUT32.442]
913 * Adds information about a type library to the user registry
914 * NOTES
915 * Docs: ITypeLib FAR * ptlib
916 * Docs: OLECHAR FAR* szFullPath
917 * Docs: OLECHAR FAR* szHelpDir
918 *
919 * RETURNS
920 * Success: S_OK
921 * Failure: Status
922 */
923 HRESULT WINAPI RegisterTypeLibForUser(
924 ITypeLib * ptlib, /* [in] Pointer to the library*/
925 OLECHAR * szFullPath, /* [in] full Path of the library*/
926 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
927 may be NULL*/
928 {
929 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
930 debugstr_w(szFullPath), debugstr_w(szHelpDir));
931 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
932 }
933
934 /******************************************************************************
935 * UnRegisterTypeLibForUser [OLEAUT32.443]
936 * Removes information about a type library from the user registry
937 *
938 * RETURNS
939 * Success: S_OK
940 * Failure: Status
941 */
942 HRESULT WINAPI UnRegisterTypeLibForUser(
943 REFGUID libid, /* [in] GUID of the library */
944 WORD wVerMajor, /* [in] major version */
945 WORD wVerMinor, /* [in] minor version */
946 LCID lcid, /* [in] locale id */
947 SYSKIND syskind)
948 {
949 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
950 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
951 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
952 }
953
954 /*======================= ITypeLib implementation =======================*/
955
956 typedef struct tagTLBCustData
957 {
958 GUID guid;
959 VARIANT data;
960 struct tagTLBCustData* next;
961 } TLBCustData;
962
963 /* data structure for import typelibs */
964 typedef struct tagTLBImpLib
965 {
966 int offset; /* offset in the file (MSFT)
967 offset in nametable (SLTG)
968 just used to identify library while reading
969 data from file */
970 GUID guid; /* libid */
971 BSTR name; /* name */
972
973 LCID lcid; /* lcid of imported typelib */
974
975 WORD wVersionMajor; /* major version number */
976 WORD wVersionMinor; /* minor version number */
977
978 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
979 NULL if not yet loaded */
980 struct tagTLBImpLib * next;
981 } TLBImpLib;
982
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
985 {
986 const ITypeLib2Vtbl *lpVtbl;
987 const ITypeCompVtbl *lpVtblTypeComp;
988 LONG ref;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
990 LCID lcid;
991
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
994 */
995 BSTR Name;
996 BSTR DocString;
997 BSTR HelpFile;
998 BSTR HelpStringDll;
999 DWORD dwHelpContext;
1000 int TypeInfoCount; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
1002 int ctCustData; /* number of items in cust data list */
1003 TLBCustData * pCustData; /* linked list to cust data */
1004 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
1005 int ctTypeDesc; /* number of items in type desc array */
1006 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1007 library. Only used while reading MSFT
1008 typelibs */
1009 struct list ref_list; /* list of ref types in this typelib */
1010 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1011
1012
1013 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1014 struct tagITypeLibImpl *next, *prev;
1015 WCHAR *path;
1016 INT index;
1017 } ITypeLibImpl;
1018
1019 static const ITypeLib2Vtbl tlbvt;
1020 static const ITypeCompVtbl tlbtcvt;
1021
1022 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1023 {
1024 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1025 }
1026
1027 /* ITypeLib methods */
1028 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1029 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1030
1031 /*======================= ITypeInfo implementation =======================*/
1032
1033 /* data for referenced types */
1034 typedef struct tagTLBRefType
1035 {
1036 INT index; /* Type index for internal ref or for external ref
1037 it the format is SLTG. -2 indicates to
1038 use guid */
1039
1040 GUID guid; /* guid of the referenced type */
1041 /* if index == TLB_REF_USE_GUID */
1042
1043 HREFTYPE reference; /* The href of this ref */
1044 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1045 TLB_REF_INTERNAL for internal refs
1046 TLB_REF_NOT_FOUND for broken refs */
1047
1048 struct list entry;
1049 } TLBRefType;
1050
1051 #define TLB_REF_USE_GUID -2
1052
1053 #define TLB_REF_INTERNAL (void*)-2
1054 #define TLB_REF_NOT_FOUND (void*)-1
1055
1056 /* internal Parameter data */
1057 typedef struct tagTLBParDesc
1058 {
1059 BSTR Name;
1060 int ctCustData;
1061 TLBCustData * pCustData; /* linked list to cust data */
1062 } TLBParDesc;
1063
1064 /* internal Function data */
1065 typedef struct tagTLBFuncDesc
1066 {
1067 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1068 BSTR Name; /* the name of this function */
1069 TLBParDesc *pParamDesc; /* array with param names and custom data */
1070 int helpcontext;
1071 int HelpStringContext;
1072 BSTR HelpString;
1073 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1074 int ctCustData;
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagTLBFuncDesc * next;
1077 } TLBFuncDesc;
1078
1079 /* internal Variable data */
1080 typedef struct tagTLBVarDesc
1081 {
1082 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1083 BSTR Name; /* the name of this variable */
1084 int HelpContext;
1085 int HelpStringContext;
1086 BSTR HelpString;
1087 int ctCustData;
1088 TLBCustData * pCustData;/* linked list to cust data; */
1089 struct tagTLBVarDesc * next;
1090 } TLBVarDesc;
1091
1092 /* internal implemented interface data */
1093 typedef struct tagTLBImplType
1094 {
1095 HREFTYPE hRef; /* hRef of interface */
1096 int implflags; /* IMPLFLAG_*s */
1097 int ctCustData;
1098 TLBCustData * pCustData;/* linked list to custom data; */
1099 struct tagTLBImplType *next;
1100 } TLBImplType;
1101
1102 /* internal TypeInfo data */
1103 typedef struct tagITypeInfoImpl
1104 {
1105 const ITypeInfo2Vtbl *lpVtbl;
1106 const ITypeCompVtbl *lpVtblTypeComp;
1107 LONG ref;
1108 BOOL not_attached_to_typelib;
1109 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1110 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1111 int index; /* index in this typelib; */
1112 HREFTYPE hreftype; /* hreftype for app object binding */
1113 /* type libs seem to store the doc strings in ascii
1114 * so why should we do it in unicode?
1115 */
1116 BSTR Name;
1117 BSTR DocString;
1118 BSTR DllName;
1119 DWORD dwHelpContext;
1120 DWORD dwHelpStringContext;
1121
1122 /* functions */
1123 TLBFuncDesc * funclist; /* linked list with function descriptions */
1124
1125 /* variables */
1126 TLBVarDesc * varlist; /* linked list with variable descriptions */
1127
1128 /* Implemented Interfaces */
1129 TLBImplType * impltypelist;
1130
1131 int ctCustData;
1132 TLBCustData * pCustData; /* linked list to cust data; */
1133 struct tagITypeInfoImpl * next;
1134 } ITypeInfoImpl;
1135
1136 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1137 {
1138 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1139 }
1140
1141 static const ITypeInfo2Vtbl tinfvt;
1142 static const ITypeCompVtbl tcompvt;
1143
1144 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1145 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1146
1147 typedef struct tagTLBContext
1148 {
1149 unsigned int oStart; /* start of TLB in file */
1150 unsigned int pos; /* current pos */
1151 unsigned int length; /* total length */
1152 void *mapping; /* memory mapping */
1153 MSFT_SegDir * pTblDir;
1154 ITypeLibImpl* pLibInfo;
1155 } TLBContext;
1156
1157
1158 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1159
1160 /*
1161 debug
1162 */
1163 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1164 if (pTD->vt & VT_RESERVED)
1165 szVarType += strlen(strcpy(szVarType, "reserved | "));
1166 if (pTD->vt & VT_BYREF)
1167 szVarType += strlen(strcpy(szVarType, "ref to "));
1168 if (pTD->vt & VT_ARRAY)
1169 szVarType += strlen(strcpy(szVarType, "array of "));
1170 if (pTD->vt & VT_VECTOR)
1171 szVarType += strlen(strcpy(szVarType, "vector of "));
1172 switch(pTD->vt & VT_TYPEMASK) {
1173 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1174 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1175 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1176 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1177 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1178 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1179 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1180 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1181 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1182 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1183 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1184 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1185 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1186 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1187 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1188 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1189 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1190 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1191 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1192 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1193 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1194 pTD->u.hreftype); break;
1195 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1196 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1197 case VT_PTR: sprintf(szVarType, "ptr to ");
1198 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1199 break;
1200 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1201 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1202 break;
1203 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1204 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1205 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1206 break;
1207
1208 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1209 }
1210 }
1211
1212 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1213 char buf[200];
1214 USHORT flags = edesc->u.paramdesc.wParamFlags;
1215 dump_TypeDesc(&edesc->tdesc,buf);
1216 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1217 MESSAGE("\t\tu.paramdesc.wParamFlags");
1218 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1219 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1220 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1221 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1222 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1223 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1224 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1225 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1226 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1227 }
1228 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1229 int i;
1230 MESSAGE("memid is %08x\n",funcdesc->memid);
1231 for (i=0;i<funcdesc->cParams;i++) {
1232 MESSAGE("Param %d:\n",i);
1233 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1234 }
1235 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1236 switch (funcdesc->funckind) {
1237 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1238 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1239 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1240 case FUNC_STATIC: MESSAGE("static");break;
1241 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1242 default: MESSAGE("unknown");break;
1243 }
1244 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1245 switch (funcdesc->invkind) {
1246 case INVOKE_FUNC: MESSAGE("func");break;
1247 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1248 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1249 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1250 }
1251 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1252 switch (funcdesc->callconv) {
1253 case CC_CDECL: MESSAGE("cdecl");break;
1254 case CC_PASCAL: MESSAGE("pascal");break;
1255 case CC_STDCALL: MESSAGE("stdcall");break;
1256 case CC_SYSCALL: MESSAGE("syscall");break;
1257 default:break;
1258 }
1259 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1260 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1261 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1262
1263 MESSAGE("\telemdescFunc (return value type):\n");
1264 dump_ELEMDESC(&funcdesc->elemdescFunc);
1265 }
1266
1267 static const char * const typekind_desc[] =
1268 {
1269 "TKIND_ENUM",
1270 "TKIND_RECORD",
1271 "TKIND_MODULE",
1272 "TKIND_INTERFACE",
1273 "TKIND_DISPATCH",
1274 "TKIND_COCLASS",
1275 "TKIND_ALIAS",
1276 "TKIND_UNION",
1277 "TKIND_MAX"
1278 };
1279
1280 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1281 {
1282 int i;
1283 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1284 for (i=0;i<pfd->funcdesc.cParams;i++)
1285 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1286
1287
1288 dump_FUNCDESC(&(pfd->funcdesc));
1289
1290 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1291 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1292 }
1293 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1294 {
1295 while (pfd)
1296 {
1297 dump_TLBFuncDescOne(pfd);
1298 pfd = pfd->next;
1299 };
1300 }
1301 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1302 {
1303 while (pvd)
1304 {
1305 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1306 pvd = pvd->next;
1307 };
1308 }
1309
1310 static void dump_TLBImpLib(const TLBImpLib *import)
1311 {
1312 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1313 debugstr_w(import->name));
1314 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1315 import->wVersionMinor, import->lcid, import->offset);
1316 }
1317
1318 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1319 {
1320 TLBRefType *ref;
1321
1322 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1323 {
1324 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1325 if(ref->index == -1)
1326 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1327 else
1328 TRACE_(typelib)("type no: %d\n", ref->index);
1329
1330 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1331 {
1332 TRACE_(typelib)("in lib\n");
1333 dump_TLBImpLib(ref->pImpTLInfo);
1334 }
1335 }
1336 }
1337
1338 static void dump_TLBImplType(const TLBImplType * impl)
1339 {
1340 while (impl) {
1341 TRACE_(typelib)(
1342 "implementing/inheriting interface hRef = %x implflags %x\n",
1343 impl->hRef, impl->implflags);
1344 impl = impl->next;
1345 }
1346 }
1347
1348 static void dump_Variant(const VARIANT * pvar)
1349 {
1350 SYSTEMTIME st;
1351
1352 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1353
1354 if (pvar)
1355 {
1356 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1357 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1358 {
1359 TRACE(",%p", V_BYREF(pvar));
1360 }
1361 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1362 {
1363 TRACE(",%p", V_ARRAY(pvar));
1364 }
1365 else switch (V_TYPE(pvar))
1366 {
1367 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1368 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1369 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1370 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1371 case VT_INT:
1372 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1373 case VT_UINT:
1374 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1375 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1376 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1377 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1378 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1379 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1380 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1381 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1382 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1383 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1384 V_CY(pvar).s.Lo); break;
1385 case VT_DATE:
1386 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1387 TRACE(",<invalid>");
1388 else
1389 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1390 st.wHour, st.wMinute, st.wSecond);
1391 break;
1392 case VT_ERROR:
1393 case VT_VOID:
1394 case VT_USERDEFINED:
1395 case VT_EMPTY:
1396 case VT_NULL: break;
1397 default: TRACE(",?"); break;
1398 }
1399 }
1400 TRACE("}\n");
1401 }
1402
1403 static void dump_DispParms(const DISPPARAMS * pdp)
1404 {
1405 unsigned int index;
1406
1407 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1408
1409 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1410 {
1411 TRACE("named args:\n");
1412 for (index = 0; index < pdp->cNamedArgs; index++)
1413 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1414 }
1415
1416 if (pdp->cArgs && pdp->rgvarg)
1417 {
1418 TRACE("args:\n");
1419 for (index = 0; index < pdp->cArgs; index++)
1420 dump_Variant( &pdp->rgvarg[index] );
1421 }
1422 }
1423
1424 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1425 {
1426 TRACE("%p ref=%u\n", pty, pty->ref);
1427 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1428 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1429 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1430 TRACE("fct:%u var:%u impl:%u\n",
1431 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1432 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1433 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1434 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1435 if (TRACE_ON(ole))
1436 dump_TLBFuncDesc(pty->funclist);
1437 dump_TLBVarDesc(pty->varlist);
1438 dump_TLBImplType(pty->impltypelist);
1439 }
1440
1441 static void dump_VARDESC(const VARDESC *v)
1442 {
1443 MESSAGE("memid %d\n",v->memid);
1444 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1445 MESSAGE("oInst %d\n",v->u.oInst);
1446 dump_ELEMDESC(&(v->elemdescVar));
1447 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1448 MESSAGE("varkind %d\n",v->varkind);
1449 }
1450
1451 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1452 {
1453 /* VT_LPWSTR is largest type that, may appear in type description */
1454 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1455 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1456 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1457 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1458 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1459 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1460 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1461 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1462 };
1463
1464 static void TLB_abort(void)
1465 {
1466 DebugBreak();
1467 }
1468
1469 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1470 {
1471 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1472 if (!ret) ERR("cannot allocate memory\n");
1473 return ret;
1474 }
1475
1476 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1477 {
1478 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1479 if (!ret) ERR("cannot allocate memory\n");
1480 return ret;
1481 }
1482
1483 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1484 {
1485 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1486 }
1487
1488 void heap_free(void *ptr)
1489 {
1490 HeapFree(GetProcessHeap(), 0, ptr);
1491 }
1492
1493 /* returns the size required for a deep copy of a typedesc into a
1494 * flat buffer */
1495 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1496 {
1497 SIZE_T size = 0;
1498
1499 if (alloc_initial_space)
1500 size += sizeof(TYPEDESC);
1501
1502 switch (tdesc->vt)
1503 {
1504 case VT_PTR:
1505 case VT_SAFEARRAY:
1506 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1507 break;
1508 case VT_CARRAY:
1509 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1510 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1511 break;
1512 }
1513 return size;
1514 }
1515
1516 /* deep copy a typedesc into a flat buffer */
1517 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1518 {
1519 if (!dest)
1520 {
1521 dest = buffer;
1522 buffer = (char *)buffer + sizeof(TYPEDESC);
1523 }
1524
1525 *dest = *src;
1526
1527 switch (src->vt)
1528 {
1529 case VT_PTR:
1530 case VT_SAFEARRAY:
1531 dest->u.lptdesc = buffer;
1532 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1533 break;
1534 case VT_CARRAY:
1535 dest->u.lpadesc = buffer;
1536 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1537 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1538 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1539 break;
1540 }
1541 return buffer;
1542 }
1543
1544 /* free custom data allocated by MSFT_CustData */
1545 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1546 {
1547 TLBCustData *pCustDataNext;
1548 for (; pCustData; pCustData = pCustDataNext)
1549 {
1550 VariantClear(&pCustData->data);
1551
1552 pCustDataNext = pCustData->next;
1553 heap_free(pCustData);
1554 }
1555 }
1556
1557 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1558 {
1559 DWORD len;
1560 BSTR ret;
1561
1562 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1563 ret = SysAllocStringLen(NULL, len - 1);
1564 if (!ret) return ret;
1565 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1566 return ret;
1567 }
1568
1569 /**********************************************************************
1570 *
1571 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1572 */
1573 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1574 {
1575 return pcx->pos;
1576 }
1577
1578 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1579 {
1580 if (where != DO_NOT_SEEK)
1581 {
1582 where += pcx->oStart;
1583 if (where > pcx->length)
1584 {
1585 /* FIXME */
1586 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1587 TLB_abort();
1588 }
1589 pcx->pos = where;
1590 }
1591 }
1592
1593 /* read function */
1594 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1595 {
1596 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1597 pcx->pos, count, pcx->oStart, pcx->length, where);
1598
1599 MSFT_Seek(pcx, where);
1600 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1601 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1602 pcx->pos += count;
1603 return count;
1604 }
1605
1606 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1607 LONG where )
1608 {
1609 DWORD ret;
1610
1611 ret = MSFT_Read(buffer, count, pcx, where);
1612 FromLEDWords(buffer, ret);
1613
1614 return ret;
1615 }
1616
1617 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1618 LONG where )
1619 {
1620 DWORD ret;
1621
1622 ret = MSFT_Read(buffer, count, pcx, where);
1623 FromLEWords(buffer, ret);
1624
1625 return ret;
1626 }
1627
1628 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1629 {
1630 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1631 memset(pGuid,0, sizeof(GUID));
1632 return;
1633 }
1634 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1635 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1636 pGuid->Data2 = FromLEWord(pGuid->Data2);
1637 pGuid->Data3 = FromLEWord(pGuid->Data3);
1638 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1639 }
1640
1641 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1642 {
1643 MSFT_NameIntro niName;
1644
1645 if (offset < 0)
1646 {
1647 ERR_(typelib)("bad offset %d\n", offset);
1648 return -1;
1649 }
1650
1651 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1652 pcx->pTblDir->pNametab.offset+offset);
1653
1654 return niName.hreftype;
1655 }
1656
1657 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1658 {
1659 char * name;
1660 MSFT_NameIntro niName;
1661 int lengthInChars;
1662 BSTR bstrName = NULL;
1663
1664 if (offset < 0)
1665 {
1666 ERR_(typelib)("bad offset %d\n", offset);
1667 return NULL;
1668 }
1669 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1670 pcx->pTblDir->pNametab.offset+offset);
1671 niName.namelen &= 0xFF; /* FIXME: correct ? */
1672 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1673 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1674 name[niName.namelen & 0xff]='\0';
1675
1676 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1677 name, -1, NULL, 0);
1678
1679 /* no invalid characters in string */
1680 if (lengthInChars)
1681 {
1682 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1683
1684 /* don't check for invalid character since this has been done previously */
1685 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1686 }
1687 heap_free(name);
1688
1689 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1690 return bstrName;
1691 }
1692
1693 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1694 {
1695 char * string;
1696 INT16 length;
1697 int lengthInChars;
1698 BSTR bstr = NULL;
1699
1700 if(offset<0) return NULL;
1701 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1702 if(length <= 0) return 0;
1703 string = heap_alloc_zero(length +1);
1704 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1705 string[length]='\0';
1706
1707 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1708 string, -1, NULL, 0);
1709
1710 /* no invalid characters in string */
1711 if (lengthInChars)
1712 {
1713 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1714
1715 /* don't check for invalid character since this has been done previously */
1716 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1717 }
1718 heap_free(string);
1719
1720 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1721 return bstr;
1722 }
1723 /*
1724 * read a value and fill a VARIANT structure
1725 */
1726 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1727 {
1728 int size;
1729
1730 TRACE_(typelib)("\n");
1731
1732 if(offset <0) { /* data are packed in here */
1733 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1734 V_I4(pVar) = offset & 0x3ffffff;
1735 return;
1736 }
1737 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1738 pcx->pTblDir->pCustData.offset + offset );
1739 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1740 switch (V_VT(pVar)){
1741 case VT_EMPTY: /* FIXME: is this right? */
1742 case VT_NULL: /* FIXME: is this right? */
1743 case VT_I2 : /* this should not happen */
1744 case VT_I4 :
1745 case VT_R4 :
1746 case VT_ERROR :
1747 case VT_BOOL :
1748 case VT_I1 :
1749 case VT_UI1 :
1750 case VT_UI2 :
1751 case VT_UI4 :
1752 case VT_INT :
1753 case VT_UINT :
1754 case VT_VOID : /* FIXME: is this right? */
1755 case VT_HRESULT :
1756 size=4; break;
1757 case VT_R8 :
1758 case VT_CY :
1759 case VT_DATE :
1760 case VT_I8 :
1761 case VT_UI8 :
1762 case VT_DECIMAL : /* FIXME: is this right? */
1763 case VT_FILETIME :
1764 size=8;break;
1765 /* pointer types with known behaviour */
1766 case VT_BSTR :{
1767 char * ptr;
1768 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1769 if(size < 0) {
1770 char next;
1771 DWORD origPos = MSFT_Tell(pcx), nullPos;
1772
1773 do {
1774 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1775 } while (next);
1776 nullPos = MSFT_Tell(pcx);
1777 size = nullPos - origPos;
1778 MSFT_Seek(pcx, origPos);
1779 }
1780 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1781 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1782 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1783 /* FIXME: do we need a AtoW conversion here? */
1784 V_UNION(pVar, bstrVal[size])='\0';
1785 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1786 heap_free(ptr);
1787 }
1788 size=-4; break;
1789 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1790 case VT_DISPATCH :
1791 case VT_VARIANT :
1792 case VT_UNKNOWN :
1793 case VT_PTR :
1794 case VT_SAFEARRAY :
1795 case VT_CARRAY :
1796 case VT_USERDEFINED :
1797 case VT_LPSTR :
1798 case VT_LPWSTR :
1799 case VT_BLOB :
1800 case VT_STREAM :
1801 case VT_STORAGE :
1802 case VT_STREAMED_OBJECT :
1803 case VT_STORED_OBJECT :
1804 case VT_BLOB_OBJECT :
1805 case VT_CF :
1806 case VT_CLSID :
1807 default:
1808 size=0;
1809 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1810 V_VT(pVar));
1811 }
1812
1813 if(size>0) /* (big|small) endian correct? */
1814 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1815 return;
1816 }
1817 /*
1818 * create a linked list with custom data
1819 */
1820 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1821 {
1822 MSFT_CDGuid entry;
1823 TLBCustData* pNew;
1824 int count=0;
1825
1826 TRACE_(typelib)("\n");
1827
1828 while(offset >=0){
1829 count++;
1830 pNew=heap_alloc_zero(sizeof(TLBCustData));
1831 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1832 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1833 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1834 /* add new custom data at head of the list */
1835 pNew->next=*ppCustData;
1836 *ppCustData=pNew;
1837 offset = entry.next;
1838 }
1839 return count;
1840 }
1841
1842 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1843 ITypeInfoImpl *pTI)
1844 {
1845 if(type <0)
1846 pTd->vt=type & VT_TYPEMASK;
1847 else
1848 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1849
1850 if(pTd->vt == VT_USERDEFINED)
1851 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1852
1853 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1854 }
1855
1856 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1857 {
1858 /* resolve referenced type if any */
1859 while (lpTypeDesc)
1860 {
1861 switch (lpTypeDesc->vt)
1862 {
1863 case VT_PTR:
1864 lpTypeDesc = lpTypeDesc->u.lptdesc;
1865 break;
1866
1867 case VT_CARRAY:
1868 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1869 break;
1870
1871 case VT_USERDEFINED:
1872 MSFT_DoRefType(pcx, pTI->pTypeLib,
1873 lpTypeDesc->u.hreftype);
1874
1875 lpTypeDesc = NULL;
1876 break;
1877
1878 default:
1879 lpTypeDesc = NULL;
1880 }
1881 }
1882 }
1883
1884 static void
1885 MSFT_DoFuncs(TLBContext* pcx,
1886 ITypeInfoImpl* pTI,
1887 int cFuncs,
1888 int cVars,
1889 int offset,
1890 TLBFuncDesc** pptfd)
1891 {
1892 /*
1893 * member information is stored in a data structure at offset
1894 * indicated by the memoffset field of the typeinfo structure
1895 * There are several distinctive parts.
1896 * The first part starts with a field that holds the total length
1897 * of this (first) part excluding this field. Then follow the records,
1898 * for each member there is one record.
1899 *
1900 * The first entry is always the length of the record (including this
1901 * length word).
1902 * The rest of the record depends on the type of the member. If there is
1903 * a field indicating the member type (function, variable, interface, etc)
1904 * I have not found it yet. At this time we depend on the information
1905 * in the type info and the usual order how things are stored.
1906 *
1907 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1908 * for each member;
1909 *
1910 * Third is an equal sized array with file offsets to the name entry
1911 * of each member.
1912 *
1913 * The fourth and last (?) part is an array with offsets to the records
1914 * in the first part of this file segment.
1915 */
1916
1917 int infolen, nameoffset, reclength, i;
1918 int recoffset = offset + sizeof(INT);
1919
1920 char *recbuf = heap_alloc(0xffff);
1921 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
1922 TLBFuncDesc *ptfd_prev = NULL;
1923
1924 TRACE_(typelib)("\n");
1925
1926 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1927
1928 for ( i = 0; i < cFuncs ; i++ )
1929 {
1930 int optional;
1931
1932 *pptfd = heap_alloc_zero(sizeof(TLBFuncDesc));
1933
1934 /* name, eventually add to a hash table */
1935 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1936 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1937
1938 /* nameoffset is sometimes -1 on the second half of a propget/propput
1939 * pair of functions */
1940 if ((nameoffset == -1) && (i > 0))
1941 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1942 else
1943 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1944
1945 /* read the function information record */
1946 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
1947
1948 reclength &= 0xffff;
1949
1950 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
1951
1952 /* size without argument data */
1953 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
1954
1955 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
1956 (*pptfd)->helpcontext = pFuncRec->HelpContext;
1957
1958 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
1959 (*pptfd)->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
1960
1961 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
1962 {
1963 if (pFuncRec->FKCCIC & 0x2000 )
1964 {
1965 if (!IS_INTRESOURCE(pFuncRec->oEntry))
1966 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
1967 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
1968 }
1969 else
1970 (*pptfd)->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
1971 }
1972 else
1973 (*pptfd)->Entry = (BSTR)-1;
1974
1975 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
1976 (*pptfd)->HelpStringContext = pFuncRec->HelpStringContext;
1977
1978 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
1979 MSFT_CustData(pcx, pFuncRec->oCustData, &(*pptfd)->pCustData);
1980
1981 /* fill the FuncDesc Structure */
1982 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1983 offset + infolen + ( i + 1) * sizeof(INT));
1984
1985 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1986 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1987 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1988 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1989 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1990 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1991 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1992
1993 MSFT_GetTdesc(pcx,
1994 pFuncRec->DataType,
1995 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1996 pTI);
1997 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1998
1999 /* do the parameters/arguments */
2000 if(pFuncRec->nrargs)
2001 {
2002 int j = 0;
2003 MSFT_ParameterInfo paraminfo;
2004
2005 (*pptfd)->funcdesc.lprgelemdescParam =
2006 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2007
2008 (*pptfd)->pParamDesc =
2009 heap_alloc_zero(pFuncRec->nrargs * sizeof(TLBParDesc));
2010
2011 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2012 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2013
2014 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2015 {
2016 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
2017
2018 MSFT_GetTdesc(pcx,
2019 paraminfo.DataType,
2020 &elemdesc->tdesc,
2021 pTI);
2022
2023 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2024
2025 /* name */
2026 if (paraminfo.oName == -1)
2027 /* this occurs for [propput] or [propget] methods, so
2028 * we should just set the name of the parameter to the
2029 * name of the method. */
2030 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
2031 else
2032 (*pptfd)->pParamDesc[j].Name =
2033 MSFT_ReadName( pcx, paraminfo.oName );
2034 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
2035
2036 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2037
2038 /* default value */
2039 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2040 (pFuncRec->FKCCIC & 0x1000) )
2041 {
2042 INT* pInt = (INT *)((char *)pFuncRec +
2043 reclength -
2044 (pFuncRec->nrargs * 4) * sizeof(INT) );
2045
2046 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2047
2048 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2049 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2050
2051 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2052 pInt[j], pcx);
2053 }
2054 else
2055 elemdesc->u.paramdesc.pparamdescex = NULL;
2056
2057 /* custom info */
2058 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2059 j*sizeof(pFuncRec->oArgCustData[0])) &&
2060 pFuncRec->FKCCIC & 0x80 )
2061 {
2062 MSFT_CustData(pcx,
2063 pFuncRec->oArgCustData[j],
2064 &(*pptfd)->pParamDesc[j].pCustData);
2065 }
2066
2067 /* SEEK value = jump to offset,
2068 * from there jump to the end of record,
2069 * go back by (j-1) arguments
2070 */
2071 MSFT_ReadLEDWords( ¶minfo ,
2072 sizeof(MSFT_ParameterInfo), pcx,
2073 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2074 * sizeof(MSFT_ParameterInfo)));
2075 }
2076 }
2077
2078 /* scode is not used: archaic win16 stuff FIXME: right? */
2079 (*pptfd)->funcdesc.cScodes = 0 ;
2080 (*pptfd)->funcdesc.lprgscode = NULL ;
2081
2082 ptfd_prev = *pptfd;
2083 pptfd = & ((*pptfd)->next);
2084 recoffset += reclength;
2085 }
2086 heap_free(recbuf);
2087 }
2088
2089 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2090 int cVars, int offset, TLBVarDesc ** pptvd)
2091 {
2092 int infolen, nameoffset, reclength;
2093 char recbuf[256];
2094 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2095 int i;
2096 int recoffset;
2097
2098 TRACE_(typelib)("\n");
2099
2100 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2101 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2102 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2103 recoffset += offset+sizeof(INT);
2104 for(i=0;i<cVars;i++){
2105 *pptvd = heap_alloc_zero(sizeof(TLBVarDesc));
2106 /* name, eventually add to a hash table */
2107 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2108 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2109 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2110 /* read the variable information record */
2111 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2112 reclength &= 0xff;
2113 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2114
2115 /* optional data */
2116 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2117 (*pptvd)->HelpContext = pVarRec->HelpContext;
2118
2119 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2120 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2121
2122 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2123 (*pptvd)->HelpStringContext = pVarRec->HelpStringContext;
2124
2125 /* fill the VarDesc Structure */
2126 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2127 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2128 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2129 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2130 MSFT_GetTdesc(pcx, pVarRec->DataType,
2131 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2132 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2133 if(pVarRec->VarKind == VAR_CONST ){
2134 (*pptvd)->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2135 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2136 pVarRec->OffsValue, pcx);
2137 } else
2138 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2139 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2140 pptvd=&((*pptvd)->next);
2141 recoffset += reclength;
2142 }
2143 }
2144 /* fill in data for a hreftype (offset). When the referenced type is contained
2145 * in the typelib, it's just an (file) offset in the type info base dir.
2146 * If comes from import, it's an offset+1 in the ImpInfo table
2147 * */
2148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2149 int offset)
2150 {
2151 TLBRefType *ref;
2152
2153 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2154
2155 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2156 {
2157 if(ref->reference == offset) return;
2158 }
2159
2160 ref = heap_alloc_zero(sizeof(TLBRefType));
2161 list_add_tail(&pTL->ref_list, &ref->entry);
2162
2163 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2164 /* external typelib */
2165 MSFT_ImpInfo impinfo;
2166 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2167
2168 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2169
2170 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2171 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2172 while (pImpLib){ /* search the known offsets of all import libraries */
2173 if(pImpLib->offset==impinfo.oImpFile) break;
2174 pImpLib=pImpLib->next;
2175 }
2176 if(pImpLib){
2177 ref->reference = offset;
2178 ref->pImpTLInfo = pImpLib;
2179 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2180 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2181 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2182 ref->index = TLB_REF_USE_GUID;
2183 } else
2184 ref->index = impinfo.oGuid;
2185 }else{
2186 ERR("Cannot find a reference\n");
2187 ref->reference = -1;
2188 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2189 }
2190 }else{
2191 /* in this typelib */
2192 ref->index = MSFT_HREFTYPE_INDEX(offset);
2193 ref->reference = offset;
2194 ref->pImpTLInfo = TLB_REF_INTERNAL;
2195 }
2196 }
2197
2198 /* process Implemented Interfaces of a com class */
2199 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2200 int offset)
2201 {
2202 int i;
2203 MSFT_RefRecord refrec;
2204 TLBImplType **ppImpl = &pTI->impltypelist;
2205
2206 TRACE_(typelib)("\n");
2207
2208 for(i=0;i<count;i++){
2209 if(offset<0) break; /* paranoia */
2210 *ppImpl = heap_alloc_zero(sizeof(**ppImpl));
2211 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2212 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2213 (*ppImpl)->hRef = refrec.reftype;
2214 (*ppImpl)->implflags=refrec.flags;
2215 (*ppImpl)->ctCustData=
2216 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2217 offset=refrec.onext;
2218 ppImpl=&((*ppImpl)->next);
2219 }
2220 }
2221 /*
2222 * process a typeinfo record
2223 */
2224 static ITypeInfoImpl * MSFT_DoTypeInfo(
2225 TLBContext *pcx,
2226 int count,
2227 ITypeLibImpl * pLibInfo)
2228 {
2229 MSFT_TypeInfoBase tiBase;
2230 ITypeInfoImpl *ptiRet;
2231
2232 TRACE_(typelib)("count=%u\n", count);
2233
2234 ptiRet = ITypeInfoImpl_Constructor();
2235 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2236 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2237
2238 /* this is where we are coming from */
2239 ptiRet->pTypeLib = pLibInfo;
2240 ptiRet->index=count;
2241 /* fill in the typeattr fields */
2242
2243 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2244 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2245 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2246 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2247 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2248 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2249 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2250 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2251 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2252 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2253 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2254 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2255 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2256 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2257 MSFT_GetTdesc(pcx, tiBase.datatype1,
2258 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2259
2260 /* FIXME: */
2261 /* IDLDESC idldescType; *//* never saw this one != zero */
2262
2263 /* name, eventually add to a hash table */
2264 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2265 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2266 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2267 /* help info */
2268 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2269 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2270 ptiRet->dwHelpContext=tiBase.helpcontext;
2271
2272 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2273 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2274
2275 /* note: InfoType's Help file and HelpStringDll come from the containing
2276 * library. Further HelpString and Docstring appear to be the same thing :(
2277 */
2278 /* functions */
2279 if(ptiRet->TypeAttr.cFuncs >0 )
2280 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2281 ptiRet->TypeAttr.cVars,
2282 tiBase.memoffset, & ptiRet->funclist);
2283 /* variables */
2284 if(ptiRet->TypeAttr.cVars >0 )
2285 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2286 ptiRet->TypeAttr.cVars,
2287 tiBase.memoffset, & ptiRet->varlist);
2288 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2289 switch(ptiRet->TypeAttr.typekind)
2290 {
2291 case TKIND_COCLASS:
2292 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2293 tiBase.datatype1);
2294 break;
2295 case TKIND_DISPATCH:
2296 /* This is not -1 when the interface is a non-base dual interface or
2297 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2298 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2299 not this interface.
2300 */
2301
2302 if (tiBase.datatype1 != -1)
2303 {
2304 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2305 ptiRet->impltypelist->hRef = tiBase.datatype1;
2306 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2307 }
2308 break;
2309 default:
2310 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2311 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2312 ptiRet->impltypelist->hRef = tiBase.datatype1;
2313 break;
2314 }
2315 }
2316 ptiRet->ctCustData=
2317 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2318
2319 TRACE_(typelib)("%s guid: %s kind:%s\n",
2320 debugstr_w(ptiRet->Name),
2321 debugstr_guid(&ptiRet->TypeAttr.guid),
2322 typekind_desc[ptiRet->TypeAttr.typekind]);
2323 if (TRACE_ON(typelib))
2324 dump_TypeInfo(ptiRet);
2325
2326 return ptiRet;
2327 }
2328
2329 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2330 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2331 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2332 * tradeoff here.
2333 */
2334 static ITypeLibImpl *tlb_cache_first;
2335 static CRITICAL_SECTION cache_section;
2336 static CRITICAL_SECTION_DEBUG cache_section_debug =
2337 {
2338 0, 0, &cache_section,
2339 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2340 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2341 };
2342 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2343
2344
2345 typedef struct TLB_PEFile
2346 {
2347 const IUnknownVtbl *lpvtbl;
2348 LONG refs;
2349 HMODULE dll;
2350 HRSRC typelib_resource;
2351 HGLOBAL typelib_global;
2352 LPVOID typelib_base;
2353 } TLB_PEFile;
2354
2355 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2356 {
2357 if (IsEqualIID(riid, &IID_IUnknown))
2358 {
2359 *ppv = iface;
2360 IUnknown_AddRef(iface);
2361 return S_OK;
2362 }
2363 *ppv = NULL;
2364 return E_NOINTERFACE;
2365 }
2366
2367 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2368 {
2369 TLB_PEFile *This = (TLB_PEFile *)iface;
2370 return InterlockedIncrement(&This->refs);
2371 }
2372
2373 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2374 {
2375 TLB_PEFile *This = (TLB_PEFile *)iface;
2376 ULONG refs = InterlockedDecrement(&This->refs);
2377 if (!refs)
2378 {
2379 if (This->typelib_global)
2380 FreeResource(This->typelib_global);
2381 if (This->dll)
2382 FreeLibrary(This->dll);
2383 heap_free(This);
2384 }
2385 return refs;
2386 }
2387
2388 static const IUnknownVtbl TLB_PEFile_Vtable =
2389 {
2390 TLB_PEFile_QueryInterface,
2391 TLB_PEFile_AddRef,
2392 TLB_PEFile_Release
2393 };
2394
2395 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2396 {
2397 TLB_PEFile *This;
2398
2399 This = heap_alloc(sizeof(TLB_PEFile));
2400 if (!This)
2401 return E_OUTOFMEMORY;
2402
2403 This->lpvtbl = &TLB_PEFile_Vtable;
2404 This->refs = 1;
2405 This->dll = NULL;
2406 This->typelib_resource = NULL;
2407 This->typelib_global = NULL;
2408 This->typelib_base = NULL;
2409
2410 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2411 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2412
2413 if (This->dll)
2414 {
2415 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2416 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2417 if (This->typelib_resource)
2418 {
2419 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2420 if (This->typelib_global)
2421 {
2422 This->typelib_base = LockResource(This->typelib_global);
2423
2424 if (This->typelib_base)
2425 {
2426 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2427 *ppBase = This->typelib_base;
2428 *ppFile = (IUnknown *)&This->lpvtbl;
2429 return S_OK;
2430 }
2431 }
2432 }
2433 }
2434
2435 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2436 return TYPE_E_CANTLOADLIBRARY;
2437 }
2438
2439 typedef struct TLB_NEFile
2440 {
2441 const IUnknownVtbl *lpvtbl;
2442 LONG refs;
2443 LPVOID typelib_base;
2444 } TLB_NEFile;
2445
2446 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2447 {
2448 if (IsEqualIID(riid, &IID_IUnknown))
2449 {
2450 *ppv = iface;
2451 IUnknown_AddRef(iface);
2452 return S_OK;
2453 }
2454 *ppv = NULL;
2455 return E_NOINTERFACE;
2456 }
2457
2458 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2459 {
2460 TLB_NEFile *This = (TLB_NEFile *)iface;
2461 return InterlockedIncrement(&This->refs);
2462 }
2463
2464 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2465 {
2466 TLB_NEFile *This = (TLB_NEFile *)iface;
2467 ULONG refs = InterlockedDecrement(&This->refs);
2468 if (!refs)
2469 {
2470 heap_free(This->typelib_base);
2471 heap_free(This);
2472 }
2473 return refs;
2474 }
2475
2476 static const IUnknownVtbl TLB_NEFile_Vtable =
2477 {
2478 TLB_NEFile_QueryInterface,
2479 TLB_NEFile_AddRef,
2480 TLB_NEFile_Release
2481 };
2482
2483 /***********************************************************************
2484 * read_xx_header [internal]
2485 */
2486 static int read_xx_header( HFILE lzfd )
2487 {
2488 IMAGE_DOS_HEADER mzh;
2489 char magic[3];
2490
2491 LZSeek( lzfd, 0, SEEK_SET );
2492 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2493 return 0;
2494 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2495 return 0;
2496
2497 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2498 if ( 2 != LZRead( lzfd, magic, 2 ) )
2499 return 0;
2500
2501 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2502
2503 if ( magic[0] == 'N' && magic[1] == 'E' )
2504 return IMAGE_OS2_SIGNATURE;
2505 if ( magic[0] == 'P' && magic[1] == 'E' )
2506 return IMAGE_NT_SIGNATURE;
2507
2508 magic[2] = '\0';
2509 WARN("Can't handle %s files.\n", magic );
2510 return 0;
2511 }
2512
2513
2514 /***********************************************************************
2515 * find_ne_resource [internal]
2516 */
2517 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2518 DWORD *resLen, DWORD *resOff )
2519 {
2520 IMAGE_OS2_HEADER nehd;
2521 NE_TYPEINFO *typeInfo;
2522 NE_NAMEINFO *nameInfo;
2523 DWORD nehdoffset;
2524 LPBYTE resTab;
2525 DWORD resTabSize;
2526 int count;
2527
2528 /* Read in NE header */
2529 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2530 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2531
2532 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2533 if ( !resTabSize )
2534 {
2535 TRACE("No resources in NE dll\n" );
2536 return FALSE;
2537 }
2538
2539 /* Read in resource table */
2540 resTab = heap_alloc( resTabSize );
2541 if ( !resTab ) return FALSE;
2542
2543 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2544 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2545 {
2546 heap_free( resTab );
2547 return FALSE;
2548 }
2549
2550 /* Find resource */
2551 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2552
2553 if (!IS_INTRESOURCE(typeid)) /* named type */
2554 {
2555 BYTE len = strlen( typeid );
2556 while (typeInfo->type_id)
2557 {
2558 if (!(typeInfo->type_id & 0x8000))
2559 {
2560 BYTE *p = resTab + typeInfo->type_id;
2561 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2562 }
2563 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2564 typeInfo->count * sizeof(NE_NAMEINFO));
2565 }
2566 }
2567 else /* numeric type id */
2568 {
2569 WORD id = LOWORD(typeid) | 0x8000;
2570 while (typeInfo->type_id)
2571 {
2572 if (typeInfo->type_id == id) goto found_type;
2573 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2574 typeInfo->count * sizeof(NE_NAMEINFO));
2575 }
2576 }
2577 TRACE("No typeid entry found for %p\n", typeid );
2578 heap_free( resTab );
2579 return FALSE;
2580
2581 found_type:
2582 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2583
2584 if (!IS_INTRESOURCE(resid)) /* named resource */
2585 {
2586 BYTE len = strlen( resid );
2587 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2588 {
2589 BYTE *p = resTab + nameInfo->id;
2590 if (nameInfo->id & 0x8000) continue;
2591 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2592 }
2593 }
2594 else /* numeric resource id */
2595 {
2596 WORD id = LOWORD(resid) | 0x8000;
2597 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2598 if (nameInfo->id == id) goto found_name;
2599 }
2600 TRACE("No resid entry found for %p\n", typeid );
2601 heap_free( resTab );
2602 return FALSE;
2603
2604 found_name:
2605 /* Return resource data */
2606 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2607 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2608
2609 heap_free( resTab );
2610 return TRUE;
2611 }
2612
2613 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2614
2615 HFILE lzfd = -1;
2616 OFSTRUCT ofs;
2617 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2618 TLB_NEFile *This;
2619
2620 This = heap_alloc(sizeof(TLB_NEFile));
2621 if (!This) return E_OUTOFMEMORY;
2622
2623 This->lpvtbl = &TLB_NEFile_Vtable;
2624 This->refs = 1;
2625 This->typelib_base = NULL;
2626
2627 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2628 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2629 {
2630 DWORD reslen, offset;
2631 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2632 {
2633 This->typelib_base = heap_alloc(reslen);
2634 if( !This->typelib_base )
2635 hr = E_OUTOFMEMORY;
2636 else
2637 {
2638 LZSeek( lzfd, offset, SEEK_SET );
2639 reslen = LZRead( lzfd, This->typelib_base, reslen );
2640 LZClose( lzfd );
2641 *ppBase = This->typelib_base;
2642 *pdwTLBLength = reslen;
2643 *ppFile = (IUnknown *)&This->lpvtbl;
2644 return S_OK;
2645 }
2646 }
2647 }
2648
2649 if( lzfd >= 0) LZClose( lzfd );
2650 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2651 return hr;
2652 }
2653
2654 typedef struct TLB_Mapping
2655 {
2656 const IUnknownVtbl *lpvtbl;
2657 LONG refs;
2658 HANDLE file;
2659 HANDLE mapping;
2660 LPVOID typelib_base;
2661 } TLB_Mapping;
2662
2663 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2664 {
2665 if (IsEqualIID(riid, &IID_IUnknown))
2666 {
2667 *ppv = iface;
2668 IUnknown_AddRef(iface);
2669 return S_OK;
2670 }
2671 *ppv = NULL;
2672 return E_NOINTERFACE;
2673 }
2674
2675 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2676 {
2677 TLB_Mapping *This = (TLB_Mapping *)iface;
2678 return InterlockedIncrement(&This->refs);
2679 }
2680
2681 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2682 {
2683 TLB_Mapping *This = (TLB_Mapping *)iface;
2684 ULONG refs = InterlockedDecrement(&This->refs);
2685 if (!refs)
2686 {
2687 if (This->typelib_base)
2688 UnmapViewOfFile(This->typelib_base);
2689 if (This->mapping)
2690 CloseHandle(This->mapping);
2691 if (This->file != INVALID_HANDLE_VALUE)
2692 CloseHandle(This->file);
2693 heap_free(This);
2694 }
2695 return refs;
2696 }
2697
2698 static const IUnknownVtbl TLB_Mapping_Vtable =
2699 {
2700 TLB_Mapping_QueryInterface,
2701 TLB_Mapping_AddRef,
2702 TLB_Mapping_Release
2703 };
2704
2705 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2706 {
2707 TLB_Mapping *This;
2708
2709 This = heap_alloc(sizeof(TLB_Mapping));
2710 if (!This)
2711 return E_OUTOFMEMORY;
2712
2713 This->lpvtbl = &TLB_Mapping_Vtable;
2714 This->refs = 1;
2715 This->file = INVALID_HANDLE_VALUE;
2716 This->mapping = NULL;
2717 This->typelib_base = NULL;
2718
2719 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2720 if (INVALID_HANDLE_VALUE != This->file)
2721 {
2722 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2723 if (This->mapping)
2724 {
2725 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2726 if(This->typelib_base)
2727 {
2728 /* retrieve file size */
2729 *pdwTLBLength = GetFileSize(This->file, NULL);
2730 *ppBase = This->typelib_base;
2731 *ppFile = (IUnknown *)&This->lpvtbl;
2732 return S_OK;
2733 }
2734 }
2735 }
2736
2737 IUnknown_Release((IUnknown *)&This->lpvtbl);
2738 return TYPE_E_CANTLOADLIBRARY;
2739 }
2740
2741 /****************************************************************************
2742 * TLB_ReadTypeLib
2743 *
2744 * find the type of the typelib file and map the typelib resource into
2745 * the memory
2746 */
2747
2748 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2749 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2750 {
2751 ITypeLibImpl *entry;
2752 HRESULT ret;
2753 INT index = 1;
2754 LPWSTR index_str, file = (LPWSTR)pszFileName;
2755 LPVOID pBase = NULL;
2756 DWORD dwTLBLength = 0;
2757 IUnknown *pFile = NULL;
2758
2759 *ppTypeLib = NULL;
2760
2761 index_str = strrchrW(pszFileName, '\\');
2762 if(index_str && *++index_str != '\0')
2763 {
2764 LPWSTR end_ptr;
2765 LONG idx = strtolW(index_str, &end_ptr, 10);
2766 if(*end_ptr == '\0')
2767 {
2768 int str_len = index_str - pszFileName - 1;
2769 index = idx;
2770 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2771 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2772 file[str_len] = 0;
2773 }
2774 }
2775
2776 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2777 {
2778 if(strchrW(file, '\\'))
2779 {
2780 lstrcpyW(pszPath, file);
2781 }
2782 else
2783 {
2784 int len = GetSystemDirectoryW(pszPath, cchPath);
2785 pszPath[len] = '\\';
2786 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2787 }
2788 }
2789
2790 if(file != pszFileName) heap_free(file);
2791
2792 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2793
2794 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2795 EnterCriticalSection(&cache_section);
2796 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2797 {
2798 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2799 {
2800 TRACE("cache hit\n");
2801 *ppTypeLib = (ITypeLib2*)entry;
2802 ITypeLib_AddRef(*ppTypeLib);
2803 LeaveCriticalSection(&cache_section);
2804 return S_OK;
2805 }
2806 }
2807 LeaveCriticalSection(&cache_section);
2808
2809 /* now actually load and parse the typelib */
2810
2811 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2812 if (ret == TYPE_E_CANTLOADLIBRARY)
2813 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2814 if (ret == TYPE_E_CANTLOADLIBRARY)
2815 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2816 if (SUCCEEDED(ret))
2817 {
2818 if (dwTLBLength >= 4)
2819 {
2820 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2821 if (dwSignature == MSFT_SIGNATURE)
2822 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2823 else if (dwSignature == SLTG_SIGNATURE)
2824 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2825 else
2826 {
2827 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2828 ret = TYPE_E_CANTLOADLIBRARY;
2829 }
2830 }
2831 else
2832 ret = TYPE_E_CANTLOADLIBRARY;
2833 IUnknown_Release(pFile);
2834 }
2835
2836 if(*ppTypeLib) {
2837 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2838
2839 TRACE("adding to cache\n");
2840 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2841 lstrcpyW(impl->path, pszPath);
2842 /* We should really canonicalise the path here. */
2843 impl->index = index;
2844
2845 /* FIXME: check if it has added already in the meantime */
2846 EnterCriticalSection(&cache_section);
2847 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2848 impl->prev = NULL;
2849 tlb_cache_first = impl;
2850 LeaveCriticalSection(&cache_section);
2851 ret = S_OK;
2852 } else
2853 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2854
2855 return ret;
2856 }
2857
2858 /*================== ITypeLib(2) Methods ===================================*/
2859
2860 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2861 {
2862 ITypeLibImpl* pTypeLibImpl;
2863
2864 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2865 if (!pTypeLibImpl) return NULL;
2866
2867 pTypeLibImpl->lpVtbl = &tlbvt;
2868 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2869 pTypeLibImpl->ref = 1;
2870
2871 list_init(&pTypeLibImpl->ref_list);
2872 pTypeLibImpl->dispatch_href = -1;
2873
2874 return pTypeLibImpl;
2875 }
2876
2877 /****************************************************************************
2878 * ITypeLib2_Constructor_MSFT
2879 *
2880 * loading an MSFT typelib from an in-memory image
2881 */
2882 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2883 {
2884 TLBContext cx;
2885 LONG lPSegDir;
2886 MSFT_Header tlbHeader;
2887 MSFT_SegDir tlbSegDir;
2888 ITypeLibImpl * pTypeLibImpl;
2889
2890 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2891
2892 pTypeLibImpl = TypeLibImpl_Constructor();
2893 if (!pTypeLibImpl) return NULL;
2894
2895 /* get pointer to beginning of typelib data */
2896 cx.pos = 0;
2897 cx.oStart=0;
2898 cx.mapping = pLib;
2899 cx.pLibInfo = pTypeLibImpl;
2900 cx.length = dwTLBLength;
2901
2902 /* read header */
2903 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2904 TRACE_(typelib)("header:\n");
2905 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2906 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2907 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2908 return NULL;
2909 }
2910 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2911
2912 /* there is a small amount of information here until the next important
2913 * part:
2914 * the segment directory . Try to calculate the amount of data */
2915 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2916
2917 /* now read the segment directory */
2918 TRACE("read segment directory (at %d)\n",lPSegDir);
2919 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2920 cx.pTblDir = &tlbSegDir;
2921
2922 /* just check two entries */
2923 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2924 {
2925 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2926 heap_free(pTypeLibImpl);
2927 return NULL;
2928 }
2929
2930 /* now fill our internal data */
2931 /* TLIBATTR fields */
2932 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2933
2934 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2935 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2936 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2937 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2938 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2939
2940 pTypeLibImpl->lcid = tlbHeader.lcid;
2941
2942 /* name, eventually add to a hash table */
2943 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2944
2945 /* help info */
2946 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2947 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2948
2949 if( tlbHeader.varflags & HELPDLLFLAG)
2950 {
2951 int offset;
2952 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2953 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2954 }
2955
2956 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2957
2958 /* custom data */
2959 if(tlbHeader.CustomDataOffset >= 0)
2960 {
2961 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2962 }
2963
2964 /* fill in type descriptions */
2965 if(tlbSegDir.pTypdescTab.length > 0)
2966 {
2967 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2968 INT16 td[4];
2969 pTypeLibImpl->ctTypeDesc = cTD;
2970 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
2971 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2972 for(i=0; i<cTD; )
2973 {
2974 /* FIXME: add several sanity checks here */
2975 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2976 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2977 {
2978 /* FIXME: check safearray */
2979 if(td[3] < 0)
2980 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
2981 else
2982 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
2983 }
2984 else if(td[0] == VT_CARRAY)
2985 {
2986 /* array descr table here */
2987 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2988 }
2989 else if(td[0] == VT_USERDEFINED)
2990 {
2991 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2992 }
2993 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2994 }
2995
2996 /* second time around to fill the array subscript info */
2997 for(i=0;i<cTD;i++)
2998 {
2999 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3000 if(tlbSegDir.pArrayDescriptions.offset>0)
3001 {
3002 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3003 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3004
3005 if(td[1]<0)
3006 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3007 else
3008 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3009
3010 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3011
3012 for(j = 0; j<td[2]; j++)
3013 {
3014 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3015 sizeof(INT), &cx, DO_NOT_SEEK);
3016 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3017 sizeof(INT), &cx, DO_NOT_SEEK);
3018 }
3019 }
3020 else
3021 {
3022 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3023 ERR("didn't find array description data\n");
3024 }
3025 }
3026 }
3027
3028 /* imported type libs */
3029 if(tlbSegDir.pImpFiles.offset>0)
3030 {
3031 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3032 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3033 UINT16 size;
3034
3035 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3036 {
3037 char *name;
3038
3039 *ppImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3040 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3041 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3042
3043 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3044 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3045 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3046 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3047
3048 size >>= 2;
3049 name = heap_alloc_zero(size+1);
3050 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3051 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3052 heap_free(name);
3053
3054 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3055 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3056
3057 ppImpLib = &(*ppImpLib)->next;
3058 }
3059 }
3060
3061 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3062 if(pTypeLibImpl->dispatch_href != -1)
3063 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3064
3065 /* type info's */
3066 if(tlbHeader.nrtypeinfos >= 0 )
3067 {
3068 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3069 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3070 int i;
3071
3072 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3073 {
3074 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3075
3076 ppTI = &((*ppTI)->next);
3077 (pTypeLibImpl->TypeInfoCount)++;
3078 }
3079 }
3080
3081 TRACE("(%p)\n", pTypeLibImpl);
3082 return (ITypeLib2*) pTypeLibImpl;
3083 }
3084
3085
3086 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3087 {
3088 char b[3];
3089 int i;
3090 short s;
3091
3092 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3093 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3094 return FALSE;
3095 }
3096
3097 guid->Data4[0] = s >> 8;
3098 guid->Data4[1] = s & 0xff;
3099
3100 b[2] = '\0';
3101 for(i = 0; i < 6; i++) {
3102 memcpy(b, str + 24 + 2 * i, 2);
3103 guid->Data4[i + 2] = strtol(b, NULL, 16);
3104 }
3105 return TRUE;
3106 }
3107
3108 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3109 {
3110 WORD bytelen;
3111 DWORD len;
3112
3113 *pBstr = NULL;
3114 bytelen = *(const WORD*)ptr;
3115 if(bytelen == 0xffff) return 2;
3116 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3117 *pBstr = SysAllocStringLen(NULL, len);
3118 if (*pBstr)
3119 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3120 return bytelen + 2;
3121 }
3122
3123 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3124 {
3125 WORD bytelen;
3126
3127 *str = NULL;
3128 bytelen = *(const WORD*)ptr;
3129 if(bytelen == 0xffff) return 2;
3130 *str = heap_alloc(bytelen + 1);
3131 memcpy(*str, ptr + 2, bytelen);
3132 (*str)[bytelen] = '\0';
3133 return bytelen + 2;
3134 }
3135
3136 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3137 {
3138 char *ptr = pLibBlk;
3139 WORD w;
3140
3141 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3142 FIXME("libblk magic = %04x\n", w);
3143 return 0;
3144 }
3145
3146 ptr += 6;
3147 if((w = *(WORD*)ptr) != 0xffff) {
3148 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3149 ptr += w;
3150 }
3151 ptr += 2;
3152
3153 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3154
3155 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3156
3157 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3158 ptr += 4;
3159
3160 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3161 ptr += 2;
3162
3163 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3164 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3165 else
3166 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3167 ptr += 2;
3168
3169 ptr += 4; /* skip res12 */
3170
3171 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3172 ptr += 2;
3173
3174 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3175 ptr += 2;
3176
3177 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3178 ptr += 2;
3179
3180 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3181 ptr += sizeof(GUID);
3182
3183 return ptr - (char*)pLibBlk;
3184 }
3185
3186 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3187 typedef struct
3188 {
3189 unsigned int num;
3190 HREFTYPE refs[1];
3191 } sltg_ref_lookup_t;
3192
3193 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3194 HREFTYPE *typelib_ref)
3195 {
3196 if(table && typeinfo_ref < table->num)
3197 {
3198 *typelib_ref = table->refs[typeinfo_ref];
3199 return S_OK;
3200 }
3201
3202 ERR_(typelib)("Unable to find reference\n");
3203 *typelib_ref = -1;
3204 return E_FAIL;
3205 }
3206
3207 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3208 {
3209 BOOL done = FALSE;
3210
3211 while(!done) {
3212 if((*pType & 0xe00) == 0xe00) {
3213 pTD->vt = VT_PTR;
3214 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3215 pTD = pTD->u.lptdesc;
3216 }
3217 switch(*pType & 0x3f) {
3218 case VT_PTR:
3219 pTD->vt = VT_PTR;
3220 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3221 pTD = pTD->u.lptdesc;
3222 break;
3223
3224 case VT_USERDEFINED:
3225 pTD->vt = VT_USERDEFINED;
3226 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3227 done = TRUE;
3228 break;
3229
3230 case VT_CARRAY:
3231 {
3232 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3233 array */
3234
3235 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3236
3237 pTD->vt = VT_CARRAY;
3238 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3239 pTD->u.lpadesc->cDims = pSA->cDims;
3240 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3241 pSA->cDims * sizeof(SAFEARRAYBOUND));
3242
3243 pTD = &pTD->u.lpadesc->tdescElem;
3244 break;
3245 }
3246
3247 case VT_SAFEARRAY:
3248 {
3249 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3250 useful? */
3251
3252 pType++;
3253 pTD->vt = VT_SAFEARRAY;
3254 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3255 pTD = pTD->u.lptdesc;
3256 break;
3257 }
3258 default:
3259 pTD->vt = *pType & 0x3f;
3260 done = TRUE;
3261 break;
3262 }
3263 pType++;
3264 }
3265 return pType;
3266 }
3267
3268 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3269 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3270 {
3271 /* Handle [in/out] first */
3272 if((*pType & 0xc000) == 0xc000)
3273 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3274 else if(*pType & 0x8000)
3275 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3276 else if(*pType & 0x4000)
3277 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3278 else
3279 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3280
3281 if(*pType & 0x2000)
3282 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3283
3284 if(*pType & 0x80)
3285 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3286
3287 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3288 }
3289
3290
3291 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3292 char *pNameTable)
3293 {
3294 unsigned int ref;
3295 char *name;
3296 TLBRefType *ref_type;
3297 sltg_ref_lookup_t *table;
3298 HREFTYPE typelib_ref;
3299
3300 if(pRef->magic != SLTG_REF_MAGIC) {
3301 FIXME("Ref magic = %x\n", pRef->magic);
3302 return NULL;
3303 }
3304 name = ( (char*)pRef->names + pRef->number);
3305
3306 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3307 table->num = pRef->number >> 3;
3308
3309 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3310
3311 /* We don't want the first href to be 0 */
3312 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3313
3314 for(ref = 0; ref < pRef->number >> 3; ref++) {
3315 char *refname;
3316 unsigned int lib_offs, type_num;
3317
3318 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3319
3320 name += SLTG_ReadStringA(name, &refname);
3321 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3322 FIXME_(typelib)("Can't sscanf ref\n");
3323 if(lib_offs != 0xffff) {
3324 TLBImpLib **import = &pTL->pImpLibs;
3325
3326 while(*import) {
3327 if((*import)->offset == lib_offs)
3328 break;
3329 import = &(*import)->next;
3330 }
3331 if(!*import) {
3332 char fname[MAX_PATH+1];
3333 int len;
3334
3335 *import = heap_alloc_zero(sizeof(**import));
3336 (*import)->offset = lib_offs;
3337 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3338 &(*import)->guid);
3339 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3340 &(*import)->wVersionMajor,
3341 &(*import)->wVersionMinor,
3342 &(*import)->lcid, fname) != 4) {
3343 FIXME_(typelib)("can't sscanf ref %s\n",
3344 pNameTable + lib_offs + 40);
3345 }
3346 len = strlen(fname);
3347 if(fname[len-1] != '#')
3348 FIXME("fname = %s\n", fname);
3349 fname[len-1] = '\0';
3350 (*import)->name = TLB_MultiByteToBSTR(fname);
3351 }
3352 ref_type->pImpTLInfo = *import;
3353
3354 /* Store a reference to IDispatch */
3355 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3356 pTL->dispatch_href = typelib_ref;
3357
3358 } else { /* internal ref */
3359 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3360 }
3361 ref_type->reference = typelib_ref;
3362 ref_type->index = type_num;
3363
3364 heap_free(refname);
3365 list_add_tail(&pTL->ref_list, &ref_type->entry);
3366
3367 table->refs[ref] = typelib_ref;
3368 typelib_ref += 4;
3369 }
3370 if((BYTE)*name != SLTG_REF_MAGIC)
3371 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3372 dump_TLBRefType(pTL);
3373 return table;
3374 }
3375
3376 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3377 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3378 {
3379 SLTG_ImplInfo *info;
3380 TLBImplType **ppImplType = &pTI->impltypelist;
3381 /* I don't really get this structure, usually it's 0x16 bytes
3382 long, but iuser.tlb contains some that are 0x18 bytes long.
3383 That's ok because we can use the next ptr to jump to the next
3384 one. But how do we know the length of the last one? The WORD
3385 at offs 0x8 might be the clue. For now I'm just assuming that
3386 the last one is the regular 0x16 bytes. */
3387
3388 info = (SLTG_ImplInfo*)pBlk;
3389 while(1) {
3390 *ppImplType = heap_alloc_zero(sizeof(**ppImplType));
3391 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3392 (*ppImplType)->implflags = info->impltypeflags;
3393 pTI->TypeAttr.cImplTypes++;
3394 ppImplType = &(*ppImplType)->next;
3395
3396 if(info->next == 0xffff)
3397 break;
3398 if(OneOnly)
3399 FIXME_(typelib)("Interface inheriting more than one interface\n");
3400 info = (SLTG_ImplInfo*)(pBlk + info->next);
3401 }
3402 info++; /* see comment at top of function */
3403 return (char*)info;
3404 }
3405
3406 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3407 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3408 {
3409 TLBVarDesc **ppVarDesc = &pTI->varlist;
3410 BSTR bstrPrevName = NULL;
3411 SLTG_Variable *pItem;
3412 unsigned short i;
3413 WORD *pType;
3414
3415 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3416 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3417
3418 *ppVarDesc = heap_alloc_zero(sizeof(**ppVarDesc));
3419 (*ppVarDesc)->vardesc.memid = pItem->memid;
3420
3421 if (pItem->magic != SLTG_VAR_MAGIC &&
3422 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3423 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3424 return;
3425 }
3426
3427 if (pItem->name == 0xfffe)
3428 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3429 else
3430 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3431
3432 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3433 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3434 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3435
3436 if(pItem->flags & 0x02)
3437 pType = &pItem->type;
3438 else
3439 pType = (WORD*)(pBlk + pItem->type);
3440
3441 if (pItem->flags & ~0xda)
3442 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3443
3444 SLTG_DoElem(pType, pBlk,
3445 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3446
3447 if (TRACE_ON(typelib)) {
3448 char buf[300];
3449 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3450 TRACE_(typelib)("elemdescVar: %s\n", buf);
3451 }
3452
3453 if (pItem->flags & 0x40) {
3454 TRACE_(typelib)("VAR_DISPATCH\n");
3455 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3456 }
3457 else if (pItem->flags & 0x10) {
3458 TRACE_(typelib)("VAR_CONST\n");
3459 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3460 (*ppVarDesc)->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3461 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3462 if (pItem->flags & 0x08)
3463 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3464 else {
3465 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3466 {
3467 case VT_LPSTR:
3468 case VT_LPWSTR:
3469 case VT_BSTR:
3470 {
3471 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3472 BSTR str;
3473 TRACE_(typelib)("len = %u\n", len);
3474 if (len == 0xffff) {
3475 str = NULL;
3476 } else {
3477 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3478 str = SysAllocStringLen(NULL, alloc_len);
3479 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3480 }
3481 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3482 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3483 break;
3484 }
3485 case VT_I2:
3486 case VT_UI2:
3487 case VT_I4:
3488 case VT_UI4:
3489 case VT_INT:
3490 case VT_UINT:
3491 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3492 *(INT*)(pBlk + pItem->byte_offs);
3493 break;
3494 default:
3495 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3496 }
3497 }
3498 }
3499 else {
3500 TRACE_(typelib)("VAR_PERINSTANCE\n");
3501 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3502 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3503 }
3504
3505 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3506 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3507
3508 if (pItem->flags & 0x80)
3509 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3510
3511 bstrPrevName = (*ppVarDesc)->Name;
3512 ppVarDesc = &((*ppVarDesc)->next);
3513 }
3514 pTI->TypeAttr.cVars = cVars;
3515 }
3516
3517 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3518 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3519 {
3520 SLTG_Function *pFunc;
3521 unsigned short i;
3522 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3523
3524 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3525 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3526
3527 int param;
3528 WORD *pType, *pArg;
3529
3530 *ppFuncDesc = heap_alloc_zero(sizeof(**ppFuncDesc));
3531
3532 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3533 case SLTG_FUNCTION_MAGIC:
3534 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3535 break;
3536 case SLTG_DISPATCH_FUNCTION_MAGIC:
3537 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3538 break;
3539 case SLTG_STATIC_FUNCTION_MAGIC:
3540 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3541 break;
3542 default:
3543 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3544 heap_free(*ppFuncDesc);
3545 *ppFuncDesc = NULL;
3546 return;
3547 }
3548 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3549
3550 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3551 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3552 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3553 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3554 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3555 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3556
3557 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3558 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3559
3560 if(pFunc->retnextopt & 0x80)
3561 pType = &pFunc->rettype;
3562 else
3563 pType = (WORD*)(pBlk + pFunc->rettype);
3564
3565 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3566
3567 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3568 heap_alloc_zero((*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3569 (*ppFuncDesc)->pParamDesc =
3570 heap_alloc_zero((*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3571
3572 pArg = (WORD*)(pBlk + pFunc->arg_off);
3573
3574 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3575 char *paramName = pNameTable + *pArg;
3576 BOOL HaveOffs;
3577 /* If arg type follows then paramName points to the 2nd
3578 letter of the name, else the next WORD is an offset to
3579 the arg type and paramName points to the first letter.
3580 So let's take one char off paramName and see if we're
3581 pointing at an alpha-numeric char. However if *pArg is
3582 0xffff or 0xfffe then the param has no name, the former
3583 meaning that the next WORD is the type, the latter
3584 meaning that the next WORD is an offset to the type. */
3585
3586 HaveOffs = FALSE;
3587 if(*pArg == 0xffff)
3588 paramName = NULL;
3589 else if(*pArg == 0xfffe) {
3590 paramName = NULL;
3591 HaveOffs = TRUE;
3592 }
3593 else if(paramName[-1] && !isalnum(paramName[-1]))
3594 HaveOffs = TRUE;
3595
3596 pArg++;
3597
3598 if(HaveOffs) { /* the next word is an offset to type */
3599 pType = (WORD*)(pBlk + *pArg);
3600 SLTG_DoElem(pType, pBlk,
3601 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3602 pArg++;
3603 } else {
3604 if(paramName)
3605 paramName--;
3606 pArg = SLTG_DoElem(pArg, pBlk,
3607 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3608 }
3609
3610 /* Are we an optional param ? */
3611 if((*ppFuncDesc)->funcdesc.cParams - param <=
3612 (*ppFuncDesc)->funcdesc.cParamsOpt)
3613 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3614
3615 if(paramName) {
3616 (*ppFuncDesc)->pParamDesc[param].Name =
3617 TLB_MultiByteToBSTR(paramName);
3618 } else {
3619 (*ppFuncDesc)->pParamDesc[param].Name =
3620 SysAllocString((*ppFuncDesc)->Name);
3621 }
3622 }
3623
3624 ppFuncDesc = &((*ppFuncDesc)->next);
3625 if(pFunc->next == 0xffff) break;
3626 }
3627 pTI->TypeAttr.cFuncs = cFuncs;
3628 }
3629
3630 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3631 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3632 SLTG_TypeInfoTail *pTITail)
3633 {
3634 char *pFirstItem;
3635 sltg_ref_lookup_t *ref_lookup = NULL;
3636
3637 if(pTIHeader->href_table != 0xffffffff) {
3638 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3639 pNameTable);
3640 }
3641
3642 pFirstItem = pBlk;
3643
3644 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3645 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3646 }
3647 heap_free(ref_lookup);
3648 }
3649
3650
3651 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3652 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3653 const SLTG_TypeInfoTail *pTITail)
3654 {
3655 char *pFirstItem;
3656 sltg_ref_lookup_t *ref_lookup = NULL;
3657
3658 if(pTIHeader->href_table != 0xffffffff) {
3659 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3660 pNameTable);
3661 }
3662
3663 pFirstItem = pBlk;
3664
3665 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3666 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3667 }
3668
3669 if (pTITail->funcs_off != 0xffff)
3670 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3671
3672 heap_free(ref_lookup);
3673
3674 if (TRACE_ON(typelib))
3675 dump_TLBFuncDesc(pTI->funclist);
3676 }
3677
3678 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3679 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3680 const SLTG_TypeInfoTail *pTITail)
3681 {
3682 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3683 }
3684
3685 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3686 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3687 const SLTG_TypeInfoTail *pTITail)
3688 {
3689 WORD *pType;
3690 sltg_ref_lookup_t *ref_lookup = NULL;
3691
3692 if (pTITail->simple_alias) {
3693 /* if simple alias, no more processing required */
3694 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3695 return;
3696 }
3697
3698 if(pTIHeader->href_table != 0xffffffff) {
3699 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3700 pNameTable);
3701 }
3702
3703 /* otherwise it is an offset to a type */
3704 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3705
3706 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3707
3708 heap_free(ref_lookup);
3709 }
3710
3711 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3712 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3713 const SLTG_TypeInfoTail *pTITail)
3714 {
3715 sltg_ref_lookup_t *ref_lookup = NULL;
3716 if (pTIHeader->href_table != 0xffffffff)
3717 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3718 pNameTable);
3719
3720 if (pTITail->vars_off != 0xffff)
3721 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3722
3723 if (pTITail->funcs_off != 0xffff)
3724 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3725
3726 if (pTITail->impls_off != 0xffff)
3727 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3728
3729 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3730 * of dispinterface functions including the IDispatch ones, so
3731 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3732 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3733
3734 heap_free(ref_lookup);
3735 if (TRACE_ON(typelib))
3736 dump_TLBFuncDesc(pTI->funclist);
3737 }
3738
3739 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3740 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3741 const SLTG_TypeInfoTail *pTITail)
3742 {
3743 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3744 }
3745
3746 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3747 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3748 const SLTG_TypeInfoTail *pTITail)
3749 {
3750 sltg_ref_lookup_t *ref_lookup = NULL;
3751 if (pTIHeader->href_table != 0xffffffff)
3752 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3753 pNameTable);
3754
3755 if (pTITail->vars_off != 0xffff)
3756 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3757
3758 if (pTITail->funcs_off != 0xffff)
3759 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3760 heap_free(ref_lookup);
3761 if (TRACE_ON(typelib))
3762 dump_TypeInfo(pTI);
3763 }
3764
3765 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3766 managable copy of it into this */
3767 typedef struct {
3768 WORD small_no;
3769 char *index_name;
3770 char *other_name;
3771 WORD res1a;
3772 WORD name_offs;
3773 WORD more_bytes;
3774 char *extra;
3775 WORD res20;
3776 DWORD helpcontext;
3777 WORD res26;
3778 GUID uuid;
3779 } SLTG_InternalOtherTypeInfo;
3780
3781 /****************************************************************************
3782 * ITypeLib2_Constructor_SLTG
3783 *
3784 * loading a SLTG typelib from an in-memory image
3785 */
3786 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3787 {
3788 ITypeLibImpl *pTypeLibImpl;
3789 SLTG_Header *pHeader;
3790 SLTG_BlkEntry *pBlkEntry;
3791 SLTG_Magic *pMagic;
3792 SLTG_Index *pIndex;
3793 SLTG_Pad9 *pPad9;
3794 LPVOID pBlk, pFirstBlk;
3795 SLTG_LibBlk *pLibBlk;
3796 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3797 char *pAfterOTIBlks = NULL;
3798 char *pNameTable, *ptr;
3799 int i;
3800 DWORD len, order;
3801 ITypeInfoImpl **ppTypeInfoImpl;
3802
3803 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3804
3805
3806 pTypeLibImpl = TypeLibImpl_Constructor();
3807 if (!pTypeLibImpl) return NULL;
3808
3809 pHeader = pLib;
3810
3811 TRACE_(typelib)("header:\n");
3812 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3813 pHeader->nrOfFileBlks );
3814 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3815 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3816 pHeader->SLTG_magic);
3817 return NULL;
3818 }
3819
3820 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3821 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3822
3823 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3824 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3825
3826 /* Next we have a magic block */
3827 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3828
3829 /* Let's see if we're still in sync */
3830 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3831 sizeof(SLTG_COMPOBJ_MAGIC))) {
3832 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3833 return NULL;
3834 }
3835 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3836 sizeof(SLTG_DIR_MAGIC))) {
3837 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3838 return NULL;
3839 }
3840
3841 pIndex = (SLTG_Index*)(pMagic+1);
3842
3843 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3844
3845 pFirstBlk = pPad9 + 1;
3846
3847 /* We'll set up a ptr to the main library block, which is the last one. */
3848
3849 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3850 pBlkEntry[order].next != 0;
3851 order = pBlkEntry[order].next - 1, i++) {
3852 pBlk = (char*)pBlk + pBlkEntry[order].len;
3853 }
3854 pLibBlk = pBlk;
3855
3856 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3857
3858 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3859 interspersed */
3860
3861 len += 0x40;
3862
3863 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3864
3865 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3866
3867
3868 ptr = (char*)pLibBlk + len;
3869
3870 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3871 WORD w, extra;
3872 len = 0;
3873
3874 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3875
3876 w = *(WORD*)(ptr + 2);
3877 if(w != 0xffff) {
3878 len += w;
3879 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3880 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3881 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3882 }
3883 w = *(WORD*)(ptr + 4 + len);
3884 if(w != 0xffff) {
3885 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3886 len += w;
3887 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
3888 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3889 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3890 }
3891 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3892 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3893 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3894 if(extra) {
3895 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
3896 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3897 len += extra;
3898 }
3899 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3900 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3901 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3902 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3903 len += sizeof(SLTG_OtherTypeInfo);
3904 ptr += len;
3905 }
3906
3907 pAfterOTIBlks = ptr;
3908
3909 /* Skip this WORD and get the next DWORD */
3910 len = *(DWORD*)(pAfterOTIBlks + 2);
3911
3912 /* Now add this to pLibBLk look at what we're pointing at and
3913 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3914 dust and we should be pointing at the beginning of the name
3915 table */
3916
3917 pNameTable = (char*)pLibBlk + len;
3918
3919 switch(*(WORD*)pNameTable) {
3920 case 0xffff:
3921 break;
3922 case 0x0200:
3923 pNameTable += 0x20;
3924 break;
3925 default:
3926 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3927 break;
3928 }
3929
3930 pNameTable += 0x216;
3931
3932 pNameTable += 2;
3933
3934 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3935
3936 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3937
3938
3939 /* Hopefully we now have enough ptrs set up to actually read in
3940 some TypeInfos. It's not clear which order to do them in, so
3941 I'll just follow the links along the BlkEntry chain and read
3942 them in the order in which they are in the file */
3943
3944 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3945
3946 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3947 pBlkEntry[order].next != 0;
3948 order = pBlkEntry[order].next - 1, i++) {
3949
3950 SLTG_TypeInfoHeader *pTIHeader;
3951 SLTG_TypeInfoTail *pTITail;
3952 SLTG_MemberHeader *pMemHeader;
3953
3954 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3955 pOtherTypeInfoBlks[i].index_name)) {
3956 FIXME_(typelib)("Index strings don't match\n");
3957 return NULL;
3958 }
3959
3960 pTIHeader = pBlk;
3961 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3962 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3963 return NULL;
3964 }
3965 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3966 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3967 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3968
3969 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
3970 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3971 (*ppTypeInfoImpl)->index = i;
3972 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3973 pOtherTypeInfoBlks[i].name_offs +
3974 pNameTable);
3975 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3976 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3977 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3978 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3979 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3980 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3981 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3982
3983 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3984 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3985
3986 if((pTIHeader->typeflags1 & 7) != 2)
3987 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3988 if(pTIHeader->typeflags3 != 2)
3989 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3990
3991 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3992 debugstr_w((*ppTypeInfoImpl)->Name),
3993 typekind_desc[pTIHeader->typekind],
3994 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3995 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3996
3997 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3998
3999 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4000
4001 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4002 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4003 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4004
4005 switch(pTIHeader->typekind) {
4006 case TKIND_ENUM:
4007 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4008 pTIHeader, pTITail);
4009 break;
4010
4011 case TKIND_RECORD:
4012 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4013 pTIHeader, pTITail);
4014 break;
4015
4016 case TKIND_INTERFACE:
4017 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4018 pTIHeader, pTITail);
4019 break;
4020
4021 case TKIND_COCLASS:
4022 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4023 pTIHeader, pTITail);
4024 break;
4025
4026 case TKIND_ALIAS:
4027 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4028 pTIHeader, pTITail);
4029 break;
4030
4031 case TKIND_DISPATCH:
4032 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4033 pTIHeader, pTITail);
4034 break;
4035
4036 case TKIND_MODULE:
4037 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4038 pTIHeader, pTITail);
4039 break;
4040
4041 default:
4042 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4043 break;
4044
4045 }
4046
4047 /* could get cFuncs, cVars and cImplTypes from here
4048 but we've already set those */
4049 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4050 X(06);
4051 X(16);
4052 X(18);
4053 X(1a);
4054 X(1e);
4055 X(24);
4056 X(26);
4057 X(2a);
4058 X(2c);
4059 X(2e);
4060 X(30);
4061 X(32);
4062 X(34);
4063 #undef X
4064 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4065 pBlk = (char*)pBlk + pBlkEntry[order].len;
4066 }
4067
4068 if(i != pTypeLibImpl->TypeInfoCount) {
4069 FIXME("Somehow processed %d TypeInfos\n", i);
4070 return NULL;
4071 }
4072
4073 heap_free(pOtherTypeInfoBlks);
4074 return (ITypeLib2*)pTypeLibImpl;
4075 }
4076
4077 /* ITypeLib::QueryInterface
4078 */
4079 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4080 ITypeLib2 * iface,
4081 REFIID riid,
4082 VOID **ppvObject)
4083 {
4084 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4085
4086 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4087
4088 *ppvObject=NULL;
4089 if(IsEqualIID(riid, &IID_IUnknown) ||
4090 IsEqualIID(riid,&IID_ITypeLib)||
4091 IsEqualIID(riid,&IID_ITypeLib2))
4092 {
4093 *ppvObject = This;
4094 }
4095
4096 if(*ppvObject)
4097 {
4098 ITypeLib2_AddRef(iface);
4099 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4100 return S_OK;
4101 }
4102 TRACE("-- Interface: E_NOINTERFACE\n");
4103 return E_NOINTERFACE;
4104 }
4105
4106 /* ITypeLib::AddRef
4107 */
4108 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4109 {
4110 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4111 ULONG ref = InterlockedIncrement(&This->ref);
4112
4113 TRACE("(%p)->ref was %u\n",This, ref - 1);
4114
4115 return ref;
4116 }
4117
4118 /* ITypeLib::Release
4119 */
4120 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4121 {
4122 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4123 ULONG ref = InterlockedDecrement(&This->ref);
4124
4125 TRACE("(%p)->(%u)\n",This, ref);
4126
4127 if (!ref)
4128 {
4129 TLBImpLib *pImpLib, *pImpLibNext;
4130 TLBCustData *pCustData, *pCustDataNext;
4131 TLBRefType *ref_type;
4132 void *cursor2;
4133 int i;
4134 ITypeInfoImpl *pTI, *pTINext;
4135
4136 /* remove cache entry */
4137 if(This->path)
4138 {
4139 TRACE("removing from cache list\n");
4140 EnterCriticalSection(&cache_section);
4141 if (This->next) This->next->prev = This->prev;
4142 if (This->prev) This->prev->next = This->next;
4143 else tlb_cache_first = This->next;
4144 LeaveCriticalSection(&cache_section);
4145 heap_free(This->path);
4146 }
4147 TRACE(" destroying ITypeLib(%p)\n",This);
4148
4149 SysFreeString(This->Name);
4150 This->Name = NULL;
4151
4152 SysFreeString(This->DocString);
4153 This->DocString = NULL;
4154
4155 SysFreeString(This->HelpFile);
4156 This->HelpFile = NULL;
4157
4158 SysFreeString(This->HelpStringDll);
4159 This->HelpStringDll = NULL;
4160
4161 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4162 {
4163 VariantClear(&pCustData->data);
4164
4165 pCustDataNext = pCustData->next;
4166 heap_free(pCustData);
4167 }
4168
4169 for (i = 0; i < This->ctTypeDesc; i++)
4170 if (This->pTypeDesc[i].vt == VT_CARRAY)
4171 heap_free(This->pTypeDesc[i].u.lpadesc);
4172
4173 heap_free(This->pTypeDesc);
4174
4175 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4176 {
4177 if (pImpLib->pImpTypeLib)
4178 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4179 SysFreeString(pImpLib->name);
4180
4181 pImpLibNext = pImpLib->next;
4182 heap_free(pImpLib);
4183 }
4184
4185 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4186 {
4187 list_remove(&ref_type->entry);
4188 heap_free(ref_type);
4189 }
4190
4191 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4192 {
4193 pTINext = pTI->next;
4194 ITypeInfoImpl_Destroy(pTI);
4195 }
4196 heap_free(This);
4197 return 0;
4198 }
4199
4200 return ref;
4201 }
4202
4203 /* ITypeLib::GetTypeInfoCount
4204 *
4205 * Returns the number of type descriptions in the type library
4206 */
4207 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4208 {
4209 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4210 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4211 return This->TypeInfoCount;
4212 }
4213
4214 /* ITypeLib::GetTypeInfo
4215 *
4216 * retrieves the specified type description in the library.
4217 */
4218 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4219 ITypeLib2 *iface,
4220 UINT index,
4221 ITypeInfo **ppTInfo)
4222 {
4223 UINT i;
4224
4225 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4226 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4227
4228 TRACE("(%p)->(index=%d)\n", This, index);
4229
4230 if (!ppTInfo) return E_INVALIDARG;
4231
4232 /* search element n in list */
4233 for(i=0; i < index; i++)
4234 {
4235 pTypeInfo = pTypeInfo->next;
4236 if (!pTypeInfo)
4237 {
4238 TRACE("-- element not found\n");
4239 return TYPE_E_ELEMENTNOTFOUND;
4240 }
4241 }
4242
4243 *ppTInfo = (ITypeInfo *) pTypeInfo;
4244
4245 ITypeInfo_AddRef(*ppTInfo);
4246 TRACE("-- found (%p)\n",*ppTInfo);
4247 return S_OK;
4248 }
4249
4250
4251 /* ITypeLibs::GetTypeInfoType
4252 *
4253 * Retrieves the type of a type description.
4254 */
4255 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4256 ITypeLib2 *iface,
4257 UINT index,
4258 TYPEKIND *pTKind)
4259 {
4260 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4261 UINT i;
4262 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4263
4264 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4265
4266 if(!pTKind) return E_INVALIDARG;
4267
4268 if(ITypeLib2_GetTypeInfoCount(iface) <= index)
4269 return TYPE_E_ELEMENTNOTFOUND;
4270
4271 /* search element n in list */
4272 for(i=0; i < index; i++)
4273 {
4274 if(!pTInfo)
4275 {
4276 TRACE("-- element not found\n");
4277 return TYPE_E_ELEMENTNOTFOUND;
4278 }
4279 pTInfo = pTInfo->next;
4280 }
4281
4282 *pTKind = pTInfo->TypeAttr.typekind;
4283 TRACE("-- found Type (%d)\n", *pTKind);
4284 return S_OK;
4285 }
4286
4287 /* ITypeLib::GetTypeInfoOfGuid
4288 *
4289 * Retrieves the type description that corresponds to the specified GUID.
4290 *
4291 */
4292 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4293 ITypeLib2 *iface,
4294 REFGUID guid,
4295 ITypeInfo **ppTInfo)
4296 {
4297 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4298 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4299
4300 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4301
4302 if (!pTypeInfo)
4303 {
4304 WARN("-- element not found\n");
4305 return TYPE_E_ELEMENTNOTFOUND;
4306 }
4307
4308 /* search linked list for guid */
4309 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4310 {
4311 pTypeInfo = pTypeInfo->next;
4312
4313 if (!pTypeInfo)
4314 {
4315 /* end of list reached */
4316 WARN("-- element not found\n");
4317 return TYPE_E_ELEMENTNOTFOUND;
4318 }
4319 }
4320
4321 TRACE("-- found (%p, %s)\n",
4322 pTypeInfo,
4323 debugstr_w(pTypeInfo->Name));
4324
4325 *ppTInfo = (ITypeInfo*)pTypeInfo;
4326 ITypeInfo_AddRef(*ppTInfo);
4327 return S_OK;
4328 }
4329
4330 /* ITypeLib::GetLibAttr
4331 *
4332 * Retrieves the structure that contains the library's attributes.
4333 *
4334 */
4335 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4336 ITypeLib2 *iface,
4337 LPTLIBATTR *attr)
4338 {
4339 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4340
4341 TRACE("(%p, %p)\n", This, attr);
4342
4343 if (!attr) return E_INVALIDARG;
4344
4345 *attr = heap_alloc(sizeof(**attr));
4346 if (!*attr) return E_OUTOFMEMORY;
4347
4348 **attr = This->LibAttr;
4349 return S_OK;
4350 }
4351
4352 /* ITypeLib::GetTypeComp
4353 *
4354 * Enables a client compiler to bind to a library's types, variables,
4355 * constants, and global functions.
4356 *
4357 */
4358 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4359 ITypeLib2 *iface,
4360 ITypeComp **ppTComp)
4361 {
4362 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4363
4364 TRACE("(%p)->(%p)\n",This,ppTComp);
4365 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4366 ITypeComp_AddRef(*ppTComp);
4367
4368 return S_OK;
4369 }
4370
4371 /* ITypeLib::GetDocumentation
4372 *
4373 * Retrieves the library's documentation string, the complete Help file name
4374 * and path, and the context identifier for the library Help topic in the Help
4375 * file.
4376 *
4377 * On a successful return all non-null BSTR pointers will have been set,
4378 * possibly to NULL.
4379 */
4380 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4381 ITypeLib2 *iface,
4382 INT index,
4383 BSTR *pBstrName,
4384 BSTR *pBstrDocString,
4385 DWORD *pdwHelpContext,
4386 BSTR *pBstrHelpFile)
4387 {
4388 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4389
4390 HRESULT result = E_INVALIDARG;
4391
4392 ITypeInfo *pTInfo;
4393
4394
4395 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4396 This, index,
4397 pBstrName, pBstrDocString,
4398 pdwHelpContext, pBstrHelpFile);
4399
4400 if(index<0)
4401 {
4402 /* documentation for the typelib */
4403 if(pBstrName)
4404 {
4405 if (This->Name)
4406 {
4407 if(!(*pBstrName = SysAllocString(This->Name)))
4408 goto memerr1;
4409 }
4410 else
4411 *pBstrName = NULL;
4412 }
4413 if(pBstrDocString)
4414 {
4415 if (This->DocString)
4416 {
4417 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4418 goto memerr2;
4419 }
4420 else if (This->Name)
4421 {
4422 if(!(*pBstrDocString = SysAllocString(This->Name)))
4423 goto memerr2;
4424 }
4425 else
4426 *pBstrDocString = NULL;
4427 }
4428 if(pdwHelpContext)
4429 {
4430 *pdwHelpContext = This->dwHelpContext;
4431 }
4432 if(pBstrHelpFile)
4433 {
4434 if (This->HelpFile)
4435 {
4436 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4437 goto memerr3;
4438 }
4439 else
4440 *pBstrHelpFile = NULL;
4441 }
4442
4443 result = S_OK;
4444 }
4445 else
4446 {
4447 /* for a typeinfo */
4448 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4449
4450 if(SUCCEEDED(result))
4451 {
4452 result = ITypeInfo_GetDocumentation(pTInfo,
4453 MEMBERID_NIL,
4454 pBstrName,
4455 pBstrDocString,
4456 pdwHelpContext, pBstrHelpFile);
4457
4458 ITypeInfo_Release(pTInfo);
4459 }
4460 }
4461 return result;
4462 memerr3:
4463 if (pBstrDocString) SysFreeString (*pBstrDocString);
4464 memerr2:
4465 if (pBstrName) SysFreeString (*pBstrName);
4466 memerr1:
4467 return STG_E_INSUFFICIENTMEMORY;
4468 }
4469
4470 /* ITypeLib::IsName
4471 *
4472 * Indicates whether a passed-in string contains the name of a type or member
4473 * described in the library.
4474 *
4475 */
4476 static HRESULT WINAPI ITypeLib2_fnIsName(
4477 ITypeLib2 *iface,
4478 LPOLESTR szNameBuf,
4479 ULONG lHashVal,
4480 BOOL *pfName)
4481 {
4482 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4483 ITypeInfoImpl *pTInfo;
4484 TLBFuncDesc *pFInfo;
4485 TLBVarDesc *pVInfo;
4486 int i;
4487 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4488
4489 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4490 pfName);
4491
4492 *pfName=TRUE;
4493 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4494 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4495 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4496 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4497 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4498 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4499 goto ITypeLib2_fnIsName_exit;
4500 }
4501 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4502 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4503
4504 }
4505 *pfName=FALSE;
4506
4507 ITypeLib2_fnIsName_exit:
4508 TRACE("(%p)slow! search for %s: %s found!\n", This,
4509 debugstr_w(szNameBuf), *pfName?"NOT":"");
4510
4511 return S_OK;
4512 }
4513
4514 /* ITypeLib::FindName
4515 *
4516 * Finds occurrences of a type description in a type library. This may be used
4517 * to quickly verify that a name exists in a type library.
4518 *
4519 */
4520 static HRESULT WINAPI ITypeLib2_fnFindName(
4521 ITypeLib2 *iface,
4522 LPOLESTR szNameBuf,
4523 ULONG lHashVal,
4524 ITypeInfo **ppTInfo,
4525 MEMBERID *rgMemId,
4526 UINT16 *pcFound)
4527 {
4528 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4529 ITypeInfoImpl *pTInfo;
4530 TLBFuncDesc *pFInfo;
4531 TLBVarDesc *pVInfo;
4532 int i,j = 0;
4533 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4534
4535 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4536 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4537 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4538 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4539 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4540 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4541 goto ITypeLib2_fnFindName_exit;
4542 }
4543 }
4544 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4545 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4546 continue;
4547 ITypeLib2_fnFindName_exit:
4548 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4549 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4550 j++;
4551 }
4552 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4553 This, *pcFound, debugstr_w(szNameBuf), j);
4554
4555 *pcFound=j;
4556
4557 return S_OK;
4558 }
4559
4560 /* ITypeLib::ReleaseTLibAttr
4561 *
4562 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4563 *
4564 */
4565 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4566 ITypeLib2 *iface,
4567 TLIBATTR *pTLibAttr)
4568 {
4569 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4570 TRACE("freeing (%p)\n",This);
4571 heap_free(pTLibAttr);
4572
4573 }
4574
4575 /* ITypeLib2::GetCustData
4576 *
4577 * gets the custom data
4578 */
4579 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4580 ITypeLib2 * iface,
4581 REFGUID guid,
4582 VARIANT *pVarVal)
4583 {
4584 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4585 TLBCustData *pCData;
4586
4587 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4588 {
4589 if( IsEqualIID(guid, &pCData->guid)) break;
4590 }
4591
4592 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4593
4594 if(pCData)
4595 {
4596 VariantInit( pVarVal);
4597 VariantCopy( pVarVal, &pCData->data);
4598 return S_OK;
4599 }
4600 return E_INVALIDARG; /* FIXME: correct? */
4601 }
4602
4603 /* ITypeLib2::GetLibStatistics
4604 *
4605 * Returns statistics about a type library that are required for efficient
4606 * sizing of hash tables.
4607 *
4608 */
4609 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4610 ITypeLib2 * iface,
4611 ULONG *pcUniqueNames,
4612 ULONG *pcchUniqueNames)
4613 {
4614 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4615
4616 FIXME("(%p): stub!\n", This);
4617
4618 if(pcUniqueNames) *pcUniqueNames=1;
4619 if(pcchUniqueNames) *pcchUniqueNames=1;
4620 return S_OK;
4621 }
4622
4623 /* ITypeLib2::GetDocumentation2
4624 *
4625 * Retrieves the library's documentation string, the complete Help file name
4626 * and path, the localization context to use, and the context ID for the
4627 * library Help topic in the Help file.
4628 *
4629 */
4630 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4631 ITypeLib2 * iface,
4632 INT index,
4633 LCID lcid,
4634 BSTR *pbstrHelpString,
4635 DWORD *pdwHelpStringContext,
4636 BSTR *pbstrHelpStringDll)
4637 {
4638 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4639 HRESULT result;
4640 ITypeInfo *pTInfo;
4641
4642 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4643
4644 /* the help string should be obtained from the helpstringdll,
4645 * using the _DLLGetDocumentation function, based on the supplied
4646 * lcid. Nice to do sometime...
4647 */
4648 if(index<0)
4649 {
4650 /* documentation for the typelib */
4651 if(pbstrHelpString)
4652 *pbstrHelpString=SysAllocString(This->DocString);
4653 if(pdwHelpStringContext)
4654 *pdwHelpStringContext=This->dwHelpContext;
4655 if(pbstrHelpStringDll)
4656 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4657
4658 result = S_OK;
4659 }
4660 else
4661 {
4662 /* for a typeinfo */
4663 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4664
4665 if(SUCCEEDED(result))
4666 {
4667 ITypeInfo2 * pTInfo2;
4668 result = ITypeInfo_QueryInterface(pTInfo,
4669 &IID_ITypeInfo2,
4670 (LPVOID*) &pTInfo2);
4671
4672 if(SUCCEEDED(result))
4673 {
4674 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4675 MEMBERID_NIL,
4676 lcid,
4677 pbstrHelpString,
4678 pdwHelpStringContext,
4679 pbstrHelpStringDll);
4680
4681 ITypeInfo2_Release(pTInfo2);
4682 }
4683
4684 ITypeInfo_Release(pTInfo);
4685 }
4686 }
4687 return result;
4688 }
4689
4690 /* ITypeLib2::GetAllCustData
4691 *
4692 * Gets all custom data items for the library.
4693 *
4694 */
4695 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4696 ITypeLib2 * iface,
4697 CUSTDATA *pCustData)
4698 {
4699 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4700 TLBCustData *pCData;
4701 int i;
4702 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4703 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
4704 if(pCustData->prgCustData ){
4705 pCustData->cCustData=This->ctCustData;
4706 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4707 pCustData->prgCustData[i].guid=pCData->guid;
4708 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4709 }
4710 }else{
4711 ERR(" OUT OF MEMORY!\n");
4712 return E_OUTOFMEMORY;
4713 }
4714 return S_OK;
4715 }
4716
4717 static const ITypeLib2Vtbl tlbvt = {
4718 ITypeLib2_fnQueryInterface,
4719 ITypeLib2_fnAddRef,
4720 ITypeLib2_fnRelease,
4721 ITypeLib2_fnGetTypeInfoCount,
4722 ITypeLib2_fnGetTypeInfo,
4723 ITypeLib2_fnGetTypeInfoType,
4724 ITypeLib2_fnGetTypeInfoOfGuid,
4725 ITypeLib2_fnGetLibAttr,
4726 ITypeLib2_fnGetTypeComp,
4727 ITypeLib2_fnGetDocumentation,
4728 ITypeLib2_fnIsName,
4729 ITypeLib2_fnFindName,
4730 ITypeLib2_fnReleaseTLibAttr,
4731
4732 ITypeLib2_fnGetCustData,
4733 ITypeLib2_fnGetLibStatistics,
4734 ITypeLib2_fnGetDocumentation2,
4735 ITypeLib2_fnGetAllCustData
4736 };
4737
4738
4739 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4740 {
4741 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4742
4743 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4744 }
4745
4746 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4747 {
4748 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4749
4750 return ITypeLib2_AddRef((ITypeLib2 *)This);
4751 }
4752
4753 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4754 {
4755 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4756
4757 return ITypeLib2_Release((ITypeLib2 *)This);
4758 }
4759
4760 static HRESULT WINAPI ITypeLibComp_fnBind(
4761 ITypeComp * iface,
4762 OLECHAR * szName,
4763 ULONG lHash,
4764 WORD wFlags,
4765 ITypeInfo ** ppTInfo,
4766 DESCKIND * pDescKind,
4767 BINDPTR * pBindPtr)
4768 {
4769 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4770 ITypeInfoImpl *pTypeInfo;
4771 int typemismatch=0;
4772
4773 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4774
4775 *pDescKind = DESCKIND_NONE;
4776 pBindPtr->lptcomp = NULL;
4777 *ppTInfo = NULL;
4778
4779 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4780 {
4781 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4782
4783 /* FIXME: check wFlags here? */
4784 /* FIXME: we should use a hash table to look this info up using lHash
4785 * instead of an O(n) search */
4786 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4787 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4788 {
4789 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4790 {
4791 *pDescKind = DESCKIND_TYPECOMP;
4792 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4793 ITypeComp_AddRef(pBindPtr->lptcomp);
4794 TRACE("module or enum: %s\n", debugstr_w(szName));
4795 return S_OK;
4796 }
4797 }
4798
4799 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4800 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4801 {
4802 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4803 HRESULT hr;
4804
4805 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4806 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4807 {
4808 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4809 return S_OK;
4810 }
4811 else if (hr == TYPE_E_TYPEMISMATCH)
4812 typemismatch = 1;
4813 }
4814
4815 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4816 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4817 {
4818 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4819 HRESULT hr;
4820 ITypeInfo *subtypeinfo;
4821 BINDPTR subbindptr;
4822 DESCKIND subdesckind;
4823
4824 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4825 &subtypeinfo, &subdesckind, &subbindptr);
4826 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4827 {
4828 TYPEDESC tdesc_appobject;
4829 const VARDESC vardesc_appobject =
4830 {
4831 -2, /* memid */
4832 NULL, /* lpstrSchema */
4833 {
4834 0 /* oInst */
4835 },
4836 {
4837 /* ELEMDESC */
4838 {
4839 /* TYPEDESC */
4840 {
4841 &tdesc_appobject
4842 },
4843 VT_PTR
4844 },
4845 },
4846 0, /* wVarFlags */
4847 VAR_STATIC /* varkind */
4848 };
4849
4850 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4851 tdesc_appobject.vt = VT_USERDEFINED;
4852
4853 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4854
4855 /* cleanup things filled in by Bind call so we can put our
4856 * application object data in there instead */
4857 switch (subdesckind)
4858 {
4859 case DESCKIND_FUNCDESC:
4860 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4861 break;
4862 case DESCKIND_VARDESC:
4863 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4864 break;
4865 default:
4866 break;
4867 }
4868 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4869
4870 if (pTypeInfo->hreftype == -1)
4871 FIXME("no hreftype for interface %p\n", pTypeInfo);
4872
4873 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4874 if (FAILED(hr))
4875 return hr;
4876
4877 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4878 *ppTInfo = (ITypeInfo *)pTypeInfo;
4879 ITypeInfo_AddRef(*ppTInfo);
4880 return S_OK;
4881 }
4882 else if (hr == TYPE_E_TYPEMISMATCH)
4883 typemismatch = 1;
4884 }
4885 }
4886
4887 if (typemismatch)
4888 {
4889 TRACE("type mismatch %s\n", debugstr_w(szName));
4890 return TYPE_E_TYPEMISMATCH;
4891 }
4892 else
4893 {
4894 TRACE("name not found %s\n", debugstr_w(szName));
4895 return S_OK;
4896 }
4897 }
4898
4899 static HRESULT WINAPI ITypeLibComp_fnBindType(
4900 ITypeComp * iface,
4901 OLECHAR * szName,
4902 ULONG lHash,
4903 ITypeInfo ** ppTInfo,
4904 ITypeComp ** ppTComp)
4905 {
4906 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4907 ITypeInfoImpl *pTypeInfo;
4908
4909 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4910
4911 if(!szName || !ppTInfo || !ppTComp)
4912 return E_INVALIDARG;
4913
4914 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4915 {
4916 /* FIXME: should use lHash to do the search */
4917 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
4918 {
4919 TRACE("returning %p\n", pTypeInfo);
4920 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4921 ITypeInfo_AddRef(*ppTInfo);
4922 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4923 ITypeComp_AddRef(*ppTComp);
4924 return S_OK;
4925 }
4926 }
4927
4928 TRACE("not found\n");
4929 *ppTInfo = NULL;
4930 *ppTComp = NULL;
4931 return S_OK;
4932 }
4933
4934 static const ITypeCompVtbl tlbtcvt =
4935 {
4936
4937 ITypeLibComp_fnQueryInterface,
4938 ITypeLibComp_fnAddRef,
4939 ITypeLibComp_fnRelease,
4940
4941 ITypeLibComp_fnBind,
4942 ITypeLibComp_fnBindType
4943 };
4944
4945 /*================== ITypeInfo(2) Methods ===================================*/
4946 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
4947 {
4948 ITypeInfoImpl *pTypeInfoImpl;
4949
4950 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
4951 if (pTypeInfoImpl)
4952 {
4953 pTypeInfoImpl->lpVtbl = &tinfvt;
4954 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4955 pTypeInfoImpl->ref = 0;
4956 pTypeInfoImpl->hreftype = -1;
4957 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4958 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4959 }
4960 TRACE("(%p)\n", pTypeInfoImpl);
4961 return pTypeInfoImpl;
4962 }
4963
4964 /* ITypeInfo::QueryInterface
4965 */
4966 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4967 ITypeInfo2 *iface,
4968 REFIID riid,
4969 VOID **ppvObject)
4970 {
4971 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4972
4973 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4974
4975 *ppvObject=NULL;
4976 if(IsEqualIID(riid, &IID_IUnknown) ||
4977 IsEqualIID(riid,&IID_ITypeInfo)||
4978 IsEqualIID(riid,&IID_ITypeInfo2))
4979 *ppvObject = This;
4980
4981 if(*ppvObject){
4982 ITypeInfo_AddRef(iface);
4983 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4984 return S_OK;
4985 }
4986 TRACE("-- Interface: E_NOINTERFACE\n");
4987 return E_NOINTERFACE;
4988 }
4989
4990 /* ITypeInfo::AddRef
4991 */
4992 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4993 {
4994 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4995 ULONG ref = InterlockedIncrement(&This->ref);
4996
4997 TRACE("(%p)->ref is %u\n",This, ref);
4998
4999 if (ref == 1 /* incremented from 0 */)
5000 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5001
5002 return ref;
5003 }
5004
5005 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5006 {
5007 TLBFuncDesc *pFInfo, *pFInfoNext;
5008 TLBVarDesc *pVInfo, *pVInfoNext;
5009 TLBImplType *pImpl, *pImplNext;
5010
5011 TRACE("destroying ITypeInfo(%p)\n",This);
5012
5013 SysFreeString(This->Name);
5014 This->Name = NULL;
5015
5016 SysFreeString(This->DocString);
5017 This->DocString = NULL;
5018
5019 SysFreeString(This->DllName);
5020 This->DllName = NULL;
5021
5022 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
5023 {
5024 INT i;
5025 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
5026 {
5027 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
5028 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5029 {
5030 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5031 heap_free(elemdesc->u.paramdesc.pparamdescex);
5032 }
5033 SysFreeString(pFInfo->pParamDesc[i].Name);
5034 }
5035 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5036 heap_free(pFInfo->pParamDesc);
5037 TLB_FreeCustData(pFInfo->pCustData);
5038 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5039 SysFreeString(pFInfo->Entry);
5040 SysFreeString(pFInfo->HelpString);
5041 SysFreeString(pFInfo->Name);
5042
5043 pFInfoNext = pFInfo->next;
5044 heap_free(pFInfo);
5045 }
5046 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5047 {
5048 if (pVInfo->vardesc.varkind == VAR_CONST)
5049 {
5050 VariantClear(pVInfo->vardesc.u.lpvarValue);
5051 heap_free(pVInfo->vardesc.u.lpvarValue);
5052 }
5053 TLB_FreeCustData(pVInfo->pCustData);
5054 SysFreeString(pVInfo->Name);
5055 pVInfoNext = pVInfo->next;
5056 heap_free(pVInfo);
5057 }
5058 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5059 {
5060 TLB_FreeCustData(pImpl->pCustData);
5061 pImplNext = pImpl->next;
5062 heap_free(pImpl);
5063 }
5064 TLB_FreeCustData(This->pCustData);
5065
5066 heap_free(This);
5067 }
5068
5069 /* ITypeInfo::Release
5070 */
5071 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5072 {
5073 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5074 ULONG ref = InterlockedDecrement(&This->ref);
5075
5076 TRACE("(%p)->(%u)\n",This, ref);
5077
5078 if (!ref)
5079 {
5080 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5081 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5082 if (not_attached_to_typelib)
5083 heap_free(This);
5084 /* otherwise This will be freed when typelib is freed */
5085 }
5086
5087 return ref;
5088 }
5089
5090 /* ITypeInfo::GetTypeAttr
5091 *
5092 * Retrieves a TYPEATTR structure that contains the attributes of the type
5093 * description.
5094 *
5095 */
5096 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5097 LPTYPEATTR *ppTypeAttr)
5098 {
5099 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5100 SIZE_T size;
5101
5102 TRACE("(%p)\n",This);
5103
5104 size = sizeof(**ppTypeAttr);
5105 if (This->TypeAttr.typekind == TKIND_ALIAS)
5106 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5107
5108 *ppTypeAttr = heap_alloc(size);
5109 if (!*ppTypeAttr)
5110 return E_OUTOFMEMORY;
5111
5112 **ppTypeAttr = This->TypeAttr;
5113
5114 if (This->TypeAttr.typekind == TKIND_ALIAS)
5115 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5116 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5117
5118 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5119 /* This should include all the inherited funcs */
5120 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5121 /* This is always the size of IDispatch's vtbl */
5122 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5123 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5124 }
5125 return S_OK;
5126 }
5127
5128 /* ITypeInfo::GetTypeComp
5129 *
5130 * Retrieves the ITypeComp interface for the type description, which enables a
5131 * client compiler to bind to the type description's members.
5132 *
5133 */
5134 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5135 ITypeComp * *ppTComp)
5136 {
5137 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5138
5139 TRACE("(%p)->(%p)\n", This, ppTComp);
5140
5141 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5142 ITypeComp_AddRef(*ppTComp);
5143 return S_OK;
5144 }
5145
5146 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5147 {
5148 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5149 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5150 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5151 return size;
5152 }
5153
5154 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5155 {
5156 *dest = *src;
5157 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5158 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5159 {
5160 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5161 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5162 *buffer += sizeof(PARAMDESCEX);
5163 *pparamdescex_dest = *pparamdescex_src;
5164 VariantInit(&pparamdescex_dest->varDefaultValue);
5165 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5166 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5167 }
5168 else
5169 dest->u.paramdesc.pparamdescex = NULL;
5170 return S_OK;
5171 }
5172
5173 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5174 {
5175 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5176 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5177 }
5178
5179 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5180 {
5181 FUNCDESC *dest;
5182 char *buffer;
5183 SIZE_T size = sizeof(*src);
5184 SHORT i;
5185 HRESULT hr;
5186
5187 size += sizeof(*src->lprgscode) * src->cScodes;
5188 size += TLB_SizeElemDesc(&src->elemdescFunc);
5189 for (i = 0; i < src->cParams; i++)
5190 {
5191 size += sizeof(ELEMDESC);
5192 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5193 }
5194
5195 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5196 if (!dest) return E_OUTOFMEMORY;
5197
5198 *dest = *src;
5199 if (dispinterface) /* overwrite funckind */
5200 dest->funckind = FUNC_DISPATCH;
5201 buffer = (char *)(dest + 1);
5202
5203 dest->lprgscode = (SCODE *)buffer;
5204 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5205 buffer += sizeof(*src->lprgscode) * src->cScodes;
5206
5207 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5208 if (FAILED(hr))
5209 {
5210 SysFreeString((BSTR)dest);
5211 return hr;
5212 }
5213
5214 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5215 buffer += sizeof(ELEMDESC) * src->cParams;
5216 for (i = 0; i < src->cParams; i++)
5217 {
5218 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5219 if (FAILED(hr))
5220 break;
5221 }
5222 if (FAILED(hr))
5223 {
5224 /* undo the above actions */
5225 for (i = i - 1; i >= 0; i--)
5226 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5227 TLB_FreeElemDesc(&dest->elemdescFunc);
5228 SysFreeString((BSTR)dest);
5229 return hr;
5230 }
5231
5232 /* special treatment for dispinterfaces: this makes functions appear
5233 * to return their [retval] value when it is really returning an
5234 * HRESULT */
5235 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5236 {
5237 if (dest->cParams &&
5238 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5239 {
5240 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5241 if (elemdesc->tdesc.vt != VT_PTR)
5242 {
5243 ERR("elemdesc should have started with VT_PTR instead of:\n");
5244 if (ERR_ON(ole))
5245 dump_ELEMDESC(elemdesc);
5246 return E_UNEXPECTED;
5247 }
5248
5249 /* copy last parameter to the return value. we are using a flat
5250 * buffer so there is no danger of leaking memory in
5251 * elemdescFunc */
5252 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5253
5254 /* remove the last parameter */
5255 dest->cParams--;
5256 }
5257 else
5258 /* otherwise this function is made to appear to have no return
5259 * value */
5260 dest->elemdescFunc.tdesc.vt = VT_VOID;
5261
5262 }
5263
5264 *dest_ptr = dest;
5265 return S_OK;
5266 }
5267
5268 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5269 {
5270 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5271 const TLBFuncDesc *pFDesc;
5272 UINT i;
5273
5274 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5275 ;
5276
5277 if (pFDesc)
5278 {
5279 *ppFuncDesc = &pFDesc->funcdesc;
5280 return S_OK;
5281 }
5282
5283 return TYPE_E_ELEMENTNOTFOUND;
5284 }
5285
5286 /* internal function to make the inherited interfaces' methods appear
5287 * part of the interface */
5288 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5289 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5290 {
5291 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5292 HRESULT hr;
5293 UINT implemented_funcs = 0;
5294
5295 if (funcs)
5296 *funcs = 0;
5297 else
5298 *hrefoffset = DISPATCH_HREF_OFFSET;
5299
5300 if(This->impltypelist)
5301 {
5302 ITypeInfo *pSubTypeInfo;
5303 UINT sub_funcs;
5304
5305 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5306 if (FAILED(hr))
5307 return hr;
5308
5309 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5310 index,
5311 ppFuncDesc,
5312 &sub_funcs, hrefoffset);
5313 implemented_funcs += sub_funcs;
5314 ITypeInfo_Release(pSubTypeInfo);
5315 if (SUCCEEDED(hr))
5316 return hr;
5317 *hrefoffset += DISPATCH_HREF_OFFSET;
5318 }
5319
5320 if (funcs)
5321 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5322 else
5323 *hrefoffset = 0;
5324
5325 if (index < implemented_funcs)
5326 return E_INVALIDARG;
5327 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5328 ppFuncDesc);
5329 }
5330
5331 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5332 {
5333 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5334 while (TRUE)
5335 {
5336 switch (pTypeDesc->vt)
5337 {
5338 case VT_USERDEFINED:
5339 pTypeDesc->u.hreftype += hrefoffset;
5340 return;
5341 case VT_PTR:
5342 case VT_SAFEARRAY:
5343 pTypeDesc = pTypeDesc->u.lptdesc;
5344 break;
5345 case VT_CARRAY:
5346 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5347 break;
5348 default:
5349 return;
5350 }
5351 }
5352 }
5353
5354 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5355 {
5356 SHORT i;
5357 for (i = 0; i < pFuncDesc->cParams; i++)
5358 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5359 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5360 }
5361
5362 /* ITypeInfo::GetFuncDesc
5363 *
5364 * Retrieves the FUNCDESC structure that contains information about a
5365 * specified function.
5366 *
5367 */
5368 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5369 LPFUNCDESC *ppFuncDesc)
5370 {
5371 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5372 const FUNCDESC *internal_funcdesc;
5373 HRESULT hr;
5374 UINT hrefoffset = 0;
5375
5376 TRACE("(%p) index %d\n", This, index);
5377
5378 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5379 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5380 &internal_funcdesc, NULL,
5381 &hrefoffset);
5382 else
5383 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5384 &internal_funcdesc);
5385 if (FAILED(hr))
5386 {
5387 WARN("description for function %d not found\n", index);
5388 return hr;
5389 }
5390
5391 hr = TLB_AllocAndInitFuncDesc(
5392 internal_funcdesc,
5393 ppFuncDesc,
5394 This->TypeAttr.typekind == TKIND_DISPATCH);
5395
5396 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5397 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5398
5399 TRACE("-- 0x%08x\n", hr);
5400 return hr;
5401 }
5402
5403 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5404 {
5405 VARDESC *dest;
5406 char *buffer;
5407 SIZE_T size = sizeof(*src);
5408 HRESULT hr;
5409
5410 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5411 if (src->varkind == VAR_CONST)
5412 size += sizeof(VARIANT);
5413 size += TLB_SizeElemDesc(&src->elemdescVar);
5414
5415 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5416 if (!dest) return E_OUTOFMEMORY;
5417
5418 *dest = *src;
5419 buffer = (char *)(dest + 1);
5420 if (src->lpstrSchema)
5421 {
5422 int len;
5423 dest->lpstrSchema = (LPOLESTR)buffer;
5424 len = strlenW(src->lpstrSchema);
5425 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5426 buffer += (len + 1) * sizeof(WCHAR);
5427 }
5428
5429 if (src->varkind == VAR_CONST)
5430 {
5431 HRESULT hr;
5432
5433 dest->u.lpvarValue = (VARIANT *)buffer;
5434 *dest->u.lpvarValue = *src->u.lpvarValue;
5435 buffer += sizeof(VARIANT);
5436 VariantInit(dest->u.lpvarValue);
5437 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5438 if (FAILED(hr))
5439 {
5440 SysFreeString((BSTR)dest);
5441 return hr;
5442 }
5443 }
5444 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5445 if (FAILED(hr))
5446 {
5447 if (src->varkind == VAR_CONST)
5448 VariantClear(dest->u.lpvarValue);
5449 SysFreeString((BSTR)dest);
5450 return hr;
5451 }
5452 *dest_ptr = dest;
5453 return S_OK;
5454 }
5455
5456 /* ITypeInfo::GetVarDesc
5457 *
5458 * Retrieves a VARDESC structure that describes the specified variable.
5459 *
5460 */
5461 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5462 LPVARDESC *ppVarDesc)
5463 {
5464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5465 UINT i;
5466 const TLBVarDesc *pVDesc;
5467
5468 TRACE("(%p) index %d\n", This, index);
5469
5470 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5471 ;
5472
5473 if (pVDesc)
5474 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5475
5476 return E_INVALIDARG;
5477 }
5478
5479 /* ITypeInfo_GetNames
5480 *
5481 * Retrieves the variable with the specified member ID (or the name of the
5482 * property or method and its parameters) that correspond to the specified
5483 * function ID.
5484 */
5485 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5486 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5487 {
5488 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5489 const TLBFuncDesc *pFDesc;
5490 const TLBVarDesc *pVDesc;
5491 int i;
5492 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5493 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5494 if(pFDesc)
5495 {
5496 /* function found, now return function and parameter names */
5497 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5498 {
5499 if(!i)
5500 *rgBstrNames=SysAllocString(pFDesc->Name);
5501 else
5502 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5503 }
5504 *pcNames=i;
5505 }
5506 else
5507 {
5508 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5509 if(pVDesc)
5510 {
5511 *rgBstrNames=SysAllocString(pVDesc->Name);
5512 *pcNames=1;
5513 }
5514 else
5515 {
5516 if(This->impltypelist &&
5517 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5518 /* recursive search */
5519 ITypeInfo *pTInfo;
5520 HRESULT result;
5521 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5522 &pTInfo);
5523 if(SUCCEEDED(result))
5524 {
5525 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5526 ITypeInfo_Release(pTInfo);
5527 return result;
5528 }
5529 WARN("Could not search inherited interface!\n");
5530 }
5531 else
5532 {
5533 WARN("no names found\n");
5534 }
5535 *pcNames=0;
5536 return TYPE_E_ELEMENTNOTFOUND;
5537 }
5538 }
5539 return S_OK;
5540 }
5541
5542
5543 /* ITypeInfo::GetRefTypeOfImplType
5544 *
5545 * If a type description describes a COM class, it retrieves the type
5546 * description of the implemented interface types. For an interface,
5547 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5548 * if any exist.
5549 *
5550 */
5551 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5552 ITypeInfo2 *iface,
5553 UINT index,
5554 HREFTYPE *pRefType)
5555 {
5556 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5557 UINT i;
5558 HRESULT hr = S_OK;
5559 const TLBImplType *pImpl = This->impltypelist;
5560
5561 TRACE("(%p) index %d\n", This, index);
5562 if (TRACE_ON(ole)) dump_TypeInfo(This);
5563
5564 if(index==(UINT)-1)
5565 {
5566 /* only valid on dual interfaces;
5567 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5568 */
5569 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5570
5571 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5572 {
5573 *pRefType = -1;
5574 }
5575 else
5576 {
5577 hr = TYPE_E_ELEMENTNOTFOUND;
5578 }
5579 }
5580 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5581 {
5582 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5583 *pRefType = This->pTypeLib->dispatch_href;
5584 }
5585 else
5586 {
5587 /* get element n from linked list */
5588 for(i=0; pImpl && i<index; i++)
5589 {
5590 pImpl = pImpl->next;
5591 }
5592
5593 if (pImpl)
5594 *pRefType = pImpl->hRef;
5595 else
5596 hr = TYPE_E_ELEMENTNOTFOUND;
5597 }
5598
5599 if(TRACE_ON(ole))
5600 {
5601 if(SUCCEEDED(hr))
5602 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5603 else
5604 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5605 }
5606
5607 return hr;
5608 }
5609
5610 /* ITypeInfo::GetImplTypeFlags
5611 *
5612 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5613 * or base interface in a type description.
5614 */
5615 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5616 UINT index, INT *pImplTypeFlags)
5617 {
5618 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5619 UINT i;
5620 TLBImplType *pImpl;
5621
5622 TRACE("(%p) index %d\n", This, index);
5623 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5624 i++, pImpl=pImpl->next)
5625 ;
5626 if(i==index && pImpl){
5627 *pImplTypeFlags=pImpl->implflags;
5628 return S_OK;
5629 }
5630 *pImplTypeFlags=0;
5631
5632 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5633 return S_OK;
5634
5635 WARN("ImplType %d not found\n", index);
5636 return TYPE_E_ELEMENTNOTFOUND;
5637 }
5638
5639 /* GetIDsOfNames
5640 * Maps between member names and member IDs, and parameter names and
5641 * parameter IDs.
5642 */
5643 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5644 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5645 {
5646 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5647 const TLBFuncDesc *pFDesc;
5648 const TLBVarDesc *pVDesc;
5649 HRESULT ret=S_OK;
5650 UINT i;
5651
5652 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5653 cNames);
5654
5655 /* init out parameters in case of failure */
5656 for (i = 0; i < cNames; i++)
5657 pMemId[i] = MEMBERID_NIL;
5658
5659 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5660 int j;
5661 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5662 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5663 for(i=1; i < cNames; i++){
5664 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5665 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5666 break;
5667 if( j<pFDesc->funcdesc.cParams)
5668 pMemId[i]=j;
5669 else
5670 ret=DISP_E_UNKNOWNNAME;
5671 };
5672 TRACE("-- 0x%08x\n", ret);
5673 return ret;
5674 }
5675 }
5676 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5677 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5678 if(cNames) *pMemId=pVDesc->vardesc.memid;
5679 return ret;
5680 }
5681 }
5682 /* not found, see if it can be found in an inherited interface */
5683 if(This->impltypelist) {
5684 /* recursive search */
5685 ITypeInfo *pTInfo;
5686 ret=ITypeInfo_GetRefTypeInfo(iface,
5687 This->impltypelist->hRef, &pTInfo);
5688 if(SUCCEEDED(ret)){
5689 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5690 ITypeInfo_Release(pTInfo);
5691 return ret;
5692 }
5693 WARN("Could not search inherited interface!\n");
5694 } else
5695 WARN("no names found\n");
5696 return DISP_E_UNKNOWNNAME;
5697 }
5698
5699
5700 #ifdef __i386__
5701
5702 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5703 __ASM_GLOBAL_FUNC( call_method,
5704 "pushl %ebp\n\t"
5705 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5706 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5707 "movl %esp,%ebp\n\t"
5708 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5709 "pushl %esi\n\t"
5710 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5711 "pushl %edi\n\t"
5712 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5713 "movl 12(%ebp),%edx\n\t"
5714 "movl %esp,%edi\n\t"
5715 "shll $2,%edx\n\t"
5716 "jz 1f\n\t"
5717 "subl %edx,%edi\n\t"
5718 "andl $~15,%edi\n\t"
5719 "movl %edi,%esp\n\t"
5720 "movl 12(%ebp),%ecx\n\t"
5721 "movl 16(%ebp),%esi\n\t"
5722 "cld\n\t"
5723 "rep; movsl\n"
5724 "1:\tcall *8(%ebp)\n\t"
5725 "subl %esp,%edi\n\t"
5726 "movl 20(%ebp),%ecx\n\t"
5727 "movl %edi,(%ecx)\n\t"
5728 "leal -8(%ebp),%esp\n\t"
5729 "popl %edi\n\t"
5730 __ASM_CFI(".cfi_same_value %edi\n\t")
5731 "popl %esi\n\t"
5732 __ASM_CFI(".cfi_same_value %esi\n\t")
5733 "popl %ebp\n\t"
5734 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5735 __ASM_CFI(".cfi_same_value %ebp\n\t")
5736 "ret" )
5737
5738 /* same function but returning floating point */
5739 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5740
5741 /* ITypeInfo::Invoke
5742 *
5743 * Invokes a method, or accesses a property of an object, that implements the
5744 * interface described by the type description.
5745 */
5746 DWORD
5747 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5748 DWORD res;
5749 int stack_offset;
5750
5751 if (TRACE_ON(ole)) {
5752 int i;
5753 TRACE("Calling %p(",func);
5754 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5755 if (nrargs > 30) TRACE("...");
5756 TRACE(")\n");
5757 }
5758
5759 switch (callconv) {
5760 case CC_STDCALL:
5761 case CC_CDECL:
5762 res = call_method( func, nrargs, args, &stack_offset );
5763 break;
5764 default:
5765 FIXME("unsupported calling convention %d\n",callconv);
5766 res = -1;
5767 break;
5768 }
5769 TRACE("returns %08x\n",res);
5770 return res;
5771 }
5772
5773 #elif defined(__x86_64__)
5774
5775 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5776 __ASM_GLOBAL_FUNC( call_method,
5777 "pushq %rbp\n\t"
5778 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5779 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5780 "movq %rsp,%rbp\n\t"
5781 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5782 "pushq %rsi\n\t"
5783 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5784 "pushq %rdi\n\t"
5785 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5786 "movq %rcx,%rax\n\t"
5787 "movq $4,%rcx\n\t"
5788 "cmp %rcx,%rdx\n\t"
5789 "cmovgq %rdx,%rcx\n\t"
5790 "leaq 0(,%rcx,8),%rdx\n\t"
5791 "subq %rdx,%rsp\n\t"
5792 "andq $~15,%rsp\n\t"
5793 "movq %rsp,%rdi\n\t"
5794 "movq %r8,%rsi\n\t"
5795 "rep; movsq\n\t"
5796 "movq 0(%rsp),%rcx\n\t"
5797 "movq 8(%rsp),%rdx\n\t"
5798 "movq 16(%rsp),%r8\n\t"
5799 "movq 24(%rsp),%r9\n\t"
5800 "movq %rcx,%xmm0\n\t"
5801 "movq %rdx,%xmm1\n\t"
5802 "movq %r8,%xmm2\n\t"
5803 "movq %r9,%xmm3\n\t"
5804 "callq *%rax\n\t"
5805 "leaq -16(%rbp),%rsp\n\t"
5806 "popq %rdi\n\t"
5807 __ASM_CFI(".cfi_same_value %rdi\n\t")
5808 "popq %rsi\n\t"
5809 __ASM_CFI(".cfi_same_value %rsi\n\t")
5810 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5811 "popq %rbp\n\t"
5812 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5813 __ASM_CFI(".cfi_same_value %rbp\n\t")
5814 "ret")
5815
5816 /* same function but returning floating point */
5817 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5818
5819 #endif /* __x86_64__ */
5820
5821 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5822 {
5823 HRESULT hr = S_OK;
5824 ITypeInfo *tinfo2 = NULL;
5825 TYPEATTR *tattr = NULL;
5826
5827 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5828 if (hr)
5829 {
5830 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5831 "hr = 0x%08x\n",
5832 tdesc->u.hreftype, hr);
5833 return hr;
5834 }
5835 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5836 if (hr)
5837 {
5838 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5839 ITypeInfo_Release(tinfo2);
5840 return hr;
5841 }
5842
5843 switch (tattr->typekind)
5844 {
5845 case TKIND_ENUM:
5846 *vt |= VT_I4;
5847 break;
5848
5849 case TKIND_ALIAS:
5850 tdesc = &tattr->tdescAlias;
5851 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5852 break;
5853
5854 case TKIND_INTERFACE:
5855 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5856 *vt |= VT_DISPATCH;
5857 else
5858 *vt |= VT_UNKNOWN;
5859 break;
5860
5861 case TKIND_DISPATCH:
5862 *vt |= VT_DISPATCH;
5863 break;
5864
5865 case TKIND_COCLASS:
5866 *vt |= VT_DISPATCH;
5867 break;
5868
5869 case TKIND_RECORD:
5870 FIXME("TKIND_RECORD unhandled.\n");
5871 hr = E_NOTIMPL;
5872 break;
5873
5874 case TKIND_UNION:
5875 FIXME("TKIND_UNION unhandled.\n");
5876 hr = E_NOTIMPL;
5877 break;
5878
5879 default:
5880 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5881 hr = E_NOTIMPL;
5882 break;
5883 }
5884 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5885 ITypeInfo_Release(tinfo2);
5886 return hr;
5887 }
5888
5889 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5890 {
5891 HRESULT hr = S_OK;
5892
5893 /* enforce only one level of pointer indirection */
5894 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5895 {
5896 tdesc = tdesc->u.lptdesc;
5897
5898 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5899 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5900 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5901 if ((tdesc->vt == VT_USERDEFINED) ||
5902 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5903 {
5904 VARTYPE vt_userdefined = 0;
5905 const TYPEDESC *tdesc_userdefined = tdesc;
5906 if (tdesc->vt == VT_PTR)
5907 {
5908 vt_userdefined = VT_BYREF;
5909 tdesc_userdefined = tdesc->u.lptdesc;
5910 }
5911 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5912 if ((hr == S_OK) &&
5913 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5914 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5915 {
5916 *vt |= vt_userdefined;
5917 return S_OK;
5918 }
5919 }
5920 *vt = VT_BYREF;
5921 }
5922
5923 switch (tdesc->vt)
5924 {
5925 case VT_HRESULT:
5926 *vt |= VT_ERROR;
5927 break;
5928 case VT_USERDEFINED:
5929 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5930 break;
5931 case VT_VOID:
5932 case VT_CARRAY:
5933 case VT_PTR:
5934 case VT_LPSTR:
5935 case VT_LPWSTR:
5936 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5937 hr = DISP_E_BADVARTYPE;
5938 break;
5939 case VT_SAFEARRAY:
5940 *vt |= VT_ARRAY;
5941 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5942 break;
5943 case VT_INT:
5944 *vt |= VT_I4;
5945 break;
5946 case VT_UINT:
5947 *vt |= VT_UI4;
5948 break;
5949 default:
5950 *vt |= tdesc->vt;
5951 break;
5952 }
5953 return hr;
5954 }
5955
5956 /***********************************************************************
5957 * DispCallFunc (OLEAUT32.@)
5958 *
5959 * Invokes a function of the specified calling convention, passing the
5960 * specified arguments and returns the result.
5961 *
5962 * PARAMS
5963 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5964 * oVft [I] The offset in the vtable. See notes.
5965 * cc [I] Calling convention of the function to call.
5966 * vtReturn [I] The return type of the function.
5967 * cActuals [I] Number of parameters.
5968 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5969 * prgpvarg [I] The arguments to pass.
5970 * pvargResult [O] The return value of the function. Can be NULL.
5971 *
5972 * RETURNS
5973 * Success: S_OK.
5974 * Failure: HRESULT code.
5975 *
5976 * NOTES
5977 * The HRESULT return value of this function is not affected by the return
5978 * value of the user supplied function, which is returned in pvargResult.
5979 *
5980 * If pvInstance is NULL then a non-object function is to be called and oVft
5981 * is the address of the function to call.
5982 *
5983 * The cc parameter can be one of the following values:
5984 *|CC_FASTCALL
5985 *|CC_CDECL
5986 *|CC_PASCAL
5987 *|CC_STDCALL
5988 *|CC_FPFASTCALL
5989 *|CC_SYSCALL
5990 *|CC_MPWCDECL
5991 *|CC_MPWPASCAL
5992 *
5993 */
5994 HRESULT WINAPI
5995 DispCallFunc(
5996 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5997 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5998 {
5999 #ifdef __i386__
6000 int argspos, stack_offset;
6001 void *func;
6002 UINT i;
6003 DWORD *args;
6004
6005 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6006 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6007 pvargResult, V_VT(pvargResult));
6008
6009 if (cc != CC_STDCALL && cc != CC_CDECL)
6010 {
6011 FIXME("unsupported calling convention %d\n",cc);
6012 return E_INVALIDARG;
6013 }
6014
6015 /* maximum size for an argument is sizeof(VARIANT) */
6016 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6017
6018 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6019 argspos = 1;
6020 if (pvInstance)
6021 {
6022 const FARPROC *vtable = *(FARPROC **)pvInstance;
6023 func = vtable[oVft/sizeof(void *)];
6024 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6025 }
6026 else func = (void *)oVft;
6027
6028 for (i = 0; i < cActuals; i++)
6029 {
6030 VARIANT *arg = prgpvarg[i];
6031
6032 switch (prgvt[i])
6033 {
6034 case VT_EMPTY:
6035 break;
6036 case VT_I8:
6037 case VT_UI8:
6038 case VT_R8:
6039 case VT_DATE:
6040 case VT_CY:
6041 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6042 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6043 break;
6044 case VT_DECIMAL:
6045 case VT_VARIANT:
6046 memcpy( &args[argspos], arg, sizeof(*arg) );
6047 argspos += sizeof(*arg) / sizeof(DWORD);
6048 break;
6049 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6050 args[argspos++] = V_BOOL(arg);
6051 break;
6052 default:
6053 args[argspos++] = V_UI4(arg);
6054 break;
6055 }
6056 TRACE("arg %u: type %d\n",i,prgvt[i]);
6057 dump_Variant(arg);
6058 }
6059
6060 switch (vtReturn)
6061 {
6062 case VT_EMPTY:
6063 call_method( func, argspos - 1, args + 1, &stack_offset );
6064 break;
6065 case VT_R4:
6066 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6067 break;
6068 case VT_R8:
6069 case VT_DATE:
6070 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6071 break;
6072 case VT_DECIMAL:
6073 case VT_VARIANT:
6074 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6075 call_method( func, argspos, args, &stack_offset );
6076 break;
6077 case VT_I8:
6078 case VT_UI8:
6079 case VT_CY:
6080 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6081 break;
6082 default:
6083 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6084 break;
6085 }
6086 heap_free( args );
6087 if (stack_offset && cc == CC_STDCALL)
6088 {
6089 WARN( "stack pointer off by %d\n", stack_offset );
6090 return DISP_E_BADCALLEE;
6091 }
6092 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6093 TRACE("retval: "); dump_Variant(pvargResult);
6094 return S_OK;
6095
6096 #elif defined(__x86_64__)
6097 int argspos;
6098 UINT i;
6099 DWORD_PTR *args;
6100 void *func;
6101
6102 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6103 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6104 pvargResult, V_VT(pvargResult));
6105
6106 if (cc != CC_STDCALL && cc != CC_CDECL)
6107 {
6108 FIXME("unsupported calling convention %d\n",cc);
6109 return E_INVALIDARG;
6110 }
6111
6112 /* maximum size for an argument is sizeof(DWORD_PTR) */
6113 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6114
6115 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6116 argspos = 1;
6117 if (pvInstance)
6118 {
6119 const FARPROC *vtable = *(FARPROC **)pvInstance;
6120 func = vtable[oVft/sizeof(void *)];
6121 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6122 }
6123 else func = (void *)oVft;
6124
6125 for (i = 0; i < cActuals; i++)
6126 {
6127 VARIANT *arg = prgpvarg[i];
6128
6129 switch (prgvt[i])
6130 {
6131 case VT_DECIMAL:
6132 case VT_VARIANT:
6133 args[argspos++] = (ULONG_PTR)arg;
6134 break;
6135 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6136 args[argspos++] = V_BOOL(arg);
6137 break;
6138 default:
6139 args[argspos++] = V_UI8(arg);
6140 break;
6141 }
6142 TRACE("arg %u: type %d\n",i,prgvt[i]);
6143 dump_Variant(arg);
6144 }
6145
6146 switch (vtReturn)
6147 {
6148 case VT_R4:
6149 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6150 break;
6151 case VT_R8:
6152 case VT_DATE:
6153 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6154 break;
6155 case VT_DECIMAL:
6156 case VT_VARIANT:
6157 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6158 call_method( func, argspos, args );
6159 break;
6160 default:
6161 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6162 break;
6163 }
6164 heap_free( args );
6165 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6166 TRACE("retval: "); dump_Variant(pvargResult);
6167 return S_OK;
6168
6169 #else
6170 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6171 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6172 return E_NOTIMPL;
6173 #endif
6174 }
6175
6176 #define INVBUF_ELEMENT_SIZE \
6177 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6178 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6179 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6180 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6181 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6182 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6183 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6184 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6185
6186 static HRESULT WINAPI ITypeInfo_fnInvoke(
6187 ITypeInfo2 *iface,
6188 VOID *pIUnk,
6189 MEMBERID memid,
6190 UINT16 wFlags,
6191 DISPPARAMS *pDispParams,
6192 VARIANT *pVarResult,
6193 EXCEPINFO *pExcepInfo,
6194 UINT *pArgErr)
6195 {
6196 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6197 int i;
6198 unsigned int var_index;
6199 TYPEKIND type_kind;
6200 HRESULT hres;
6201 const TLBFuncDesc *pFuncInfo;
6202
6203 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6204 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6205 );
6206
6207 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6208 return DISP_E_MEMBERNOTFOUND;
6209
6210 if (!pDispParams)
6211 {
6212 ERR("NULL pDispParams not allowed\n");
6213 return E_INVALIDARG;
6214 }
6215
6216 dump_DispParms(pDispParams);
6217
6218 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6219 {
6220 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6221 pDispParams->cNamedArgs, pDispParams->cArgs);
6222 return E_INVALIDARG;
6223 }
6224
6225 /* we do this instead of using GetFuncDesc since it will return a fake
6226 * FUNCDESC for dispinterfaces and we want the real function description */
6227 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6228 if ((memid == pFuncInfo->funcdesc.memid) &&
6229 (wFlags & pFuncInfo->funcdesc.invkind) &&
6230 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6231 break;
6232
6233 if (pFuncInfo) {
6234 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6235
6236 if (TRACE_ON(ole))
6237 {
6238 TRACE("invoking:\n");
6239 dump_TLBFuncDescOne(pFuncInfo);
6240 }
6241
6242 switch (func_desc->funckind) {
6243 case FUNC_PUREVIRTUAL:
6244 case FUNC_VIRTUAL: {
6245 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6246 VARIANT varresult;
6247 VARIANT retval; /* pointer for storing byref retvals in */
6248 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6249 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6250 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6251 UINT cNamedArgs = pDispParams->cNamedArgs;
6252 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6253 UINT vargs_converted=0;
6254
6255 hres = S_OK;
6256
6257 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6258 {
6259 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6260 {
6261 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6262 hres = DISP_E_PARAMNOTFOUND;
6263 goto func_fail;
6264 }
6265 }
6266
6267 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6268 {
6269 ERR("functions with the vararg attribute do not support named arguments\n");
6270 hres = DISP_E_NONAMEDARGS;
6271 goto func_fail;
6272 }
6273
6274 for (i = 0; i < func_desc->cParams; i++)
6275 {
6276 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6277 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6278 if (FAILED(hres))
6279 goto func_fail;
6280 }
6281
6282 TRACE("changing args\n");
6283 for (i = 0; i < func_desc->cParams; i++)
6284 {
6285 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6286 VARIANTARG *src_arg;
6287
6288 if (wParamFlags & PARAMFLAG_FLCID)
6289 {
6290 VARIANTARG *arg;
6291 arg = prgpvarg[i] = &rgvarg[i];
6292 V_VT(arg) = VT_I4;
6293 V_I4(arg) = This->pTypeLib->lcid;
6294 continue;
6295 }
6296
6297 src_arg = NULL;
6298
6299 if (cNamedArgs)
6300 {
6301 USHORT j;
6302 for (j = 0; j < cNamedArgs; j++)
6303 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6304 {
6305 src_arg = &pDispParams->rgvarg[j];
6306 break;
6307 }
6308 }
6309
6310 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6311 {
6312 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6313 vargs_converted++;
6314 }
6315
6316 if (wParamFlags & PARAMFLAG_FRETVAL)
6317 {
6318 /* under most conditions the caller is not allowed to
6319 * pass in a dispparam arg in the index of what would be
6320 * the retval parameter. however, there is an exception
6321 * where the extra parameter is used in an extra
6322 * IDispatch::Invoke below */
6323 if ((i < pDispParams->cArgs) &&
6324 ((func_desc->cParams != 1) || !pVarResult ||
6325 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6326 {
6327 hres = DISP_E_BADPARAMCOUNT;
6328 break;
6329 }
6330
6331 /* note: this check is placed so that if the caller passes
6332 * in a VARIANTARG for the retval we just ignore it, like
6333 * native does */
6334 if (i == func_desc->cParams - 1)
6335 {
6336 VARIANTARG *arg;
6337 arg = prgpvarg[i] = &rgvarg[i];
6338 memset(arg, 0, sizeof(*arg));
6339 V_VT(arg) = rgvt[i];
6340 memset(&retval, 0, sizeof(retval));
6341 V_BYREF(arg) = &retval;
6342 }
6343 else
6344 {
6345 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6346 hres = E_UNEXPECTED;
6347 break;
6348 }
6349 }
6350 else if (src_arg)
6351 {
6352 dump_Variant(src_arg);
6353
6354 if (rgvt[i] == VT_VARIANT)
6355 hres = VariantCopy(&rgvarg[i], src_arg);
6356 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6357 {
6358 if (rgvt[i] == V_VT(src_arg))
6359 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6360 else
6361 {
6362 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6363 if (wParamFlags & PARAMFLAG_FIN)
6364 hres = VariantCopy(&missing_arg[i], src_arg);
6365 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6366 }
6367 V_VT(&rgvarg[i]) = rgvt[i];
6368 }
6369 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6370 {
6371 SAFEARRAY *a;
6372 SAFEARRAYBOUND bound;
6373 VARIANT *v;
6374 LONG j;
6375 bound.lLbound = 0;
6376 bound.cElements = pDispParams->cArgs-i;
6377 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6378 {
6379 ERR("SafeArrayCreate failed\n");
6380 break;
6381 }
6382 hres = SafeArrayAccessData(a, (LPVOID)&v);
6383 if (hres != S_OK)
6384 {
6385 ERR("SafeArrayAccessData failed with %x\n", hres);
6386 break;
6387 }
6388 for (j = 0; j < bound.cElements; j++)
6389 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6390 hres = SafeArrayUnaccessData(a);
6391 if (hres != S_OK)
6392 {
6393 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6394 break;
6395 }
6396 V_ARRAY(&rgvarg[i]) = a;
6397 V_VT(&rgvarg[i]) = rgvt[i];
6398 }
6399 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6400 {
6401 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6402 if (wParamFlags & PARAMFLAG_FIN)
6403 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6404 else
6405 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6406 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6407 V_VT(&rgvarg[i]) = rgvt[i];
6408 }
6409 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6410 {
6411 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6412 V_VT(&rgvarg[i]) = rgvt[i];
6413 }
6414 else
6415 {
6416 /* FIXME: this doesn't work for VT_BYREF arguments if
6417 * they are not the same type as in the paramdesc */
6418 V_VT(&rgvarg[i]) = V_VT(src_arg);
6419 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6420 V_VT(&rgvarg[i]) = rgvt[i];
6421 }
6422
6423 if (FAILED(hres))
6424 {
6425 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6426 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6427 debugstr_VT(src_arg), debugstr_VF(src_arg));
6428 break;
6429 }
6430 prgpvarg[i] = &rgvarg[i];
6431 }
6432 else if (wParamFlags & PARAMFLAG_FOPT)
6433 {
6434 VARIANTARG *arg;
6435 arg = prgpvarg[i] = &rgvarg[i];
6436 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6437 {
6438 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6439 if (FAILED(hres))
6440 break;
6441 }
6442 else
6443 {
6444 VARIANTARG *missing_arg;
6445 /* if the function wants a pointer to a variant then
6446 * set that up, otherwise just pass the VT_ERROR in
6447 * the argument by value */
6448 if (rgvt[i] & VT_BYREF)
6449 {
6450 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6451 V_VT(arg) = VT_VARIANT | VT_BYREF;
6452 V_VARIANTREF(arg) = missing_arg;
6453 }
6454 else
6455 missing_arg = arg;
6456 V_VT(missing_arg) = VT_ERROR;
6457 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6458 }
6459 }
6460 else
6461 {
6462 hres = DISP_E_BADPARAMCOUNT;
6463 break;
6464 }
6465 }
6466 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6467
6468 /* VT_VOID is a special case for return types, so it is not
6469 * handled in the general function */
6470 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6471 V_VT(&varresult) = VT_EMPTY;
6472 else
6473 {
6474 V_VT(&varresult) = 0;
6475 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6476 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6477 }
6478
6479 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6480 V_VT(&varresult), func_desc->cParams, rgvt,
6481 prgpvarg, &varresult);
6482
6483 vargs_converted = 0;
6484
6485 for (i = 0; i < func_desc->cParams; i++)
6486 {
6487 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6488 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6489
6490 if (wParamFlags & PARAMFLAG_FLCID)
6491 continue;
6492 else if (wParamFlags & PARAMFLAG_FRETVAL)
6493 {
6494 if (TRACE_ON(ole))
6495 {
6496 TRACE("[retval] value: ");
6497 dump_Variant(prgpvarg[i]);
6498 }
6499
6500 if (pVarResult)
6501 {
6502 VariantInit(pVarResult);
6503 /* deref return value */
6504 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6505 }
6506
6507 VARIANT_ClearInd(prgpvarg[i]);
6508 }
6509 else if (vargs_converted < pDispParams->cArgs)
6510 {
6511 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6512 if (wParamFlags & PARAMFLAG_FOUT)
6513 {
6514 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6515 {
6516 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6517
6518 if (FAILED(hres))
6519 {
6520 ERR("failed to convert param %d to vt %d\n", i,
6521 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6522 break;
6523 }
6524 }
6525 }
6526 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6527 func_desc->cParamsOpt < 0 &&
6528 i == func_desc->cParams-1)
6529 {
6530 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6531 LONG j, ubound;
6532 VARIANT *v;
6533 hres = SafeArrayGetUBound(a, 1, &ubound);
6534 if (hres != S_OK)
6535 {
6536 ERR("SafeArrayGetUBound failed with %x\n", hres);
6537 break;
6538 }
6539 hres = SafeArrayAccessData(a, (LPVOID)&v);
6540 if (hres != S_OK)
6541 {
6542 ERR("SafeArrayAccessData failed with %x\n", hres);
6543 break;
6544 }
6545 for (j = 0; j <= ubound; j++)
6546 VariantClear(&v[j]);
6547 hres = SafeArrayUnaccessData(a);
6548 if (hres != S_OK)
6549 {
6550 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6551 break;
6552 }
6553 }
6554 VariantClear(&rgvarg[i]);
6555 vargs_converted++;
6556 }
6557 else if (wParamFlags & PARAMFLAG_FOPT)
6558 {
6559 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6560 VariantClear(&rgvarg[i]);
6561 }
6562
6563 VariantClear(&missing_arg[i]);
6564 }
6565
6566 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6567 {
6568 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6569 hres = DISP_E_EXCEPTION;
6570 if (pExcepInfo)
6571 {
6572 IErrorInfo *pErrorInfo;
6573 pExcepInfo->scode = V_ERROR(&varresult);
6574 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6575 {
6576 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6577 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6578 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6579 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6580
6581 IErrorInfo_Release(pErrorInfo);
6582 }
6583 }
6584 }
6585 if (V_VT(&varresult) != VT_ERROR)
6586 {
6587 TRACE("varresult value: ");
6588 dump_Variant(&varresult);
6589
6590 if (pVarResult)
6591 {
6592 VariantClear(pVarResult);
6593 *pVarResult = varresult;
6594 }
6595 else
6596 VariantClear(&varresult);
6597 }
6598
6599 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6600 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6601 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6602 (pDispParams->cArgs != 0))
6603 {
6604 if (V_VT(pVarResult) == VT_DISPATCH)
6605 {
6606 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6607 /* Note: not VariantClear; we still need the dispatch
6608 * pointer to be valid */
6609 VariantInit(pVarResult);
6610 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6611 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6612 pDispParams, pVarResult, pExcepInfo, pArgErr);
6613 IDispatch_Release(pDispatch);
6614 }
6615 else
6616 {
6617 VariantClear(pVarResult);
6618 hres = DISP_E_NOTACOLLECTION;
6619 }
6620 }
6621
6622 func_fail:
6623 heap_free(buffer);
6624 break;
6625 }
6626 case FUNC_DISPATCH: {
6627 IDispatch *disp;
6628
6629 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6630 if (SUCCEEDED(hres)) {
6631 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6632 hres = IDispatch_Invoke(
6633 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6634 pVarResult,pExcepInfo,pArgErr
6635 );
6636 if (FAILED(hres))
6637 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6638 IDispatch_Release(disp);
6639 } else
6640 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6641 break;
6642 }
6643 default:
6644 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6645 hres = E_FAIL;
6646 break;
6647 }
6648
6649 TRACE("-- 0x%08x\n", hres);
6650 return hres;
6651
6652 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6653 VARDESC *var_desc;
6654
6655 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6656 if(FAILED(hres)) return hres;
6657
6658 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6659 dump_VARDESC(var_desc);
6660 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6661 return E_NOTIMPL;
6662 }
6663
6664 /* not found, look for it in inherited interfaces */
6665 ITypeInfo2_GetTypeKind(iface, &type_kind);
6666 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6667 if(This->impltypelist) {
6668 /* recursive search */
6669 ITypeInfo *pTInfo;
6670 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6671 if(SUCCEEDED(hres)){
6672 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6673 ITypeInfo_Release(pTInfo);
6674 return hres;
6675 }
6676 WARN("Could not search inherited interface!\n");
6677 }
6678 }
6679 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6680 return DISP_E_MEMBERNOTFOUND;
6681 }
6682
6683 /* ITypeInfo::GetDocumentation
6684 *
6685 * Retrieves the documentation string, the complete Help file name and path,
6686 * and the context ID for the Help topic for a specified type description.
6687 *
6688 * (Can be tested by the Visual Basic Editor in Word for instance.)
6689 */
6690 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6691 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6692 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6693 {
6694 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6695 const TLBFuncDesc *pFDesc;
6696 const TLBVarDesc *pVDesc;
6697 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6698 " HelpContext(%p) HelpFile(%p)\n",
6699 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6700 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6701 if(pBstrName)
6702 *pBstrName=SysAllocString(This->Name);
6703 if(pBstrDocString)
6704 *pBstrDocString=SysAllocString(This->DocString);
6705 if(pdwHelpContext)
6706 *pdwHelpContext=This->dwHelpContext;
6707 if(pBstrHelpFile)
6708 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6709 return S_OK;
6710 }else {/* for a member */
6711 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6712 if(pFDesc->funcdesc.memid==memid){
6713 if(pBstrName)
6714 *pBstrName = SysAllocString(pFDesc->Name);
6715 if(pBstrDocString)
6716 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6717 if(pdwHelpContext)
6718 *pdwHelpContext=pFDesc->helpcontext;
6719 return S_OK;
6720 }
6721 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6722 if(pVDesc->vardesc.memid==memid){
6723 if(pBstrName)
6724 *pBstrName = SysAllocString(pVDesc->Name);
6725 if(pBstrDocString)
6726 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6727 if(pdwHelpContext)
6728 *pdwHelpContext=pVDesc->HelpContext;
6729 return S_OK;
6730 }
6731 }
6732
6733 if(This->impltypelist &&
6734 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6735 /* recursive search */
6736 ITypeInfo *pTInfo;
6737 HRESULT result;
6738 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6739 &pTInfo);
6740 if(SUCCEEDED(result)) {
6741 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6742 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6743 ITypeInfo_Release(pTInfo);
6744 return result;
6745 }
6746 WARN("Could not search inherited interface!\n");
6747 }
6748
6749 WARN("member %d not found\n", memid);
6750 return TYPE_E_ELEMENTNOTFOUND;
6751 }
6752
6753 /* ITypeInfo::GetDllEntry
6754 *
6755 * Retrieves a description or specification of an entry point for a function
6756 * in a DLL.
6757 */
6758 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6759 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6760 WORD *pwOrdinal)
6761 {
6762 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6763 const TLBFuncDesc *pFDesc;
6764
6765 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6766
6767 if (pBstrDllName) *pBstrDllName = NULL;
6768 if (pBstrName) *pBstrName = NULL;
6769 if (pwOrdinal) *pwOrdinal = 0;
6770
6771 if (This->TypeAttr.typekind != TKIND_MODULE)
6772 return TYPE_E_BADMODULEKIND;
6773
6774 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6775 if(pFDesc->funcdesc.memid==memid){
6776 dump_TypeInfo(This);
6777 if (TRACE_ON(ole))
6778 dump_TLBFuncDescOne(pFDesc);
6779
6780 if (pBstrDllName)
6781 *pBstrDllName = SysAllocString(This->DllName);
6782
6783 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {