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