[OLEAUT32]
[reactos.git] / reactos / dll / win32 / oleaut32 / typelib.c
1 /*
2 * TYPELIB
3 *
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 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 ITypeLib_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[] = {'{','0','0','0','2','0','4','2','4','-',
530 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
531 '0','0','0','0','0','0','0','0','0','0','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 list entry;
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 list entry;
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 **typeinfos;
1002 struct list custdata_list;
1003 struct list implib_list;
1004 int ctTypeDesc; /* number of items in type desc array */
1005 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1006 library. Only used while reading MSFT
1007 typelibs */
1008 struct list ref_list; /* list of ref types in this typelib */
1009 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1010
1011
1012 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1013 struct list entry;
1014 WCHAR *path;
1015 INT index;
1016 } ITypeLibImpl;
1017
1018 static const ITypeLib2Vtbl tlbvt;
1019 static const ITypeCompVtbl tlbtcvt;
1020
1021 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1022 {
1023 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1024 }
1025
1026 /* ITypeLib methods */
1027 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1028 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1029
1030 /*======================= ITypeInfo implementation =======================*/
1031
1032 /* data for referenced types */
1033 typedef struct tagTLBRefType
1034 {
1035 INT index; /* Type index for internal ref or for external ref
1036 it the format is SLTG. -2 indicates to
1037 use guid */
1038
1039 GUID guid; /* guid of the referenced type */
1040 /* if index == TLB_REF_USE_GUID */
1041
1042 HREFTYPE reference; /* The href of this ref */
1043 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1044 TLB_REF_INTERNAL for internal refs
1045 TLB_REF_NOT_FOUND for broken refs */
1046
1047 struct list entry;
1048 } TLBRefType;
1049
1050 #define TLB_REF_USE_GUID -2
1051
1052 #define TLB_REF_INTERNAL (void*)-2
1053 #define TLB_REF_NOT_FOUND (void*)-1
1054
1055 /* internal Parameter data */
1056 typedef struct tagTLBParDesc
1057 {
1058 BSTR Name;
1059 struct list custdata_list;
1060 } TLBParDesc;
1061
1062 /* internal Function data */
1063 typedef struct tagTLBFuncDesc
1064 {
1065 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1066 BSTR Name; /* the name of this function */
1067 TLBParDesc *pParamDesc; /* array with param names and custom data */
1068 int helpcontext;
1069 int HelpStringContext;
1070 BSTR HelpString;
1071 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1072 struct list custdata_list;
1073 } TLBFuncDesc;
1074
1075 /* internal Variable data */
1076 typedef struct tagTLBVarDesc
1077 {
1078 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1079 BSTR Name; /* the name of this variable */
1080 int HelpContext;
1081 int HelpStringContext;
1082 BSTR HelpString;
1083 struct list custdata_list;
1084 } TLBVarDesc;
1085
1086 /* internal implemented interface data */
1087 typedef struct tagTLBImplType
1088 {
1089 HREFTYPE hRef; /* hRef of interface */
1090 int implflags; /* IMPLFLAG_*s */
1091 struct list custdata_list;
1092 } TLBImplType;
1093
1094 /* internal TypeInfo data */
1095 typedef struct tagITypeInfoImpl
1096 {
1097 const ITypeInfo2Vtbl *lpVtbl;
1098 const ITypeCompVtbl *lpVtblTypeComp;
1099 LONG ref;
1100 BOOL not_attached_to_typelib;
1101 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1102 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1103 int index; /* index in this typelib; */
1104 HREFTYPE hreftype; /* hreftype for app object binding */
1105 /* type libs seem to store the doc strings in ascii
1106 * so why should we do it in unicode?
1107 */
1108 BSTR Name;
1109 BSTR DocString;
1110 BSTR DllName;
1111 DWORD dwHelpContext;
1112 DWORD dwHelpStringContext;
1113
1114 /* functions */
1115 TLBFuncDesc *funcdescs;
1116
1117 /* variables */
1118 TLBVarDesc *vardescs;
1119
1120 /* Implemented Interfaces */
1121 TLBImplType *impltypes;
1122
1123 struct list custdata_list;
1124 } ITypeInfoImpl;
1125
1126 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1127 {
1128 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1129 }
1130
1131 static const ITypeInfo2Vtbl tinfvt;
1132 static const ITypeCompVtbl tcompvt;
1133
1134 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1135 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1136
1137 typedef struct tagTLBContext
1138 {
1139 unsigned int oStart; /* start of TLB in file */
1140 unsigned int pos; /* current pos */
1141 unsigned int length; /* total length */
1142 void *mapping; /* memory mapping */
1143 MSFT_SegDir * pTblDir;
1144 ITypeLibImpl* pLibInfo;
1145 } TLBContext;
1146
1147
1148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1149
1150 /*
1151 debug
1152 */
1153 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1154 if (pTD->vt & VT_RESERVED)
1155 szVarType += strlen(strcpy(szVarType, "reserved | "));
1156 if (pTD->vt & VT_BYREF)
1157 szVarType += strlen(strcpy(szVarType, "ref to "));
1158 if (pTD->vt & VT_ARRAY)
1159 szVarType += strlen(strcpy(szVarType, "array of "));
1160 if (pTD->vt & VT_VECTOR)
1161 szVarType += strlen(strcpy(szVarType, "vector of "));
1162 switch(pTD->vt & VT_TYPEMASK) {
1163 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1164 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1165 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1166 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1167 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1168 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1169 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1170 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1171 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1172 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1173 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1174 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1175 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1176 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1177 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1178 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1179 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1180 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1181 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1182 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1183 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1184 pTD->u.hreftype); break;
1185 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1186 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1187 case VT_PTR: sprintf(szVarType, "ptr to ");
1188 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1189 break;
1190 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1191 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1192 break;
1193 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1194 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1195 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1196 break;
1197
1198 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1199 }
1200 }
1201
1202 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1203 char buf[200];
1204 USHORT flags = edesc->u.paramdesc.wParamFlags;
1205 dump_TypeDesc(&edesc->tdesc,buf);
1206 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1207 MESSAGE("\t\tu.paramdesc.wParamFlags");
1208 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1209 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1210 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1211 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1212 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1213 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1214 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1215 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1216 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1217 }
1218 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1219 int i;
1220 MESSAGE("memid is %08x\n",funcdesc->memid);
1221 for (i=0;i<funcdesc->cParams;i++) {
1222 MESSAGE("Param %d:\n",i);
1223 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1224 }
1225 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1226 switch (funcdesc->funckind) {
1227 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1228 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1229 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1230 case FUNC_STATIC: MESSAGE("static");break;
1231 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1232 default: MESSAGE("unknown");break;
1233 }
1234 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1235 switch (funcdesc->invkind) {
1236 case INVOKE_FUNC: MESSAGE("func");break;
1237 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1238 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1239 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1240 }
1241 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1242 switch (funcdesc->callconv) {
1243 case CC_CDECL: MESSAGE("cdecl");break;
1244 case CC_PASCAL: MESSAGE("pascal");break;
1245 case CC_STDCALL: MESSAGE("stdcall");break;
1246 case CC_SYSCALL: MESSAGE("syscall");break;
1247 default:break;
1248 }
1249 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1250 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1251 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1252
1253 MESSAGE("\telemdescFunc (return value type):\n");
1254 dump_ELEMDESC(&funcdesc->elemdescFunc);
1255 }
1256
1257 static const char * const typekind_desc[] =
1258 {
1259 "TKIND_ENUM",
1260 "TKIND_RECORD",
1261 "TKIND_MODULE",
1262 "TKIND_INTERFACE",
1263 "TKIND_DISPATCH",
1264 "TKIND_COCLASS",
1265 "TKIND_ALIAS",
1266 "TKIND_UNION",
1267 "TKIND_MAX"
1268 };
1269
1270 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1271 {
1272 int i;
1273 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1274 for (i=0;i<pfd->funcdesc.cParams;i++)
1275 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1276
1277
1278 dump_FUNCDESC(&(pfd->funcdesc));
1279
1280 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1281 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1282 }
1283 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1284 {
1285 while (n)
1286 {
1287 dump_TLBFuncDescOne(pfd);
1288 ++pfd;
1289 --n;
1290 }
1291 }
1292 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1293 {
1294 while (n)
1295 {
1296 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1297 ++pvd;
1298 --n;
1299 }
1300 }
1301
1302 static void dump_TLBImpLib(const TLBImpLib *import)
1303 {
1304 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1305 debugstr_w(import->name));
1306 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1307 import->wVersionMinor, import->lcid, import->offset);
1308 }
1309
1310 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1311 {
1312 TLBRefType *ref;
1313
1314 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1315 {
1316 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1317 if(ref->index == -1)
1318 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1319 else
1320 TRACE_(typelib)("type no: %d\n", ref->index);
1321
1322 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1323 {
1324 TRACE_(typelib)("in lib\n");
1325 dump_TLBImpLib(ref->pImpTLInfo);
1326 }
1327 }
1328 }
1329
1330 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1331 {
1332 if(!impl)
1333 return;
1334 while (n) {
1335 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1336 impl->hRef, impl->implflags);
1337 ++impl;
1338 --n;
1339 }
1340 }
1341
1342 static void dump_Variant(const VARIANT * pvar)
1343 {
1344 SYSTEMTIME st;
1345
1346 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1347
1348 if (pvar)
1349 {
1350 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1351 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1352 {
1353 TRACE(",%p", V_BYREF(pvar));
1354 }
1355 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1356 {
1357 TRACE(",%p", V_ARRAY(pvar));
1358 }
1359 else switch (V_TYPE(pvar))
1360 {
1361 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1362 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1363 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1364 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1365 case VT_INT:
1366 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1367 case VT_UINT:
1368 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1369 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1370 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1371 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1372 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1373 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1374 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1375 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1376 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1377 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1378 V_CY(pvar).s.Lo); break;
1379 case VT_DATE:
1380 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1381 TRACE(",<invalid>");
1382 else
1383 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1384 st.wHour, st.wMinute, st.wSecond);
1385 break;
1386 case VT_ERROR:
1387 case VT_VOID:
1388 case VT_USERDEFINED:
1389 case VT_EMPTY:
1390 case VT_NULL: break;
1391 default: TRACE(",?"); break;
1392 }
1393 }
1394 TRACE("}\n");
1395 }
1396
1397 static void dump_DispParms(const DISPPARAMS * pdp)
1398 {
1399 unsigned int index;
1400
1401 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1402
1403 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1404 {
1405 TRACE("named args:\n");
1406 for (index = 0; index < pdp->cNamedArgs; index++)
1407 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1408 }
1409
1410 if (pdp->cArgs && pdp->rgvarg)
1411 {
1412 TRACE("args:\n");
1413 for (index = 0; index < pdp->cArgs; index++)
1414 dump_Variant( &pdp->rgvarg[index] );
1415 }
1416 }
1417
1418 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1419 {
1420 TRACE("%p ref=%u\n", pty, pty->ref);
1421 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1422 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1423 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1424 TRACE("fct:%u var:%u impl:%u\n",
1425 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1426 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1427 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1428 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1429 if (TRACE_ON(ole))
1430 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1431 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1432 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1433 }
1434
1435 static void dump_VARDESC(const VARDESC *v)
1436 {
1437 MESSAGE("memid %d\n",v->memid);
1438 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1439 MESSAGE("oInst %d\n",v->u.oInst);
1440 dump_ELEMDESC(&(v->elemdescVar));
1441 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1442 MESSAGE("varkind %d\n",v->varkind);
1443 }
1444
1445 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1446 {
1447 /* VT_LPWSTR is largest type that, may appear in type description */
1448 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1449 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1450 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1451 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1452 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1453 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1454 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1455 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1456 };
1457
1458 static void TLB_abort(void)
1459 {
1460 DebugBreak();
1461 }
1462
1463 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1464 {
1465 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1466 if (!ret) ERR("cannot allocate memory\n");
1467 return ret;
1468 }
1469
1470 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1471 {
1472 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1473 if (!ret) ERR("cannot allocate memory\n");
1474 return ret;
1475 }
1476
1477 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1478 {
1479 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1480 }
1481
1482 void heap_free(void *ptr)
1483 {
1484 HeapFree(GetProcessHeap(), 0, ptr);
1485 }
1486
1487 /* returns the size required for a deep copy of a typedesc into a
1488 * flat buffer */
1489 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1490 {
1491 SIZE_T size = 0;
1492
1493 if (alloc_initial_space)
1494 size += sizeof(TYPEDESC);
1495
1496 switch (tdesc->vt)
1497 {
1498 case VT_PTR:
1499 case VT_SAFEARRAY:
1500 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1501 break;
1502 case VT_CARRAY:
1503 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1504 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1505 break;
1506 }
1507 return size;
1508 }
1509
1510 /* deep copy a typedesc into a flat buffer */
1511 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1512 {
1513 if (!dest)
1514 {
1515 dest = buffer;
1516 buffer = (char *)buffer + sizeof(TYPEDESC);
1517 }
1518
1519 *dest = *src;
1520
1521 switch (src->vt)
1522 {
1523 case VT_PTR:
1524 case VT_SAFEARRAY:
1525 dest->u.lptdesc = buffer;
1526 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1527 break;
1528 case VT_CARRAY:
1529 dest->u.lpadesc = buffer;
1530 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1531 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1532 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1533 break;
1534 }
1535 return buffer;
1536 }
1537
1538 /* free custom data allocated by MSFT_CustData */
1539 static inline void TLB_FreeCustData(struct list *custdata_list)
1540 {
1541 TLBCustData *cd, *cdn;
1542 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1543 {
1544 list_remove(&cd->entry);
1545 VariantClear(&cd->data);
1546 heap_free(cd);
1547 }
1548 }
1549
1550 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1551 {
1552 DWORD len;
1553 BSTR ret;
1554
1555 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1556 ret = SysAllocStringLen(NULL, len - 1);
1557 if (!ret) return ret;
1558 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1559 return ret;
1560 }
1561
1562 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1563 UINT n, MEMBERID memid)
1564 {
1565 while(n){
1566 if(funcdescs->funcdesc.memid == memid)
1567 return funcdescs;
1568 ++funcdescs;
1569 --n;
1570 }
1571 return NULL;
1572 }
1573
1574 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1575 UINT n, const OLECHAR *name)
1576 {
1577 while(n){
1578 if(!lstrcmpiW(funcdescs->Name, name))
1579 return funcdescs;
1580 ++funcdescs;
1581 --n;
1582 }
1583 return NULL;
1584 }
1585
1586 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1587 UINT n, MEMBERID memid)
1588 {
1589 while(n){
1590 if(vardescs->vardesc.memid == memid)
1591 return vardescs;
1592 ++vardescs;
1593 --n;
1594 }
1595 return NULL;
1596 }
1597
1598 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1599 UINT n, const OLECHAR *name)
1600 {
1601 while(n){
1602 if(!lstrcmpiW(vardescs->Name, name))
1603 return vardescs;
1604 ++vardescs;
1605 --n;
1606 }
1607 return NULL;
1608 }
1609
1610 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1611 {
1612 TLBCustData *cust_data;
1613 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1614 if(IsEqualIID(&cust_data->guid, guid))
1615 return cust_data;
1616 return NULL;
1617 }
1618
1619 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1620 {
1621 TLBVarDesc *ret;
1622
1623 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1624 if(!ret)
1625 return NULL;
1626
1627 while(n){
1628 list_init(&ret[n-1].custdata_list);
1629 --n;
1630 }
1631
1632 return ret;
1633 }
1634
1635 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1636 {
1637 TLBParDesc *ret;
1638
1639 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1640 if(!ret)
1641 return NULL;
1642
1643 while(n){
1644 list_init(&ret[n-1].custdata_list);
1645 --n;
1646 }
1647
1648 return ret;
1649 }
1650
1651 static TLBFuncDesc *TLBFuncDesc_Constructor(UINT n)
1652 {
1653 TLBFuncDesc *ret;
1654
1655 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1656 if(!ret)
1657 return NULL;
1658
1659 while(n){
1660 list_init(&ret[n-1].custdata_list);
1661 --n;
1662 }
1663
1664 return ret;
1665 }
1666
1667 static TLBImplType *TLBImplType_Constructor(UINT n)
1668 {
1669 TLBImplType *ret;
1670
1671 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1672 if(!ret)
1673 return NULL;
1674
1675 while(n){
1676 list_init(&ret[n-1].custdata_list);
1677 --n;
1678 }
1679
1680 return ret;
1681 }
1682
1683 /**********************************************************************
1684 *
1685 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1686 */
1687 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1688 {
1689 return pcx->pos;
1690 }
1691
1692 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1693 {
1694 if (where != DO_NOT_SEEK)
1695 {
1696 where += pcx->oStart;
1697 if (where > pcx->length)
1698 {
1699 /* FIXME */
1700 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1701 TLB_abort();
1702 }
1703 pcx->pos = where;
1704 }
1705 }
1706
1707 /* read function */
1708 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1709 {
1710 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1711 pcx->pos, count, pcx->oStart, pcx->length, where);
1712
1713 MSFT_Seek(pcx, where);
1714 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1715 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1716 pcx->pos += count;
1717 return count;
1718 }
1719
1720 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1721 LONG where )
1722 {
1723 DWORD ret;
1724
1725 ret = MSFT_Read(buffer, count, pcx, where);
1726 FromLEDWords(buffer, ret);
1727
1728 return ret;
1729 }
1730
1731 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1732 LONG where )
1733 {
1734 DWORD ret;
1735
1736 ret = MSFT_Read(buffer, count, pcx, where);
1737 FromLEWords(buffer, ret);
1738
1739 return ret;
1740 }
1741
1742 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1743 {
1744 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1745 memset(pGuid,0, sizeof(GUID));
1746 return;
1747 }
1748 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1749 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1750 pGuid->Data2 = FromLEWord(pGuid->Data2);
1751 pGuid->Data3 = FromLEWord(pGuid->Data3);
1752 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1753 }
1754
1755 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1756 {
1757 MSFT_NameIntro niName;
1758
1759 if (offset < 0)
1760 {
1761 ERR_(typelib)("bad offset %d\n", offset);
1762 return -1;
1763 }
1764
1765 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1766 pcx->pTblDir->pNametab.offset+offset);
1767
1768 return niName.hreftype;
1769 }
1770
1771 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1772 {
1773 char * name;
1774 MSFT_NameIntro niName;
1775 int lengthInChars;
1776 BSTR bstrName = NULL;
1777
1778 if (offset < 0)
1779 {
1780 ERR_(typelib)("bad offset %d\n", offset);
1781 return NULL;
1782 }
1783 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1784 pcx->pTblDir->pNametab.offset+offset);
1785 niName.namelen &= 0xFF; /* FIXME: correct ? */
1786 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1787 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1788 name[niName.namelen & 0xff]='\0';
1789
1790 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1791 name, -1, NULL, 0);
1792
1793 /* no invalid characters in string */
1794 if (lengthInChars)
1795 {
1796 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1797
1798 /* don't check for invalid character since this has been done previously */
1799 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1800 }
1801 heap_free(name);
1802
1803 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1804 return bstrName;
1805 }
1806
1807 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1808 {
1809 char * string;
1810 INT16 length;
1811 int lengthInChars;
1812 BSTR bstr = NULL;
1813
1814 if(offset<0) return NULL;
1815 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1816 if(length <= 0) return 0;
1817 string = heap_alloc_zero(length +1);
1818 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1819 string[length]='\0';
1820
1821 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1822 string, -1, NULL, 0);
1823
1824 /* no invalid characters in string */
1825 if (lengthInChars)
1826 {
1827 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1828
1829 /* don't check for invalid character since this has been done previously */
1830 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1831 }
1832 heap_free(string);
1833
1834 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1835 return bstr;
1836 }
1837 /*
1838 * read a value and fill a VARIANT structure
1839 */
1840 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1841 {
1842 int size;
1843
1844 TRACE_(typelib)("\n");
1845
1846 if(offset <0) { /* data are packed in here */
1847 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1848 V_I4(pVar) = offset & 0x3ffffff;
1849 return;
1850 }
1851 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1852 pcx->pTblDir->pCustData.offset + offset );
1853 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1854 switch (V_VT(pVar)){
1855 case VT_EMPTY: /* FIXME: is this right? */
1856 case VT_NULL: /* FIXME: is this right? */
1857 case VT_I2 : /* this should not happen */
1858 case VT_I4 :
1859 case VT_R4 :
1860 case VT_ERROR :
1861 case VT_BOOL :
1862 case VT_I1 :
1863 case VT_UI1 :
1864 case VT_UI2 :
1865 case VT_UI4 :
1866 case VT_INT :
1867 case VT_UINT :
1868 case VT_VOID : /* FIXME: is this right? */
1869 case VT_HRESULT :
1870 size=4; break;
1871 case VT_R8 :
1872 case VT_CY :
1873 case VT_DATE :
1874 case VT_I8 :
1875 case VT_UI8 :
1876 case VT_DECIMAL : /* FIXME: is this right? */
1877 case VT_FILETIME :
1878 size=8;break;
1879 /* pointer types with known behaviour */
1880 case VT_BSTR :{
1881 char * ptr;
1882 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1883 if(size < 0) {
1884 char next;
1885 DWORD origPos = MSFT_Tell(pcx), nullPos;
1886
1887 do {
1888 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1889 } while (next);
1890 nullPos = MSFT_Tell(pcx);
1891 size = nullPos - origPos;
1892 MSFT_Seek(pcx, origPos);
1893 }
1894 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1895 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1896 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1897 /* FIXME: do we need a AtoW conversion here? */
1898 V_UNION(pVar, bstrVal[size])='\0';
1899 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1900 heap_free(ptr);
1901 }
1902 size=-4; break;
1903 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1904 case VT_DISPATCH :
1905 case VT_VARIANT :
1906 case VT_UNKNOWN :
1907 case VT_PTR :
1908 case VT_SAFEARRAY :
1909 case VT_CARRAY :
1910 case VT_USERDEFINED :
1911 case VT_LPSTR :
1912 case VT_LPWSTR :
1913 case VT_BLOB :
1914 case VT_STREAM :
1915 case VT_STORAGE :
1916 case VT_STREAMED_OBJECT :
1917 case VT_STORED_OBJECT :
1918 case VT_BLOB_OBJECT :
1919 case VT_CF :
1920 case VT_CLSID :
1921 default:
1922 size=0;
1923 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1924 V_VT(pVar));
1925 }
1926
1927 if(size>0) /* (big|small) endian correct? */
1928 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1929 return;
1930 }
1931 /*
1932 * create a linked list with custom data
1933 */
1934 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
1935 {
1936 MSFT_CDGuid entry;
1937 TLBCustData* pNew;
1938 int count=0;
1939
1940 TRACE_(typelib)("\n");
1941
1942 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
1943
1944 while(offset >=0){
1945 count++;
1946 pNew=heap_alloc_zero(sizeof(TLBCustData));
1947 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1948 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1949 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1950 list_add_head(custdata_list, &pNew->entry);
1951 offset = entry.next;
1952 }
1953 return count;
1954 }
1955
1956 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1957 ITypeInfoImpl *pTI)
1958 {
1959 if(type <0)
1960 pTd->vt=type & VT_TYPEMASK;
1961 else
1962 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1963
1964 if(pTd->vt == VT_USERDEFINED)
1965 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1966
1967 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1968 }
1969
1970 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1971 {
1972 /* resolve referenced type if any */
1973 while (lpTypeDesc)
1974 {
1975 switch (lpTypeDesc->vt)
1976 {
1977 case VT_PTR:
1978 lpTypeDesc = lpTypeDesc->u.lptdesc;
1979 break;
1980
1981 case VT_CARRAY:
1982 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1983 break;
1984
1985 case VT_USERDEFINED:
1986 MSFT_DoRefType(pcx, pTI->pTypeLib,
1987 lpTypeDesc->u.hreftype);
1988
1989 lpTypeDesc = NULL;
1990 break;
1991
1992 default:
1993 lpTypeDesc = NULL;
1994 }
1995 }
1996 }
1997
1998 static void
1999 MSFT_DoFuncs(TLBContext* pcx,
2000 ITypeInfoImpl* pTI,
2001 int cFuncs,
2002 int cVars,
2003 int offset,
2004 TLBFuncDesc** pptfd)
2005 {
2006 /*
2007 * member information is stored in a data structure at offset
2008 * indicated by the memoffset field of the typeinfo structure
2009 * There are several distinctive parts.
2010 * The first part starts with a field that holds the total length
2011 * of this (first) part excluding this field. Then follow the records,
2012 * for each member there is one record.
2013 *
2014 * The first entry is always the length of the record (including this
2015 * length word).
2016 * The rest of the record depends on the type of the member. If there is
2017 * a field indicating the member type (function, variable, interface, etc)
2018 * I have not found it yet. At this time we depend on the information
2019 * in the type info and the usual order how things are stored.
2020 *
2021 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2022 * for each member;
2023 *
2024 * Third is an equal sized array with file offsets to the name entry
2025 * of each member.
2026 *
2027 * The fourth and last (?) part is an array with offsets to the records
2028 * in the first part of this file segment.
2029 */
2030
2031 int infolen, nameoffset, reclength, i;
2032 int recoffset = offset + sizeof(INT);
2033
2034 char *recbuf = heap_alloc(0xffff);
2035 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2036 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2037
2038 TRACE_(typelib)("\n");
2039
2040 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2041
2042 *pptfd = TLBFuncDesc_Constructor(cFuncs);
2043 ptfd = *pptfd;
2044 for ( i = 0; i < cFuncs ; i++ )
2045 {
2046 int optional;
2047
2048 /* name, eventually add to a hash table */
2049 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2050 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2051
2052 /* nameoffset is sometimes -1 on the second half of a propget/propput
2053 * pair of functions */
2054 if ((nameoffset == -1) && (i > 0))
2055 ptfd->Name = SysAllocString(ptfd_prev->Name);
2056 else
2057 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2058
2059 /* read the function information record */
2060 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2061
2062 reclength &= 0xffff;
2063
2064 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2065
2066 /* size without argument data */
2067 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2068
2069 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2070 ptfd->helpcontext = pFuncRec->HelpContext;
2071
2072 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2073 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2074
2075 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2076 {
2077 if (pFuncRec->FKCCIC & 0x2000 )
2078 {
2079 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2080 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2081 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2082 }
2083 else
2084 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2085 }
2086 else
2087 ptfd->Entry = (BSTR)-1;
2088
2089 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2090 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2091
2092 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2093 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2094
2095 /* fill the FuncDesc Structure */
2096 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2097 offset + infolen + ( i + 1) * sizeof(INT));
2098
2099 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2100 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2101 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2102 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2103 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2104 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2105 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2106
2107 MSFT_GetTdesc(pcx,
2108 pFuncRec->DataType,
2109 &ptfd->funcdesc.elemdescFunc.tdesc,
2110 pTI);
2111 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2112
2113 /* do the parameters/arguments */
2114 if(pFuncRec->nrargs)
2115 {
2116 int j = 0;
2117 MSFT_ParameterInfo paraminfo;
2118
2119 ptfd->funcdesc.lprgelemdescParam =
2120 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2121
2122 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2123
2124 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2125 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2126
2127 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2128 {
2129 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2130
2131 MSFT_GetTdesc(pcx,
2132 paraminfo.DataType,
2133 &elemdesc->tdesc,
2134 pTI);
2135
2136 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2137
2138 /* name */
2139 if (paraminfo.oName == -1)
2140 /* this occurs for [propput] or [propget] methods, so
2141 * we should just set the name of the parameter to the
2142 * name of the method. */
2143 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2144 else
2145 ptfd->pParamDesc[j].Name =
2146 MSFT_ReadName( pcx, paraminfo.oName );
2147 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2148
2149 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2150
2151 /* default value */
2152 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2153 (pFuncRec->FKCCIC & 0x1000) )
2154 {
2155 INT* pInt = (INT *)((char *)pFuncRec +
2156 reclength -
2157 (pFuncRec->nrargs * 4) * sizeof(INT) );
2158
2159 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2160
2161 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2162 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2163
2164 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2165 pInt[j], pcx);
2166 }
2167 else
2168 elemdesc->u.paramdesc.pparamdescex = NULL;
2169
2170 /* custom info */
2171 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2172 j*sizeof(pFuncRec->oArgCustData[0])) &&
2173 pFuncRec->FKCCIC & 0x80 )
2174 {
2175 MSFT_CustData(pcx,
2176 pFuncRec->oArgCustData[j],
2177 &ptfd->pParamDesc[j].custdata_list);
2178 }
2179
2180 /* SEEK value = jump to offset,
2181 * from there jump to the end of record,
2182 * go back by (j-1) arguments
2183 */
2184 MSFT_ReadLEDWords( &paraminfo ,
2185 sizeof(MSFT_ParameterInfo), pcx,
2186 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2187 * sizeof(MSFT_ParameterInfo)));
2188 }
2189 }
2190
2191 /* scode is not used: archaic win16 stuff FIXME: right? */
2192 ptfd->funcdesc.cScodes = 0 ;
2193 ptfd->funcdesc.lprgscode = NULL ;
2194
2195 ptfd_prev = ptfd;
2196 ++ptfd;
2197 recoffset += reclength;
2198 }
2199 heap_free(recbuf);
2200 }
2201
2202 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2203 int cVars, int offset, TLBVarDesc ** pptvd)
2204 {
2205 int infolen, nameoffset, reclength;
2206 char recbuf[256];
2207 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2208 TLBVarDesc *ptvd;
2209 int i;
2210 int recoffset;
2211
2212 TRACE_(typelib)("\n");
2213
2214 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2215 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2216 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2217 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2218 recoffset += offset+sizeof(INT);
2219 for(i=0;i<cVars;i++, ++ptvd){
2220 /* name, eventually add to a hash table */
2221 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2222 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2223 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2224 /* read the variable information record */
2225 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2226 reclength &= 0xff;
2227 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2228
2229 /* optional data */
2230 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2231 ptvd->HelpContext = pVarRec->HelpContext;
2232
2233 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2234 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2235
2236 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2237 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2238
2239 /* fill the VarDesc Structure */
2240 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2241 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2242 ptvd->vardesc.varkind = pVarRec->VarKind;
2243 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2244 MSFT_GetTdesc(pcx, pVarRec->DataType,
2245 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2246 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2247 if(pVarRec->VarKind == VAR_CONST ){
2248 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2249 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2250 pVarRec->OffsValue, pcx);
2251 } else
2252 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2253 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2254 recoffset += reclength;
2255 }
2256 }
2257
2258 /* fill in data for a hreftype (offset). When the referenced type is contained
2259 * in the typelib, it's just an (file) offset in the type info base dir.
2260 * If comes from import, it's an offset+1 in the ImpInfo table
2261 * */
2262 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2263 int offset)
2264 {
2265 TLBRefType *ref;
2266
2267 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2268
2269 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2270 {
2271 if(ref->reference == offset) return;
2272 }
2273
2274 ref = heap_alloc_zero(sizeof(TLBRefType));
2275 list_add_tail(&pTL->ref_list, &ref->entry);
2276
2277 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2278 /* external typelib */
2279 MSFT_ImpInfo impinfo;
2280 TLBImpLib *pImpLib;
2281
2282 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2283
2284 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2285 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2286
2287 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2288 if(pImpLib->offset==impinfo.oImpFile)
2289 break;
2290
2291 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2292 ref->reference = offset;
2293 ref->pImpTLInfo = pImpLib;
2294 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2295 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2296 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2297 ref->index = TLB_REF_USE_GUID;
2298 } else
2299 ref->index = impinfo.oGuid;
2300 }else{
2301 ERR("Cannot find a reference\n");
2302 ref->reference = -1;
2303 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2304 }
2305 }else{
2306 /* in this typelib */
2307 ref->index = MSFT_HREFTYPE_INDEX(offset);
2308 ref->reference = offset;
2309 ref->pImpTLInfo = TLB_REF_INTERNAL;
2310 }
2311 }
2312
2313 /* process Implemented Interfaces of a com class */
2314 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2315 int offset)
2316 {
2317 int i;
2318 MSFT_RefRecord refrec;
2319 TLBImplType *pImpl;
2320
2321 TRACE_(typelib)("\n");
2322
2323 pTI->impltypes = TLBImplType_Constructor(count);
2324 pImpl = pTI->impltypes;
2325 for(i=0;i<count;i++){
2326 if(offset<0) break; /* paranoia */
2327 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2328 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2329 pImpl->hRef = refrec.reftype;
2330 pImpl->implflags=refrec.flags;
2331 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2332 offset=refrec.onext;
2333 ++pImpl;
2334 }
2335 }
2336 /*
2337 * process a typeinfo record
2338 */
2339 static ITypeInfoImpl * MSFT_DoTypeInfo(
2340 TLBContext *pcx,
2341 int count,
2342 ITypeLibImpl * pLibInfo)
2343 {
2344 MSFT_TypeInfoBase tiBase;
2345 ITypeInfoImpl *ptiRet;
2346
2347 TRACE_(typelib)("count=%u\n", count);
2348
2349 ptiRet = ITypeInfoImpl_Constructor();
2350 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2351 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2352
2353 /* this is where we are coming from */
2354 ptiRet->pTypeLib = pLibInfo;
2355 ptiRet->index=count;
2356 /* fill in the typeattr fields */
2357
2358 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2359 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2360 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2361 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2362 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2363 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2364 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2365 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2366 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2367 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2368 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2369 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2370 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2371 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2372 MSFT_GetTdesc(pcx, tiBase.datatype1,
2373 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2374
2375 /* FIXME: */
2376 /* IDLDESC idldescType; *//* never saw this one != zero */
2377
2378 /* name, eventually add to a hash table */
2379 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2380 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2381 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2382 /* help info */
2383 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2384 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2385 ptiRet->dwHelpContext=tiBase.helpcontext;
2386
2387 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2388 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2389
2390 /* note: InfoType's Help file and HelpStringDll come from the containing
2391 * library. Further HelpString and Docstring appear to be the same thing :(
2392 */
2393 /* functions */
2394 if(ptiRet->TypeAttr.cFuncs >0 )
2395 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2396 ptiRet->TypeAttr.cVars,
2397 tiBase.memoffset, &ptiRet->funcdescs);
2398 /* variables */
2399 if(ptiRet->TypeAttr.cVars >0 )
2400 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2401 ptiRet->TypeAttr.cVars,
2402 tiBase.memoffset, &ptiRet->vardescs);
2403 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2404 switch(ptiRet->TypeAttr.typekind)
2405 {
2406 case TKIND_COCLASS:
2407 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2408 tiBase.datatype1);
2409 break;
2410 case TKIND_DISPATCH:
2411 /* This is not -1 when the interface is a non-base dual interface or
2412 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2413 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2414 not this interface.
2415 */
2416
2417 if (tiBase.datatype1 != -1)
2418 {
2419 ptiRet->impltypes = TLBImplType_Constructor(1);
2420 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2421 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2422 }
2423 break;
2424 default:
2425 ptiRet->impltypes = TLBImplType_Constructor(1);
2426 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2427 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2428 break;
2429 }
2430 }
2431 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2432
2433 TRACE_(typelib)("%s guid: %s kind:%s\n",
2434 debugstr_w(ptiRet->Name),
2435 debugstr_guid(&ptiRet->TypeAttr.guid),
2436 typekind_desc[ptiRet->TypeAttr.typekind]);
2437 if (TRACE_ON(typelib))
2438 dump_TypeInfo(ptiRet);
2439
2440 return ptiRet;
2441 }
2442
2443 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2444 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2445 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2446 * tradeoff here.
2447 */
2448 static struct list tlb_cache = LIST_INIT(tlb_cache);
2449 static CRITICAL_SECTION cache_section;
2450 static CRITICAL_SECTION_DEBUG cache_section_debug =
2451 {
2452 0, 0, &cache_section,
2453 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2454 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2455 };
2456 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2457
2458
2459 typedef struct TLB_PEFile
2460 {
2461 const IUnknownVtbl *lpvtbl;
2462 LONG refs;
2463 HMODULE dll;
2464 HRSRC typelib_resource;
2465 HGLOBAL typelib_global;
2466 LPVOID typelib_base;
2467 } TLB_PEFile;
2468
2469 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2470 {
2471 if (IsEqualIID(riid, &IID_IUnknown))
2472 {
2473 *ppv = iface;
2474 IUnknown_AddRef(iface);
2475 return S_OK;
2476 }
2477 *ppv = NULL;
2478 return E_NOINTERFACE;
2479 }
2480
2481 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2482 {
2483 TLB_PEFile *This = (TLB_PEFile *)iface;
2484 return InterlockedIncrement(&This->refs);
2485 }
2486
2487 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2488 {
2489 TLB_PEFile *This = (TLB_PEFile *)iface;
2490 ULONG refs = InterlockedDecrement(&This->refs);
2491 if (!refs)
2492 {
2493 if (This->typelib_global)
2494 FreeResource(This->typelib_global);
2495 if (This->dll)
2496 FreeLibrary(This->dll);
2497 heap_free(This);
2498 }
2499 return refs;
2500 }
2501
2502 static const IUnknownVtbl TLB_PEFile_Vtable =
2503 {
2504 TLB_PEFile_QueryInterface,
2505 TLB_PEFile_AddRef,
2506 TLB_PEFile_Release
2507 };
2508
2509 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2510 {
2511 TLB_PEFile *This;
2512 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2513
2514 This = heap_alloc(sizeof(TLB_PEFile));
2515 if (!This)
2516 return E_OUTOFMEMORY;
2517
2518 This->lpvtbl = &TLB_PEFile_Vtable;
2519 This->refs = 1;
2520 This->dll = NULL;
2521 This->typelib_resource = NULL;
2522 This->typelib_global = NULL;
2523 This->typelib_base = NULL;
2524
2525 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2526 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2527
2528 if (This->dll)
2529 {
2530 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2531 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2532 if (This->typelib_resource)
2533 {
2534 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2535 if (This->typelib_global)
2536 {
2537 This->typelib_base = LockResource(This->typelib_global);
2538
2539 if (This->typelib_base)
2540 {
2541 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2542 *ppBase = This->typelib_base;
2543 *ppFile = (IUnknown *)&This->lpvtbl;
2544 return S_OK;
2545 }
2546 }
2547
2548 hr = E_FAIL;
2549 }
2550 }
2551
2552 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2553 return hr;
2554 }
2555
2556 typedef struct TLB_NEFile
2557 {
2558 const IUnknownVtbl *lpvtbl;
2559 LONG refs;
2560 LPVOID typelib_base;
2561 } TLB_NEFile;
2562
2563 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2564 {
2565 if (IsEqualIID(riid, &IID_IUnknown))
2566 {
2567 *ppv = iface;
2568 IUnknown_AddRef(iface);
2569 return S_OK;
2570 }
2571 *ppv = NULL;
2572 return E_NOINTERFACE;
2573 }
2574
2575 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2576 {
2577 TLB_NEFile *This = (TLB_NEFile *)iface;
2578 return InterlockedIncrement(&This->refs);
2579 }
2580
2581 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2582 {
2583 TLB_NEFile *This = (TLB_NEFile *)iface;
2584 ULONG refs = InterlockedDecrement(&This->refs);
2585 if (!refs)
2586 {
2587 heap_free(This->typelib_base);
2588 heap_free(This);
2589 }
2590 return refs;
2591 }
2592
2593 static const IUnknownVtbl TLB_NEFile_Vtable =
2594 {
2595 TLB_NEFile_QueryInterface,
2596 TLB_NEFile_AddRef,
2597 TLB_NEFile_Release
2598 };
2599
2600 /***********************************************************************
2601 * read_xx_header [internal]
2602 */
2603 static int read_xx_header( HFILE lzfd )
2604 {
2605 IMAGE_DOS_HEADER mzh;
2606 char magic[3];
2607
2608 LZSeek( lzfd, 0, SEEK_SET );
2609 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2610 return 0;
2611 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2612 return 0;
2613
2614 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2615 if ( 2 != LZRead( lzfd, magic, 2 ) )
2616 return 0;
2617
2618 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2619
2620 if ( magic[0] == 'N' && magic[1] == 'E' )
2621 return IMAGE_OS2_SIGNATURE;
2622 if ( magic[0] == 'P' && magic[1] == 'E' )
2623 return IMAGE_NT_SIGNATURE;
2624
2625 magic[2] = '\0';
2626 WARN("Can't handle %s files.\n", magic );
2627 return 0;
2628 }
2629
2630
2631 /***********************************************************************
2632 * find_ne_resource [internal]
2633 */
2634 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2635 DWORD *resLen, DWORD *resOff )
2636 {
2637 IMAGE_OS2_HEADER nehd;
2638 NE_TYPEINFO *typeInfo;
2639 NE_NAMEINFO *nameInfo;
2640 DWORD nehdoffset;
2641 LPBYTE resTab;
2642 DWORD resTabSize;
2643 int count;
2644
2645 /* Read in NE header */
2646 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2647 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2648
2649 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2650 if ( !resTabSize )
2651 {
2652 TRACE("No resources in NE dll\n" );
2653 return FALSE;
2654 }
2655
2656 /* Read in resource table */
2657 resTab = heap_alloc( resTabSize );
2658 if ( !resTab ) return FALSE;
2659
2660 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2661 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2662 {
2663 heap_free( resTab );
2664 return FALSE;
2665 }
2666
2667 /* Find resource */
2668 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2669
2670 if (!IS_INTRESOURCE(typeid)) /* named type */
2671 {
2672 BYTE len = strlen( typeid );
2673 while (typeInfo->type_id)
2674 {
2675 if (!(typeInfo->type_id & 0x8000))
2676 {
2677 BYTE *p = resTab + typeInfo->type_id;
2678 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2679 }
2680 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2681 typeInfo->count * sizeof(NE_NAMEINFO));
2682 }
2683 }
2684 else /* numeric type id */
2685 {
2686 WORD id = LOWORD(typeid) | 0x8000;
2687 while (typeInfo->type_id)
2688 {
2689 if (typeInfo->type_id == id) goto found_type;
2690 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2691 typeInfo->count * sizeof(NE_NAMEINFO));
2692 }
2693 }
2694 TRACE("No typeid entry found for %p\n", typeid );
2695 heap_free( resTab );
2696 return FALSE;
2697
2698 found_type:
2699 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2700
2701 if (!IS_INTRESOURCE(resid)) /* named resource */
2702 {
2703 BYTE len = strlen( resid );
2704 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2705 {
2706 BYTE *p = resTab + nameInfo->id;
2707 if (nameInfo->id & 0x8000) continue;
2708 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2709 }
2710 }
2711 else /* numeric resource id */
2712 {
2713 WORD id = LOWORD(resid) | 0x8000;
2714 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2715 if (nameInfo->id == id) goto found_name;
2716 }
2717 TRACE("No resid entry found for %p\n", typeid );
2718 heap_free( resTab );
2719 return FALSE;
2720
2721 found_name:
2722 /* Return resource data */
2723 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2724 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2725
2726 heap_free( resTab );
2727 return TRUE;
2728 }
2729
2730 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2731
2732 HFILE lzfd = -1;
2733 OFSTRUCT ofs;
2734 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2735 TLB_NEFile *This;
2736
2737 This = heap_alloc(sizeof(TLB_NEFile));
2738 if (!This) return E_OUTOFMEMORY;
2739
2740 This->lpvtbl = &TLB_NEFile_Vtable;
2741 This->refs = 1;
2742 This->typelib_base = NULL;
2743
2744 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2745 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2746 {
2747 DWORD reslen, offset;
2748 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2749 {
2750 This->typelib_base = heap_alloc(reslen);
2751 if( !This->typelib_base )
2752 hr = E_OUTOFMEMORY;
2753 else
2754 {
2755 LZSeek( lzfd, offset, SEEK_SET );
2756 reslen = LZRead( lzfd, This->typelib_base, reslen );
2757 LZClose( lzfd );
2758 *ppBase = This->typelib_base;
2759 *pdwTLBLength = reslen;
2760 *ppFile = (IUnknown *)&This->lpvtbl;
2761 return S_OK;
2762 }
2763 }
2764 }
2765
2766 if( lzfd >= 0) LZClose( lzfd );
2767 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2768 return hr;
2769 }
2770
2771 typedef struct TLB_Mapping
2772 {
2773 const IUnknownVtbl *lpvtbl;
2774 LONG refs;
2775 HANDLE file;
2776 HANDLE mapping;
2777 LPVOID typelib_base;
2778 } TLB_Mapping;
2779
2780 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2781 {
2782 if (IsEqualIID(riid, &IID_IUnknown))
2783 {
2784 *ppv = iface;
2785 IUnknown_AddRef(iface);
2786 return S_OK;
2787 }
2788 *ppv = NULL;
2789 return E_NOINTERFACE;
2790 }
2791
2792 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2793 {
2794 TLB_Mapping *This = (TLB_Mapping *)iface;
2795 return InterlockedIncrement(&This->refs);
2796 }
2797
2798 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2799 {
2800 TLB_Mapping *This = (TLB_Mapping *)iface;
2801 ULONG refs = InterlockedDecrement(&This->refs);
2802 if (!refs)
2803 {
2804 if (This->typelib_base)
2805 UnmapViewOfFile(This->typelib_base);
2806 if (This->mapping)
2807 CloseHandle(This->mapping);
2808 if (This->file != INVALID_HANDLE_VALUE)
2809 CloseHandle(This->file);
2810 heap_free(This);
2811 }
2812 return refs;
2813 }
2814
2815 static const IUnknownVtbl TLB_Mapping_Vtable =
2816 {
2817 TLB_Mapping_QueryInterface,
2818 TLB_Mapping_AddRef,
2819 TLB_Mapping_Release
2820 };
2821
2822 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2823 {
2824 TLB_Mapping *This;
2825
2826 This = heap_alloc(sizeof(TLB_Mapping));
2827 if (!This)
2828 return E_OUTOFMEMORY;
2829
2830 This->lpvtbl = &TLB_Mapping_Vtable;
2831 This->refs = 1;
2832 This->file = INVALID_HANDLE_VALUE;
2833 This->mapping = NULL;
2834 This->typelib_base = NULL;
2835
2836 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2837 if (INVALID_HANDLE_VALUE != This->file)
2838 {
2839 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2840 if (This->mapping)
2841 {
2842 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2843 if(This->typelib_base)
2844 {
2845 /* retrieve file size */
2846 *pdwTLBLength = GetFileSize(This->file, NULL);
2847 *ppBase = This->typelib_base;
2848 *ppFile = (IUnknown *)&This->lpvtbl;
2849 return S_OK;
2850 }
2851 }
2852 }
2853
2854 IUnknown_Release((IUnknown *)&This->lpvtbl);
2855 return TYPE_E_CANTLOADLIBRARY;
2856 }
2857
2858 /****************************************************************************
2859 * TLB_ReadTypeLib
2860 *
2861 * find the type of the typelib file and map the typelib resource into
2862 * the memory
2863 */
2864
2865 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2866 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2867 {
2868 ITypeLibImpl *entry;
2869 HRESULT ret;
2870 INT index = 1;
2871 LPWSTR index_str, file = (LPWSTR)pszFileName;
2872 LPVOID pBase = NULL;
2873 DWORD dwTLBLength = 0;
2874 IUnknown *pFile = NULL;
2875
2876 *ppTypeLib = NULL;
2877
2878 index_str = strrchrW(pszFileName, '\\');
2879 if(index_str && *++index_str != '\0')
2880 {
2881 LPWSTR end_ptr;
2882 LONG idx = strtolW(index_str, &end_ptr, 10);
2883 if(*end_ptr == '\0')
2884 {
2885 int str_len = index_str - pszFileName - 1;
2886 index = idx;
2887 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2888 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2889 file[str_len] = 0;
2890 }
2891 }
2892
2893 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2894 {
2895 if(strchrW(file, '\\'))
2896 {
2897 lstrcpyW(pszPath, file);
2898 }
2899 else
2900 {
2901 int len = GetSystemDirectoryW(pszPath, cchPath);
2902 pszPath[len] = '\\';
2903 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2904 }
2905 }
2906
2907 if(file != pszFileName) heap_free(file);
2908
2909 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2910
2911 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2912 EnterCriticalSection(&cache_section);
2913 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
2914 {
2915 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2916 {
2917 TRACE("cache hit\n");
2918 *ppTypeLib = (ITypeLib2*)entry;
2919 ITypeLib2_AddRef(*ppTypeLib);
2920 LeaveCriticalSection(&cache_section);
2921 return S_OK;
2922 }
2923 }
2924 LeaveCriticalSection(&cache_section);
2925
2926 /* now actually load and parse the typelib */
2927
2928 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2929 if (ret == TYPE_E_CANTLOADLIBRARY)
2930 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2931 if (ret == TYPE_E_CANTLOADLIBRARY)
2932 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2933 if (SUCCEEDED(ret))
2934 {
2935 if (dwTLBLength >= 4)
2936 {
2937 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2938 if (dwSignature == MSFT_SIGNATURE)
2939 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2940 else if (dwSignature == SLTG_SIGNATURE)
2941 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2942 else
2943 {
2944 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2945 ret = TYPE_E_CANTLOADLIBRARY;
2946 }
2947 }
2948 else
2949 ret = TYPE_E_CANTLOADLIBRARY;
2950 IUnknown_Release(pFile);
2951 }
2952 else
2953 ret = TYPE_E_CANTLOADLIBRARY;
2954
2955 if(*ppTypeLib) {
2956 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2957
2958 TRACE("adding to cache\n");
2959 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2960 lstrcpyW(impl->path, pszPath);
2961 /* We should really canonicalise the path here. */
2962 impl->index = index;
2963
2964 /* FIXME: check if it has added already in the meantime */
2965 EnterCriticalSection(&cache_section);
2966 list_add_head(&tlb_cache, &impl->entry);
2967 LeaveCriticalSection(&cache_section);
2968 ret = S_OK;
2969 } else
2970 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2971
2972 return ret;
2973 }
2974
2975 /*================== ITypeLib(2) Methods ===================================*/
2976
2977 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2978 {
2979 ITypeLibImpl* pTypeLibImpl;
2980
2981 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2982 if (!pTypeLibImpl) return NULL;
2983
2984 pTypeLibImpl->lpVtbl = &tlbvt;
2985 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2986 pTypeLibImpl->ref = 1;
2987
2988 list_init(&pTypeLibImpl->implib_list);
2989 list_init(&pTypeLibImpl->custdata_list);
2990 list_init(&pTypeLibImpl->ref_list);
2991 pTypeLibImpl->dispatch_href = -1;
2992
2993 return pTypeLibImpl;
2994 }
2995
2996 /****************************************************************************
2997 * ITypeLib2_Constructor_MSFT
2998 *
2999 * loading an MSFT typelib from an in-memory image
3000 */
3001 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3002 {
3003 TLBContext cx;
3004 LONG lPSegDir;
3005 MSFT_Header tlbHeader;
3006 MSFT_SegDir tlbSegDir;
3007 ITypeLibImpl * pTypeLibImpl;
3008
3009 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3010
3011 pTypeLibImpl = TypeLibImpl_Constructor();
3012 if (!pTypeLibImpl) return NULL;
3013
3014 /* get pointer to beginning of typelib data */
3015 cx.pos = 0;
3016 cx.oStart=0;
3017 cx.mapping = pLib;
3018 cx.pLibInfo = pTypeLibImpl;
3019 cx.length = dwTLBLength;
3020
3021 /* read header */
3022 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3023 TRACE_(typelib)("header:\n");
3024 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3025 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3026 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3027 return NULL;
3028 }
3029 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3030
3031 /* there is a small amount of information here until the next important
3032 * part:
3033 * the segment directory . Try to calculate the amount of data */
3034 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3035
3036 /* now read the segment directory */
3037 TRACE("read segment directory (at %d)\n",lPSegDir);
3038 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3039 cx.pTblDir = &tlbSegDir;
3040
3041 /* just check two entries */
3042 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3043 {
3044 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3045 heap_free(pTypeLibImpl);
3046 return NULL;
3047 }
3048
3049 /* now fill our internal data */
3050 /* TLIBATTR fields */
3051 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3052
3053 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3054 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3055 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3056 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3057 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3058
3059 pTypeLibImpl->lcid = tlbHeader.lcid;
3060
3061 /* name, eventually add to a hash table */
3062 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3063
3064 /* help info */
3065 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3066 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3067
3068 if( tlbHeader.varflags & HELPDLLFLAG)
3069 {
3070 int offset;
3071 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3072 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3073 }
3074
3075 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3076
3077 /* custom data */
3078 if(tlbHeader.CustomDataOffset >= 0)
3079 {
3080 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3081 }
3082
3083 /* fill in type descriptions */
3084 if(tlbSegDir.pTypdescTab.length > 0)
3085 {
3086 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3087 INT16 td[4];
3088 pTypeLibImpl->ctTypeDesc = cTD;
3089 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3090 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3091 for(i=0; i<cTD; )
3092 {
3093 /* FIXME: add several sanity checks here */
3094 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3095 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3096 {
3097 /* FIXME: check safearray */
3098 if(td[3] < 0)
3099 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3100 else
3101 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3102 }
3103 else if(td[0] == VT_CARRAY)
3104 {
3105 /* array descr table here */
3106 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3107 }
3108 else if(td[0] == VT_USERDEFINED)
3109 {
3110 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3111 }
3112 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3113 }
3114
3115 /* second time around to fill the array subscript info */
3116 for(i=0;i<cTD;i++)
3117 {
3118 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3119 if(tlbSegDir.pArrayDescriptions.offset>0)
3120 {
3121 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3122 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3123
3124 if(td[1]<0)
3125 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3126 else
3127 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3128
3129 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3130
3131 for(j = 0; j<td[2]; j++)
3132 {
3133 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3134 sizeof(INT), &cx, DO_NOT_SEEK);
3135 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3136 sizeof(INT), &cx, DO_NOT_SEEK);
3137 }
3138 }
3139 else
3140 {
3141 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3142 ERR("didn't find array description data\n");
3143 }
3144 }
3145 }
3146
3147 /* imported type libs */
3148 if(tlbSegDir.pImpFiles.offset>0)
3149 {
3150 TLBImpLib *pImpLib;
3151 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3152 UINT16 size;
3153
3154 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3155 {
3156 char *name;
3157
3158 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3159 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3160 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3161
3162 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3163 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3164 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3165 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3166
3167 size >>= 2;
3168 name = heap_alloc_zero(size+1);
3169 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3170 pImpLib->name = TLB_MultiByteToBSTR(name);
3171 heap_free(name);
3172
3173 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3174 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3175
3176 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3177 }
3178 }
3179
3180 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3181 if(pTypeLibImpl->dispatch_href != -1)
3182 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3183
3184 /* type infos */
3185 if(tlbHeader.nrtypeinfos >= 0 )
3186 {
3187 ITypeInfoImpl **ppTI;
3188 int i;
3189
3190 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3191
3192 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3193 {
3194 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3195
3196 ++ppTI;
3197 (pTypeLibImpl->TypeInfoCount)++;
3198 }
3199 }
3200
3201 TRACE("(%p)\n", pTypeLibImpl);
3202 return (ITypeLib2*) pTypeLibImpl;
3203 }
3204
3205
3206 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3207 {
3208 char b[3];
3209 int i;
3210 short s;
3211
3212 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3213 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3214 return FALSE;
3215 }
3216
3217 guid->Data4[0] = s >> 8;
3218 guid->Data4[1] = s & 0xff;
3219
3220 b[2] = '\0';
3221 for(i = 0; i < 6; i++) {
3222 memcpy(b, str + 24 + 2 * i, 2);
3223 guid->Data4[i + 2] = strtol(b, NULL, 16);
3224 }
3225 return TRUE;
3226 }
3227
3228 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3229 {
3230 WORD bytelen;
3231 DWORD len;
3232
3233 *pBstr = NULL;
3234 bytelen = *(const WORD*)ptr;
3235 if(bytelen == 0xffff) return 2;
3236 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3237 *pBstr = SysAllocStringLen(NULL, len);
3238 if (*pBstr)
3239 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3240 return bytelen + 2;
3241 }
3242
3243 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3244 {
3245 WORD bytelen;
3246
3247 *str = NULL;
3248 bytelen = *(const WORD*)ptr;
3249 if(bytelen == 0xffff) return 2;
3250 *str = heap_alloc(bytelen + 1);
3251 memcpy(*str, ptr + 2, bytelen);
3252 (*str)[bytelen] = '\0';
3253 return bytelen + 2;
3254 }
3255
3256 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3257 {
3258 char *ptr = pLibBlk;
3259 WORD w;
3260
3261 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3262 FIXME("libblk magic = %04x\n", w);
3263 return 0;
3264 }
3265
3266 ptr += 6;
3267 if((w = *(WORD*)ptr) != 0xffff) {
3268 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3269 ptr += w;
3270 }
3271 ptr += 2;
3272
3273 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3274
3275 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3276
3277 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3278 ptr += 4;
3279
3280 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3281 ptr += 2;
3282
3283 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3284 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3285 else
3286 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3287 ptr += 2;
3288
3289 ptr += 4; /* skip res12 */
3290
3291 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3292 ptr += 2;
3293
3294 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3295 ptr += 2;
3296
3297 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3298 ptr += 2;
3299
3300 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3301 ptr += sizeof(GUID);
3302
3303 return ptr - (char*)pLibBlk;
3304 }
3305
3306 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3307 typedef struct
3308 {
3309 unsigned int num;
3310 HREFTYPE refs[1];
3311 } sltg_ref_lookup_t;
3312
3313 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3314 HREFTYPE *typelib_ref)
3315 {
3316 if(table && typeinfo_ref < table->num)
3317 {
3318 *typelib_ref = table->refs[typeinfo_ref];
3319 return S_OK;
3320 }
3321
3322 ERR_(typelib)("Unable to find reference\n");
3323 *typelib_ref = -1;
3324 return E_FAIL;
3325 }
3326
3327 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3328 {
3329 BOOL done = FALSE;
3330
3331 while(!done) {
3332 if((*pType & 0xe00) == 0xe00) {
3333 pTD->vt = VT_PTR;
3334 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3335 pTD = pTD->u.lptdesc;
3336 }
3337 switch(*pType & 0x3f) {
3338 case VT_PTR:
3339 pTD->vt = VT_PTR;
3340 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3341 pTD = pTD->u.lptdesc;
3342 break;
3343
3344 case VT_USERDEFINED:
3345 pTD->vt = VT_USERDEFINED;
3346 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3347 done = TRUE;
3348 break;
3349
3350 case VT_CARRAY:
3351 {
3352 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3353 array */
3354
3355 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3356
3357 pTD->vt = VT_CARRAY;
3358 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3359 pTD->u.lpadesc->cDims = pSA->cDims;
3360 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3361 pSA->cDims * sizeof(SAFEARRAYBOUND));
3362
3363 pTD = &pTD->u.lpadesc->tdescElem;
3364 break;
3365 }
3366
3367 case VT_SAFEARRAY:
3368 {
3369 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3370 useful? */
3371
3372 pType++;
3373 pTD->vt = VT_SAFEARRAY;
3374 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3375 pTD = pTD->u.lptdesc;
3376 break;
3377 }
3378 default:
3379 pTD->vt = *pType & 0x3f;
3380 done = TRUE;
3381 break;
3382 }
3383 pType++;
3384 }
3385 return pType;
3386 }
3387
3388 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3389 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3390 {
3391 /* Handle [in/out] first */
3392 if((*pType & 0xc000) == 0xc000)
3393 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3394 else if(*pType & 0x8000)
3395 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3396 else if(*pType & 0x4000)
3397 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3398 else
3399 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3400
3401 if(*pType & 0x2000)
3402 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3403
3404 if(*pType & 0x80)
3405 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3406
3407 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3408 }
3409
3410
3411 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3412 char *pNameTable)
3413 {
3414 unsigned int ref;
3415 char *name;
3416 TLBRefType *ref_type;
3417 sltg_ref_lookup_t *table;
3418 HREFTYPE typelib_ref;
3419
3420 if(pRef->magic != SLTG_REF_MAGIC) {
3421 FIXME("Ref magic = %x\n", pRef->magic);
3422 return NULL;
3423 }
3424 name = ( (char*)pRef->names + pRef->number);
3425
3426 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3427 table->num = pRef->number >> 3;
3428
3429 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3430
3431 /* We don't want the first href to be 0 */
3432 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3433
3434 for(ref = 0; ref < pRef->number >> 3; ref++) {
3435 char *refname;
3436 unsigned int lib_offs, type_num;
3437
3438 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3439
3440 name += SLTG_ReadStringA(name, &refname);
3441 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3442 FIXME_(typelib)("Can't sscanf ref\n");
3443 if(lib_offs != 0xffff) {
3444 TLBImpLib *import;
3445
3446 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3447 if(import->offset == lib_offs)
3448 break;
3449
3450 if(&import->entry == &pTL->implib_list) {
3451 char fname[MAX_PATH+1];
3452 int len;
3453
3454 import = heap_alloc_zero(sizeof(*import));
3455 import->offset = lib_offs;
3456 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3457 &import->guid);
3458 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3459 &import->wVersionMajor,
3460 &import->wVersionMinor,
3461 &import->lcid, fname) != 4) {
3462 FIXME_(typelib)("can't sscanf ref %s\n",
3463 pNameTable + lib_offs + 40);
3464 }
3465 len = strlen(fname);
3466 if(fname[len-1] != '#')
3467 FIXME("fname = %s\n", fname);
3468 fname[len-1] = '\0';
3469 import->name = TLB_MultiByteToBSTR(fname);
3470 list_add_tail(&pTL->implib_list, &import->entry);
3471 }
3472 ref_type->pImpTLInfo = import;
3473
3474 /* Store a reference to IDispatch */
3475 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3476 pTL->dispatch_href = typelib_ref;
3477
3478 } else { /* internal ref */
3479 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3480 }
3481 ref_type->reference = typelib_ref;
3482 ref_type->index = type_num;
3483
3484 heap_free(refname);
3485 list_add_tail(&pTL->ref_list, &ref_type->entry);
3486
3487 table->refs[ref] = typelib_ref;
3488 typelib_ref += 4;
3489 }
3490 if((BYTE)*name != SLTG_REF_MAGIC)
3491 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3492 dump_TLBRefType(pTL);
3493 return table;
3494 }
3495
3496 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3497 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3498 {
3499 SLTG_ImplInfo *info;
3500 TLBImplType *pImplType;
3501 /* I don't really get this structure, usually it's 0x16 bytes
3502 long, but iuser.tlb contains some that are 0x18 bytes long.
3503 That's ok because we can use the next ptr to jump to the next
3504 one. But how do we know the length of the last one? The WORD
3505 at offs 0x8 might be the clue. For now I'm just assuming that
3506 the last one is the regular 0x16 bytes. */
3507
3508 info = (SLTG_ImplInfo*)pBlk;
3509 while(1){
3510 pTI->TypeAttr.cImplTypes++;
3511 if(info->next == 0xffff)
3512 break;
3513 info = (SLTG_ImplInfo*)(pBlk + info->next);
3514 }
3515
3516 info = (SLTG_ImplInfo*)pBlk;
3517 pTI->impltypes = TLBImplType_Constructor(pTI->TypeAttr.cImplTypes);
3518 pImplType = pTI->impltypes;
3519 while(1) {
3520 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3521 pImplType->implflags = info->impltypeflags;
3522 ++pImplType;
3523
3524 if(info->next == 0xffff)
3525 break;
3526 if(OneOnly)
3527 FIXME_(typelib)("Interface inheriting more than one interface\n");
3528 info = (SLTG_ImplInfo*)(pBlk + info->next);
3529 }
3530 info++; /* see comment at top of function */
3531 return (char*)info;
3532 }
3533
3534 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3535 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3536 {
3537 TLBVarDesc *pVarDesc;
3538 BSTR bstrPrevName = NULL;
3539 SLTG_Variable *pItem;
3540 unsigned short i;
3541 WORD *pType;
3542
3543 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3544
3545 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3546 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3547
3548 pVarDesc->vardesc.memid = pItem->memid;
3549
3550 if (pItem->magic != SLTG_VAR_MAGIC &&
3551 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3552 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3553 return;
3554 }
3555
3556 if (pItem->name == 0xfffe)
3557 pVarDesc->Name = SysAllocString(bstrPrevName);
3558 else
3559 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3560
3561 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3562 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3563 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3564
3565 if(pItem->flags & 0x02)
3566 pType = &pItem->type;
3567 else
3568 pType = (WORD*)(pBlk + pItem->type);
3569
3570 if (pItem->flags & ~0xda)
3571 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3572
3573 SLTG_DoElem(pType, pBlk,
3574 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3575
3576 if (TRACE_ON(typelib)) {
3577 char buf[300];
3578 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3579 TRACE_(typelib)("elemdescVar: %s\n", buf);
3580 }
3581
3582 if (pItem->flags & 0x40) {
3583 TRACE_(typelib)("VAR_DISPATCH\n");
3584 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3585 }
3586 else if (pItem->flags & 0x10) {
3587 TRACE_(typelib)("VAR_CONST\n");
3588 pVarDesc->vardesc.varkind = VAR_CONST;
3589 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3590 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3591 if (pItem->flags & 0x08)
3592 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3593 else {
3594 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3595 {
3596 case VT_LPSTR:
3597 case VT_LPWSTR:
3598 case VT_BSTR:
3599 {
3600 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3601 BSTR str;
3602 TRACE_(typelib)("len = %u\n", len);
3603 if (len == 0xffff) {
3604 str = NULL;
3605 } else {
3606 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3607 str = SysAllocStringLen(NULL, alloc_len);
3608 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3609 }
3610 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3611 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3612 break;
3613 }
3614 case VT_I2:
3615 case VT_UI2:
3616 case VT_I4:
3617 case VT_UI4:
3618 case VT_INT:
3619 case VT_UINT:
3620 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3621 *(INT*)(pBlk + pItem->byte_offs);
3622 break;
3623 default:
3624 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3625 }
3626 }
3627 }
3628 else {
3629 TRACE_(typelib)("VAR_PERINSTANCE\n");
3630 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3631 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3632 }
3633
3634 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3635 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3636
3637 if (pItem->flags & 0x80)
3638 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3639
3640 bstrPrevName = pVarDesc->Name;
3641 }
3642 pTI->TypeAttr.cVars = cVars;
3643 }
3644
3645 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3646 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3647 {
3648 SLTG_Function *pFunc;
3649 unsigned short i;
3650 TLBFuncDesc *pFuncDesc;
3651
3652 pTI->funcdescs = TLBFuncDesc_Constructor(cFuncs);
3653
3654 pFuncDesc = pTI->funcdescs;
3655 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3656 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3657
3658 int param;
3659 WORD *pType, *pArg;
3660
3661 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3662 case SLTG_FUNCTION_MAGIC:
3663 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3664 break;
3665 case SLTG_DISPATCH_FUNCTION_MAGIC:
3666 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3667 break;
3668 case SLTG_STATIC_FUNCTION_MAGIC:
3669 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3670 break;
3671 default:
3672 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3673 continue;
3674 }
3675 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3676
3677 pFuncDesc->funcdesc.memid = pFunc->dispid;
3678 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3679 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3680 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3681 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3682 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3683
3684 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3685 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3686
3687 if(pFunc->retnextopt & 0x80)
3688 pType = &pFunc->rettype;
3689 else
3690 pType = (WORD*)(pBlk + pFunc->rettype);
3691
3692 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3693
3694 pFuncDesc->funcdesc.lprgelemdescParam =
3695 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3696 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3697
3698 pArg = (WORD*)(pBlk + pFunc->arg_off);
3699
3700 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3701 char *paramName = pNameTable + *pArg;
3702 BOOL HaveOffs;
3703 /* If arg type follows then paramName points to the 2nd
3704 letter of the name, else the next WORD is an offset to
3705 the arg type and paramName points to the first letter.
3706 So let's take one char off paramName and see if we're
3707 pointing at an alpha-numeric char. However if *pArg is
3708 0xffff or 0xfffe then the param has no name, the former
3709 meaning that the next WORD is the type, the latter
3710 meaning that the next WORD is an offset to the type. */
3711
3712 HaveOffs = FALSE;
3713 if(*pArg == 0xffff)
3714 paramName = NULL;
3715 else if(*pArg == 0xfffe) {
3716 paramName = NULL;
3717 HaveOffs = TRUE;
3718 }
3719 else if(paramName[-1] && !isalnum(paramName[-1]))
3720 HaveOffs = TRUE;
3721
3722 pArg++;
3723
3724 if(HaveOffs) { /* the next word is an offset to type */
3725 pType = (WORD*)(pBlk + *pArg);
3726 SLTG_DoElem(pType, pBlk,
3727 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3728 pArg++;
3729 } else {
3730 if(paramName)
3731 paramName--;
3732 pArg = SLTG_DoElem(pArg, pBlk,
3733 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3734 }
3735
3736 /* Are we an optional param ? */
3737 if(pFuncDesc->funcdesc.cParams - param <=
3738 pFuncDesc->funcdesc.cParamsOpt)
3739 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3740
3741 if(paramName) {
3742 pFuncDesc->pParamDesc[param].Name =
3743 TLB_MultiByteToBSTR(paramName);
3744 } else {
3745 pFuncDesc->pParamDesc[param].Name =
3746 SysAllocString(pFuncDesc->Name);
3747 }
3748 }
3749 }
3750 pTI->TypeAttr.cFuncs = cFuncs;
3751 }
3752
3753 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3754 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3755 SLTG_TypeInfoTail *pTITail)
3756 {
3757 char *pFirstItem;
3758 sltg_ref_lookup_t *ref_lookup = NULL;
3759
3760 if(pTIHeader->href_table != 0xffffffff) {
3761 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3762 pNameTable);
3763 }
3764
3765 pFirstItem = pBlk;
3766
3767 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3768 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3769 }
3770 heap_free(ref_lookup);
3771 }
3772
3773
3774 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3775 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3776 const SLTG_TypeInfoTail *pTITail)
3777 {
3778 char *pFirstItem;
3779 sltg_ref_lookup_t *ref_lookup = NULL;
3780
3781 if(pTIHeader->href_table != 0xffffffff) {
3782 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3783 pNameTable);
3784 }
3785
3786 pFirstItem = pBlk;
3787
3788 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3789 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3790 }
3791
3792 if (pTITail->funcs_off != 0xffff)
3793 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3794
3795 heap_free(ref_lookup);
3796
3797 if (TRACE_ON(typelib))
3798 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3799 }
3800
3801 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3802 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3803 const SLTG_TypeInfoTail *pTITail)
3804 {
3805 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3806 }
3807
3808 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3809 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3810 const SLTG_TypeInfoTail *pTITail)
3811 {
3812 WORD *pType;
3813 sltg_ref_lookup_t *ref_lookup = NULL;
3814
3815 if (pTITail->simple_alias) {
3816 /* if simple alias, no more processing required */
3817 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3818 return;
3819 }
3820
3821 if(pTIHeader->href_table != 0xffffffff) {
3822 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3823 pNameTable);
3824 }
3825
3826 /* otherwise it is an offset to a type */
3827 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3828
3829 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3830
3831 heap_free(ref_lookup);
3832 }
3833
3834 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3835 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3836 const SLTG_TypeInfoTail *pTITail)
3837 {
3838 sltg_ref_lookup_t *ref_lookup = NULL;
3839 if (pTIHeader->href_table != 0xffffffff)
3840 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3841 pNameTable);
3842
3843 if (pTITail->vars_off != 0xffff)
3844 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3845
3846 if (pTITail->funcs_off != 0xffff)
3847 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3848
3849 if (pTITail->impls_off != 0xffff)
3850 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3851
3852 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3853 * of dispinterface functions including the IDispatch ones, so
3854 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3855 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3856
3857 heap_free(ref_lookup);
3858 if (TRACE_ON(typelib))
3859 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3860 }
3861
3862 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3863 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3864 const SLTG_TypeInfoTail *pTITail)
3865 {
3866 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3867 }
3868
3869 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3870 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3871 const SLTG_TypeInfoTail *pTITail)
3872 {
3873 sltg_ref_lookup_t *ref_lookup = NULL;
3874 if (pTIHeader->href_table != 0xffffffff)
3875 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3876 pNameTable);
3877
3878 if (pTITail->vars_off != 0xffff)
3879 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3880
3881 if (pTITail->funcs_off != 0xffff)
3882 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3883 heap_free(ref_lookup);
3884 if (TRACE_ON(typelib))
3885 dump_TypeInfo(pTI);
3886 }
3887
3888 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3889 manageable copy of it into this */
3890 typedef struct {
3891 WORD small_no;
3892 char *index_name;
3893 char *other_name;
3894 WORD res1a;
3895 WORD name_offs;
3896 WORD more_bytes;
3897 char *extra;
3898 WORD res20;
3899 DWORD helpcontext;
3900 WORD res26;
3901 GUID uuid;
3902 } SLTG_InternalOtherTypeInfo;
3903
3904 /****************************************************************************
3905 * ITypeLib2_Constructor_SLTG
3906 *
3907 * loading a SLTG typelib from an in-memory image
3908 */
3909 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3910 {
3911 ITypeLibImpl *pTypeLibImpl;
3912 SLTG_Header *pHeader;
3913 SLTG_BlkEntry *pBlkEntry;
3914 SLTG_Magic *pMagic;
3915 SLTG_Index *pIndex;
3916 SLTG_Pad9 *pPad9;
3917 LPVOID pBlk, pFirstBlk;
3918 SLTG_LibBlk *pLibBlk;
3919 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3920 char *pAfterOTIBlks = NULL;
3921 char *pNameTable, *ptr;
3922 int i;
3923 DWORD len, order;
3924 ITypeInfoImpl **ppTypeInfoImpl;
3925
3926 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3927
3928
3929 pTypeLibImpl = TypeLibImpl_Constructor();
3930 if (!pTypeLibImpl) return NULL;
3931
3932 pHeader = pLib;
3933
3934 TRACE_(typelib)("header:\n");
3935 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3936 pHeader->nrOfFileBlks );
3937 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3938 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3939 pHeader->SLTG_magic);
3940 return NULL;
3941 }
3942
3943 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3944 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3945
3946 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3947 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3948
3949 /* Next we have a magic block */
3950 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3951
3952 /* Let's see if we're still in sync */
3953 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3954 sizeof(SLTG_COMPOBJ_MAGIC))) {
3955 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3956 return NULL;
3957 }
3958 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3959 sizeof(SLTG_DIR_MAGIC))) {
3960 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3961 return NULL;
3962 }
3963
3964 pIndex = (SLTG_Index*)(pMagic+1);
3965
3966 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3967
3968 pFirstBlk = pPad9 + 1;
3969
3970 /* We'll set up a ptr to the main library block, which is the last one. */
3971
3972 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3973 pBlkEntry[order].next != 0;
3974 order = pBlkEntry[order].next - 1, i++) {
3975 pBlk = (char*)pBlk + pBlkEntry[order].len;
3976 }
3977 pLibBlk = pBlk;
3978
3979 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3980
3981 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3982 interspersed */
3983
3984 len += 0x40;
3985
3986 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3987
3988 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3989
3990
3991 ptr = (char*)pLibBlk + len;
3992
3993 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3994 WORD w, extra;
3995 len = 0;
3996
3997 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3998
3999 w = *(WORD*)(ptr + 2);
4000 if(w != 0xffff) {
4001 len += w;
4002 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4003 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4004 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4005 }
4006 w = *(WORD*)(ptr + 4 + len);
4007 if(w != 0xffff) {
4008 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4009 len += w;
4010 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4011 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4012 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4013 }
4014 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4015 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4016 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4017 if(extra) {
4018 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4019 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4020 len += extra;
4021 }
4022 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4023 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4024 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4025 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4026 len += sizeof(SLTG_OtherTypeInfo);
4027 ptr += len;
4028 }
4029
4030 pAfterOTIBlks = ptr;
4031
4032 /* Skip this WORD and get the next DWORD */
4033 len = *(DWORD*)(pAfterOTIBlks + 2);
4034
4035 /* Now add this to pLibBLk look at what we're pointing at and
4036 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4037 dust and we should be pointing at the beginning of the name
4038 table */
4039
4040 pNameTable = (char*)pLibBlk + len;
4041
4042 switch(*(WORD*)pNameTable) {
4043 case 0xffff:
4044 break;
4045 case 0x0200:
4046 pNameTable += 0x20;
4047 break;
4048 default:
4049 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4050 break;
4051 }
4052
4053 pNameTable += 0x216;
4054
4055 pNameTable += 2;
4056
4057 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4058
4059 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4060
4061
4062 /* Hopefully we now have enough ptrs set up to actually read in
4063 some TypeInfos. It's not clear which order to do them in, so
4064 I'll just follow the links along the BlkEntry chain and read
4065 them in the order in which they are in the file */
4066
4067 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4068 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4069
4070 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4071 pBlkEntry[order].next != 0;
4072 order = pBlkEntry[order].next - 1, i++) {
4073
4074 SLTG_TypeInfoHeader *pTIHeader;
4075 SLTG_TypeInfoTail *pTITail;
4076 SLTG_MemberHeader *pMemHeader;
4077
4078 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4079 FIXME_(typelib)("Index strings don't match\n");
4080 heap_free(pOtherTypeInfoBlks);
4081 return NULL;
4082 }
4083
4084 pTIHeader = pBlk;
4085 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4086 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4087 heap_free(pOtherTypeInfoBlks);
4088 return NULL;
4089 }
4090 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4091 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4092 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4093
4094 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4095 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4096 (*ppTypeInfoImpl)->index = i;
4097 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4098 pOtherTypeInfoBlks[i].name_offs +
4099 pNameTable);
4100 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4101 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4102 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4103 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4104 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4105 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4106 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4107
4108 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4109 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4110
4111 if((pTIHeader->typeflags1 & 7) != 2)
4112 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4113 if(pTIHeader->typeflags3 != 2)
4114 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4115
4116 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4117 debugstr_w((*ppTypeInfoImpl)->Name),
4118 typekind_desc[pTIHeader->typekind],
4119 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4120 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4121
4122 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4123
4124 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4125
4126 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4127 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4128 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4129
4130 switch(pTIHeader->typekind) {
4131 case TKIND_ENUM:
4132 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4133 pTIHeader, pTITail);
4134 break;
4135
4136 case TKIND_RECORD:
4137 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4138 pTIHeader, pTITail);
4139 break;
4140
4141 case TKIND_INTERFACE:
4142 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4143 pTIHeader, pTITail);
4144 break;
4145
4146 case TKIND_COCLASS:
4147 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4148 pTIHeader, pTITail);
4149 break;
4150
4151 case TKIND_ALIAS:
4152 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4153 pTIHeader, pTITail);
4154 break;
4155
4156 case TKIND_DISPATCH:
4157 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4158 pTIHeader, pTITail);
4159 break;
4160
4161 case TKIND_MODULE:
4162 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4163 pTIHeader, pTITail);
4164 break;
4165
4166 default:
4167 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4168 break;
4169
4170 }
4171
4172 /* could get cFuncs, cVars and cImplTypes from here
4173 but we've already set those */
4174 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4175 X(06);
4176 X(16);
4177 X(18);
4178 X(1a);
4179 X(1e);
4180 X(24);
4181 X(26);
4182 X(2a);
4183 X(2c);
4184 X(2e);
4185 X(30);
4186 X(32);
4187 X(34);
4188 #undef X
4189 ++ppTypeInfoImpl;
4190 pBlk = (char*)pBlk + pBlkEntry[order].len;
4191 }
4192
4193 if(i != pTypeLibImpl->TypeInfoCount) {
4194 FIXME("Somehow processed %d TypeInfos\n", i);
4195 heap_free(pOtherTypeInfoBlks);
4196 return NULL;
4197 }
4198
4199 heap_free(pOtherTypeInfoBlks);
4200 return (ITypeLib2*)pTypeLibImpl;
4201 }
4202
4203 /* ITypeLib::QueryInterface
4204 */
4205 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4206 ITypeLib2 * iface,
4207 REFIID riid,
4208 VOID **ppvObject)
4209 {
4210 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4211
4212 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4213
4214 *ppvObject=NULL;
4215 if(IsEqualIID(riid, &IID_IUnknown) ||
4216 IsEqualIID(riid,&IID_ITypeLib)||
4217 IsEqualIID(riid,&IID_ITypeLib2))
4218 {
4219 *ppvObject = This;
4220 }
4221
4222 if(*ppvObject)
4223 {
4224 ITypeLib2_AddRef(iface);
4225 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4226 return S_OK;
4227 }
4228 TRACE("-- Interface: E_NOINTERFACE\n");
4229 return E_NOINTERFACE;
4230 }
4231
4232 /* ITypeLib::AddRef
4233 */
4234 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4235 {
4236 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4237 ULONG ref = InterlockedIncrement(&This->ref);
4238
4239 TRACE("(%p)->ref was %u\n",This, ref - 1);
4240
4241 return ref;
4242 }
4243
4244 /* ITypeLib::Release
4245 */
4246 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4247 {
4248 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4249 ULONG ref = InterlockedDecrement(&This->ref);
4250
4251 TRACE("(%p)->(%u)\n",This, ref);
4252
4253 if (!ref)
4254 {
4255 TLBImpLib *pImpLib, *pImpLibNext;
4256 TLBRefType *ref_type;
4257 void *cursor2;
4258 int i;
4259
4260 /* remove cache entry */
4261 if(This->path)
4262 {
4263 TRACE("removing from cache list\n");
4264 EnterCriticalSection(&cache_section);
4265 if(This->entry.next)
4266 list_remove(&This->entry);
4267 LeaveCriticalSection(&cache_section);
4268 heap_free(This->path);
4269 }
4270 TRACE(" destroying ITypeLib(%p)\n",This);
4271
4272 SysFreeString(This->Name);
4273 This->Name = NULL;
4274
4275 SysFreeString(This->DocString);
4276 This->DocString = NULL;
4277
4278 SysFreeString(This->HelpFile);
4279 This->HelpFile = NULL;
4280
4281 SysFreeString(This->HelpStringDll);
4282 This->HelpStringDll = NULL;
4283
4284 TLB_FreeCustData(&This->custdata_list);
4285
4286 for (i = 0; i < This->ctTypeDesc; i++)
4287 if (This->pTypeDesc[i].vt == VT_CARRAY)
4288 heap_free(This->pTypeDesc[i].u.lpadesc);
4289
4290 heap_free(This->pTypeDesc);
4291
4292 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4293 {
4294 if (pImpLib->pImpTypeLib)
4295 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4296 SysFreeString(pImpLib->name);
4297
4298 list_remove(&pImpLib->entry);
4299 heap_free(pImpLib);
4300 }
4301
4302 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4303 {
4304 list_remove(&ref_type->entry);
4305 heap_free(ref_type);
4306 }
4307
4308 for (i = 0; i < This->TypeInfoCount; ++i)
4309 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4310 heap_free(This->typeinfos);
4311 heap_free(This);
4312 return 0;
4313 }
4314
4315 return ref;
4316 }
4317
4318 /* ITypeLib::GetTypeInfoCount
4319 *
4320 * Returns the number of type descriptions in the type library
4321 */
4322 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4323 {
4324 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4325 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4326 return This->TypeInfoCount;
4327 }
4328
4329 /* ITypeLib::GetTypeInfo
4330 *
4331 * retrieves the specified type description in the library.
4332 */
4333 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4334 ITypeLib2 *iface,
4335 UINT index,
4336 ITypeInfo **ppTInfo)
4337 {
4338 ITypeLibImpl *This = (ITypeLibImpl*)iface;
4339
4340 TRACE("%p %u %p\n", This, index, ppTInfo);
4341
4342 if(!ppTInfo)
4343 return E_INVALIDARG;
4344
4345 if(index >= This->TypeInfoCount)
4346 return TYPE_E_ELEMENTNOTFOUND;
4347
4348 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4349 ITypeInfo_AddRef(*ppTInfo);
4350
4351 return S_OK;
4352 }
4353
4354
4355 /* ITypeLibs::GetTypeInfoType
4356 *
4357 * Retrieves the type of a type description.
4358 */
4359 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4360 ITypeLib2 *iface,
4361 UINT index,
4362 TYPEKIND *pTKind)
4363 {
4364 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4365
4366 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4367
4368 if(!pTKind)
4369 return E_INVALIDARG;
4370
4371 if(index >= This->TypeInfoCount)
4372 return TYPE_E_ELEMENTNOTFOUND;
4373
4374 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4375
4376 return S_OK;
4377 }
4378
4379 /* ITypeLib::GetTypeInfoOfGuid
4380 *
4381 * Retrieves the type description that corresponds to the specified GUID.
4382 *
4383 */
4384 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4385 ITypeLib2 *iface,
4386 REFGUID guid,
4387 ITypeInfo **ppTInfo)
4388 {
4389 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4390 UINT i;
4391
4392 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4393
4394 for(i = 0; i < This->TypeInfoCount; ++i){
4395 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4396 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4397 ITypeInfo_AddRef(*ppTInfo);
4398 return S_OK;
4399 }
4400 }
4401
4402 return TYPE_E_ELEMENTNOTFOUND;
4403 }
4404
4405 /* ITypeLib::GetLibAttr
4406 *
4407 * Retrieves the structure that contains the library's attributes.
4408 *
4409 */
4410 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4411 ITypeLib2 *iface,
4412 LPTLIBATTR *attr)
4413 {
4414 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4415
4416 TRACE("(%p, %p)\n", This, attr);
4417
4418 if (!attr) return E_INVALIDARG;
4419
4420 *attr = heap_alloc(sizeof(**attr));
4421 if (!*attr) return E_OUTOFMEMORY;
4422
4423 **attr = This->LibAttr;
4424 return S_OK;
4425 }
4426
4427 /* ITypeLib::GetTypeComp
4428 *
4429 * Enables a client compiler to bind to a library's types, variables,
4430 * constants, and global functions.
4431 *
4432 */
4433 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4434 ITypeLib2 *iface,
4435 ITypeComp **ppTComp)
4436 {
4437 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4438
4439 TRACE("(%p)->(%p)\n",This,ppTComp);
4440 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4441 ITypeComp_AddRef(*ppTComp);
4442
4443 return S_OK;
4444 }
4445
4446 /* ITypeLib::GetDocumentation
4447 *
4448 * Retrieves the library's documentation string, the complete Help file name
4449 * and path, and the context identifier for the library Help topic in the Help
4450 * file.
4451 *
4452 * On a successful return all non-null BSTR pointers will have been set,
4453 * possibly to NULL.
4454 */
4455 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4456 ITypeLib2 *iface,
4457 INT index,
4458 BSTR *pBstrName,
4459 BSTR *pBstrDocString,
4460 DWORD *pdwHelpContext,
4461 BSTR *pBstrHelpFile)
4462 {
4463 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4464
4465 HRESULT result = E_INVALIDARG;
4466
4467 ITypeInfo *pTInfo;
4468
4469
4470 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4471 This, index,
4472 pBstrName, pBstrDocString,
4473 pdwHelpContext, pBstrHelpFile);
4474
4475 if(index<0)
4476 {
4477 /* documentation for the typelib */
4478 if(pBstrName)
4479 {
4480 if (This->Name)
4481 {
4482 if(!(*pBstrName = SysAllocString(This->Name)))
4483 goto memerr1;
4484 }
4485 else
4486 *pBstrName = NULL;
4487 }
4488 if(pBstrDocString)
4489 {
4490 if (This->DocString)
4491 {
4492 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4493 goto memerr2;
4494 }
4495 else if (This->Name)
4496 {
4497 if(!(*pBstrDocString = SysAllocString(This->Name)))
4498 goto memerr2;
4499 }
4500 else
4501 *pBstrDocString = NULL;
4502 }
4503 if(pdwHelpContext)
4504 {
4505 *pdwHelpContext = This->dwHelpContext;
4506 }
4507 if(pBstrHelpFile)
4508 {
4509 if (This->HelpFile)
4510 {
4511 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4512 goto memerr3;
4513 }
4514 else
4515 *pBstrHelpFile = NULL;
4516 }
4517
4518 result = S_OK;
4519 }
4520 else
4521 {
4522 /* for a typeinfo */
4523 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4524
4525 if(SUCCEEDED(result))
4526 {
4527 result = ITypeInfo_GetDocumentation(pTInfo,
4528 MEMBERID_NIL,
4529 pBstrName,
4530 pBstrDocString,
4531 pdwHelpContext, pBstrHelpFile);
4532
4533 ITypeInfo_Release(pTInfo);
4534 }
4535 }
4536 return result;
4537 memerr3:
4538 if (pBstrDocString) SysFreeString (*pBstrDocString);
4539 memerr2:
4540 if (pBstrName) SysFreeString (*pBstrName);
4541 memerr1:
4542 return STG_E_INSUFFICIENTMEMORY;
4543 }
4544
4545 /* ITypeLib::IsName
4546 *
4547 * Indicates whether a passed-in string contains the name of a type or member
4548 * described in the library.
4549 *
4550 */
4551 static HRESULT WINAPI ITypeLib2_fnIsName(
4552 ITypeLib2 *iface,
4553 LPOLESTR szNameBuf,
4554 ULONG lHashVal,
4555 BOOL *pfName)
4556 {
4557 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4558 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), tic, fdc, vrc, pc;
4559
4560 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4561 pfName);
4562
4563 *pfName=TRUE;
4564 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4565 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4566 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4567 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4568 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4569 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4570 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4571 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4572 goto ITypeLib2_fnIsName_exit;
4573 }
4574 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4575 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4576 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4577 }
4578
4579 }
4580 *pfName=FALSE;
4581
4582 ITypeLib2_fnIsName_exit:
4583 TRACE("(%p)slow! search for %s: %s found!\n", This,
4584 debugstr_w(szNameBuf), *pfName?"NOT":"");
4585
4586 return S_OK;
4587 }
4588
4589 /* ITypeLib::FindName
4590 *
4591 * Finds occurrences of a type description in a type library. This may be used
4592 * to quickly verify that a name exists in a type library.
4593 *
4594 */
4595 static HRESULT WINAPI ITypeLib2_fnFindName(
4596 ITypeLib2 *iface,
4597 LPOLESTR name,
4598 ULONG hash,
4599 ITypeInfo **ppTInfo,
4600 MEMBERID *memid,
4601 UINT16 *found)
4602 {
4603 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4604 UINT tic, count = 0;
4605 UINT len;
4606
4607 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4608
4609 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4610 return E_INVALIDARG;
4611
4612 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4613 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4614 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4615 TLBVarDesc *var;
4616 UINT fdc;
4617
4618 if(!memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4619 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4620 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4621 UINT pc;
4622
4623 if(!memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4624 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4625 if(!memcmp(name, func->pParamDesc[pc].Name, len))
4626 goto ITypeLib2_fnFindName_exit;
4627 }
4628 }
4629
4630 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, name);
4631 if (var)
4632 goto ITypeLib2_fnFindName_exit;
4633
4634 continue;
4635 ITypeLib2_fnFindName_exit:
4636 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4637 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4638 count++;
4639 }
4640 TRACE("found %d typeinfos\n", count);
4641
4642 *found = count;
4643
4644 return S_OK;
4645 }
4646
4647 /* ITypeLib::ReleaseTLibAttr
4648 *
4649 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4650 *
4651 */
4652 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4653 ITypeLib2 *iface,
4654 TLIBATTR *pTLibAttr)
4655 {
4656 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4657 TRACE("freeing (%p)\n",This);
4658 heap_free(pTLibAttr);
4659
4660 }
4661
4662 /* ITypeLib2::GetCustData
4663 *
4664 * gets the custom data
4665 */
4666 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4667 ITypeLib2 * iface,
4668 REFGUID guid,
4669 VARIANT *pVarVal)
4670 {
4671 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4672 TLBCustData *pCData;
4673
4674 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
4675
4676 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4677 if(!pCData)
4678 return TYPE_E_ELEMENTNOTFOUND;
4679
4680 VariantInit(pVarVal);
4681 VariantCopy(pVarVal, &pCData->data);
4682
4683 return S_OK;
4684 }
4685
4686 /* ITypeLib2::GetLibStatistics
4687 *
4688 * Returns statistics about a type library that are required for efficient
4689 * sizing of hash tables.
4690 *
4691 */
4692 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4693 ITypeLib2 * iface,
4694 ULONG *pcUniqueNames,
4695 ULONG *pcchUniqueNames)
4696 {
4697 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4698
4699 FIXME("(%p): stub!\n", This);
4700
4701 if(pcUniqueNames) *pcUniqueNames=1;
4702 if(pcchUniqueNames) *pcchUniqueNames=1;
4703 return S_OK;
4704 }
4705
4706 /* ITypeLib2::GetDocumentation2
4707 *
4708 * Retrieves the library's documentation string, the complete Help file name
4709 * and path, the localization context to use, and the context ID for the
4710 * library Help topic in the Help file.
4711 *
4712 */
4713 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4714 ITypeLib2 * iface,
4715 INT index,
4716 LCID lcid,
4717 BSTR *pbstrHelpString,
4718 DWORD *pdwHelpStringContext,
4719 BSTR *pbstrHelpStringDll)
4720 {
4721 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4722 HRESULT result;
4723 ITypeInfo *pTInfo;
4724
4725 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4726
4727 /* the help string should be obtained from the helpstringdll,
4728 * using the _DLLGetDocumentation function, based on the supplied
4729 * lcid. Nice to do sometime...
4730 */
4731 if(index<0)
4732 {
4733 /* documentation for the typelib */
4734 if(pbstrHelpString)
4735 *pbstrHelpString=SysAllocString(This->DocString);
4736 if(pdwHelpStringContext)
4737 *pdwHelpStringContext=This->dwHelpContext;
4738 if(pbstrHelpStringDll)
4739 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4740
4741 result = S_OK;
4742 }
4743 else
4744 {
4745 /* for a typeinfo */
4746 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4747
4748 if(SUCCEEDED(result))
4749 {
4750 ITypeInfo2 * pTInfo2;
4751 result = ITypeInfo_QueryInterface(pTInfo,
4752 &IID_ITypeInfo2,
4753 (LPVOID*) &pTInfo2);
4754
4755 if(SUCCEEDED(result))
4756 {
4757 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4758 MEMBERID_NIL,
4759 lcid,
4760 pbstrHelpString,
4761 pdwHelpStringContext,
4762 pbstrHelpStringDll);
4763
4764 ITypeInfo2_Release(pTInfo2);
4765 }
4766
4767 ITypeInfo_Release(pTInfo);
4768 }
4769 }
4770 return result;
4771 }
4772
4773 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4774 {
4775 TLBCustData *pCData;
4776 unsigned int ct;
4777 CUSTDATAITEM *cdi;
4778
4779 ct = list_count(custdata_list);
4780
4781 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4782 if(!pCustData->prgCustData)
4783 return E_OUTOFMEMORY;
4784
4785 pCustData->cCustData = ct;
4786
4787 cdi = pCustData->prgCustData;
4788 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4789 cdi->guid = pCData->guid;
4790 VariantCopy(&cdi->varValue, &pCData->data);
4791 ++cdi;
4792 }
4793
4794 return S_OK;
4795 }
4796
4797
4798 /* ITypeLib2::GetAllCustData
4799 *
4800 * Gets all custom data items for the library.
4801 *
4802 */
4803 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4804 ITypeLib2 * iface,
4805 CUSTDATA *pCustData)
4806 {
4807 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4808 TRACE("%p %p\n", iface, pCustData);
4809 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4810 }
4811
4812 static const ITypeLib2Vtbl tlbvt = {
4813 ITypeLib2_fnQueryInterface,
4814 ITypeLib2_fnAddRef,
4815 ITypeLib2_fnRelease,
4816 ITypeLib2_fnGetTypeInfoCount,
4817 ITypeLib2_fnGetTypeInfo,
4818 ITypeLib2_fnGetTypeInfoType,
4819 ITypeLib2_fnGetTypeInfoOfGuid,
4820 ITypeLib2_fnGetLibAttr,
4821 ITypeLib2_fnGetTypeComp,
4822 ITypeLib2_fnGetDocumentation,
4823 ITypeLib2_fnIsName,
4824 ITypeLib2_fnFindName,
4825 ITypeLib2_fnReleaseTLibAttr,
4826
4827 ITypeLib2_fnGetCustData,
4828 ITypeLib2_fnGetLibStatistics,
4829 ITypeLib2_fnGetDocumentation2,
4830 ITypeLib2_fnGetAllCustData
4831 };
4832
4833
4834 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4835 {
4836 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4837
4838 return ITypeLib2_QueryInterface((ITypeLib2 *)This, riid, ppv);
4839 }
4840
4841 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4842 {
4843 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4844
4845 return ITypeLib2_AddRef((ITypeLib2 *)This);
4846 }
4847
4848 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4849 {
4850 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4851
4852 return ITypeLib2_Release((ITypeLib2 *)This);
4853 }
4854
4855 static HRESULT WINAPI ITypeLibComp_fnBind(
4856 ITypeComp * iface,
4857 OLECHAR * szName,
4858 ULONG lHash,
4859 WORD wFlags,
4860 ITypeInfo ** ppTInfo,
4861 DESCKIND * pDescKind,
4862 BINDPTR * pBindPtr)
4863 {
4864 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4865 int typemismatch=0, i;
4866
4867 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4868
4869 *pDescKind = DESCKIND_NONE;
4870 pBindPtr->lptcomp = NULL;
4871 *ppTInfo = NULL;
4872
4873 for(i = 0; i < This->TypeInfoCount; ++i){
4874 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4875 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4876
4877 /* FIXME: check wFlags here? */
4878 /* FIXME: we should use a hash table to look this info up using lHash
4879 * instead of an O(n) search */
4880 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4881 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4882 {
4883 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4884 {
4885 *pDescKind = DESCKIND_TYPECOMP;
4886 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4887 ITypeComp_AddRef(pBindPtr->lptcomp);
4888 TRACE("module or enum: %s\n", debugstr_w(szName));
4889 return S_OK;
4890 }
4891 }
4892
4893 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4894 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4895 {
4896 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4897 HRESULT hr;
4898
4899 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4900 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4901 {
4902 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4903 return S_OK;
4904 }
4905 else if (hr == TYPE_E_TYPEMISMATCH)
4906 typemismatch = 1;
4907 }
4908
4909 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4910 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4911 {
4912 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4913 HRESULT hr;
4914 ITypeInfo *subtypeinfo;
4915 BINDPTR subbindptr;
4916 DESCKIND subdesckind;
4917
4918 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4919 &subtypeinfo, &subdesckind, &subbindptr);
4920 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4921 {
4922 TYPEDESC tdesc_appobject;
4923 const VARDESC vardesc_appobject =
4924 {
4925 -2, /* memid */
4926 NULL, /* lpstrSchema */
4927 {
4928 0 /* oInst */
4929 },
4930 {
4931 /* ELEMDESC */
4932 {
4933 /* TYPEDESC */
4934 {
4935 &tdesc_appobject
4936 },
4937 VT_PTR
4938 },
4939 },
4940 0, /* wVarFlags */
4941 VAR_STATIC /* varkind */
4942 };
4943
4944 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4945 tdesc_appobject.vt = VT_USERDEFINED;
4946
4947 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4948
4949 /* cleanup things filled in by Bind call so we can put our
4950 * application object data in there instead */
4951 switch (subdesckind)
4952 {
4953 case DESCKIND_FUNCDESC:
4954 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4955 break;
4956 case DESCKIND_VARDESC:
4957 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4958 break;
4959 default:
4960 break;
4961 }
4962 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4963
4964 if (pTypeInfo->hreftype == -1)
4965 FIXME("no hreftype for interface %p\n", pTypeInfo);
4966
4967 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4968 if (FAILED(hr))
4969 return hr;
4970
4971 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4972 *ppTInfo = (ITypeInfo *)pTypeInfo;
4973 ITypeInfo_AddRef(*ppTInfo);
4974 return S_OK;
4975 }
4976 else if (hr == TYPE_E_TYPEMISMATCH)
4977 typemismatch = 1;
4978 }
4979 }
4980
4981 if (typemismatch)
4982 {
4983 TRACE("type mismatch %s\n", debugstr_w(szName));
4984 return TYPE_E_TYPEMISMATCH;
4985 }
4986 else
4987 {
4988 TRACE("name not found %s\n", debugstr_w(szName));
4989 return S_OK;
4990 }
4991 }
4992
4993 static HRESULT WINAPI ITypeLibComp_fnBindType(
4994 ITypeComp * iface,
4995 OLECHAR * szName,
4996 ULONG lHash,
4997 ITypeInfo ** ppTInfo,
4998 ITypeComp ** ppTComp)
4999 {
5000 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5001 UINT i;
5002
5003 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5004
5005 if(!szName || !ppTInfo || !ppTComp)
5006 return E_INVALIDARG;
5007
5008 for(i = 0; i < This->TypeInfoCount; ++i)
5009 {
5010 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5011 /* FIXME: should use lHash to do the search */
5012 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
5013 {
5014 TRACE("returning %p\n", pTypeInfo);
5015 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
5016 ITypeInfo_AddRef(*ppTInfo);
5017 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
5018 ITypeComp_AddRef(*ppTComp);
5019 return S_OK;
5020 }
5021 }
5022
5023 TRACE("not found\n");
5024 *ppTInfo = NULL;
5025 *ppTComp = NULL;
5026 return S_OK;
5027 }
5028
5029 static const ITypeCompVtbl tlbtcvt =
5030 {
5031
5032 ITypeLibComp_fnQueryInterface,
5033 ITypeLibComp_fnAddRef,
5034 ITypeLibComp_fnRelease,
5035
5036 ITypeLibComp_fnBind,
5037 ITypeLibComp_fnBindType
5038 };
5039
5040 /*================== ITypeInfo(2) Methods ===================================*/
5041 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5042 {
5043 ITypeInfoImpl *pTypeInfoImpl;
5044
5045 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5046 if (pTypeInfoImpl)
5047 {
5048 pTypeInfoImpl->lpVtbl = &tinfvt;
5049 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
5050 pTypeInfoImpl->ref = 0;
5051 pTypeInfoImpl->hreftype = -1;
5052 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5053 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5054 list_init(&pTypeInfoImpl->custdata_list);
5055 }
5056 TRACE("(%p)\n", pTypeInfoImpl);
5057 return pTypeInfoImpl;
5058 }
5059
5060 /* ITypeInfo::QueryInterface
5061 */
5062 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5063 ITypeInfo2 *iface,
5064 REFIID riid,
5065 VOID **ppvObject)
5066 {
5067 ITypeLibImpl *This = (ITypeLibImpl *)iface;
5068
5069 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5070
5071 *ppvObject=NULL;
5072 if(IsEqualIID(riid, &IID_IUnknown) ||
5073 IsEqualIID(riid,&IID_ITypeInfo)||
5074 IsEqualIID(riid,&IID_ITypeInfo2))
5075 *ppvObject = This;
5076
5077 if(*ppvObject){
5078 ITypeInfo2_AddRef(iface);
5079 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5080 return S_OK;
5081 }
5082 TRACE("-- Interface: E_NOINTERFACE\n");
5083 return E_NOINTERFACE;
5084 }
5085
5086 /* ITypeInfo::AddRef
5087 */
5088 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5089 {
5090 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5091 ULONG ref = InterlockedIncrement(&This->ref);
5092
5093 TRACE("(%p)->ref is %u\n",This, ref);
5094
5095 if (ref == 1 /* incremented from 0 */)
5096 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5097
5098 return ref;
5099 }
5100
5101 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5102 {
5103 UINT i, j;
5104
5105 TRACE("destroying ITypeInfo(%p)\n",This);
5106
5107 SysFreeString(This->Name);
5108 This->Name = NULL;
5109
5110 SysFreeString(This->DocString);
5111 This->DocString = NULL;
5112
5113 SysFreeString(This->DllName);
5114 This->DllName = NULL;
5115
5116 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5117 {
5118 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5119 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5120 {
5121 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5122 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5123 {
5124 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5125 heap_free(elemdesc->u.paramdesc.pparamdescex);
5126 }
5127 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5128 SysFreeString(pFInfo->pParamDesc[j].Name);
5129 }
5130 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5131 heap_free(pFInfo->pParamDesc);
5132 TLB_FreeCustData(&pFInfo->custdata_list);
5133 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5134 SysFreeString(pFInfo->Entry);
5135 SysFreeString(pFInfo->HelpString);
5136 SysFreeString(pFInfo->Name);
5137 }
5138 heap_free(This->funcdescs);
5139
5140 for(i = 0; i < This->TypeAttr.cVars; ++i)
5141 {
5142 TLBVarDesc *pVInfo = &This->vardescs[i];
5143 if (pVInfo->vardesc.varkind == VAR_CONST)
5144 {
5145 VariantClear(pVInfo->vardesc.u.lpvarValue);
5146 heap_free(pVInfo->vardesc.u.lpvarValue);
5147 }
5148 TLB_FreeCustData(&pVInfo->custdata_list);
5149 SysFreeString(pVInfo->Name);
5150 SysFreeString(pVInfo->HelpString);
5151 }
5152 heap_free(This->vardescs);
5153
5154 if(This->impltypes){
5155 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5156 TLBImplType *pImpl = &This->impltypes[i];
5157 TLB_FreeCustData(&pImpl->custdata_list);
5158 }
5159 heap_free(This->impltypes);
5160 }
5161
5162 TLB_FreeCustData(&This->custdata_list);
5163
5164 heap_free(This);
5165 }
5166
5167 /* ITypeInfo::Release
5168 */
5169 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5170 {
5171 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5172 ULONG ref = InterlockedDecrement(&This->ref);
5173
5174 TRACE("(%p)->(%u)\n",This, ref);
5175
5176 if (!ref)
5177 {
5178 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5179 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5180 if (not_attached_to_typelib)
5181 heap_free(This);
5182 /* otherwise This will be freed when typelib is freed */
5183 }
5184
5185 return ref;
5186 }
5187
5188 /* ITypeInfo::GetTypeAttr
5189 *
5190 * Retrieves a TYPEATTR structure that contains the attributes of the type
5191 * description.
5192 *
5193 */
5194 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5195 LPTYPEATTR *ppTypeAttr)
5196 {
5197 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5198 SIZE_T size;
5199
5200 TRACE("(%p)\n",This);
5201
5202 size = sizeof(**ppTypeAttr);
5203 if (This->TypeAttr.typekind == TKIND_ALIAS)
5204 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5205
5206 *ppTypeAttr = heap_alloc(size);
5207 if (!*ppTypeAttr)
5208 return E_OUTOFMEMORY;
5209
5210 **ppTypeAttr = This->TypeAttr;
5211
5212 if (This->TypeAttr.typekind == TKIND_ALIAS)
5213 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5214 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5215
5216 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5217 /* This should include all the inherited funcs */
5218 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5219 /* This is always the size of IDispatch's vtbl */
5220 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5221 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5222 }
5223 return S_OK;
5224 }
5225
5226 /* ITypeInfo::GetTypeComp
5227 *
5228 * Retrieves the ITypeComp interface for the type description, which enables a
5229 * client compiler to bind to the type description's members.
5230 *
5231 */
5232 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5233 ITypeComp * *ppTComp)
5234 {
5235 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5236
5237 TRACE("(%p)->(%p)\n", This, ppTComp);
5238
5239 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5240 ITypeComp_AddRef(*ppTComp);
5241 return S_OK;
5242 }
5243
5244 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5245 {
5246 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5247 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5248 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5249 return size;
5250 }
5251
5252 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5253 {
5254 *dest = *src;
5255 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5256 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5257 {
5258 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5259 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5260 *buffer += sizeof(PARAMDESCEX);
5261 *pparamdescex_dest = *pparamdescex_src;
5262 VariantInit(&pparamdescex_dest->varDefaultValue);
5263 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5264 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5265 }
5266 else
5267 dest->u.paramdesc.pparamdescex = NULL;
5268 return S_OK;
5269 }
5270
5271 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5272 {
5273 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5274 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5275 }
5276
5277 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5278 {
5279 FUNCDESC *dest;
5280 char *buffer;
5281 SIZE_T size = sizeof(*src);
5282 SHORT i;
5283 HRESULT hr;
5284
5285 size += sizeof(*src->lprgscode) * src->cScodes;
5286 size += TLB_SizeElemDesc(&src->elemdescFunc);
5287 for (i = 0; i < src->cParams; i++)
5288 {
5289 size += sizeof(ELEMDESC);
5290 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5291 }
5292
5293 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5294 if (!dest) return E_OUTOFMEMORY;
5295
5296 *dest = *src;
5297 if (dispinterface) /* overwrite funckind */
5298 dest->funckind = FUNC_DISPATCH;
5299 buffer = (char *)(dest + 1);
5300
5301 dest->lprgscode = (SCODE *)buffer;
5302 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5303 buffer += sizeof(*src->lprgscode) * src->cScodes;
5304
5305 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5306 if (FAILED(hr))
5307 {
5308 SysFreeString((BSTR)dest);
5309 return hr;
5310 }
5311
5312 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5313 buffer += sizeof(ELEMDESC) * src->cParams;
5314 for (i = 0; i < src->cParams; i++)
5315 {
5316 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5317 if (FAILED(hr))
5318 break;
5319 }
5320 if (FAILED(hr))
5321 {
5322 /* undo the above actions */
5323 for (i = i - 1; i >= 0; i--)
5324 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5325 TLB_FreeElemDesc(&dest->elemdescFunc);
5326 SysFreeString((BSTR)dest);
5327 return hr;
5328 }
5329
5330 /* special treatment for dispinterfaces: this makes functions appear
5331 * to return their [retval] value when it is really returning an
5332 * HRESULT */
5333 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5334 {
5335 if (dest->cParams &&
5336 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5337 {
5338 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5339 if (elemdesc->tdesc.vt != VT_PTR)
5340 {
5341 ERR("elemdesc should have started with VT_PTR instead of:\n");
5342 if (ERR_ON(ole))
5343 dump_ELEMDESC(elemdesc);
5344 return E_UNEXPECTED;
5345 }
5346
5347 /* copy last parameter to the return value. we are using a flat
5348 * buffer so there is no danger of leaking memory in
5349 * elemdescFunc */
5350 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5351
5352 /* remove the last parameter */
5353 dest->cParams--;
5354 }
5355 else
5356 /* otherwise this function is made to appear to have no return
5357 * value */
5358 dest->elemdescFunc.tdesc.vt = VT_VOID;
5359
5360 }
5361
5362 *dest_ptr = dest;
5363 return S_OK;
5364 }
5365
5366 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5367 {
5368 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5369
5370 if (index >= This->TypeAttr.cFuncs)
5371 return TYPE_E_ELEMENTNOTFOUND;
5372
5373 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5374 return S_OK;
5375 }
5376
5377 /* internal function to make the inherited interfaces' methods appear
5378 * part of the interface */
5379 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5380 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5381 {
5382 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5383 HRESULT hr;
5384 UINT implemented_funcs = 0;
5385
5386 if (funcs)
5387 *funcs = 0;
5388 else
5389 *hrefoffset = DISPATCH_HREF_OFFSET;
5390
5391 if(This->impltypes)
5392 {
5393 ITypeInfo *pSubTypeInfo;
5394 UINT sub_funcs;
5395
5396 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5397 if (FAILED(hr))
5398 return hr;
5399
5400 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5401 index,
5402 ppFuncDesc,
5403 &sub_funcs, hrefoffset);
5404 implemented_funcs += sub_funcs;
5405 ITypeInfo_Release(pSubTypeInfo);
5406 if (SUCCEEDED(hr))
5407 return hr;
5408 *hrefoffset += DISPATCH_HREF_OFFSET;
5409 }
5410
5411 if (funcs)
5412 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5413 else
5414 *hrefoffset = 0;
5415
5416 if (index < implemented_funcs)
5417 return E_INVALIDARG;
5418 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5419 ppFuncDesc);
5420 }
5421
5422 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5423 {
5424 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5425 while (TRUE)
5426 {
5427 switch (pTypeDesc->vt)
5428 {
5429 case VT_USERDEFINED:
5430 pTypeDesc->u.hreftype += hrefoffset;
5431 return;
5432 case VT_PTR:
5433 case VT_SAFEARRAY:
5434 pTypeDesc = pTypeDesc->u.lptdesc;
5435 break;
5436 case VT_CARRAY:
5437 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5438 break;
5439 default:
5440 return;
5441 }
5442 }
5443 }
5444
5445 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5446 {
5447 SHORT i;
5448 for (i = 0; i < pFuncDesc->cParams; i++)
5449 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5450 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5451 }
5452
5453 /* ITypeInfo::GetFuncDesc
5454 *
5455 * Retrieves the FUNCDESC structure that contains information about a
5456 * specified function.
5457 *
5458 */
5459 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5460 LPFUNCDESC *ppFuncDesc)
5461 {
5462 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5463 const FUNCDESC *internal_funcdesc;
5464 HRESULT hr;
5465 UINT hrefoffset = 0;
5466
5467 TRACE("(%p) index %d\n", This, index);
5468
5469 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5470 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5471 &internal_funcdesc, NULL,
5472 &hrefoffset);
5473 else
5474 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5475 &internal_funcdesc);
5476 if (FAILED(hr))
5477 {
5478 WARN("description for function %d not found\n", index);
5479 return hr;
5480 }
5481
5482 hr = TLB_AllocAndInitFuncDesc(
5483 internal_funcdesc,
5484 ppFuncDesc,
5485 This->TypeAttr.typekind == TKIND_DISPATCH);
5486
5487 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5488 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5489
5490 TRACE("-- 0x%08x\n", hr);
5491 return hr;
5492 }
5493
5494 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5495 {
5496 VARDESC *dest;
5497 char *buffer;
5498 SIZE_T size = sizeof(*src);
5499 HRESULT hr;
5500
5501 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5502 if (src->varkind == VAR_CONST)
5503 size += sizeof(VARIANT);
5504 size += TLB_SizeElemDesc(&src->elemdescVar);
5505
5506 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5507 if (!dest) return E_OUTOFMEMORY;
5508
5509 *dest = *src;
5510 buffer = (char *)(dest + 1);
5511 if (src->lpstrSchema)
5512 {
5513 int len;
5514 dest->lpstrSchema = (LPOLESTR)buffer;
5515 len = strlenW(src->lpstrSchema);
5516 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5517 buffer += (len + 1) * sizeof(WCHAR);
5518 }
5519
5520 if (src->varkind == VAR_CONST)
5521 {
5522 HRESULT hr;
5523
5524 dest->u.lpvarValue = (VARIANT *)buffer;
5525 *dest->u.lpvarValue = *src->u.lpvarValue;
5526 buffer += sizeof(VARIANT);
5527 VariantInit(dest->u.lpvarValue);
5528 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5529 if (FAILED(hr))
5530 {
5531 SysFreeString((BSTR)dest);
5532 return hr;
5533 }
5534 }
5535 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5536 if (FAILED(hr))
5537 {
5538 if (src->varkind == VAR_CONST)
5539 VariantClear(dest->u.lpvarValue);
5540 SysFreeString((BSTR)dest);
5541 return hr;
5542 }
5543 *dest_ptr = dest;
5544 return S_OK;
5545 }
5546
5547 /* ITypeInfo::GetVarDesc
5548 *
5549 * Retrieves a VARDESC structure that describes the specified variable.
5550 *
5551 */
5552 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5553 LPVARDESC *ppVarDesc)
5554 {
5555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5556 const TLBVarDesc *pVDesc = &This->vardescs[index];
5557
5558 TRACE("(%p) index %d\n", This, index);
5559
5560 if(index >= This->TypeAttr.cVars)
5561 return TYPE_E_ELEMENTNOTFOUND;
5562
5563 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5564 }
5565
5566 /* ITypeInfo_GetNames
5567 *
5568 * Retrieves the variable with the specified member ID (or the name of the
5569 * property or method and its parameters) that correspond to the specified
5570 * function ID.
5571 */
5572 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5573 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5574 {
5575 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5576 const TLBFuncDesc *pFDesc;
5577 const TLBVarDesc *pVDesc;
5578 int i;
5579 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5580 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5581 if(pFDesc)
5582 {
5583 /* function found, now return function and parameter names */
5584 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5585 {
5586 if(!i)
5587 *rgBstrNames=SysAllocString(pFDesc->Name);
5588 else
5589 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5590 }
5591 *pcNames=i;
5592 }
5593 else
5594 {
5595 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5596 if(pVDesc)
5597 {
5598 *rgBstrNames=SysAllocString(pVDesc->Name);
5599 *pcNames=1;
5600 }
5601 else
5602 {
5603 if(This->impltypes &&
5604 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5605 /* recursive search */
5606 ITypeInfo *pTInfo;
5607 HRESULT result;
5608 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5609 if(SUCCEEDED(result))
5610 {
5611 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5612 ITypeInfo_Release(pTInfo);
5613 return result;
5614 }
5615 WARN("Could not search inherited interface!\n");
5616 }
5617 else
5618 {
5619 WARN("no names found\n");
5620 }
5621 *pcNames=0;
5622 return TYPE_E_ELEMENTNOTFOUND;
5623 }
5624 }
5625 return S_OK;
5626 }
5627
5628
5629 /* ITypeInfo::GetRefTypeOfImplType
5630 *
5631 * If a type description describes a COM class, it retrieves the type
5632 * description of the implemented interface types. For an interface,
5633 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5634 * if any exist.
5635 *
5636 */
5637 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5638 ITypeInfo2 *iface,
5639 UINT index,
5640 HREFTYPE *pRefType)
5641 {
5642 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5643 HRESULT hr = S_OK;
5644
5645 TRACE("(%p) index %d\n", This, index);
5646 if (TRACE_ON(ole)) dump_TypeInfo(This);
5647
5648 if(index==(UINT)-1)
5649 {
5650 /* only valid on dual interfaces;
5651 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5652 */
5653 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5654
5655 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5656 {
5657 *pRefType = -1;
5658 }
5659 else
5660 {
5661 hr = TYPE_E_ELEMENTNOTFOUND;
5662 }
5663 }
5664 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5665 {
5666 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5667 *pRefType = This->pTypeLib->dispatch_href;
5668 }
5669 else
5670 {
5671 if(index >= This->TypeAttr.cImplTypes)
5672 hr = TYPE_E_ELEMENTNOTFOUND;
5673 else
5674 *pRefType = This->impltypes[index].hRef;
5675 }
5676
5677 if(TRACE_ON(ole))
5678 {
5679 if(SUCCEEDED(hr))
5680 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5681 else
5682 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5683 }
5684
5685 return hr;
5686 }
5687
5688 /* ITypeInfo::GetImplTypeFlags
5689 *
5690 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5691 * or base interface in a type description.
5692 */
5693 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5694 UINT index, INT *pImplTypeFlags)
5695 {
5696 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5697
5698 TRACE("(%p) index %d\n", This, index);
5699
5700 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5701 *pImplTypeFlags = 0;
5702 return S_OK;
5703 }
5704
5705 if(index >= This->TypeAttr.cImplTypes)
5706 return TYPE_E_ELEMENTNOTFOUND;
5707
5708 *pImplTypeFlags = This->impltypes[index].implflags;
5709
5710 return S_OK;
5711 }
5712
5713 /* GetIDsOfNames
5714 * Maps between member names and member IDs, and parameter names and
5715 * parameter IDs.
5716 */
5717 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5718 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5719 {
5720 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5721 const TLBVarDesc *pVDesc;
5722 HRESULT ret=S_OK;
5723 UINT i, fdc;
5724
5725 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5726 cNames);
5727
5728 /* init out parameters in case of failure */
5729 for (i = 0; i < cNames; i++)
5730 pMemId[i] = MEMBERID_NIL;
5731
5732 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5733 int j;
5734 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5735 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5736 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5737 for(i=1; i < cNames; i++){
5738 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5739 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5740 break;
5741 if( j<pFDesc->funcdesc.cParams)
5742 pMemId[i]=j;
5743 else
5744 ret=DISP_E_UNKNOWNNAME;
5745 };
5746 TRACE("-- 0x%08x\n", ret);
5747 return ret;
5748 }
5749 }
5750 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5751 if(pVDesc){
5752 if(cNames)
5753 *pMemId = pVDesc->vardesc.memid;
5754 return ret;
5755 }
5756 /* not found, see if it can be found in an inherited interface */
5757 if(This->impltypes) {
5758 /* recursive search */
5759 ITypeInfo *pTInfo;
5760 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5761 if(SUCCEEDED(ret)){
5762 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5763 ITypeInfo_Release(pTInfo);
5764 return ret;
5765 }
5766 WARN("Could not search inherited interface!\n");
5767 } else
5768 WARN("no names found\n");
5769 return DISP_E_UNKNOWNNAME;
5770 }
5771
5772
5773 #ifdef __i386__
5774
5775 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5776 __ASM_GLOBAL_FUNC( call_method,
5777 "pushl %ebp\n\t"
5778 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5779 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5780 "movl %esp,%ebp\n\t"
5781 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5782 "pushl %esi\n\t"
5783 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5784 "pushl %edi\n\t"
5785 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5786 "movl 12(%ebp),%edx\n\t"
5787 "movl %esp,%edi\n\t"
5788 "shll $2,%edx\n\t"
5789 "jz 1f\n\t"
5790 "subl %edx,%edi\n\t"
5791 "andl $~15,%edi\n\t"
5792 "movl %edi,%esp\n\t"
5793 "movl 12(%ebp),%ecx\n\t"
5794 "movl 16(%ebp),%esi\n\t"
5795 "cld\n\t"
5796 "rep; movsl\n"
5797 "1:\tcall *8(%ebp)\n\t"
5798 "subl %esp,%edi\n\t"
5799 "movl 20(%ebp),%ecx\n\t"
5800 "movl %edi,(%ecx)\n\t"
5801 "leal -8(%ebp),%esp\n\t"
5802 "popl %edi\n\t"
5803 __ASM_CFI(".cfi_same_value %edi\n\t")
5804 "popl %esi\n\t"
5805 __ASM_CFI(".cfi_same_value %esi\n\t")
5806 "popl %ebp\n\t"
5807 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5808 __ASM_CFI(".cfi_same_value %ebp\n\t")
5809 "ret" )
5810
5811 /* same function but returning floating point */
5812 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5813
5814 /* ITypeInfo::Invoke
5815 *
5816 * Invokes a method, or accesses a property of an object, that implements the
5817 * interface described by the type description.
5818 */
5819 DWORD
5820 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5821 DWORD res;
5822 int stack_offset;
5823
5824 if (TRACE_ON(ole)) {
5825 int i;
5826 TRACE("Calling %p(",func);
5827 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5828 if (nrargs > 30) TRACE("...");
5829 TRACE(")\n");
5830 }
5831
5832 switch (callconv) {
5833 case CC_STDCALL:
5834 case CC_CDECL:
5835 res = call_method( func, nrargs, args, &stack_offset );
5836 break;
5837 default:
5838 FIXME("unsupported calling convention %d\n",callconv);
5839 res = -1;
5840 break;
5841 }
5842 TRACE("returns %08x\n",res);
5843 return res;
5844 }
5845
5846 #elif defined(__x86_64__)
5847
5848 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5849 __ASM_GLOBAL_FUNC( call_method,
5850 "pushq %rbp\n\t"
5851 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5852 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5853 "movq %rsp,%rbp\n\t"
5854 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5855 "pushq %rsi\n\t"
5856 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5857 "pushq %rdi\n\t"
5858 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5859 "movq %rcx,%rax\n\t"
5860 "movq $4,%rcx\n\t"
5861 "cmp %rcx,%rdx\n\t"
5862 "cmovgq %rdx,%rcx\n\t"
5863 "leaq 0(,%rcx,8),%rdx\n\t"
5864 "subq %rdx,%rsp\n\t"
5865 "andq $~15,%rsp\n\t"
5866 "movq %rsp,%rdi\n\t"
5867 "movq %r8,%rsi\n\t"
5868 "rep; movsq\n\t"
5869 "movq 0(%rsp),%rcx\n\t"
5870 "movq 8(%rsp),%rdx\n\t"
5871 "movq 16(%rsp),%r8\n\t"
5872 "movq 24(%rsp),%r9\n\t"
5873 "movq %rcx,%xmm0\n\t"
5874 "movq %rdx,%xmm1\n\t"
5875 "movq %r8,%xmm2\n\t"
5876 "movq %r9,%xmm3\n\t"
5877 "callq *%rax\n\t"
5878 "leaq -16(%rbp),%rsp\n\t"
5879 "popq %rdi\n\t"
5880 __ASM_CFI(".cfi_same_value %rdi\n\t")
5881 "popq %rsi\n\t"
5882 __ASM_CFI(".cfi_same_value %rsi\n\t")
5883 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5884 "popq %rbp\n\t"
5885 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5886 __ASM_CFI(".cfi_same_value %rbp\n\t")
5887 "ret")
5888
5889 /* same function but returning floating point */
5890 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5891
5892 #endif /* __x86_64__ */
5893
5894 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5895 {
5896 HRESULT hr = S_OK;
5897 ITypeInfo *tinfo2 = NULL;
5898 TYPEATTR *tattr = NULL;
5899
5900 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5901 if (hr)
5902 {
5903 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5904 "hr = 0x%08x\n",
5905 tdesc->u.hreftype, hr);
5906 return hr;
5907 }
5908 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5909 if (hr)
5910 {
5911 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5912 ITypeInfo_Release(tinfo2);
5913 return hr;
5914 }
5915
5916 switch (tattr->typekind)
5917 {
5918 case TKIND_ENUM:
5919 *vt |= VT_I4;
5920 break;
5921
5922 case TKIND_ALIAS:
5923 tdesc = &tattr->tdescAlias;
5924 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5925 break;
5926
5927 case TKIND_INTERFACE:
5928 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5929 *vt |= VT_DISPATCH;
5930 else
5931 *vt |= VT_UNKNOWN;
5932 break;
5933
5934 case TKIND_DISPATCH:
5935 *vt |= VT_DISPATCH;
5936 break;
5937
5938 case TKIND_COCLASS:
5939 *vt |= VT_DISPATCH;
5940 break;
5941
5942 case TKIND_RECORD:
5943 FIXME("TKIND_RECORD unhandled.\n");
5944 hr = E_NOTIMPL;
5945 break;
5946
5947 case TKIND_UNION:
5948 FIXME("TKIND_UNION unhandled.\n");
5949 hr = E_NOTIMPL;
5950 break;
5951
5952 default:
5953 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5954 hr = E_NOTIMPL;
5955 break;
5956 }
5957 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5958 ITypeInfo_Release(tinfo2);
5959 return hr;
5960 }
5961
5962 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5963 {
5964 HRESULT hr = S_OK;
5965
5966 /* enforce only one level of pointer indirection */
5967 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5968 {
5969 tdesc = tdesc->u.lptdesc;
5970
5971 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5972 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5973 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5974 if ((tdesc->vt == VT_USERDEFINED) ||
5975 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5976 {
5977 VARTYPE vt_userdefined = 0;
5978 const TYPEDESC *tdesc_userdefined = tdesc;
5979 if (tdesc->vt == VT_PTR)
5980 {
5981 vt_userdefined = VT_BYREF;
5982 tdesc_userdefined = tdesc->u.lptdesc;
5983 }
5984 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5985 if ((hr == S_OK) &&
5986 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5987 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5988 {
5989 *vt |= vt_userdefined;
5990 return S_OK;
5991 }
5992 }
5993 *vt = VT_BYREF;
5994 }
5995
5996 switch (tdesc->vt)
5997 {
5998 case VT_HRESULT:
5999 *vt |= VT_ERROR;
6000 break;
6001 case VT_USERDEFINED:
6002 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6003 break;
6004 case VT_VOID:
6005 case VT_CARRAY:
6006 case VT_PTR:
6007 case VT_LPSTR:
6008 case VT_LPWSTR:
6009 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6010 hr = DISP_E_BADVARTYPE;
6011 break;
6012 case VT_SAFEARRAY:
6013 *vt |= VT_ARRAY;
6014 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6015 break;
6016 case VT_INT:
6017 *vt |= VT_I4;
6018 break;
6019 case VT_UINT:
6020 *vt |= VT_UI4;
6021 break;
6022 default:
6023 *vt |= tdesc->vt;
6024 break;
6025 }
6026 return hr;
6027 }
6028
6029 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6030 {
6031 ITypeInfo *tinfo2;
6032 TYPEATTR *tattr;
6033 HRESULT hres;
6034
6035 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6036 if(FAILED(hres))
6037 return hres;
6038
6039 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6040 if(FAILED(hres)) {
6041 ITypeInfo_Release(tinfo2);
6042 return hres;
6043 }
6044
6045 switch(tattr->typekind) {
6046 case TKIND_ALIAS:
6047 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6048 break;
6049
6050 case TKIND_INTERFACE:
6051 case TKIND_DISPATCH:
6052 *guid = tattr->guid;
6053 break;
6054
6055 default:
6056 ERR("Unexpected typekind %d\n", tattr->typekind);
6057 hres = E_UNEXPECTED;
6058 }
6059
6060 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6061 ITypeInfo_Release(tinfo2);
6062 return hres;
6063 }
6064
6065 /***********************************************************************
6066 * DispCallFunc (OLEAUT32.@)
6067 *
6068 * Invokes a function of the specified calling convention, passing the
6069 * specified arguments and returns the result.
6070 *
6071 * PARAMS
6072 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6073 * oVft [I] The offset in the vtable. See notes.
6074 * cc [I] Calling convention of the function to call.
6075 * vtReturn [I] The return type of the function.
6076 * cActuals [I] Number of parameters.
6077 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6078 * prgpvarg [I] The arguments to pass.
6079 * pvargResult [O] The return value of the function. Can be NULL.
6080 *
6081 * RETURNS
6082 * Success: S_OK.
6083 * Failure: HRESULT code.
6084 *
6085 * NOTES
6086 * The HRESULT return value of this function is not affected by the return
6087 * value of the user supplied function, which is returned in pvargResult.
6088 *
6089 * If pvInstance is NULL then a non-object function is to be called and oVft
6090 * is the address of the function to call.
6091 *
6092 * The cc parameter can be one of the following values:
6093 *|CC_FASTCALL
6094 *|CC_CDECL
6095 *|CC_PASCAL
6096 *|CC_STDCALL
6097 *|CC_FPFASTCALL
6098 *|CC_SYSCALL
6099 *|CC_MPWCDECL
6100 *|CC_MPWPASCAL
6101 *
6102 */
6103 HRESULT WINAPI
6104 DispCallFunc(
6105 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6106 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6107 {
6108 #ifdef __i386__
6109 int argspos, stack_offset;
6110 void *func;
6111 UINT i;
6112 DWORD *args;
6113
6114 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6115 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6116 pvargResult, V_VT(pvargResult));
6117
6118 if (cc != CC_STDCALL && cc != CC_CDECL)
6119 {
6120 FIXME("unsupported calling convention %d\n",cc);
6121 return E_INVALIDARG;
6122 }
6123
6124 /* maximum size for an argument is sizeof(VARIANT) */
6125 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6126
6127 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6128 argspos = 1;
6129 if (pvInstance)
6130 {
6131 const FARPROC *vtable = *(FARPROC **)pvInstance;
6132 func = vtable[oVft/sizeof(void *)];
6133 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6134 }
6135 else func = (void *)oVft;
6136
6137 for (i = 0; i < cActuals; i++)
6138 {
6139 VARIANT *arg = prgpvarg[i];
6140
6141 switch (prgvt[i])
6142 {
6143 case VT_EMPTY:
6144 break;
6145 case VT_I8:
6146 case VT_UI8:
6147 case VT_R8:
6148 case VT_DATE:
6149 case VT_CY:
6150 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6151 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6152 break;
6153 case VT_DECIMAL:
6154 case VT_VARIANT:
6155 memcpy( &args[argspos], arg, sizeof(*arg) );
6156 argspos += sizeof(*arg) / sizeof(DWORD);
6157 break;
6158 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6159 args[argspos++] = V_BOOL(arg);
6160 break;
6161 default:
6162 args[argspos++] = V_UI4(arg);
6163 break;
6164 }
6165 TRACE("arg %u: type %d\n",i,prgvt[i]);
6166 dump_Variant(arg);
6167 }
6168
6169 switch (vtReturn)
6170 {
6171 case VT_EMPTY:
6172 call_method( func, argspos - 1, args + 1, &stack_offset );
6173 break;
6174 case VT_R4:
6175 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6176 break;
6177 case VT_R8:
6178 case VT_DATE:
6179 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6180 break;
6181 case VT_DECIMAL:
6182 case VT_VARIANT:
6183 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6184 call_method( func, argspos, args, &stack_offset );
6185 break;
6186 case VT_I8:
6187 case VT_UI8:
6188 case VT_CY:
6189 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6190 break;
6191 default:
6192 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6193 break;
6194 }
6195 heap_free( args );
6196 if (stack_offset && cc == CC_STDCALL)
6197 {
6198 WARN( "stack pointer off by %d\n", stack_offset );
6199 return DISP_E_BADCALLEE;
6200 }
6201 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6202 TRACE("retval: "); dump_Variant(pvargResult);
6203 return S_OK;
6204
6205 #elif defined(__x86_64__)
6206 int argspos;
6207 UINT i;
6208 DWORD_PTR *args;
6209 void *func;
6210
6211 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6212 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6213 pvargResult, V_VT(pvargResult));
6214
6215 if (cc != CC_STDCALL && cc != CC_CDECL)
6216 {
6217 FIXME("unsupported calling convention %d\n",cc);
6218 return E_INVALIDARG;
6219 }
6220
6221 /* maximum size for an argument is sizeof(DWORD_PTR) */
6222 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6223
6224 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6225 argspos = 1;
6226 if (pvInstance)
6227 {
6228 const FARPROC *vtable = *(FARPROC **)pvInstance;
6229 func = vtable[oVft/sizeof(void *)];
6230 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6231 }
6232 else func = (void *)oVft;
6233
6234 for (i = 0; i < cActuals; i++)
6235 {
6236 VARIANT *arg = prgpvarg[i];
6237
6238 switch (prgvt[i])
6239 {
6240 case VT_DECIMAL:
6241 case VT_VARIANT:
6242 args[argspos++] = (ULONG_PTR)arg;
6243 break;
6244 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6245 args[argspos++] = V_BOOL(arg);
6246 break;
6247 default:
6248 args[argspos++] = V_UI8(arg);
6249 break;
6250 }
6251 TRACE("arg %u: type %d\n",i,prgvt[i]);
6252 dump_Variant(arg);
6253 }
6254
6255 switch (vtReturn)
6256 {
6257 case VT_R4:
6258 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6259 break;
6260 case VT_R8:
6261 case VT_DATE:
6262 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6263 break;
6264 case VT_DECIMAL:
6265 case VT_VARIANT:
6266 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6267 call_method( func, argspos, args );
6268 break;
6269 default:
6270 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6271 break;
6272 }
6273 heap_free( args );
6274 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6275 TRACE("retval: "); dump_Variant(pvargResult);
6276 return S_OK;
6277
6278 #else
6279 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6280 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6281 return E_NOTIMPL;
6282 #endif
6283 }
6284
6285 static inline BOOL func_restricted( const FUNCDESC *desc )
6286 {
6287 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6288 }
6289
6290 #define INVBUF_ELEMENT_SIZE \
6291 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6292 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6293 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6294 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6295 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6296 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6297 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6298 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6299
6300 static HRESULT WINAPI ITypeInfo_fnInvoke(
6301 ITypeInfo2 *iface,
6302 VOID *pIUnk,
6303 MEMBERID memid,
6304 UINT16 wFlags,
6305 DISPPARAMS *pDispParams,
6306 VARIANT *pVarResult,
6307 EXCEPINFO *pExcepInfo,
6308 UINT *pArgErr)
6309 {
6310 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6311 int i;
6312 unsigned int var_index;
6313 TYPEKIND type_kind;
6314 HRESULT hres;
6315 const TLBFuncDesc *pFuncInfo;
6316 UINT fdc;
6317
6318 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6319 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6320 );
6321
6322 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6323 return DISP_E_MEMBERNOTFOUND;
6324
6325 if (!pDispParams)
6326 {
6327 ERR("NULL pDispParams not allowed\n");
6328 return E_INVALIDARG;
6329 }
6330
6331 dump_DispParms(pDispParams);
6332
6333 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6334 {
6335 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6336 pDispParams->cNamedArgs, pDispParams->cArgs);
6337 return E_INVALIDARG;
6338 }
6339
6340 /* we do this instead of using GetFuncDesc since it will return a fake
6341 * FUNCDESC for dispinterfaces and we want the real function description */
6342 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6343 pFuncInfo = &This->funcdescs[fdc];
6344 if ((memid == pFuncInfo->funcdesc.memid) &&
6345 (wFlags & pFuncInfo->funcdesc.invkind) &&
6346 !func_restricted( &pFuncInfo->funcdesc ))
6347 break;
6348 }
6349
6350 if (fdc < This->TypeAttr.cFuncs) {
6351 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6352
6353 if (TRACE_ON(ole))
6354 {
6355 TRACE("invoking:\n");
6356 dump_TLBFuncDescOne(pFuncInfo);
6357 }
6358
6359 switch (func_desc->funckind) {
6360 case FUNC_PUREVIRTUAL:
6361 case FUNC_VIRTUAL: {
6362 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6363 VARIANT varresult;
6364 VARIANT retval; /* pointer for storing byref retvals in */
6365 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6366 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6367 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6368 UINT cNamedArgs = pDispParams->cNamedArgs;
6369 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6370 UINT vargs_converted=0;
6371
6372 hres = S_OK;
6373
6374 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6375 {
6376 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6377 {
6378 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6379 hres = DISP_E_PARAMNOTFOUND;
6380 goto func_fail;
6381 }
6382 }
6383
6384 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6385 {
6386 ERR("functions with the vararg attribute do not support named arguments\n");
6387 hres = DISP_E_NONAMEDARGS;
6388 goto func_fail;
6389 }
6390
6391 for (i = 0; i < func_desc->cParams; i++)
6392 {
6393 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6394 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6395 if (FAILED(hres))
6396 goto func_fail;
6397 }
6398
6399 TRACE("changing args\n");
6400 for (i = 0; i < func_desc->cParams; i++)
6401 {
6402 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6403 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6404 VARIANTARG *src_arg;
6405
6406 if (wParamFlags & PARAMFLAG_FLCID)
6407 {
6408 VARIANTARG *arg;
6409 arg = prgpvarg[i] = &rgvarg[i];
6410 V_VT(arg) = VT_I4;
6411 V_I4(arg) = This->pTypeLib->lcid;
6412 continue;
6413 }
6414
6415 src_arg = NULL;
6416
6417 if (cNamedArgs)
6418 {
6419 USHORT j;
6420 for (j = 0; j < cNamedArgs; j++)
6421 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6422 {
6423 src_arg = &pDispParams->rgvarg[j];
6424 break;
6425 }
6426 }
6427
6428 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6429 {
6430 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6431 vargs_converted++;
6432 }
6433
6434 if (wParamFlags & PARAMFLAG_FRETVAL)
6435 {
6436 /* under most conditions the caller is not allowed to
6437 * pass in a dispparam arg in the index of what would be
6438 * the retval parameter. however, there is an exception
6439 * where the extra parameter is used in an extra
6440 * IDispatch::Invoke below */
6441 if ((i < pDispParams->cArgs) &&
6442 ((func_desc->cParams != 1) || !pVarResult ||
6443 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6444 {
6445 hres = DISP_E_BADPARAMCOUNT;
6446 break;
6447 }
6448
6449 /* note: this check is placed so that if the caller passes
6450 * in a VARIANTARG for the retval we just ignore it, like
6451 * native does */
6452 if (i == func_desc->cParams - 1)
6453 {
6454 VARIANTARG *arg;
6455 arg = prgpvarg[i] = &rgvarg[i];
6456 memset(arg, 0, sizeof(*arg));
6457 V_VT(arg) = rgvt[i];
6458 memset(&retval, 0, sizeof(retval));
6459 V_BYREF(arg) = &retval;
6460 }
6461 else
6462 {
6463 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6464 hres = E_UNEXPECTED;
6465 break;
6466 }
6467 }
6468 else if (src_arg)
6469 {
6470 dump_Variant(src_arg);
6471
6472 if(rgvt[i]!=V_VT(src_arg))
6473 {
6474 if (rgvt[i] == VT_VARIANT)
6475 hres = VariantCopy(&rgvarg[i], src_arg);
6476 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6477 {
6478 if (rgvt[i] == V_VT(src_arg))
6479 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6480 else
6481 {
6482 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6483 if (wParamFlags & PARAMFLAG_FIN)
6484 hres = VariantCopy(&missing_arg[i], src_arg);
6485 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6486 }
6487 V_VT(&rgvarg[i]) = rgvt[i];
6488 }
6489 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6490 {
6491 SAFEARRAY *a;
6492 SAFEARRAYBOUND bound;
6493 VARIANT *v;
6494 LONG j;
6495 bound.lLbound = 0;
6496 bound.cElements = pDispParams->cArgs-i;
6497 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6498 {
6499 ERR("SafeArrayCreate failed\n");
6500 break;
6501 }
6502 hres = SafeArrayAccessData(a, (LPVOID)&v);
6503 if (hres != S_OK)
6504 {
6505 ERR("SafeArrayAccessData failed with %x\n", hres);
6506 SafeArrayDestroy(a);
6507 break;
6508 }
6509 for (j = 0; j < bound.cElements; j++)
6510 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6511 hres = SafeArrayUnaccessData(a);
6512 if (hres != S_OK)
6513 {
6514 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6515 SafeArrayDestroy(a);
6516 break;
6517 }
6518 V_ARRAY(&rgvarg[i]) = a;
6519 V_VT(&rgvarg[i]) = rgvt[i];
6520 }
6521 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6522 {
6523 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6524 if (wParamFlags & PARAMFLAG_FIN)
6525 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6526 else
6527 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6528 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6529 V_VT(&rgvarg[i]) = rgvt[i];
6530 }
6531 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6532 {
6533 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6534 V_VT(&rgvarg[i]) = rgvt[i];
6535 }
6536 else
6537 {
6538 /* FIXME: this doesn't work for VT_BYREF arguments if
6539 * they are not the same type as in the paramdesc */
6540 V_VT(&rgvarg[i]) = V_VT(src_arg);
6541 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6542 V_VT(&rgvarg[i]) = rgvt[i];
6543 }
6544
6545 if (FAILED(hres))
6546 {
6547 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6548 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6549 debugstr_VT(src_arg), debugstr_VF(src_arg));
6550 break;
6551 }
6552 prgpvarg[i] = &rgvarg[i];
6553 }
6554 else
6555 {
6556 prgpvarg[i] = src_arg;
6557 }
6558
6559 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6560 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6561 && V_UNKNOWN(prgpvarg[i])) {
6562 IUnknown *userdefined_iface;
6563 GUID guid;
6564
6565 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6566 if(FAILED(hres))
6567 break;
6568
6569 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6570 if(FAILED(hres)) {
6571 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6572 break;
6573 }
6574
6575 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6576 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6577 }
6578 }
6579 else if (wParamFlags & PARAMFLAG_FOPT)
6580 {
6581 VARIANTARG *arg;
6582 arg = prgpvarg[i] = &rgvarg[i];
6583 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6584 {
6585 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6586 if (FAILED(hres))
6587 break;
6588 }
6589 else
6590 {
6591 VARIANTARG *missing_arg;
6592 /* if the function wants a pointer to a variant then
6593 * set that up, otherwise just pass the VT_ERROR in
6594 * the argument by value */
6595 if (rgvt[i] & VT_BYREF)
6596 {
6597 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6598 V_VT(arg) = VT_VARIANT | VT_BYREF;
6599 V_VARIANTREF(arg) = missing_arg;
6600 }
6601 else
6602 missing_arg = arg;
6603 V_VT(missing_arg) = VT_ERROR;
6604 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6605 }
6606 }
6607 else
6608 {
6609 hres = DISP_E_BADPARAMCOUNT;
6610 break;
6611 }
6612 }
6613 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6614
6615 /* VT_VOID is a special case for return types, so it is not
6616 * handled in the general function */
6617 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6618 V_VT(&varresult) = VT_EMPTY;
6619 else
6620 {
6621 V_VT(&varresult) = 0;
6622 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6623 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6624 }
6625
6626 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6627 V_VT(&varresult), func_desc->cParams, rgvt,
6628 prgpvarg, &varresult);
6629
6630 vargs_converted = 0;
6631
6632 for (i = 0; i < func_desc->cParams; i++)
6633 {
6634 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6635 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6636
6637 if (wParamFlags & PARAMFLAG_FLCID)
6638 continue;
6639 else if (wParamFlags & PARAMFLAG_FRETVAL)
6640 {
6641 if (TRACE_ON(ole))
6642 {
6643 TRACE("[retval] value: ");
6644 dump_Variant(prgpvarg[i]);
6645 }
6646
6647 if (pVarResult)
6648 {
6649 VariantInit(pVarResult);
6650 /* deref return value */
6651 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6652 }
6653
6654 VARIANT_ClearInd(prgpvarg[i]);
6655 }
6656 else if (vargs_converted < pDispParams->cArgs)
6657 {
6658 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6659 if (wParamFlags & PARAMFLAG_FOUT)
6660 {
6661 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6662 {
6663 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6664
6665 if (FAILED(hres))
6666 {
6667 ERR("failed to convert param %d to vt %d\n", i,
6668 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6669 break;
6670 }
6671 }
6672 }
6673 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6674 func_desc->cParamsOpt < 0 &&
6675 i == func_desc->cParams-1)
6676 {
6677 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6678 LONG j, ubound;
6679 VARIANT *v;
6680 hres = SafeArrayGetUBound(a, 1, &ubound);
6681 if (hres != S_OK)
6682 {
6683 ERR("SafeArrayGetUBound failed with %x\n", hres);
6684 break;
6685 }
6686 hres = SafeArrayAccessData(a, (LPVOID)&v);
6687 if (hres != S_OK)
6688 {
6689 ERR("SafeArrayAccessData failed with %x\n", hres);
6690 break;
6691 }
6692 for (j = 0; j <= ubound; j++)
6693 VariantClear(&v[j]);
6694 hres = SafeArrayUnaccessData(a);
6695 if (hres != S_OK)
6696 {
6697 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6698 break;
6699 }
6700 }
6701 VariantClear(&rgvarg[i]);
6702 vargs_converted++;
6703 }
6704 else if (wParamFlags & PARAMFLAG_FOPT)
6705 {
6706 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6707 VariantClear(&rgvarg[i]);
6708 }
6709
6710 VariantClear(&missing_arg[i]);
6711 }
6712
6713 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6714 {
6715 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6716 hres = DISP_E_EXCEPTION;
6717 if (pExcepInfo)
6718 {
6719 IErrorInfo *pErrorInfo;
6720 pExcepInfo->scode = V_ERROR(&varresult);
6721 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6722 {
6723 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6724 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6725 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6726 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6727
6728 IErrorInfo_Release(pErrorInfo);
6729 }
6730 }
6731 }
6732 if (V_VT(&varresult) != VT_ERROR)
6733 {
6734 TRACE("varresult value: ");
6735 dump_Variant(&varresult);
6736
6737 if (pVarResult)
6738 {
6739 VariantClear(pVarResult);
6740 *pVarResult = varresult;
6741 }
6742 else
6743 VariantClear(&varresult);
6744 }
6745
6746 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6747 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6748 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6749 (pDispParams->cArgs != 0))
6750 {
6751 if (V_VT(pVarResult) == VT_DISPATCH)
6752 {
6753 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6754 /* Note: not VariantClear; we still need the dispatch
6755 * pointer to be valid */
6756 VariantInit(pVarResult);
6757 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6758 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6759 pDispParams, pVarResult, pExcepInfo, pArgErr);
6760 IDispatch_Release(pDispatch);
6761 }
6762 else
6763 {
6764 VariantClear(pVarResult);
6765 hres = DISP_E_NOTACOLLECTION;
6766 }
6767 }
6768
6769 func_fail:
6770 heap_free(buffer);
6771 break;
6772 }
6773 case FUNC_DISPATCH: {
6774 IDispatch *disp;
6775
6776 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6777 if (SUCCEEDED(hres)) {
6778 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6779 hres = IDispatch_Invoke(
6780 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6781 pVarResult,pExcepInfo,pArgErr
6782 );
6783 if (FAILED(hres))
6784 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6785 IDispatch_Release(disp);
6786 } else
6787 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6788 break;
6789 }
6790 default:
6791 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6792 hres = E_FAIL;
6793 break;
6794 }
6795
6796 TRACE("-- 0x%08x\n", hres);
6797 return hres;
6798
6799 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6800 VARDESC *var_desc;
6801
6802 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6803 if(FAILED(hres)) return hres;
6804
6805 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6806 dump_VARDESC(var_desc);
6807 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6808 return E_NOTIMPL;
6809 }
6810
6811 /* not found, look for it in inherited interfaces */
6812 ITypeInfo2_GetTypeKind(iface, &type_kind);
6813 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6814 if(This->impltypes) {
6815 /* recursive search */
6816 ITypeInfo *pTInfo;
6817 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6818 if(SUCCEEDED(hres)){
6819 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6820 ITypeInfo_Release(pTInfo);
6821 return hres;
6822 }
6823 WARN("Could not search inherited interface!\n");
6824 }
6825 }
6826 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6827 return DISP_E_MEMBERNOTFOUND;
6828 }
6829
6830 /* ITypeInfo::GetDocumentation
6831 *
6832 * Retrieves the documentation string, the complete Help file name and path,
6833 * and the context ID for the Help topic for a specified type description.
6834 *
6835 * (Can be tested by the Visual Basic Editor in Word for instance.)
6836 */
6837 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6838 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6839 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6840 {
6841 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6842 const TLBFuncDesc *pFDesc;
6843 const TLBVarDesc *pVDesc;
6844 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6845 " HelpContext(%p) HelpFile(%p)\n",
6846 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6847 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6848 if(pBstrName)
6849 *pBstrName=SysAllocString(This->Name);
6850 if(pBstrDocString)
6851 *pBstrDocString=SysAllocString(This->DocString);
6852 if(pdwHelpContext)
6853 *pdwHelpContext=This->dwHelpContext;
6854 if(pBstrHelpFile)
6855 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6856 return S_OK;
6857 }else {/* for a member */
6858 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6859 if(pFDesc){
6860 if(pBstrName)
6861 *pBstrName = SysAllocString(pFDesc->Name);
6862 if(pBstrDocString)
6863 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6864 if(pdwHelpContext)
6865 *pdwHelpContext=pFDesc->helpcontext;
6866 return S_OK;
6867 }
6868 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6869 if(pVDesc){
6870 if(pBstrName)
6871 *pBstrName = SysAllocString(pVDesc->Name);
6872 if(pBstrDocString)
6873 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6874 if(pdwHelpContext)
6875 *pdwHelpContext=pVDesc->HelpContext;
6876 return S_OK;
6877 }
6878 }
6879
6880 if(This->impltypes &&
6881 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6882 /* recursive search */
6883 ITypeInfo *pTInfo;
6884 HRESULT result;
6885 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6886 if(SUCCEEDED(result)) {
6887 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6888 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6889 ITypeInfo_Release(pTInfo);
6890 return result;
6891 }
6892 WARN("Could not search inherited interface!\n");
6893 }
6894
6895 WARN("member %d not found\n", memid);
6896 return TYPE_E_ELEMENTNOTFOUND;
6897 }
6898
6899 /* ITypeInfo::GetDllEntry
6900 *
6901 * Retrieves a description or specification of an entry point for a function
6902 * in a DLL.
6903 */
6904 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6905 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6906 WORD *pwOrdinal)
6907 {
6908 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6909 const TLBFuncDesc *pFDesc;
6910
6911 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6912
6913 if (pBstrDllName) *pBstrDllName = NULL;
6914 if (pBstrName) *pBstrName = NULL;
6915 if (pwOrdinal) *pwOrdinal = 0;
6916
6917 if (This->TypeAttr.typekind != TKIND_MODULE)
6918 return TYPE_E_BADMODULEKIND;
6919
6920 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6921 if(pFDesc){
6922 dump_TypeInfo(This);
6923 if (TRACE_ON(ole))
6924 dump_TLBFuncDescOne(pFDesc);
6925
6926 if (pBstrDllName)
6927 *pBstrDllName = SysAllocString(This->DllName);
6928
6929 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6930 if (pBstrName)
6931 *pBstrName = SysAllocString(pFDesc->Entry);
6932 if (pwOrdinal)
6933 *pwOrdinal = -1;
6934 return S_OK;
6935 }
6936 if (pBstrName)
6937 *pBstrName = NULL;
6938 if (pwOrdinal)
6939 *pwOrdinal = LOWORD(pFDesc->Entry);
6940 return S_OK;
6941 }
6942 return TYPE_E_ELEMENTNOTFOUND;
6943 }
6944
6945 /* internal function to make the inherited interfaces' methods appear
6946 * part of the interface */
6947 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6948 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6949 {
6950 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6951 HRESULT hr;
6952
6953 TRACE("%p, 0x%x\n", iface, *hRefType);
6954
6955 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
6956 {
6957 ITypeInfo *pSubTypeInfo;
6958
6959 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6960 if (FAILED(hr))
6961 return hr;
6962
6963 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6964 hRefType, ppTInfo);
6965 ITypeInfo_Release(pSubTypeInfo);
6966 if (SUCCEEDED(hr))
6967 return hr;
6968 }
6969 *hRefType -= DISPATCH_HREF_OFFSET;
6970
6971 if (!(*hRefType & DISPATCH_HREF_MASK))
6972 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6973 else
6974 return E_FAIL;
6975 }
6976
6977 /* ITypeInfo::GetRefTypeInfo
6978 *
6979 * If a type description references other type descriptions, it retrieves
6980 * the referenced type descriptions.
6981 */
6982 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6983 ITypeInfo2 *iface,
6984 HREFTYPE hRefType,
6985 ITypeInfo **ppTInfo)
6986 {
6987 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6988 HRESULT result = E_FAIL;
6989
6990 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6991 {
6992 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6993 ITypeInfo_AddRef(*ppTInfo);
6994 result = S_OK;
6995 }
6996 else if (hRefType == -1 &&
6997 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6998 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6999 {
7000 /* when we meet a DUAL dispinterface, we must create the interface
7001 * version of it.
7002 */
7003 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
7004
7005
7006 /* the interface version contains the same information as the dispinterface
7007 * copy the contents of the structs.
7008 */
7009 *pTypeInfoImpl = *This;
7010 pTypeInfoImpl->ref = 0;
7011
7012 /* change the type to interface */
7013 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
7014
7015 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
7016
7017 /* the AddRef implicitly adds a reference to the parent typelib, which
7018 * stops the copied data from being destroyed until the new typeinfo's
7019 * refcount goes to zero, but we need to signal to the new instance to
7020 * not free its data structures when it is destroyed */
7021 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7022
7023 ITypeInfo_AddRef(*ppTInfo);
7024
7025 result = S_OK;
7026
7027 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
7028 (This->TypeAttr.typekind == TKIND_DISPATCH))
7029 {
7030 HREFTYPE href_dispatch = hRefType;
7031 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7032 } else {
7033 TLBRefType *ref_type;
7034 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7035 {
7036 if(ref_type->reference == hRefType)
7037 break;
7038 }
7039 if(&ref_type->entry == &This->pTypeLib->ref_list)
7040 {
7041 FIXME("Can't find pRefType for ref %x\n", hRefType);
7042 goto end;
7043 }
7044 if(hRefType != -1) {
7045 ITypeLib *pTLib = NULL;
7046
7047 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7048 UINT Index;
7049 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7050 } else {
7051 if(ref_type->pImpTLInfo->pImpTypeLib) {
7052 TRACE("typeinfo in imported typelib that is already loaded\n");
7053 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
7054 ITypeLib_AddRef(pTLib);
7055 result = S_OK;
7056 } else {
7057 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7058 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
7059 ref_type->pImpTLInfo->wVersionMajor,
7060 ref_type->pImpTLInfo->wVersionMinor,
7061 ref_type->pImpTLInfo->lcid,
7062 &pTLib);
7063
7064 if(FAILED(result)) {
7065 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7066 result=LoadTypeLib(libnam, &pTLib);
7067 SysFreeString(libnam);
7068 }
7069 if(SUCCEEDED(result)) {
7070 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
7071 ITypeLib_AddRef(pTLib);
7072 }
7073 }
7074 }
7075 if(SUCCEEDED(result)) {
7076 if(ref_type->index == TLB_REF_USE_GUID)
7077 result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
7078 else
7079 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7080 }
7081 if (pTLib != NULL)
7082 ITypeLib_Release(pTLib);
7083 }
7084 }
7085
7086 end:
7087 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7088 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7089 return result;
7090 }
7091
7092 /* ITypeInfo::AddressOfMember
7093 *
7094 * Retrieves the addresses of static functions or variables, such as those
7095 * defined in a DLL.
7096 */
7097 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7098 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7099 {
7100 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7101 HRESULT hr;
7102 BSTR dll, entry;
7103 WORD ordinal;
7104 HMODULE module;
7105
7106 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7107
7108 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7109 if (FAILED(hr))
7110 return hr;
7111
7112 module = LoadLibraryW(dll);
7113 if (!module)
7114 {
7115 ERR("couldn't load %s\n", debugstr_w(dll));
7116 SysFreeString(dll);
7117 SysFreeString(entry);
7118 return STG_E_FILENOTFOUND;
7119 }
7120 /* FIXME: store library somewhere where we can free it */
7121
7122 if (entry)
7123 {
7124 LPSTR entryA;
7125 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7126 entryA = heap_alloc(len);
7127 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7128
7129 *ppv = GetProcAddress(module, entryA);
7130 if (!*ppv)
7131 ERR("function not found %s\n", debugstr_a(entryA));
7132
7133 heap_free(entryA);
7134 }
7135 else
7136 {
7137 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7138 if (!*ppv)
7139 ERR("function not found %d\n", ordinal);
7140 }
7141
7142 SysFreeString(dll);
7143 SysFreeString(entry);
7144
7145 if (!*ppv)
7146 return TYPE_E_DLLFUNCTIONNOTFOUND;
7147
7148 return S_OK;
7149 }
7150
7151 /* ITypeInfo::CreateInstance
7152 *
7153 * Creates a new instance of a type that describes a component object class
7154 * (coclass).
7155 */
7156 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7157 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7158 {
7159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7160 HRESULT hr;
7161 TYPEATTR *pTA;
7162
7163 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7164
7165 *ppvObj = NULL;
7166
7167 if(pOuterUnk)
7168 {
7169 WARN("Not able to aggregate\n");
7170 return CLASS_E_NOAGGREGATION;
7171 }
7172
7173 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7174 if(FAILED(hr)) return hr;
7175
7176 if(pTA->typekind != TKIND_COCLASS)
7177 {
7178 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7179 hr = E_INVALIDARG;
7180 goto end;
7181 }
7182
7183 hr = S_FALSE;
7184 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7185 {
7186 IUnknown *pUnk;
7187 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7188 TRACE("GetActiveObject rets %08x\n", hr);
7189 if(hr == S_OK)
7190 {
7191 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7192 IUnknown_Release(pUnk);
7193 }
7194 }
7195
7196 if(hr != S_OK)
7197 hr = CoCreateInstance(&pTA->guid, NULL,
7198 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7199 riid, ppvObj);
7200
7201 end:
7202 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7203 return hr;
7204 }
7205
7206 /* ITypeInfo::GetMops
7207 *
7208 * Retrieves marshalling information.
7209 */
7210 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7211 BSTR *pBstrMops)
7212 {
7213 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7214 FIXME("(%p %d) stub!\n", This, memid);
7215 *pBstrMops = NULL;
7216 return S_OK;
7217 }
7218
7219 /* ITypeInfo::GetContainingTypeLib
7220 *
7221 * Retrieves the containing type library and the index of the type description
7222 * within that type library.
7223 */
7224 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7225 ITypeLib * *ppTLib, UINT *pIndex)
7226 {
7227 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7228
7229 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7230 if (pIndex) {
7231 *pIndex=This->index;
7232 TRACE("returning pIndex=%d\n", *pIndex);
7233 }
7234
7235 if (ppTLib) {
7236 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7237 ITypeLib_AddRef(*ppTLib);
7238 TRACE("returning ppTLib=%p\n", *ppTLib);
7239 }
7240
7241 return S_OK;
7242 }
7243
7244 /* ITypeInfo::ReleaseTypeAttr
7245 *
7246 * Releases a TYPEATTR previously returned by GetTypeAttr.
7247 *
7248 */
7249 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7250 TYPEATTR* pTypeAttr)
7251 {
7252 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7253 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7254 heap_free(pTypeAttr);
7255 }
7256
7257 /* ITypeInfo::ReleaseFuncDesc
7258 *
7259 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7260 */
7261 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7262 ITypeInfo2 *iface,
7263 FUNCDESC *pFuncDesc)
7264 {
7265 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7266 SHORT i;
7267
7268 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7269
7270 for (i = 0; i < pFuncDesc->cParams; i++)
7271 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7272 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7273
7274 SysFreeString((BSTR)pFuncDesc);
7275 }
7276
7277 /* ITypeInfo::ReleaseVarDesc
7278 *
7279 * Releases a VARDESC previously returned by GetVarDesc.
7280 */
7281 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7282 VARDESC *pVarDesc)
7283 {
7284 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7285 TRACE("(%p)->(%p)\n", This, pVarDesc);
7286
7287 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7288 if (pVarDesc->varkind == VAR_CONST)
7289 VariantClear(pVarDesc->u.lpvarValue);
7290 SysFreeString((BSTR)pVarDesc);
7291 }
7292
7293 /* ITypeInfo2::GetTypeKind
7294 *
7295 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7296 *
7297 */
7298 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7299 TYPEKIND *pTypeKind)
7300 {
7301 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7302 *pTypeKind=This->TypeAttr.typekind;
7303 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7304 return S_OK;
7305 }
7306
7307 /* ITypeInfo2::GetTypeFlags
7308 *
7309 * Returns the type flags without any allocations. This returns a DWORD type
7310 * flag, which expands the type flags without growing the TYPEATTR (type
7311 * attribute).
7312 *
7313 */
7314 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7315 {
7316 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7317 *pTypeFlags=This->TypeAttr.wTypeFlags;
7318 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7319 return S_OK;
7320 }
7321
7322 /* ITypeInfo2::GetFuncIndexOfMemId
7323 * Binds to a specific member based on a known DISPID, where the member name
7324 * is not known (for example, when binding to a default member).
7325 *
7326 */
7327 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7328 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7329 {
7330 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7331 UINT fdc;
7332 HRESULT result;
7333
7334 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7335 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7336 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7337 break;
7338 }
7339 if(fdc < This->TypeAttr.cFuncs) {
7340 *pFuncIndex = fdc;
7341 result = S_OK;
7342 } else
7343 result = TYPE_E_ELEMENTNOTFOUND;
7344
7345 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7346 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7347 return result;
7348 }
7349
7350 /* TypeInfo2::GetVarIndexOfMemId
7351 *
7352 * Binds to a specific member based on a known DISPID, where the member name
7353 * is not known (for example, when binding to a default member).
7354 *
7355 */
7356 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7357 MEMBERID memid, UINT *pVarIndex)
7358 {
7359 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7360 TLBVarDesc *pVarInfo;
7361
7362 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7363
7364 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7365 if(!pVarInfo)
7366 return TYPE_E_ELEMENTNOTFOUND;
7367
7368 *pVarIndex = (pVarInfo - This->vardescs);
7369
7370 return S_OK;
7371 }
7372
7373 /* ITypeInfo2::GetCustData
7374 *
7375 * Gets the custom data
7376 */
7377 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7378 ITypeInfo2 * iface,
7379 REFGUID guid,
7380 VARIANT *pVarVal)
7381 {
7382 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7383 TLBCustData *pCData;
7384
7385 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7386
7387 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7388
7389 VariantInit( pVarVal);
7390 if (pCData)
7391 VariantCopy( pVarVal, &pCData->data);
7392 else
7393 VariantClear( pVarVal );
7394 return S_OK;
7395 }
7396
7397 /* ITypeInfo2::GetFuncCustData
7398 *
7399 * Gets the custom data
7400 */
7401 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7402 ITypeInfo2 * iface,
7403 UINT index,
7404 REFGUID guid,
7405 VARIANT *pVarVal)
7406 {
7407 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7408 TLBCustData *pCData;
7409 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7410
7411 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7412
7413 if(index >= This->TypeAttr.cFuncs)
7414 return TYPE_E_ELEMENTNOTFOUND;
7415
7416 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7417 if(!pCData)
7418 return TYPE_E_ELEMENTNOTFOUND;
7419
7420 VariantInit(pVarVal);
7421 VariantCopy(pVarVal, &pCData->data);
7422
7423 return S_OK;
7424 }
7425
7426 /* ITypeInfo2::GetParamCustData
7427 *
7428 * Gets the custom data
7429 */
7430 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7431 ITypeInfo2 * iface,
7432 UINT indexFunc,
7433 UINT indexParam,
7434 REFGUID guid,
7435 VARIANT *pVarVal)
7436 {
7437 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7438 TLBCustData *pCData;
7439 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7440
7441 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7442 debugstr_guid(guid), pVarVal);
7443
7444 if(indexFunc >= This->TypeAttr.cFuncs)
7445 return TYPE_E_ELEMENTNOTFOUND;
7446
7447 if(indexParam >= pFDesc->funcdesc.cParams)
7448 return TYPE_E_ELEMENTNOTFOUND;
7449
7450 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7451 if(!pCData)
7452 return TYPE_E_ELEMENTNOTFOUND;
7453
7454 VariantInit(pVarVal);
7455 VariantCopy(pVarVal, &pCData->data);
7456
7457 return S_OK;
7458 }
7459
7460 /* ITypeInfo2::GetVarCustData
7461 *
7462 * Gets the custom data
7463 */
7464 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7465 ITypeInfo2 * iface,
7466 UINT index,
7467 REFGUID guid,
7468 VARIANT *pVarVal)
7469 {
7470 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7471 TLBCustData *pCData;
7472 TLBVarDesc *pVDesc = &This->vardescs[index];
7473
7474 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7475
7476 if(index >= This->TypeAttr.cVars)
7477 return TYPE_E_ELEMENTNOTFOUND;
7478
7479 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7480 if(!pCData)
7481 return TYPE_E_ELEMENTNOTFOUND;
7482
7483 VariantInit(pVarVal);
7484 VariantCopy(pVarVal, &pCData->data);
7485
7486 return S_OK;
7487 }
7488
7489 /* ITypeInfo2::GetImplCustData
7490 *
7491 * Gets the custom data
7492 */
7493 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7494 ITypeInfo2 * iface,
7495 UINT index,
7496 REFGUID guid,
7497 VARIANT *pVarVal)
7498 {
7499 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7500 TLBCustData *pCData;
7501 TLBImplType *pRDesc = &This->impltypes[index];
7502
7503 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7504
7505 if(index >= This->TypeAttr.cImplTypes)
7506 return TYPE_E_ELEMENTNOTFOUND;
7507
7508 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7509 if(!pCData)
7510 return TYPE_E_ELEMENTNOTFOUND;
7511
7512 VariantInit(pVarVal);
7513 VariantCopy(pVarVal, &pCData->data);
7514
7515 return S_OK;
7516 }
7517
7518 /* ITypeInfo2::GetDocumentation2
7519 *
7520 * Retrieves the documentation string, the complete Help file name and path,
7521 * the localization context to use, and the context ID for the library Help
7522 * topic in the Help file.
7523 *
7524 */
7525 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7526 ITypeInfo2 * iface,
7527 MEMBERID memid,
7528 LCID lcid,
7529 BSTR *pbstrHelpString,
7530 DWORD *pdwHelpStringContext,
7531 BSTR *pbstrHelpStringDll)
7532 {
7533 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7534 const TLBFuncDesc *pFDesc;
7535 const TLBVarDesc *pVDesc;
7536 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7537 "HelpStringContext(%p) HelpStringDll(%p)\n",
7538 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7539 pbstrHelpStringDll );
7540 /* the help string should be obtained from the helpstringdll,
7541 * using the _DLLGetDocumentation function, based on the supplied
7542 * lcid. Nice to do sometime...
7543 */
7544 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7545 if(pbstrHelpString)
7546 *pbstrHelpString=SysAllocString(This->Name);
7547 if(pdwHelpStringContext)
7548 *pdwHelpStringContext=This->dwHelpStringContext;
7549 if(pbstrHelpStringDll)
7550 *pbstrHelpStringDll=
7551 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7552 return S_OK;
7553 }else {/* for a member */
7554 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7555 if(pFDesc){
7556 if(pbstrHelpString)
7557 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7558 if(pdwHelpStringContext)
7559 *pdwHelpStringContext=pFDesc->HelpStringContext;
7560 if(pbstrHelpStringDll)
7561 *pbstrHelpStringDll=
7562 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7563 return S_OK;
7564 }
7565 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7566 if(pVDesc){
7567 if(pbstrHelpString)
7568 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7569 if(pdwHelpStringContext)
7570 *pdwHelpStringContext=pVDesc->HelpStringContext;
7571 if(pbstrHelpStringDll)
7572 *pbstrHelpStringDll=
7573 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7574 return S_OK;
7575 }
7576 }
7577 return TYPE_E_ELEMENTNOTFOUND;
7578 }
7579
7580 /* ITypeInfo2::GetAllCustData
7581 *
7582 * Gets all custom data items for the Type info.
7583 *
7584 */
7585 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7586 ITypeInfo2 * iface,
7587 CUSTDATA *pCustData)
7588 {
7589 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7590
7591 TRACE("%p %p\n", This, pCustData);
7592
7593 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7594 }
7595
7596 /* ITypeInfo2::GetAllFuncCustData
7597 *
7598 * Gets all custom data items for the specified Function
7599 *
7600 */
7601 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7602 ITypeInfo2 * iface,
7603 UINT index,
7604 CUSTDATA *pCustData)
7605 {
7606 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7607 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7608
7609 TRACE("%p %u %p\n", This, index, pCustData);
7610
7611 if(index >= This->TypeAttr.cFuncs)
7612 return TYPE_E_ELEMENTNOTFOUND;
7613
7614 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7615 }
7616
7617 /* ITypeInfo2::GetAllParamCustData
7618 *
7619 * Gets all custom data items for the Functions
7620 *
7621 */
7622 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7623 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7624 {
7625 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7626 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7627
7628 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7629
7630 if(indexFunc >= This->TypeAttr.cFuncs)
7631 return TYPE_E_ELEMENTNOTFOUND;
7632
7633 if(indexParam >= pFDesc->funcdesc.cParams)
7634 return TYPE_E_ELEMENTNOTFOUND;
7635
7636 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7637 }
7638
7639 /* ITypeInfo2::GetAllVarCustData
7640 *
7641 * Gets all custom data items for the specified Variable
7642 *
7643 */
7644 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7645 UINT index, CUSTDATA *pCustData)
7646 {
7647 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7648 TLBVarDesc * pVDesc = &This->vardescs[index];
7649
7650 TRACE("%p %u %p\n", This, index, pCustData);
7651
7652 if(index >= This->TypeAttr.cVars)
7653 return TYPE_E_ELEMENTNOTFOUND;
7654
7655 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7656 }
7657
7658 /* ITypeInfo2::GetAllImplCustData
7659 *
7660 * Gets all custom data items for the specified implementation type
7661 *
7662 */
7663 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7664 ITypeInfo2 * iface,
7665 UINT index,
7666 CUSTDATA *pCustData)
7667 {
7668 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7669 TLBImplType *pRDesc = &This->impltypes[index];
7670
7671 TRACE("%p %u %p\n", This, index, pCustData);
7672
7673 if(index >= This->TypeAttr.cImplTypes)
7674 return TYPE_E_ELEMENTNOTFOUND;
7675
7676 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7677 }
7678
7679 static const ITypeInfo2Vtbl tinfvt =
7680 {
7681
7682 ITypeInfo_fnQueryInterface,
7683 ITypeInfo_fnAddRef,
7684 ITypeInfo_fnRelease,
7685
7686 ITypeInfo_fnGetTypeAttr,
7687 ITypeInfo_fnGetTypeComp,
7688 ITypeInfo_fnGetFuncDesc,
7689 ITypeInfo_fnGetVarDesc,
7690 ITypeInfo_fnGetNames,
7691 ITypeInfo_fnGetRefTypeOfImplType,
7692 ITypeInfo_fnGetImplTypeFlags,
7693 ITypeInfo_fnGetIDsOfNames,
7694 ITypeInfo_fnInvoke,
7695 ITypeInfo_fnGetDocumentation,
7696 ITypeInfo_fnGetDllEntry,
7697 ITypeInfo_fnGetRefTypeInfo,
7698 ITypeInfo_fnAddressOfMember,
7699 ITypeInfo_fnCreateInstance,
7700 ITypeInfo_fnGetMops,
7701 ITypeInfo_fnGetContainingTypeLib,
7702 ITypeInfo_fnReleaseTypeAttr,
7703 ITypeInfo_fnReleaseFuncDesc,
7704 ITypeInfo_fnReleaseVarDesc,
7705
7706 ITypeInfo2_fnGetTypeKind,
7707 ITypeInfo2_fnGetTypeFlags,
7708 ITypeInfo2_fnGetFuncIndexOfMemId,
7709 ITypeInfo2_fnGetVarIndexOfMemId,
7710 ITypeInfo2_fnGetCustData,
7711 ITypeInfo2_fnGetFuncCustData,
7712 ITypeInfo2_fnGetParamCustData,
7713 ITypeInfo2_fnGetVarCustData,
7714 ITypeInfo2_fnGetImplTypeCustData,
7715 ITypeInfo2_fnGetDocumentation2,
7716 ITypeInfo2_fnGetAllCustData,
7717 ITypeInfo2_fnGetAllFuncCustData,
7718 ITypeInfo2_fnGetAllParamCustData,
7719 ITypeInfo2_fnGetAllVarCustData,
7720 ITypeInfo2_fnGetAllImplTypeCustData,
7721 };
7722
7723 /******************************************************************************
7724 * CreateDispTypeInfo [OLEAUT32.31]
7725 *
7726 * Build type information for an object so it can be called through an
7727 * IDispatch interface.
7728 *
7729 * RETURNS
7730 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7731 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7732 *
7733 * NOTES
7734 * This call allows an objects methods to be accessed through IDispatch, by
7735 * building an ITypeInfo object that IDispatch can use to call through.
7736 */
7737 HRESULT WINAPI CreateDispTypeInfo(
7738 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7739 LCID lcid, /* [I] Locale Id */
7740 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7741 {
7742 ITypeInfoImpl *pTIClass, *pTIIface;
7743 ITypeLibImpl *pTypeLibImpl;
7744 unsigned int param, func;
7745 TLBFuncDesc *pFuncDesc;
7746 TLBRefType *ref;
7747
7748 TRACE("\n");
7749 pTypeLibImpl = TypeLibImpl_Constructor();
7750 if (!pTypeLibImpl) return E_FAIL;
7751
7752 pTypeLibImpl->TypeInfoCount = 2;
7753 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7754
7755 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7756 pTIIface->pTypeLib = pTypeLibImpl;
7757 pTIIface->index = 0;
7758 pTIIface->Name = NULL;
7759 pTIIface->dwHelpContext = -1;
7760 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7761 pTIIface->TypeAttr.lcid = lcid;
7762 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7763 pTIIface->TypeAttr.wMajorVerNum = 0;
7764 pTIIface->TypeAttr.wMinorVerNum = 0;
7765 pTIIface->TypeAttr.cbAlignment = 2;
7766 pTIIface->TypeAttr.cbSizeInstance = -1;
7767 pTIIface->TypeAttr.cbSizeVft = -1;
7768 pTIIface->TypeAttr.cFuncs = 0;
7769 pTIIface->TypeAttr.cImplTypes = 0;
7770 pTIIface->TypeAttr.cVars = 0;
7771 pTIIface->TypeAttr.wTypeFlags = 0;
7772
7773 pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
7774 pFuncDesc = pTIIface->funcdescs;
7775 for(func = 0; func < pidata->cMembers; func++) {
7776 METHODDATA *md = pidata->pmethdata + func;
7777 pFuncDesc->Name = SysAllocString(md->szName);
7778 pFuncDesc->funcdesc.memid = md->dispid;
7779 pFuncDesc->funcdesc.lprgscode = NULL;
7780 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7781 pFuncDesc->funcdesc.invkind = md->wFlags;
7782 pFuncDesc->funcdesc.callconv = md->cc;
7783 pFuncDesc->funcdesc.cParams = md->cArgs;
7784 pFuncDesc->funcdesc.cParamsOpt = 0;
7785 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7786 pFuncDesc->funcdesc.cScodes = 0;
7787 pFuncDesc->funcdesc.wFuncFlags = 0;
7788 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7789 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7790 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7791 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7792 md->cArgs * sizeof(ELEMDESC));
7793 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7794 for(param = 0; param < md->cArgs; param++) {
7795 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7796 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7797 }
7798 pFuncDesc->helpcontext = 0;
7799 pFuncDesc->HelpStringContext = 0;
7800 pFuncDesc->HelpString = NULL;
7801 pFuncDesc->Entry = NULL;
7802 list_init(&pFuncDesc->custdata_list);
7803 pTIIface->TypeAttr.cFuncs++;
7804 ++pFuncDesc;
7805 }
7806
7807 dump_TypeInfo(pTIIface);
7808
7809 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7810 pTIClass->pTypeLib = pTypeLibImpl;
7811 pTIClass->index = 1;
7812 pTIClass->Name = NULL;
7813 pTIClass->dwHelpContext = -1;
7814 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7815 pTIClass->TypeAttr.lcid = lcid;
7816 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7817 pTIClass->TypeAttr.wMajorVerNum = 0;
7818 pTIClass->TypeAttr.wMinorVerNum = 0;
7819 pTIClass->TypeAttr.cbAlignment = 2;
7820 pTIClass->TypeAttr.cbSizeInstance = -1;
7821 pTIClass->TypeAttr.cbSizeVft = -1;
7822 pTIClass->TypeAttr.cFuncs = 0;
7823 pTIClass->TypeAttr.cImplTypes = 1;
7824 pTIClass->TypeAttr.cVars = 0;
7825 pTIClass->TypeAttr.wTypeFlags = 0;
7826
7827 pTIClass->impltypes = TLBImplType_Constructor(1);
7828
7829 ref = heap_alloc_zero(sizeof(*ref));
7830 ref->pImpTLInfo = TLB_REF_INTERNAL;
7831 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7832
7833 dump_TypeInfo(pTIClass);
7834
7835 *pptinfo = (ITypeInfo*)pTIClass;
7836
7837 ITypeInfo_AddRef(*pptinfo);
7838 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7839
7840 return S_OK;
7841
7842 }
7843
7844 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7845 {
7846 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7847
7848 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7849 }
7850
7851 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7852 {
7853 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7854
7855 return ITypeInfo_AddRef((ITypeInfo *)This);
7856 }
7857
7858 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7859 {
7860 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7861
7862 return ITypeInfo_Release((ITypeInfo *)This);
7863 }
7864
7865 static HRESULT WINAPI ITypeComp_fnBind(
7866 ITypeComp * iface,
7867 OLECHAR * szName,
7868 ULONG lHash,
7869 WORD wFlags,
7870 ITypeInfo ** ppTInfo,
7871 DESCKIND * pDescKind,
7872 BINDPTR * pBindPtr)
7873 {
7874 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7875 const TLBFuncDesc *pFDesc;
7876 const TLBVarDesc *pVDesc;
7877 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7878 UINT fdc;
7879
7880 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7881
7882 *pDescKind = DESCKIND_NONE;
7883 pBindPtr->lpfuncdesc = NULL;
7884 *ppTInfo = NULL;
7885
7886 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7887 pFDesc = &This->funcdescs[fdc];
7888 if (!strcmpiW(pFDesc->Name, szName)) {
7889 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7890 break;
7891 else
7892 /* name found, but wrong flags */
7893 hr = TYPE_E_TYPEMISMATCH;
7894 }
7895 }
7896
7897 if (fdc < This->TypeAttr.cFuncs)
7898 {
7899 HRESULT hr = TLB_AllocAndInitFuncDesc(
7900 &pFDesc->funcdesc,
7901 &pBindPtr->lpfuncdesc,
7902 This->TypeAttr.typekind == TKIND_DISPATCH);
7903 if (FAILED(hr))
7904 return hr;
7905 *pDescKind = DESCKIND_FUNCDESC;
7906 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7907 ITypeInfo_AddRef(*ppTInfo);
7908 return S_OK;
7909 } else {
7910 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
7911 if(pVDesc){
7912 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7913 if (FAILED(hr))
7914 return hr;
7915 *pDescKind = DESCKIND_VARDESC;
7916 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7917 ITypeInfo_AddRef(*ppTInfo);
7918 return S_OK;
7919 }
7920 }
7921 /* FIXME: search each inherited interface, not just the first */
7922 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
7923 /* recursive search */
7924 ITypeInfo *pTInfo;
7925 ITypeComp *pTComp;
7926 HRESULT hr;
7927 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypes[0].hRef, &pTInfo);
7928 if (SUCCEEDED(hr))
7929 {
7930 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7931 ITypeInfo_Release(pTInfo);
7932 }
7933 if (SUCCEEDED(hr))
7934 {
7935 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7936 ITypeComp_Release(pTComp);
7937 return hr;
7938 }
7939 WARN("Could not search inherited interface!\n");
7940 }
7941 if (hr == DISP_E_MEMBERNOTFOUND)
7942 hr = S_OK;
7943 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7944 return hr;
7945 }
7946
7947 static HRESULT WINAPI ITypeComp_fnBindType(
7948 ITypeComp * iface,
7949 OLECHAR * szName,
7950 ULONG lHash,
7951 ITypeInfo ** ppTInfo,
7952 ITypeComp ** ppTComp)
7953 {
7954 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7955
7956 /* strange behaviour (does nothing) but like the
7957 * original */
7958
7959 if (!ppTInfo || !ppTComp)
7960 return E_POINTER;
7961
7962 *ppTInfo = NULL;
7963 *ppTComp = NULL;
7964
7965 return S_OK;
7966 }
7967
7968 static const ITypeCompVtbl tcompvt =
7969 {
7970
7971 ITypeComp_fnQueryInterface,
7972 ITypeComp_fnAddRef,
7973 ITypeComp_fnRelease,
7974
7975 ITypeComp_fnBind,
7976 ITypeComp_fnBindType
7977 };