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