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