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