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