Merge 13831:14550 from trunk
[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 * First entry is always the length of the record (including this
1633 * length word).
1634 * Rest of the record depends on the type of the member. If there is
1635 * a field indicating the member type (function variable intereface 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 memeber id
1640 * for each member;
1641 *
1642 * Third is a equal sized array with file offsets to the name entry
1643 * of each member.
1644 *
1645 * Forth and last (?) part is an array with offsets to the records in the
1646 * 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 VARTYPE oldvt;
4520 VARIANT va;
4521
4522 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4523 memcpy(argpos,&arg,sizeof(void*));
4524 return S_OK;
4525 }
4526
4527 if (V_VT(arg) == vt) {
4528 memcpy(argpos, &V_I4(arg), arglen);
4529 return S_OK;
4530 }
4531
4532 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4533 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4534 return S_OK;
4535 }
4536
4537 if (vt == VT_VARIANT) {
4538 memcpy(argpos, arg, arglen);
4539 return S_OK;
4540 }
4541 /* Deref BYREF vars if there is need */
4542 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4543 memcpy(argpos,(void*)V_I4(arg), arglen);
4544 return S_OK;
4545 }
4546 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4547 /* in this context, if the type lib specifies IUnknown*, giving an
4548 IDispatch* is correct; so, don't invoke VariantChangeType */
4549 memcpy(argpos,&V_I4(arg), arglen);
4550 return S_OK;
4551 }
4552 if ((vt == VT_PTR) && tdesc)
4553 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4554
4555 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4556 ITypeInfo *tinfo2 = NULL;
4557 TYPEATTR *tattr = NULL;
4558 HRESULT hres;
4559
4560 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4561 if (hres) {
4562 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4563 "while coercing from vt 0x%x. Copying 4 byte.\n",
4564 tdesc->u.hreftype,V_VT(arg));
4565 memcpy(argpos, &V_I4(arg), 4);
4566 return S_OK;
4567 }
4568 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4569 if( hres )
4570 {
4571 ERR("GetTypeAttr failed\n");
4572 ITypeInfo_Release(tinfo2);
4573 return hres;
4574 }
4575 switch (tattr->typekind) {
4576 case TKIND_ENUM:
4577 switch ( V_VT( arg ) ) {
4578 case VT_I2:
4579 *argpos = V_I2(arg);
4580 hres = S_OK;
4581 break;
4582 case VT_I4:
4583 memcpy(argpos, &V_I4(arg), 4);
4584 hres = S_OK;
4585 break;
4586 default:
4587 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4588 hres = E_FAIL;
4589 break;
4590 }
4591 break;
4592
4593 case TKIND_ALIAS:
4594 tdesc = &(tattr->tdescAlias);
4595 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4596 break;
4597
4598 case TKIND_INTERFACE:
4599 if (V_VT(arg) == VT_DISPATCH) {
4600 IDispatch *disp;
4601 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4602 memcpy(argpos, &V_DISPATCH(arg), 4);
4603 hres = S_OK;
4604 break;
4605 }
4606 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4607 &IID_IDispatch,(LPVOID*)&disp);
4608 if (SUCCEEDED(hres)) {
4609 memcpy(argpos,&disp,4);
4610 IUnknown_Release(V_DISPATCH(arg));
4611 hres = S_OK;
4612 break;
4613 }
4614 FIXME("Failed to query IDispatch interface from %s while "
4615 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4616 hres = E_FAIL;
4617 break;
4618 }
4619 if (V_VT(arg) == VT_UNKNOWN) {
4620 memcpy(argpos, &V_UNKNOWN(arg), 4);
4621 hres = S_OK;
4622 break;
4623 }
4624 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4625 V_VT(arg),debugstr_guid(&(tattr->guid)));
4626 hres = E_FAIL;
4627 break;
4628
4629 case TKIND_DISPATCH:
4630 if (V_VT(arg) == VT_DISPATCH) {
4631 memcpy(argpos, &V_DISPATCH(arg), 4);
4632 hres = S_OK;
4633 }
4634 else {
4635 hres = E_FAIL;
4636 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4637 }
4638 break;
4639 case TKIND_RECORD:
4640 FIXME("TKIND_RECORD unhandled.\n");
4641 hres = E_FAIL;
4642 break;
4643 default:
4644 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4645 hres = E_FAIL;
4646 break;
4647 }
4648 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4649 ITypeInfo_Release(tinfo2);
4650 return hres;
4651 }
4652
4653 oldvt = V_VT(arg);
4654 VariantInit(&va);
4655 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4656 memcpy(argpos,&V_I4(&va), arglen);
4657 FIXME("Should not use VariantChangeType here."
4658 " (conversion from 0x%x -> 0x%x) %08lx\n",
4659 V_VT(arg), vt, *argpos
4660 );
4661 return S_OK;
4662 }
4663 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4664 return E_FAIL;
4665 }
4666
4667 /***********************************************************************
4668 * DispCallFunc (OLEAUT32.@)
4669 */
4670 HRESULT WINAPI
4671 DispCallFunc(
4672 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4673 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4674 ) {
4675 int i, argsize, argspos;
4676 DWORD *args;
4677 HRESULT hres;
4678
4679 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4680 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4681 );
4682 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4683 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4684 argsize = 1;
4685 for (i=0;i<cActuals;i++) {
4686 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4687 dump_Variant(prgpvarg[i]);
4688 argsize += _argsize(prgvt[i]);
4689 }
4690 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4691 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4692 argspos = 1;
4693 for (i=0;i<cActuals;i++) {
4694 VARIANT *arg = prgpvarg[i];
4695 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4696 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4697 argspos += _argsize(prgvt[i]);
4698 }
4699
4700 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4701 {
4702 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4703 hres=S_OK;
4704 }
4705 else
4706 {
4707 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4708 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4709 FIXME("Method returned %lx\n",hres);
4710 }
4711 HeapFree(GetProcessHeap(),0,args);
4712 return hres;
4713 }
4714
4715 static HRESULT WINAPI ITypeInfo_fnInvoke(
4716 ITypeInfo2 *iface,
4717 VOID *pIUnk,
4718 MEMBERID memid,
4719 UINT16 dwFlags,
4720 DISPPARAMS *pDispParams,
4721 VARIANT *pVarResult,
4722 EXCEPINFO *pExcepInfo,
4723 UINT *pArgErr)
4724 {
4725 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4726 int i;
4727 unsigned int func_index, var_index;
4728 TYPEKIND type_kind;
4729 HRESULT hres;
4730
4731 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4732 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4733 );
4734 dump_DispParms(pDispParams);
4735
4736 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4737 if (SUCCEEDED(hres)) {
4738 FUNCDESC *func_desc;
4739
4740 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4741 if(FAILED(hres)) return hres;
4742
4743 switch (func_desc->funckind) {
4744 case FUNC_PUREVIRTUAL:
4745 case FUNC_VIRTUAL: {
4746 DWORD res;
4747 int numargs, numargs2, argspos, args2pos;
4748 DWORD *args , *args2;
4749 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4750 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4751
4752 hres = S_OK;
4753 numargs = 1; numargs2 = 0;
4754 for (i = 0; i < func_desc->cParams; i++) {
4755 if (i<pDispParams->cArgs)
4756 numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4757 else {
4758 numargs += 1; /* sizeof(lpvoid) */
4759 numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4760 }
4761 }
4762
4763 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4764 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4765
4766 args[0] = (DWORD)pIUnk;
4767 argspos = 1; args2pos = 0;
4768 for (i = 0; i < func_desc->cParams; i++) {
4769 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4770 if (i<pDispParams->cArgs) {
4771 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4772 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4773 USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
4774 if (paramFlags & PARAMFLAG_FOPT) {
4775 if(i < func_desc->cParams - func_desc->cParamsOpt)
4776 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4777 if(V_VT(arg) == VT_EMPTY
4778 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4779 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4780 How to determine it? */
4781
4782 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4783 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4784 V_VT(arg) = VT_ERROR;
4785 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4786 arglen = _argsize(VT_ERROR);
4787 }
4788 }
4789 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4790 if (FAILED(hres)) goto func_fail;
4791 argspos += arglen;
4792 } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
4793 VARIANT *arg = &rgvarg[i];
4794 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4795 if(i < func_desc->cParams - func_desc->cParamsOpt)
4796 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4797 if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4798 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4799 V_VT(arg) = VT_ERROR;
4800 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4801 arglen = _argsize(VT_ERROR);
4802 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4803 if (FAILED(hres)) goto func_fail;
4804 argspos += arglen;
4805 } else {
4806 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);
4807 if (tdesc->vt != VT_PTR)
4808 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4809 /*FIXME: give pointers for the rest, so propertyget works*/
4810 args[argspos] = (DWORD)&args2[args2pos];
4811
4812 /* If pointer to variant, pass reference it. */
4813 if ((tdesc->vt == VT_PTR) &&
4814 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4815 pVarResult
4816 )
4817 args[argspos]= (DWORD)pVarResult;
4818 argspos += 1;
4819 args2pos += arglen;
4820 }
4821 }
4822 if (func_desc->cParamsOpt < 0)
4823 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4824
4825 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4826 func_desc->callconv,
4827 numargs,
4828 args
4829 );
4830
4831 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4832 args2pos = 0;
4833 for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
4834 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4835 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);
4836 TYPEDESC i4_tdesc;
4837 i4_tdesc.vt = VT_I4;
4838
4839 /* If we are a pointer to a variant, we are done already */
4840 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4841 continue;
4842
4843 VariantInit(pVarResult);
4844 memcpy(&V_INT(pVarResult),&args2[args2pos],arglen*sizeof(DWORD));
4845
4846 if (tdesc->vt == VT_PTR)
4847 tdesc = tdesc->u.lptdesc;
4848 if (tdesc->vt == VT_USERDEFINED) {
4849 ITypeInfo *tinfo2;
4850 TYPEATTR *tattr;
4851
4852 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4853 if (FAILED(hres)) {
4854 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4855 goto func_fail;
4856 }
4857 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4858 switch (tattr->typekind) {
4859 case TKIND_ENUM:
4860 /* force the return type to be VT_I4 */
4861 tdesc = &i4_tdesc;
4862 break;
4863 case TKIND_ALIAS:
4864 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4865 tdesc = &(tattr->tdescAlias);
4866 break;
4867
4868 case TKIND_INTERFACE:
4869 FIXME("TKIND_INTERFACE unhandled.\n");
4870 break;
4871 case TKIND_DISPATCH:
4872 FIXME("TKIND_DISPATCH unhandled.\n");
4873 break;
4874 case TKIND_RECORD:
4875 FIXME("TKIND_RECORD unhandled.\n");
4876 break;
4877 default:
4878 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4879 break;
4880 }
4881 ITypeInfo_Release(tinfo2);
4882 }
4883 V_VT(pVarResult) = tdesc->vt;
4884
4885 /* HACK: VB5 likes this.
4886 * I do not know why. There is 1 example in MSDN which uses
4887 * this which appears broken (mixes int vals and
4888 * IDispatch*.).
4889 */
4890 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4891 V_VT(pVarResult) = VT_DISPATCH;
4892 TRACE("storing into variant:\n");
4893 dump_Variant(pVarResult);
4894 args2pos += arglen;
4895 }
4896 }
4897 func_fail:
4898 HeapFree(GetProcessHeap(), 0, rgvarg);
4899 HeapFree(GetProcessHeap(),0,args2);
4900 HeapFree(GetProcessHeap(),0,args);
4901 break;
4902 }
4903 case FUNC_DISPATCH: {
4904 IDispatch *disp;
4905
4906 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4907 if (SUCCEEDED(hres)) {
4908 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4909 hres = IDispatch_Invoke(
4910 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4911 pVarResult,pExcepInfo,pArgErr
4912 );
4913 if (FAILED(hres))
4914 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
4915 IDispatch_Release(disp);
4916 } else
4917 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4918 break;
4919 }
4920 default:
4921 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
4922 hres = E_FAIL;
4923 break;
4924 }
4925
4926 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
4927 return hres;
4928
4929 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
4930 VARDESC *var_desc;
4931
4932 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
4933 if(FAILED(hres)) return hres;
4934
4935 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4936 dump_VARDESC(var_desc);
4937 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
4938 return E_NOTIMPL;
4939 }
4940
4941 /* not found, look for it in inherited interfaces */
4942 ITypeInfo2_GetTypeKind(iface, &type_kind);
4943 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
4944 HREFTYPE ref_type;
4945 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
4946 /* recursive search */
4947 ITypeInfo *pTInfo;
4948 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
4949 if(SUCCEEDED(hres)){
4950 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4951 ITypeInfo_Release(pTInfo);
4952 return hres;
4953 }
4954 WARN("Could not search inherited interface!\n");
4955 }
4956 }
4957 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
4958 return DISP_E_MEMBERNOTFOUND;
4959 }
4960
4961 /* ITypeInfo::GetDocumentation
4962 *
4963 * Retrieves the documentation string, the complete Help file name and path,
4964 * and the context ID for the Help topic for a specified type description.
4965 *
4966 * (Can be tested by the Visual Basic Editor in Word for instance.)
4967 */
4968 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4969 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4970 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4971 {
4972 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4973 TLBFuncDesc * pFDesc;
4974 TLBVarDesc * pVDesc;
4975 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4976 " HelpContext(%p) HelpFile(%p)\n",
4977 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4978 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4979 if(pBstrName)
4980 *pBstrName=SysAllocString(This->Name);
4981 if(pBstrDocString)
4982 *pBstrDocString=SysAllocString(This->DocString);
4983 if(pdwHelpContext)
4984 *pdwHelpContext=This->dwHelpContext;
4985 if(pBstrHelpFile)
4986 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4987 return S_OK;
4988 }else {/* for a member */
4989 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4990 if(pFDesc->funcdesc.memid==memid){
4991 if(pBstrName)
4992 *pBstrName = SysAllocString(pFDesc->Name);
4993 if(pBstrDocString)
4994 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4995 if(pdwHelpContext)
4996 *pdwHelpContext=pFDesc->helpcontext;
4997 return S_OK;
4998 }
4999 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5000 if(pVDesc->vardesc.memid==memid){
5001 if(pBstrName)
5002 *pBstrName = SysAllocString(pVDesc->Name);
5003 if(pBstrDocString)
5004 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5005 if(pdwHelpContext)
5006 *pdwHelpContext=pVDesc->HelpContext;
5007 return S_OK;
5008 }
5009 }
5010 return TYPE_E_ELEMENTNOTFOUND;
5011 }
5012
5013 /* ITypeInfo::GetDllEntry
5014 *
5015 * Retrieves a description or specification of an entry point for a function
5016 * in a DLL.
5017 */
5018 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5019 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5020 WORD *pwOrdinal)
5021 {
5022 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5023 TLBFuncDesc *pFDesc;
5024
5025 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5026
5027 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5028 if(pFDesc->funcdesc.memid==memid){
5029 dump_TypeInfo(This);
5030 dump_TLBFuncDescOne(pFDesc);
5031
5032 /* FIXME: This is wrong, but how do you find that out? */
5033 if (pBstrDllName) {
5034 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5035 *pBstrDllName = SysAllocString(oleaut32W);
5036 }
5037
5038 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5039 if (pBstrName)
5040 *pBstrName = SysAllocString(pFDesc->Entry);
5041 if (pwOrdinal)
5042 *pwOrdinal = -1;
5043 return S_OK;
5044 }
5045 if (pBstrName)
5046 *pBstrName = NULL;
5047 if (pwOrdinal)
5048 *pwOrdinal = (DWORD)pFDesc->Entry;
5049 return S_OK;
5050 }
5051 return E_FAIL;
5052 }
5053
5054 /* ITypeInfo::GetRefTypeInfo
5055 *
5056 * If a type description references other type descriptions, it retrieves
5057 * the referenced type descriptions.
5058 */
5059 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5060 ITypeInfo2 *iface,
5061 HREFTYPE hRefType,
5062 ITypeInfo **ppTInfo)
5063 {
5064 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5065 HRESULT result = E_FAIL;
5066
5067
5068 if (hRefType == -1 &&
5069 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5070 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5071 {
5072 /* when we meet a DUAL dispinterface, we must create the interface
5073 * version of it.
5074 */
5075 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5076
5077
5078 /* the interface version contains the same information as the dispinterface
5079 * copy the contents of the structs.
5080 */
5081 *pTypeInfoImpl = *This;
5082 pTypeInfoImpl->ref = 1;
5083
5084 /* change the type to interface */
5085 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5086
5087 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5088
5089 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5090
5091 result = S_OK;
5092
5093 } else {
5094 TLBRefType *pRefType;
5095 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5096 if(pRefType->reference == hRefType)
5097 break;
5098 }
5099 if(!pRefType)
5100 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5101 if(pRefType && hRefType != -1) {
5102 ITypeLib *pTLib = NULL;
5103
5104 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5105 int Index;
5106 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5107 } else {
5108 if(pRefType->pImpTLInfo->pImpTypeLib) {
5109 TRACE("typeinfo in imported typelib that is already loaded\n");
5110 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5111 ITypeLib2_AddRef((ITypeLib*) pTLib);
5112 result = S_OK;
5113 } else {
5114 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5115 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5116 pRefType->pImpTLInfo->wVersionMajor,
5117 pRefType->pImpTLInfo->wVersionMinor,
5118 pRefType->pImpTLInfo->lcid,
5119 &pTLib);
5120
5121 if(!SUCCEEDED(result)) {
5122 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5123 result=LoadTypeLib(libnam, &pTLib);
5124 SysFreeString(libnam);
5125 }
5126 if(SUCCEEDED(result)) {
5127 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5128 ITypeLib2_AddRef(pTLib);
5129 }
5130 }
5131 }
5132 if(SUCCEEDED(result)) {
5133 if(pRefType->index == TLB_REF_USE_GUID)
5134 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5135 &pRefType->guid,
5136 ppTInfo);
5137 else
5138 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5139 ppTInfo);
5140 }
5141 if (pTLib != NULL)
5142 ITypeLib2_Release(pTLib);
5143 }
5144 }
5145
5146 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5147 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5148 return result;
5149 }
5150
5151 /* ITypeInfo::AddressOfMember
5152 *
5153 * Retrieves the addresses of static functions or variables, such as those
5154 * defined in a DLL.
5155 */
5156 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5157 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5158 {
5159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5160 FIXME("(%p) stub!\n", This);
5161 return S_OK;
5162 }
5163
5164 /* ITypeInfo::CreateInstance
5165 *
5166 * Creates a new instance of a type that describes a component object class
5167 * (coclass).
5168 */
5169 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5170 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5171 {
5172 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5173 FIXME("(%p) stub!\n", This);
5174 return S_OK;
5175 }
5176
5177 /* ITypeInfo::GetMops
5178 *
5179 * Retrieves marshalling information.
5180 */
5181 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5182 BSTR *pBstrMops)
5183 {
5184 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5185 FIXME("(%p) stub!\n", This);
5186 return S_OK;
5187 }
5188
5189 /* ITypeInfo::GetContainingTypeLib
5190 *
5191 * Retrieves the containing type library and the index of the type description
5192 * within that type library.
5193 */
5194 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5195 ITypeLib * *ppTLib, UINT *pIndex)
5196 {
5197 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5198
5199 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5200 if (pIndex) {
5201 *pIndex=This->index;
5202 TRACE("returning pIndex=%d\n", *pIndex);
5203 }
5204
5205 if (ppTLib) {
5206 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5207 ITypeLib2_AddRef(*ppTLib);
5208 TRACE("returning ppTLib=%p\n", *ppTLib);
5209 }
5210
5211 return S_OK;
5212 }
5213
5214 /* ITypeInfo::ReleaseTypeAttr
5215 *
5216 * Releases a TYPEATTR previously returned by GetTypeAttr.
5217 *
5218 */
5219 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5220 TYPEATTR* pTypeAttr)
5221 {
5222 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5223 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5224 if(This->TypeAttr.typekind == TKIND_ALIAS)
5225 free_deep_typedesc(&pTypeAttr->tdescAlias);
5226 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5227 }
5228
5229 /* ITypeInfo::ReleaseFuncDesc
5230 *
5231 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5232 */
5233 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5234 ITypeInfo2 *iface,
5235 FUNCDESC *pFuncDesc)
5236 {
5237 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5238 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5239 }
5240
5241 /* ITypeInfo::ReleaseVarDesc
5242 *
5243 * Releases a VARDESC previously returned by GetVarDesc.
5244 */
5245 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5246 VARDESC *pVarDesc)
5247 {
5248 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5249 TRACE("(%p)->(%p)\n", This, pVarDesc);
5250 }
5251
5252 /* ITypeInfo2::GetTypeKind
5253 *
5254 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5255 *
5256 */
5257 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5258 TYPEKIND *pTypeKind)
5259 {
5260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5261 *pTypeKind=This->TypeAttr.typekind;
5262 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5263 return S_OK;
5264 }
5265
5266 /* ITypeInfo2::GetTypeFlags
5267 *
5268 * Returns the type flags without any allocations. This returns a DWORD type
5269 * flag, which expands the type flags without growing the TYPEATTR (type
5270 * attribute).
5271 *
5272 */
5273 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5274 {
5275 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5276 *pTypeFlags=This->TypeAttr.wTypeFlags;
5277 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5278 return S_OK;
5279 }
5280
5281 /* ITypeInfo2::GetFuncIndexOfMemId
5282 * Binds to a specific member based on a known DISPID, where the member name
5283 * is not known (for example, when binding to a default member).
5284 *
5285 */
5286 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5287 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5288 {
5289 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5290 TLBFuncDesc *pFuncInfo;
5291 int i;
5292 HRESULT result;
5293
5294 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5295 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5296 break;
5297 if(pFuncInfo) {
5298 *pFuncIndex = i;
5299 result = S_OK;
5300 } else
5301 result = TYPE_E_ELEMENTNOTFOUND;
5302
5303 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5304 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5305 return result;
5306 }
5307
5308 /* TypeInfo2::GetVarIndexOfMemId
5309 *
5310 * Binds to a specific member based on a known DISPID, where the member name
5311 * is not known (for example, when binding to a default member).
5312 *
5313 */
5314 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5315 MEMBERID memid, UINT *pVarIndex)
5316 {
5317 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5318 TLBVarDesc *pVarInfo;
5319 int i;
5320 HRESULT result;
5321 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5322 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5323 ;
5324 if(pVarInfo) {
5325 *pVarIndex = i;
5326 result = S_OK;
5327 } else
5328 result = TYPE_E_ELEMENTNOTFOUND;
5329
5330 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5331 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5332 return result;
5333 }
5334
5335 /* ITypeInfo2::GetCustData
5336 *
5337 * Gets the custom data
5338 */
5339 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5340 ITypeInfo2 * iface,
5341 REFGUID guid,
5342 VARIANT *pVarVal)
5343 {
5344 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5345 TLBCustData *pCData;
5346
5347 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5348 if( IsEqualIID(guid, &pCData->guid)) break;
5349
5350 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5351
5352 if(pCData)
5353 {
5354 VariantInit( pVarVal);
5355 VariantCopy( pVarVal, &pCData->data);
5356 return S_OK;
5357 }
5358 return E_INVALIDARG; /* FIXME: correct? */
5359 }
5360
5361 /* ITypeInfo2::GetFuncCustData
5362 *
5363 * Gets the custom data
5364 */
5365 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5366 ITypeInfo2 * iface,
5367 UINT index,
5368 REFGUID guid,
5369 VARIANT *pVarVal)
5370 {
5371 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5372 TLBCustData *pCData=NULL;
5373 TLBFuncDesc * pFDesc;
5374 int i;
5375 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5376 pFDesc=pFDesc->next);
5377
5378 if(pFDesc)
5379 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5380 if( IsEqualIID(guid, &pCData->guid)) break;
5381
5382 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5383
5384 if(pCData){
5385 VariantInit( pVarVal);
5386 VariantCopy( pVarVal, &pCData->data);
5387 return S_OK;
5388 }
5389 return E_INVALIDARG; /* FIXME: correct? */
5390 }
5391
5392 /* ITypeInfo2::GetParamCustData
5393 *
5394 * Gets the custom data
5395 */
5396 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5397 ITypeInfo2 * iface,
5398 UINT indexFunc,
5399 UINT indexParam,
5400 REFGUID guid,
5401 VARIANT *pVarVal)
5402 {
5403 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5404 TLBCustData *pCData=NULL;
5405 TLBFuncDesc * pFDesc;
5406 int i;
5407
5408 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5409
5410 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5411 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5412 pCData = pCData->next)
5413 if( IsEqualIID(guid, &pCData->guid)) break;
5414
5415 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5416
5417 if(pCData)
5418 {
5419 VariantInit( pVarVal);
5420 VariantCopy( pVarVal, &pCData->data);
5421 return S_OK;
5422 }
5423 return E_INVALIDARG; /* FIXME: correct? */
5424 }
5425
5426 /* ITypeInfo2::GetVarCustData
5427 *
5428 * Gets the custom data
5429 */
5430 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5431 ITypeInfo2 * iface,
5432 UINT index,
5433 REFGUID guid,
5434 VARIANT *pVarVal)
5435 {
5436 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5437 TLBCustData *pCData=NULL;
5438 TLBVarDesc * pVDesc;
5439 int i;
5440
5441 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5442
5443 if(pVDesc)
5444 {
5445 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5446 {
5447 if( IsEqualIID(guid, &pCData->guid)) break;
5448 }
5449 }
5450
5451 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5452
5453 if(pCData)
5454 {
5455 VariantInit( pVarVal);
5456 VariantCopy( pVarVal, &pCData->data);
5457 return S_OK;
5458 }
5459 return E_INVALIDARG; /* FIXME: correct? */
5460 }
5461
5462 /* ITypeInfo2::GetImplCustData
5463 *
5464 * Gets the custom data
5465 */
5466 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5467 ITypeInfo2 * iface,
5468 UINT index,
5469 REFGUID guid,
5470 VARIANT *pVarVal)
5471 {
5472 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5473 TLBCustData *pCData=NULL;
5474 TLBImplType * pRDesc;
5475 int i;
5476
5477 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5478
5479 if(pRDesc)
5480 {
5481 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5482 {
5483 if( IsEqualIID(guid, &pCData->guid)) break;
5484 }
5485 }
5486
5487 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5488
5489 if(pCData)
5490 {
5491 VariantInit( pVarVal);
5492 VariantCopy( pVarVal, &pCData->data);
5493 return S_OK;
5494 }
5495 return E_INVALIDARG; /* FIXME: correct? */
5496 }
5497
5498 /* ITypeInfo2::GetDocumentation2
5499 *
5500 * Retrieves the documentation string, the complete Help file name and path,
5501 * the localization context to use, and the context ID for the library Help
5502 * topic in the Help file.
5503 *
5504 */
5505 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5506 ITypeInfo2 * iface,
5507 MEMBERID memid,
5508 LCID lcid,
5509 BSTR *pbstrHelpString,
5510 DWORD *pdwHelpStringContext,
5511 BSTR *pbstrHelpStringDll)
5512 {
5513 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5514 TLBFuncDesc * pFDesc;
5515 TLBVarDesc * pVDesc;
5516 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5517 "HelpStringContext(%p) HelpStringDll(%p)\n",
5518 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5519 pbstrHelpStringDll );
5520 /* the help string should be obtained from the helpstringdll,
5521 * using the _DLLGetDocumentation function, based on the supplied
5522 * lcid. Nice to do sometime...
5523 */
5524 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5525 if(pbstrHelpString)
5526 *pbstrHelpString=SysAllocString(This->Name);
5527 if(pdwHelpStringContext)
5528 *pdwHelpStringContext=This->dwHelpStringContext;
5529 if(pbstrHelpStringDll)
5530 *pbstrHelpStringDll=
5531 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5532 return S_OK;
5533 }else {/* for a member */
5534 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5535 if(pFDesc->funcdesc.memid==memid){
5536 if(pbstrHelpString)
5537 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5538 if(pdwHelpStringContext)
5539 *pdwHelpStringContext=pFDesc->HelpStringContext;
5540 if(pbstrHelpStringDll)
5541 *pbstrHelpStringDll=
5542 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5543 return S_OK;
5544 }
5545 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5546 if(pVDesc->vardesc.memid==memid){
5547 if(pbstrHelpString)
5548 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5549 if(pdwHelpStringContext)
5550 *pdwHelpStringContext=pVDesc->HelpStringContext;
5551 if(pbstrHelpStringDll)
5552 *pbstrHelpStringDll=
5553 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5554 return S_OK;
5555 }
5556 }
5557 return TYPE_E_ELEMENTNOTFOUND;
5558 }
5559
5560 /* ITypeInfo2::GetAllCustData
5561 *
5562 * Gets all custom data items for the Type info.
5563 *
5564 */
5565 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5566 ITypeInfo2 * iface,
5567 CUSTDATA *pCustData)
5568 {
5569 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5570 TLBCustData *pCData;
5571 int i;
5572
5573 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5574
5575 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5576 if(pCustData->prgCustData ){
5577 pCustData->cCustData=This->ctCustData;
5578 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5579 pCustData->prgCustData[i].guid=pCData->guid;
5580 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5581 }
5582 }else{
5583 ERR(" OUT OF MEMORY! \n");
5584 return E_OUTOFMEMORY;
5585 }
5586 return S_OK;
5587 }
5588
5589 /* ITypeInfo2::GetAllFuncCustData
5590 *
5591 * Gets all custom data items for the specified Function
5592 *
5593 */
5594 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5595 ITypeInfo2 * iface,
5596 UINT index,
5597 CUSTDATA *pCustData)
5598 {
5599 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5600 TLBCustData *pCData;
5601 TLBFuncDesc * pFDesc;
5602 int i;
5603 TRACE("(%p) index %d\n", This, index);
5604 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5605 pFDesc=pFDesc->next)
5606 ;
5607 if(pFDesc){
5608 pCustData->prgCustData =
5609 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5610 if(pCustData->prgCustData ){
5611 pCustData->cCustData=pFDesc->ctCustData;
5612 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5613 pCData = pCData->next){
5614 pCustData->prgCustData[i].guid=pCData->guid;
5615 VariantCopy(& pCustData->prgCustData[i].varValue,
5616 & pCData->data);
5617 }
5618 }else{
5619 ERR(" OUT OF MEMORY! \n");
5620 return E_OUTOFMEMORY;
5621 }
5622 return S_OK;
5623 }
5624 return TYPE_E_ELEMENTNOTFOUND;
5625 }
5626
5627 /* ITypeInfo2::GetAllParamCustData
5628 *
5629 * Gets all custom data items for the Functions
5630 *
5631 */
5632 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5633 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5634 {
5635 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5636 TLBCustData *pCData=NULL;
5637 TLBFuncDesc * pFDesc;
5638 int i;
5639 TRACE("(%p) index %d\n", This, indexFunc);
5640 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5641 pFDesc=pFDesc->next)
5642 ;
5643 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5644 pCustData->prgCustData =
5645 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5646 sizeof(CUSTDATAITEM));
5647 if(pCustData->prgCustData ){
5648 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5649 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5650 pCData; i++, pCData = pCData->next){
5651 pCustData->prgCustData[i].guid=pCData->guid;
5652 VariantCopy(& pCustData->prgCustData[i].varValue,
5653 & pCData->data);
5654 }
5655 }else{
5656 ERR(" OUT OF MEMORY! \n");
5657 return E_OUTOFMEMORY;
5658 }
5659 return S_OK;
5660 }
5661 return TYPE_E_ELEMENTNOTFOUND;
5662 }
5663
5664 /* ITypeInfo2::GetAllVarCustData
5665 *
5666 * Gets all custom data items for the specified Variable
5667 *
5668 */
5669 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5670 UINT index, CUSTDATA *pCustData)
5671 {
5672 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5673 TLBCustData *pCData;
5674 TLBVarDesc * pVDesc;
5675 int i;
5676 TRACE("(%p) index %d\n", This, index);
5677 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5678 pVDesc=pVDesc->next)
5679 ;
5680 if(pVDesc){
5681 pCustData->prgCustData =
5682 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5683 if(pCustData->prgCustData ){
5684 pCustData->cCustData=pVDesc->ctCustData;
5685 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5686 pCData = pCData->next){
5687 pCustData->prgCustData[i].guid=pCData->guid;
5688 VariantCopy(& pCustData->prgCustData[i].varValue,
5689 & pCData->data);
5690 }
5691 }else{
5692 ERR(" OUT OF MEMORY! \n");
5693 return E_OUTOFMEMORY;
5694 }
5695 return S_OK;
5696 }
5697 return TYPE_E_ELEMENTNOTFOUND;
5698 }
5699
5700 /* ITypeInfo2::GetAllImplCustData
5701 *
5702 * Gets all custom data items for the specified implementation type
5703 *
5704 */
5705 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5706 ITypeInfo2 * iface,
5707 UINT index,
5708 CUSTDATA *pCustData)
5709 {
5710 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5711 TLBCustData *pCData;
5712 TLBImplType * pRDesc;
5713 int i;
5714 TRACE("(%p) index %d\n", This, index);
5715 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5716 pRDesc=pRDesc->next)
5717 ;
5718 if(pRDesc){
5719 pCustData->prgCustData =
5720 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5721 if(pCustData->prgCustData ){
5722 pCustData->cCustData=pRDesc->ctCustData;
5723 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5724 pCData = pCData->next){
5725 pCustData->prgCustData[i].guid=pCData->guid;
5726 VariantCopy(& pCustData->prgCustData[i].varValue,
5727 & pCData->data);
5728 }
5729 }else{
5730 ERR(" OUT OF MEMORY! \n");
5731 return E_OUTOFMEMORY;
5732 }
5733 return S_OK;
5734 }
5735 return TYPE_E_ELEMENTNOTFOUND;
5736 }
5737
5738 static ITypeInfo2Vtbl tinfvt =
5739 {
5740
5741 ITypeInfo_fnQueryInterface,
5742 ITypeInfo_fnAddRef,
5743 ITypeInfo_fnRelease,
5744
5745 ITypeInfo_fnGetTypeAttr,
5746 ITypeInfo_fnGetTypeComp,
5747 ITypeInfo_fnGetFuncDesc,
5748 ITypeInfo_fnGetVarDesc,
5749 ITypeInfo_fnGetNames,
5750 ITypeInfo_fnGetRefTypeOfImplType,
5751 ITypeInfo_fnGetImplTypeFlags,
5752 ITypeInfo_fnGetIDsOfNames,
5753 ITypeInfo_fnInvoke,
5754 ITypeInfo_fnGetDocumentation,
5755 ITypeInfo_fnGetDllEntry,
5756 ITypeInfo_fnGetRefTypeInfo,
5757 ITypeInfo_fnAddressOfMember,
5758 ITypeInfo_fnCreateInstance,
5759 ITypeInfo_fnGetMops,
5760 ITypeInfo_fnGetContainingTypeLib,
5761 ITypeInfo_fnReleaseTypeAttr,
5762 ITypeInfo_fnReleaseFuncDesc,
5763 ITypeInfo_fnReleaseVarDesc,
5764
5765 ITypeInfo2_fnGetTypeKind,
5766 ITypeInfo2_fnGetTypeFlags,
5767 ITypeInfo2_fnGetFuncIndexOfMemId,
5768 ITypeInfo2_fnGetVarIndexOfMemId,
5769 ITypeInfo2_fnGetCustData,
5770 ITypeInfo2_fnGetFuncCustData,
5771 ITypeInfo2_fnGetParamCustData,
5772 ITypeInfo2_fnGetVarCustData,
5773 ITypeInfo2_fnGetImplTypeCustData,
5774 ITypeInfo2_fnGetDocumentation2,
5775 ITypeInfo2_fnGetAllCustData,
5776 ITypeInfo2_fnGetAllFuncCustData,
5777 ITypeInfo2_fnGetAllParamCustData,
5778 ITypeInfo2_fnGetAllVarCustData,
5779 ITypeInfo2_fnGetAllImplTypeCustData,
5780 };
5781
5782 /******************************************************************************
5783 * CreateDispTypeInfo [OLEAUT32.31]
5784 *
5785 * Build type information for an object so it can be called through an
5786 * IDispatch interface.
5787 *
5788 * RETURNS
5789 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5790 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5791 *
5792 * NOTES
5793 * This call allows an objects methods to be accessed through IDispatch, by
5794 * building an ITypeInfo object that IDispatch can use to call through.
5795 */
5796 HRESULT WINAPI CreateDispTypeInfo(
5797 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5798 LCID lcid, /* [I] Locale Id */
5799 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5800 {
5801 ITypeInfoImpl *pTIImpl;
5802 int param, func;
5803 TLBFuncDesc **ppFuncDesc;
5804
5805 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5806 pTIImpl->pTypeLib = NULL;
5807 pTIImpl->index = 0;
5808 pTIImpl->Name = NULL;
5809 pTIImpl->dwHelpContext = -1;
5810 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5811 pTIImpl->TypeAttr.lcid = lcid;
5812 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5813 pTIImpl->TypeAttr.wMajorVerNum = 0;
5814 pTIImpl->TypeAttr.wMinorVerNum = 0;
5815 pTIImpl->TypeAttr.cbAlignment = 2;
5816 pTIImpl->TypeAttr.cbSizeInstance = -1;
5817 pTIImpl->TypeAttr.cbSizeVft = -1;
5818 pTIImpl->TypeAttr.cFuncs = 0;
5819 pTIImpl->TypeAttr.cImplTypes = 1;
5820 pTIImpl->TypeAttr.cVars = 0;
5821 pTIImpl->TypeAttr.wTypeFlags = 0;
5822
5823 ppFuncDesc = &pTIImpl->funclist;
5824 for(func = 0; func < pidata->cMembers; func++) {
5825 METHODDATA *md = pidata->pmethdata + func;
5826 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5827 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5828 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5829 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5830 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5831 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5832 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5833 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5834 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5835 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5836 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5837 md->cArgs * sizeof(ELEMDESC));
5838 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5839 md->cArgs * sizeof(TLBParDesc));
5840 for(param = 0; param < md->cArgs; param++) {
5841 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5842 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5843 }
5844 ppFuncDesc = &(*ppFuncDesc)->next;
5845 }
5846 *pptinfo = (ITypeInfo*)pTIImpl;
5847 return S_OK;
5848
5849 }
5850
5851 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5852 {
5853 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5854
5855 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5856 }
5857
5858 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5859 {
5860 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5861
5862 return ITypeInfo_AddRef((ITypeInfo *)This);
5863 }
5864
5865 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5866 {
5867 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5868
5869 return ITypeInfo_Release((ITypeInfo *)This);
5870 }
5871
5872 static HRESULT WINAPI ITypeComp_fnBind(
5873 ITypeComp * iface,
5874 OLECHAR * szName,
5875 ULONG lHash,
5876 WORD wFlags,
5877 ITypeInfo ** ppTInfo,
5878 DESCKIND * pDescKind,
5879 BINDPTR * pBindPtr)
5880 {
5881 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5882 TLBFuncDesc * pFDesc;
5883 TLBVarDesc * pVDesc;
5884
5885 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5886
5887 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5888 if (pFDesc->funcdesc.invkind & wFlags)
5889 if (!strcmpW(pFDesc->Name, szName)) {
5890 break;
5891 }
5892
5893 if (pFDesc)
5894 {
5895 *pDescKind = DESCKIND_FUNCDESC;
5896 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5897 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5898 return S_OK;
5899 } else {
5900 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5901 {
5902 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5903 if (!strcmpW(pVDesc->Name, szName)) {
5904 *pDescKind = DESCKIND_VARDESC;
5905 pBindPtr->lpvardesc = &pVDesc->vardesc;
5906 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5907 return S_OK;
5908 }
5909 }
5910 }
5911 }
5912 /* not found, look for it in inherited interfaces */
5913 if (This->TypeAttr.cImplTypes &&
5914 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5915 /* recursive search */
5916 ITypeInfo *pTInfo;
5917 ITypeComp *pTComp;
5918 HRESULT hr;
5919 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5920 if (SUCCEEDED(hr))
5921 {
5922 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5923 ITypeInfo_Release(pTInfo);
5924 }
5925 if (SUCCEEDED(hr))
5926 {
5927 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5928 ITypeComp_Release(pTComp);
5929 return hr;
5930 }
5931 WARN("Could not search inherited interface!\n");
5932 }
5933 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5934 *pDescKind = DESCKIND_NONE;
5935 pBindPtr->lpfuncdesc = NULL;
5936 *ppTInfo = NULL;
5937 return DISP_E_MEMBERNOTFOUND;
5938 }
5939
5940 static HRESULT WINAPI ITypeComp_fnBindType(
5941 ITypeComp * iface,
5942 OLECHAR * szName,
5943 ULONG lHash,
5944 ITypeInfo ** ppTInfo,
5945 ITypeComp ** ppTComp)
5946 {
5947 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5948
5949 /* strange behaviour (does nothing) but like the
5950 * original */
5951
5952 if (!ppTInfo || !ppTComp)
5953 return E_POINTER;
5954
5955 *ppTInfo = NULL;
5956 *ppTComp = NULL;
5957
5958 return S_OK;
5959 }
5960
5961 static ITypeCompVtbl tcompvt =
5962 {
5963
5964 ITypeComp_fnQueryInterface,
5965 ITypeComp_fnAddRef,
5966 ITypeComp_fnRelease,
5967
5968 ITypeComp_fnBind,
5969 ITypeComp_fnBindType
5970 };