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