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