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