Sync to Wine-0_9_3:
[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 * 2005 Robert Shearman, for CodeWeavers
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
26 *
27 * - Tested using OLEVIEW (Platform SDK tool) only.
28 *
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
34 *
35 * - locale stuff is partially implemented but hasn't been tested.
36 *
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
39 *
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
42 *
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
48 * behaviour.
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
53 *
54 */
55
56 #include "config.h"
57 #include "wine/port.h"
58
59 #include <stdlib.h>
60 #include <string.h>
61 #include <stdarg.h>
62 #include <stdio.h>
63 #include <ctype.h>
64
65 #define COBJMACROS
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
68
69 #include "winerror.h"
70 #include "windef.h"
71 #include "winbase.h"
72 #include "winnls.h"
73 #include "winreg.h"
74 #include "winuser.h"
75
76 #include "wine/unicode.h"
77 #include "objbase.h"
78 #include "typelib.h"
79 #include "wine/debug.h"
80 #include "variant.h"
81
82 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84
85 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
86 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87
88 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt);
89 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
90
91 /****************************************************************************
92 * FromLExxx
93 *
94 * Takes p_iVal (which is in little endian) and returns it
95 * in the host machine's byte order.
96 */
97 #ifdef WORDS_BIGENDIAN
98 static WORD FromLEWord(WORD p_iVal)
99 {
100 return (((p_iVal & 0x00FF) << 8) |
101 ((p_iVal & 0xFF00) >> 8));
102 }
103
104
105 static DWORD FromLEDWord(DWORD p_iVal)
106 {
107 return (((p_iVal & 0x000000FF) << 24) |
108 ((p_iVal & 0x0000FF00) << 8) |
109 ((p_iVal & 0x00FF0000) >> 8) |
110 ((p_iVal & 0xFF000000) >> 24));
111 }
112 #else
113 #define FromLEWord(X) (X)
114 #define FromLEDWord(X) (X)
115 #endif
116
117
118 /****************************************************************************
119 * FromLExxx
120 *
121 * Fix byte order in any structure if necessary
122 */
123 #ifdef WORDS_BIGENDIAN
124 static void FromLEWords(void *p_Val, int p_iSize)
125 {
126 WORD *Val = p_Val;
127
128 p_iSize /= sizeof(WORD);
129
130 while (p_iSize) {
131 *Val = FromLEWord(*Val);
132 Val++;
133 p_iSize--;
134 }
135 }
136
137
138 static void FromLEDWords(void *p_Val, int p_iSize)
139 {
140 DWORD *Val = p_Val;
141
142 p_iSize /= sizeof(DWORD);
143
144 while (p_iSize) {
145 *Val = FromLEDWord(*Val);
146 Val++;
147 p_iSize--;
148 }
149 }
150 #else
151 #define FromLEWords(X,Y) /*nothing*/
152 #define FromLEDWords(X,Y) /*nothing*/
153 #endif
154
155 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
156 /* buffer must be at least 60 characters long */
157 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
158 {
159 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
160 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
161
162 memcpy( buffer, TypelibW, sizeof(TypelibW) );
163 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
165 return buffer;
166 }
167
168 /* get the path of an interface key, in the form "Interface\\<guid>" */
169 /* buffer must be at least 50 characters long */
170 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
171 {
172 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
173
174 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
175 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
176 return buffer;
177 }
178
179 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
180 /* buffer must be at least 16 characters long */
181 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
182 {
183 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
184 static const WCHAR win16W[] = {'w','i','n','1','6',0};
185 static const WCHAR win32W[] = {'w','i','n','3','2',0};
186
187 sprintfW( buffer, LcidFormatW, lcid );
188 switch(syskind)
189 {
190 case SYS_WIN16: strcatW( buffer, win16W ); break;
191 case SYS_WIN32: strcatW( buffer, win32W ); break;
192 default:
193 TRACE("Typelib is for unsupported syskind %i\n", syskind);
194 return NULL;
195 }
196 return buffer;
197 }
198
199 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
200
201
202 /****************************************************************************
203 * QueryPathOfRegTypeLib [OLEAUT32.164]
204 *
205 * Gets the path to a registered type library.
206 *
207 * PARAMS
208 * guid [I] referenced guid
209 * wMaj [I] major version
210 * wMin [I] minor version
211 * lcid [I] locale id
212 * path [O] path of typelib
213 *
214 * RETURNS
215 * Success: S_OK.
216 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
217 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
218 * opened.
219 */
220 HRESULT WINAPI QueryPathOfRegTypeLib(
221 REFGUID guid,
222 WORD wMaj,
223 WORD wMin,
224 LCID lcid,
225 LPBSTR path )
226 {
227 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
228 LCID myLCID = lcid;
229 HKEY hkey;
230 WCHAR buffer[60];
231 WCHAR Path[MAX_PATH];
232 LONG res;
233
234 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
235
236 get_typelib_key( guid, wMaj, wMin, buffer );
237
238 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
239 if (res == ERROR_FILE_NOT_FOUND)
240 {
241 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
242 return TYPE_E_LIBNOTREGISTERED;
243 }
244 else if (res != ERROR_SUCCESS)
245 {
246 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
247 return TYPE_E_REGISTRYACCESS;
248 }
249
250 while (hr != S_OK)
251 {
252 LONG dwPathLen = sizeof(Path);
253
254 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
255
256 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
257 {
258 if (!lcid)
259 break;
260 else if (myLCID == lcid)
261 {
262 /* try with sub-langid */
263 myLCID = SUBLANGID(lcid);
264 }
265 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
266 {
267 /* try with system langid */
268 myLCID = 0;
269 }
270 else
271 {
272 break;
273 }
274 }
275 else
276 {
277 *path = SysAllocString( Path );
278 hr = S_OK;
279 }
280 }
281 RegCloseKey( hkey );
282 TRACE_(typelib)("-- 0x%08lx\n", hr);
283 return hr;
284 }
285
286 /******************************************************************************
287 * CreateTypeLib [OLEAUT32.160] creates a typelib
288 *
289 * RETURNS
290 * Success: S_OK
291 * Failure: Status
292 */
293 HRESULT WINAPI CreateTypeLib(
294 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
295 ) {
296 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
297 return E_FAIL;
298 }
299
300 /******************************************************************************
301 * LoadTypeLib [OLEAUT32.161]
302 *
303 * Loads a type library
304 *
305 * PARAMS
306 * szFile [I] Name of file to load from.
307 * pptLib [O] Pointer that receives ITypeLib object on success.
308 *
309 * RETURNS
310 * Success: S_OK
311 * Failure: Status
312 *
313 * SEE
314 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
315 */
316 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
317 {
318 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
319 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
320 }
321
322 /******************************************************************************
323 * LoadTypeLibEx [OLEAUT32.183]
324 *
325 * Loads and optionally registers a type library
326 *
327 * RETURNS
328 * Success: S_OK
329 * Failure: Status
330 */
331 HRESULT WINAPI LoadTypeLibEx(
332 LPCOLESTR szFile, /* [in] Name of file to load from */
333 REGKIND regkind, /* [in] Specify kind of registration */
334 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
335 {
336 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
337 WCHAR *pIndexStr;
338 HRESULT res;
339 INT index = 1;
340
341 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
342
343 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
344 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
345
346 *pptLib = NULL;
347 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
348 NULL)) {
349
350 /* Look for a trailing '\\' followed by an index */
351 pIndexStr = strrchrW(szFile, '\\');
352 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
353 index = atoiW(pIndexStr);
354 memcpy(szFileCopy, szFile,
355 (pIndexStr - szFile - 1) * sizeof(WCHAR));
356 szFileCopy[pIndexStr - szFile - 1] = '\0';
357 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
358 szPath,NULL))
359 return TYPE_E_CANTLOADLIBRARY;
360 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
361 return TYPE_E_CANTLOADLIBRARY;
362 }
363 }
364
365 TRACE("File %s index %d\n", debugstr_w(szPath), index);
366
367 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
368
369 if (SUCCEEDED(res))
370 switch(regkind)
371 {
372 case REGKIND_DEFAULT:
373 /* don't register typelibs supplied with full path. Experimentation confirms the following */
374 if ((!szFile) ||
375 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
376 (szFile[0] && (szFile[1] == ':'))) break;
377 /* else fall-through */
378
379 case REGKIND_REGISTER:
380 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
381 {
382 IUnknown_Release(*pptLib);
383 *pptLib = 0;
384 }
385 break;
386 case REGKIND_NONE:
387 break;
388 }
389
390 TRACE(" returns %08lx\n",res);
391 return res;
392 }
393
394 /******************************************************************************
395 * LoadRegTypeLib [OLEAUT32.162]
396 *
397 * Loads a registered type library.
398 *
399 * PARAMS
400 * rguid [I] GUID of the registered type library.
401 * wVerMajor [I] major version.
402 * wVerMinor [I] minor version.
403 * lcid [I] locale ID.
404 * ppTLib [O] pointer that receives an ITypeLib object on success.
405 *
406 * RETURNS
407 * Success: S_OK.
408 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
409 * LoadTypeLib.
410 */
411 HRESULT WINAPI LoadRegTypeLib(
412 REFGUID rguid,
413 WORD wVerMajor,
414 WORD wVerMinor,
415 LCID lcid,
416 ITypeLib **ppTLib)
417 {
418 BSTR bstr=NULL;
419 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
420
421 if(SUCCEEDED(res))
422 {
423 res= LoadTypeLib(bstr, ppTLib);
424 SysFreeString(bstr);
425 }
426
427 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
428
429 return res;
430 }
431
432
433 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
434 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
435 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
436 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
437 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
438 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
439
440 /******************************************************************************
441 * RegisterTypeLib [OLEAUT32.163]
442 * Adds information about a type library to the System Registry
443 * NOTES
444 * Docs: ITypeLib FAR * ptlib
445 * Docs: OLECHAR FAR* szFullPath
446 * Docs: OLECHAR FAR* szHelpDir
447 *
448 * RETURNS
449 * Success: S_OK
450 * Failure: Status
451 */
452 HRESULT WINAPI RegisterTypeLib(
453 ITypeLib * ptlib, /* [in] Pointer to the library*/
454 OLECHAR * szFullPath, /* [in] full Path of the library*/
455 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
456 may be NULL*/
457 {
458 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
459 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
460 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
461 HRESULT res;
462 TLIBATTR *attr;
463 WCHAR keyName[60];
464 WCHAR tmp[16];
465 HKEY key, subKey;
466 UINT types, tidx;
467 TYPEKIND kind;
468 DWORD disposition;
469
470 if (ptlib == NULL || szFullPath == NULL)
471 return E_INVALIDARG;
472
473 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
474 return E_FAIL;
475
476 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
477
478 res = S_OK;
479 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
480 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
481 {
482 LPOLESTR doc;
483
484 /* Set the human-readable name of the typelib */
485 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
486 {
487 if (RegSetValueExW(key, NULL, 0, REG_SZ,
488 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
489 res = E_FAIL;
490
491 SysFreeString(doc);
492 }
493 else
494 res = E_FAIL;
495
496 /* Make up the name of the typelib path subkey */
497 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
498
499 /* Create the typelib path subkey */
500 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
501 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
502 {
503 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
504 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
505 res = E_FAIL;
506
507 RegCloseKey(subKey);
508 }
509 else
510 res = E_FAIL;
511
512 /* Create the flags subkey */
513 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
514 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
515 {
516 /* FIXME: is %u correct? */
517 static const WCHAR formatW[] = {'%','u',0};
518 WCHAR buf[20];
519 sprintfW(buf, formatW, attr->wLibFlags);
520 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
521 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
522 res = E_FAIL;
523
524 RegCloseKey(subKey);
525 }
526 else
527 res = E_FAIL;
528
529 /* create the helpdir subkey */
530 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
531 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
532 {
533 BOOL freeHelpDir = FALSE;
534 OLECHAR* pIndexStr;
535
536 /* if we created a new key, and helpDir was null, set the helpdir
537 to the directory which contains the typelib. However,
538 if we just opened an existing key, we leave the helpdir alone */
539 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
540 szHelpDir = SysAllocString(szFullPath);
541 pIndexStr = strrchrW(szHelpDir, '\\');
542 if (pIndexStr) {
543 *pIndexStr = 0;
544 }
545 freeHelpDir = TRUE;
546 }
547
548 /* if we have an szHelpDir, set it! */
549 if (szHelpDir != NULL) {
550 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
551 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
552 res = E_FAIL;
553 }
554 }
555
556 /* tidy up */
557 if (freeHelpDir) SysFreeString(szHelpDir);
558 RegCloseKey(subKey);
559
560 } else {
561 res = E_FAIL;
562 }
563
564 RegCloseKey(key);
565 }
566 else
567 res = E_FAIL;
568
569 /* register OLE Automation-compatible interfaces for this typelib */
570 types = ITypeLib_GetTypeInfoCount(ptlib);
571 for (tidx=0; tidx<types; tidx++) {
572 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
573 LPOLESTR name = NULL;
574 ITypeInfo *tinfo = NULL;
575
576 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
577
578 switch (kind) {
579 case TKIND_INTERFACE:
580 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
581 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
582 break;
583
584 case TKIND_DISPATCH:
585 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
586 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
587 break;
588
589 default:
590 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
591 break;
592 }
593
594 if (tinfo) {
595 TYPEATTR *tattr = NULL;
596 ITypeInfo_GetTypeAttr(tinfo, &tattr);
597
598 if (tattr) {
599 TRACE_(typelib)("guid=%s, flags=%04x (",
600 debugstr_guid(&tattr->guid),
601 tattr->wTypeFlags);
602
603 if (TRACE_ON(typelib)) {
604 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
605 XX(FAPPOBJECT);
606 XX(FCANCREATE);
607 XX(FLICENSED);
608 XX(FPREDECLID);
609 XX(FHIDDEN);
610 XX(FCONTROL);
611 XX(FDUAL);
612 XX(FNONEXTENSIBLE);
613 XX(FOLEAUTOMATION);
614 XX(FRESTRICTED);
615 XX(FAGGREGATABLE);
616 XX(FREPLACEABLE);
617 XX(FDISPATCHABLE);
618 XX(FREVERSEBIND);
619 XX(FPROXY);
620 #undef XX
621 MESSAGE("\n");
622 }
623
624 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
625 {
626 /* register interface<->typelib coupling */
627 get_interface_key( &tattr->guid, keyName );
628 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
629 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
630 {
631 if (name)
632 RegSetValueExW(key, NULL, 0, REG_SZ,
633 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
634
635 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
636 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
637 RegSetValueExW(subKey, NULL, 0, REG_SZ,
638 (BYTE*)PSOA, sizeof PSOA);
639 RegCloseKey(subKey);
640 }
641
642 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
643 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
644 RegSetValueExW(subKey, NULL, 0, REG_SZ,
645 (BYTE*)PSOA, sizeof PSOA);
646 RegCloseKey(subKey);
647 }
648
649 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
650 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
651 {
652 WCHAR buffer[40];
653 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
654 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
655
656 StringFromGUID2(&attr->guid, buffer, 40);
657 RegSetValueExW(subKey, NULL, 0, REG_SZ,
658 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
659 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
660 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
661 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
662 RegCloseKey(subKey);
663 }
664
665 RegCloseKey(key);
666 }
667 }
668
669 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
670 }
671
672 ITypeInfo_Release(tinfo);
673 }
674
675 SysFreeString(name);
676 }
677 }
678
679 ITypeLib_ReleaseTLibAttr(ptlib, attr);
680
681 return res;
682 }
683
684
685 /******************************************************************************
686 * UnRegisterTypeLib [OLEAUT32.186]
687 * Removes information about a type library from the System Registry
688 * NOTES
689 *
690 * RETURNS
691 * Success: S_OK
692 * Failure: Status
693 */
694 HRESULT WINAPI UnRegisterTypeLib(
695 REFGUID libid, /* [in] Guid of the library */
696 WORD wVerMajor, /* [in] major version */
697 WORD wVerMinor, /* [in] minor version */
698 LCID lcid, /* [in] locale id */
699 SYSKIND syskind)
700 {
701 BSTR tlibPath = NULL;
702 DWORD tmpLength;
703 WCHAR keyName[60];
704 WCHAR subKeyName[50];
705 int result = S_OK;
706 DWORD i = 0;
707 BOOL deleteOtherStuff;
708 HKEY key = NULL;
709 HKEY subKey = NULL;
710 TYPEATTR* typeAttr = NULL;
711 TYPEKIND kind;
712 ITypeInfo* typeInfo = NULL;
713 ITypeLib* typeLib = NULL;
714 int numTypes;
715
716 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
717
718 /* Create the path to the key */
719 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
720
721 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
722 {
723 TRACE("Unsupported syskind %i\n", syskind);
724 result = E_INVALIDARG;
725 goto end;
726 }
727
728 /* get the path to the typelib on disk */
729 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
730 result = E_INVALIDARG;
731 goto end;
732 }
733
734 /* Try and open the key to the type library. */
735 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
736 result = E_INVALIDARG;
737 goto end;
738 }
739
740 /* Try and load the type library */
741 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
742 result = TYPE_E_INVALIDSTATE;
743 goto end;
744 }
745
746 /* remove any types registered with this typelib */
747 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
748 for (i=0; i<numTypes; i++) {
749 /* get the kind of type */
750 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
751 goto enddeleteloop;
752 }
753
754 /* skip non-interfaces, and get type info for the type */
755 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
756 goto enddeleteloop;
757 }
758 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
759 goto enddeleteloop;
760 }
761 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
762 goto enddeleteloop;
763 }
764
765 /* the path to the type */
766 get_interface_key( &typeAttr->guid, subKeyName );
767
768 /* Delete its bits */
769 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
770 goto enddeleteloop;
771 }
772 RegDeleteKeyW(subKey, ProxyStubClsidW);
773 RegDeleteKeyW(subKey, ProxyStubClsid32W);
774 RegDeleteKeyW(subKey, TypeLibW);
775 RegCloseKey(subKey);
776 subKey = NULL;
777 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
778
779 enddeleteloop:
780 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
781 typeAttr = NULL;
782 if (typeInfo) ITypeInfo_Release(typeInfo);
783 typeInfo = NULL;
784 }
785
786 /* Now, delete the type library path subkey */
787 get_lcid_subkey( lcid, syskind, subKeyName );
788 RegDeleteKeyW(key, subKeyName);
789 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
790 RegDeleteKeyW(key, subKeyName);
791
792 /* check if there is anything besides the FLAGS/HELPDIR keys.
793 If there is, we don't delete them */
794 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
795 deleteOtherStuff = TRUE;
796 i = 0;
797 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
798 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
799
800 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
801 if (!strcmpW(subKeyName, FLAGSW)) continue;
802 if (!strcmpW(subKeyName, HELPDIRW)) continue;
803 deleteOtherStuff = FALSE;
804 break;
805 }
806
807 /* only delete the other parts of the key if we're absolutely sure */
808 if (deleteOtherStuff) {
809 RegDeleteKeyW(key, FLAGSW);
810 RegDeleteKeyW(key, HELPDIRW);
811 RegCloseKey(key);
812 key = NULL;
813
814 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
815 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
816 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
817 }
818
819 end:
820 if (tlibPath) SysFreeString(tlibPath);
821 if (typeLib) ITypeLib_Release(typeLib);
822 if (subKey) RegCloseKey(subKey);
823 if (key) RegCloseKey(key);
824 return result;
825 }
826
827 /*======================= ITypeLib implementation =======================*/
828
829 typedef struct tagTLBCustData
830 {
831 GUID guid;
832 VARIANT data;
833 struct tagTLBCustData* next;
834 } TLBCustData;
835
836 /* data structure for import typelibs */
837 typedef struct tagTLBImpLib
838 {
839 int offset; /* offset in the file (MSFT)
840 offset in nametable (SLTG)
841 just used to identify library while reading
842 data from file */
843 GUID guid; /* libid */
844 BSTR name; /* name */
845
846 LCID lcid; /* lcid of imported typelib */
847
848 WORD wVersionMajor; /* major version number */
849 WORD wVersionMinor; /* minor version number */
850
851 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
852 NULL if not yet loaded */
853 struct tagTLBImpLib * next;
854 } TLBImpLib;
855
856 /* internal ITypeLib data */
857 typedef struct tagITypeLibImpl
858 {
859 const ITypeLib2Vtbl *lpVtbl;
860 const ITypeCompVtbl *lpVtblTypeComp;
861 LONG ref;
862 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
863
864 /* strings can be stored in tlb as multibyte strings BUT they are *always*
865 * exported to the application as a UNICODE string.
866 */
867 BSTR Name;
868 BSTR DocString;
869 BSTR HelpFile;
870 BSTR HelpStringDll;
871 unsigned long dwHelpContext;
872 int TypeInfoCount; /* nr of typeinfo's in librarry */
873 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
874 int ctCustData; /* number of items in cust data list */
875 TLBCustData * pCustData; /* linked list to cust data */
876 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
877 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
878 libary. Only used while read MSFT
879 typelibs */
880
881 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
882 struct tagITypeLibImpl *next, *prev;
883 WCHAR *path;
884 INT index;
885 } ITypeLibImpl;
886
887 static const ITypeLib2Vtbl tlbvt;
888 static const ITypeCompVtbl tlbtcvt;
889
890 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
891 {
892 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
893 }
894
895 /* ITypeLib methods */
896 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
897 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
898
899 /*======================= ITypeInfo implementation =======================*/
900
901 /* data for referenced types */
902 typedef struct tagTLBRefType
903 {
904 INT index; /* Type index for internal ref or for external ref
905 it the format is SLTG. -2 indicates to
906 use guid */
907
908 GUID guid; /* guid of the referenced type */
909 /* if index == TLB_REF_USE_GUID */
910
911 HREFTYPE reference; /* The href of this ref */
912 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
913 TLB_REF_INTERNAL for internal refs
914 TLB_REF_NOT_FOUND for broken refs */
915
916 struct tagTLBRefType * next;
917 } TLBRefType;
918
919 #define TLB_REF_USE_GUID -2
920
921 #define TLB_REF_INTERNAL (void*)-2
922 #define TLB_REF_NOT_FOUND (void*)-1
923
924 /* internal Parameter data */
925 typedef struct tagTLBParDesc
926 {
927 BSTR Name;
928 int ctCustData;
929 TLBCustData * pCustData; /* linked list to cust data */
930 } TLBParDesc;
931
932 /* internal Function data */
933 typedef struct tagTLBFuncDesc
934 {
935 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
936 BSTR Name; /* the name of this function */
937 TLBParDesc *pParamDesc; /* array with param names and custom data */
938 int helpcontext;
939 int HelpStringContext;
940 BSTR HelpString;
941 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
942 int ctCustData;
943 TLBCustData * pCustData; /* linked list to cust data; */
944 struct tagTLBFuncDesc * next;
945 } TLBFuncDesc;
946
947 /* internal Variable data */
948 typedef struct tagTLBVarDesc
949 {
950 VARDESC vardesc; /* lots of info on the variable and its attributes. */
951 BSTR Name; /* the name of this variable */
952 int HelpContext;
953 int HelpStringContext; /* FIXME: where? */
954 BSTR HelpString;
955 int ctCustData;
956 TLBCustData * pCustData;/* linked list to cust data; */
957 struct tagTLBVarDesc * next;
958 } TLBVarDesc;
959
960 /* internal implemented interface data */
961 typedef struct tagTLBImplType
962 {
963 HREFTYPE hRef; /* hRef of interface */
964 int implflags; /* IMPLFLAG_*s */
965 int ctCustData;
966 TLBCustData * pCustData;/* linked list to custom data; */
967 struct tagTLBImplType *next;
968 } TLBImplType;
969
970 /* internal TypeInfo data */
971 typedef struct tagITypeInfoImpl
972 {
973 const ITypeInfo2Vtbl *lpVtbl;
974 const ITypeCompVtbl *lpVtblTypeComp;
975 LONG ref;
976 TYPEATTR TypeAttr ; /* _lots_ of type information. */
977 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
978 int index; /* index in this typelib; */
979 HREFTYPE hreftype; /* hreftype for app object binding */
980 /* type libs seem to store the doc strings in ascii
981 * so why should we do it in unicode?
982 */
983 BSTR Name;
984 BSTR DocString;
985 BSTR DllName;
986 unsigned long dwHelpContext;
987 unsigned long dwHelpStringContext;
988
989 /* functions */
990 TLBFuncDesc * funclist; /* linked list with function descriptions */
991
992 /* variables */
993 TLBVarDesc * varlist; /* linked list with variable descriptions */
994
995 /* Implemented Interfaces */
996 TLBImplType * impltypelist;
997
998 TLBRefType * reflist;
999 int ctCustData;
1000 TLBCustData * pCustData; /* linked list to cust data; */
1001 struct tagITypeInfoImpl * next;
1002 } ITypeInfoImpl;
1003
1004 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1005 {
1006 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1007 }
1008
1009 static const ITypeInfo2Vtbl tinfvt;
1010 static const ITypeCompVtbl tcompvt;
1011
1012 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1013
1014 typedef struct tagTLBContext
1015 {
1016 unsigned int oStart; /* start of TLB in file */
1017 unsigned int pos; /* current pos */
1018 unsigned int length; /* total length */
1019 void *mapping; /* memory mapping */
1020 MSFT_SegDir * pTblDir;
1021 ITypeLibImpl* pLibInfo;
1022 } TLBContext;
1023
1024
1025 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1026
1027 /*
1028 debug
1029 */
1030 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1031 if (pTD->vt & VT_RESERVED)
1032 szVarType += strlen(strcpy(szVarType, "reserved | "));
1033 if (pTD->vt & VT_BYREF)
1034 szVarType += strlen(strcpy(szVarType, "ref to "));
1035 if (pTD->vt & VT_ARRAY)
1036 szVarType += strlen(strcpy(szVarType, "array of "));
1037 if (pTD->vt & VT_VECTOR)
1038 szVarType += strlen(strcpy(szVarType, "vector of "));
1039 switch(pTD->vt & VT_TYPEMASK) {
1040 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1041 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1042 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1043 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1044 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1045 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1046 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1047 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1048 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1049 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1050 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1051 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1052 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1053 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1054 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1055 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1056 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1057 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1058 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1059 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1060 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1061 pTD->u.hreftype); break;
1062 case VT_PTR: sprintf(szVarType, "ptr to ");
1063 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1064 break;
1065 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1066 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1067 break;
1068 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1069 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1070 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1071 break;
1072
1073 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1074 }
1075 }
1076
1077 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1078 char buf[200];
1079 USHORT flags = edesc->u.paramdesc.wParamFlags;
1080 dump_TypeDesc(&edesc->tdesc,buf);
1081 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1082 MESSAGE("\t\tu.paramdesc.wParamFlags");
1083 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1084 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1085 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1086 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1087 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1088 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1089 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1090 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1091 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1092 }
1093 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1094 int i;
1095 MESSAGE("memid is %08lx\n",funcdesc->memid);
1096 for (i=0;i<funcdesc->cParams;i++) {
1097 MESSAGE("Param %d:\n",i);
1098 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1099 }
1100 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1101 switch (funcdesc->funckind) {
1102 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1103 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1104 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1105 case FUNC_STATIC: MESSAGE("static");break;
1106 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1107 default: MESSAGE("unknown");break;
1108 }
1109 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1110 switch (funcdesc->invkind) {
1111 case INVOKE_FUNC: MESSAGE("func");break;
1112 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1113 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1114 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1115 }
1116 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1117 switch (funcdesc->callconv) {
1118 case CC_CDECL: MESSAGE("cdecl");break;
1119 case CC_PASCAL: MESSAGE("pascal");break;
1120 case CC_STDCALL: MESSAGE("stdcall");break;
1121 case CC_SYSCALL: MESSAGE("syscall");break;
1122 default:break;
1123 }
1124 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1125 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1126 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1127
1128 MESSAGE("\telemdescFunc (return value type):\n");
1129 dump_ELEMDESC(&funcdesc->elemdescFunc);
1130 }
1131
1132 static const char * typekind_desc[] =
1133 {
1134 "TKIND_ENUM",
1135 "TKIND_RECORD",
1136 "TKIND_MODULE",
1137 "TKIND_INTERFACE",
1138 "TKIND_DISPATCH",
1139 "TKIND_COCLASS",
1140 "TKIND_ALIAS",
1141 "TKIND_UNION",
1142 "TKIND_MAX"
1143 };
1144
1145 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1146 {
1147 int i;
1148 if (!TRACE_ON(typelib))
1149 return;
1150 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1151 for (i=0;i<pfd->funcdesc.cParams;i++)
1152 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1153
1154
1155 dump_FUNCDESC(&(pfd->funcdesc));
1156
1157 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1158 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1159 }
1160 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1161 {
1162 while (pfd)
1163 {
1164 dump_TLBFuncDescOne(pfd);
1165 pfd = pfd->next;
1166 };
1167 }
1168 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1169 {
1170 while (pvd)
1171 {
1172 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1173 pvd = pvd->next;
1174 };
1175 }
1176
1177 static void dump_TLBImpLib(const TLBImpLib *import)
1178 {
1179 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1180 debugstr_w(import->name));
1181 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1182 import->wVersionMinor, import->lcid, import->offset);
1183 }
1184
1185 static void dump_TLBRefType(const TLBRefType * prt)
1186 {
1187 while (prt)
1188 {
1189 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1190 if(prt->index == -1)
1191 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1192 else
1193 TRACE_(typelib)("type no: %d\n", prt->index);
1194
1195 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1196 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1197 TRACE_(typelib)("in lib\n");
1198 dump_TLBImpLib(prt->pImpTLInfo);
1199 }
1200 prt = prt->next;
1201 };
1202 }
1203
1204 static void dump_TLBImplType(const TLBImplType * impl)
1205 {
1206 while (impl) {
1207 TRACE_(typelib)(
1208 "implementing/inheriting interface hRef = %lx implflags %x\n",
1209 impl->hRef, impl->implflags);
1210 impl = impl->next;
1211 }
1212 }
1213
1214 void dump_Variant(const VARIANT * pvar)
1215 {
1216 SYSTEMTIME st;
1217
1218 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1219
1220 if (pvar)
1221 {
1222 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1223 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1224 {
1225 TRACE(",%p", V_BYREF(pvar));
1226 }
1227 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1228 {
1229 TRACE(",FIXME");
1230 }
1231 else switch (V_TYPE(pvar))
1232 {
1233 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1234 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1235 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1236 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1237 case VT_INT:
1238 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1239 case VT_UINT:
1240 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1241 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1242 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1243 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1244 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1245 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1246 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1247 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1248 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1249 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1250 V_CY(pvar).s.Lo); break;
1251 case VT_DATE:
1252 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1253 TRACE(",<invalid>");
1254 else
1255 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1256 st.wHour, st.wMinute, st.wSecond);
1257 break;
1258 case VT_ERROR:
1259 case VT_VOID:
1260 case VT_USERDEFINED:
1261 case VT_EMPTY:
1262 case VT_NULL: break;
1263 default: TRACE(",?"); break;
1264 }
1265 }
1266 TRACE("}\n");
1267 }
1268
1269 static void dump_DispParms(const DISPPARAMS * pdp)
1270 {
1271 int index = 0;
1272
1273 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1274
1275 while (index < pdp->cArgs)
1276 {
1277 dump_Variant( &pdp->rgvarg[index] );
1278 ++index;
1279 }
1280 }
1281
1282 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1283 {
1284 TRACE("%p ref=%lu\n", pty, pty->ref);
1285 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1286 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1287 TRACE("fct:%u var:%u impl:%u\n",
1288 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1289 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1290 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1291 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1292 dump_TLBFuncDesc(pty->funclist);
1293 dump_TLBVarDesc(pty->varlist);
1294 dump_TLBImplType(pty->impltypelist);
1295 }
1296
1297 static void dump_VARDESC(const VARDESC *v)
1298 {
1299 MESSAGE("memid %ld\n",v->memid);
1300 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1301 MESSAGE("oInst %ld\n",v->u.oInst);
1302 dump_ELEMDESC(&(v->elemdescVar));
1303 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1304 MESSAGE("varkind %d\n",v->varkind);
1305 }
1306
1307 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1308 {
1309 /* VT_LPWSTR is largest type that */
1310 /* may appear in type description*/
1311 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1312 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1313 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1314 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1315 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1316 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1317 {{0},30},{{0},31}
1318 };
1319
1320 static void TLB_abort(void)
1321 {
1322 DebugBreak();
1323 }
1324 static void * TLB_Alloc(unsigned size)
1325 {
1326 void * ret;
1327 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1328 /* FIXME */
1329 ERR("cannot allocate memory\n");
1330 }
1331 return ret;
1332 }
1333
1334 static void TLB_Free(void * ptr)
1335 {
1336 HeapFree(GetProcessHeap(), 0, ptr);
1337 }
1338
1339 /* returns the size required for a deep copy of a typedesc into a
1340 * flat buffer */
1341 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1342 {
1343 SIZE_T size = 0;
1344
1345 if (alloc_initial_space)
1346 size += sizeof(TYPEDESC);
1347
1348 switch (tdesc->vt)
1349 {
1350 case VT_PTR:
1351 case VT_SAFEARRAY:
1352 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1353 break;
1354 case VT_CARRAY:
1355 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1356 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1357 break;
1358 }
1359 return size;
1360 }
1361
1362 /* deep copy a typedesc into a flat buffer */
1363 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1364 {
1365 if (!dest)
1366 {
1367 dest = buffer;
1368 buffer = (char *)buffer + sizeof(TYPEDESC);
1369 }
1370
1371 *dest = *src;
1372
1373 switch (src->vt)
1374 {
1375 case VT_PTR:
1376 case VT_SAFEARRAY:
1377 dest->u.lptdesc = buffer;
1378 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1379 break;
1380 case VT_CARRAY:
1381 dest->u.lpadesc = buffer;
1382 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1383 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1384 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1385 break;
1386 }
1387 return buffer;
1388 }
1389
1390 /**********************************************************************
1391 *
1392 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1393 */
1394 /* read function */
1395 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1396 {
1397 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1398 pcx->pos, count, pcx->oStart, pcx->length, where);
1399
1400 if (where != DO_NOT_SEEK)
1401 {
1402 where += pcx->oStart;
1403 if (where > pcx->length)
1404 {
1405 /* FIXME */
1406 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1407 TLB_abort();
1408 }
1409 pcx->pos = where;
1410 }
1411 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1412 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1413 pcx->pos += count;
1414 return count;
1415 }
1416
1417 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1418 long where )
1419 {
1420 DWORD ret;
1421
1422 ret = MSFT_Read(buffer, count, pcx, where);
1423 FromLEDWords(buffer, ret);
1424
1425 return ret;
1426 }
1427
1428 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1429 long where )
1430 {
1431 DWORD ret;
1432
1433 ret = MSFT_Read(buffer, count, pcx, where);
1434 FromLEWords(buffer, ret);
1435
1436 return ret;
1437 }
1438
1439 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1440 {
1441 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1442 memset(pGuid,0, sizeof(GUID));
1443 return;
1444 }
1445 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1446 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1447 pGuid->Data2 = FromLEWord(pGuid->Data2);
1448 pGuid->Data3 = FromLEWord(pGuid->Data3);
1449 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1450 }
1451
1452 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1453 {
1454 MSFT_NameIntro niName;
1455
1456 if (offset < 0)
1457 {
1458 ERR_(typelib)("bad offset %d\n", offset);
1459 return -1;
1460 }
1461
1462 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1463 pcx->pTblDir->pNametab.offset+offset);
1464
1465 return niName.hreftype;
1466 }
1467
1468 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1469 {
1470 char * name;
1471 MSFT_NameIntro niName;
1472 int lengthInChars;
1473 WCHAR* pwstring = NULL;
1474 BSTR bstrName = NULL;
1475
1476 if (offset < 0)
1477 {
1478 ERR_(typelib)("bad offset %d\n", offset);
1479 return NULL;
1480 }
1481 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1482 pcx->pTblDir->pNametab.offset+offset);
1483 niName.namelen &= 0xFF; /* FIXME: correct ? */
1484 name=TLB_Alloc((niName.namelen & 0xff) +1);
1485 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1486 name[niName.namelen & 0xff]='\0';
1487
1488 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1489 name, -1, NULL, 0);
1490
1491 /* no invalid characters in string */
1492 if (lengthInChars)
1493 {
1494 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1495
1496 /* don't check for invalid character since this has been done previously */
1497 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1498
1499 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1500 lengthInChars = SysStringLen(bstrName);
1501 HeapFree(GetProcessHeap(), 0, pwstring);
1502 }
1503
1504 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1505 return bstrName;
1506 }
1507
1508 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1509 {
1510 char * string;
1511 INT16 length;
1512 int lengthInChars;
1513 BSTR bstr = NULL;
1514
1515 if(offset<0) return NULL;
1516 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1517 if(length <= 0) return 0;
1518 string=TLB_Alloc(length +1);
1519 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1520 string[length]='\0';
1521
1522 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1523 string, -1, NULL, 0);
1524
1525 /* no invalid characters in string */
1526 if (lengthInChars)
1527 {
1528 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1529
1530 /* don't check for invalid character since this has been done previously */
1531 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1532
1533 bstr = SysAllocStringLen(pwstring, lengthInChars);
1534 lengthInChars = SysStringLen(bstr);
1535 HeapFree(GetProcessHeap(), 0, pwstring);
1536 }
1537
1538 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1539 return bstr;
1540 }
1541 /*
1542 * read a value and fill a VARIANT structure
1543 */
1544 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1545 {
1546 int size;
1547
1548 TRACE_(typelib)("\n");
1549
1550 if(offset <0) { /* data are packed in here */
1551 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1552 V_I4(pVar) = offset & 0x3ffffff;
1553 return;
1554 }
1555 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1556 pcx->pTblDir->pCustData.offset + offset );
1557 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1558 switch (V_VT(pVar)){
1559 case VT_EMPTY: /* FIXME: is this right? */
1560 case VT_NULL: /* FIXME: is this right? */
1561 case VT_I2 : /* this should not happen */
1562 case VT_I4 :
1563 case VT_R4 :
1564 case VT_ERROR :
1565 case VT_BOOL :
1566 case VT_I1 :
1567 case VT_UI1 :
1568 case VT_UI2 :
1569 case VT_UI4 :
1570 case VT_INT :
1571 case VT_UINT :
1572 case VT_VOID : /* FIXME: is this right? */
1573 case VT_HRESULT :
1574 size=4; break;
1575 case VT_R8 :
1576 case VT_CY :
1577 case VT_DATE :
1578 case VT_I8 :
1579 case VT_UI8 :
1580 case VT_DECIMAL : /* FIXME: is this right? */
1581 case VT_FILETIME :
1582 size=8;break;
1583 /* pointer types with known behaviour */
1584 case VT_BSTR :{
1585 char * ptr;
1586 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1587 if(size < 0) {
1588 FIXME("BSTR length = %d?\n", size);
1589 } else {
1590 ptr=TLB_Alloc(size);/* allocate temp buffer */
1591 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1592 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1593 /* FIXME: do we need a AtoW conversion here? */
1594 V_UNION(pVar, bstrVal[size])=L'\0';
1595 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1596 TLB_Free(ptr);
1597 }
1598 }
1599 size=-4; break;
1600 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1601 case VT_DISPATCH :
1602 case VT_VARIANT :
1603 case VT_UNKNOWN :
1604 case VT_PTR :
1605 case VT_SAFEARRAY :
1606 case VT_CARRAY :
1607 case VT_USERDEFINED :
1608 case VT_LPSTR :
1609 case VT_LPWSTR :
1610 case VT_BLOB :
1611 case VT_STREAM :
1612 case VT_STORAGE :
1613 case VT_STREAMED_OBJECT :
1614 case VT_STORED_OBJECT :
1615 case VT_BLOB_OBJECT :
1616 case VT_CF :
1617 case VT_CLSID :
1618 default:
1619 size=0;
1620 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1621 V_VT(pVar));
1622 }
1623
1624 if(size>0) /* (big|small) endian correct? */
1625 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1626 return;
1627 }
1628 /*
1629 * create a linked list with custom data
1630 */
1631 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1632 {
1633 MSFT_CDGuid entry;
1634 TLBCustData* pNew;
1635 int count=0;
1636
1637 TRACE_(typelib)("\n");
1638
1639 while(offset >=0){
1640 count++;
1641 pNew=TLB_Alloc(sizeof(TLBCustData));
1642 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1643 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1644 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1645 /* add new custom data at head of the list */
1646 pNew->next=*ppCustData;
1647 *ppCustData=pNew;
1648 offset = entry.next;
1649 }
1650 return count;
1651 }
1652
1653 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1654 ITypeInfoImpl *pTI)
1655 {
1656 if(type <0)
1657 pTd->vt=type & VT_TYPEMASK;
1658 else
1659 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1660
1661 if(pTd->vt == VT_USERDEFINED)
1662 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1663
1664 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1665 }
1666
1667 static void
1668 MSFT_DoFuncs(TLBContext* pcx,
1669 ITypeInfoImpl* pTI,
1670 int cFuncs,
1671 int cVars,
1672 int offset,
1673 TLBFuncDesc** pptfd)
1674 {
1675 /*
1676 * member information is stored in a data structure at offset
1677 * indicated by the memoffset field of the typeinfo structure
1678 * There are several distinctive parts.
1679 * The first part starts with a field that holds the total length
1680 * of this (first) part excluding this field. Then follow the records,
1681 * for each member there is one record.
1682 *
1683 * The first entry is always the length of the record (including this
1684 * length word).
1685 * The rest of the record depends on the type of the member. If there is
1686 * a field indicating the member type (function, variable, interface, etc)
1687 * I have not found it yet. At this time we depend on the information
1688 * in the type info and the usual order how things are stored.
1689 *
1690 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1691 * for each member;
1692 *
1693 * Third is an equal sized array with file offsets to the name entry
1694 * of each member.
1695 *
1696 * The fourth and last (?) part is an array with offsets to the records
1697 * in the first part of this file segment.
1698 */
1699
1700 int infolen, nameoffset, reclength, nrattributes, i;
1701 int recoffset = offset + sizeof(INT);
1702
1703 char recbuf[512];
1704 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1705 TLBFuncDesc *ptfd_prev = NULL;
1706
1707 TRACE_(typelib)("\n");
1708
1709 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1710
1711 for ( i = 0; i < cFuncs ; i++ )
1712 {
1713 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1714
1715 /* name, eventually add to a hash table */
1716 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1717 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1718
1719 /* nameoffset is sometimes -1 on the second half of a propget/propput
1720 * pair of functions */
1721 if ((nameoffset == -1) && (i > 0))
1722 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1723 else
1724 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1725
1726 /* read the function information record */
1727 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1728
1729 reclength &= 0x1ff;
1730
1731 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1732
1733 /* do the attributes */
1734 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1735 / sizeof(int);
1736
1737 if ( nrattributes > 0 )
1738 {
1739 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1740
1741 if ( nrattributes > 1 )
1742 {
1743 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1744 pFuncRec->OptAttr[1]) ;
1745
1746 if ( nrattributes > 2 )
1747 {
1748 if ( pFuncRec->FKCCIC & 0x2000 )
1749 {
1750 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1751 }
1752 else
1753 {
1754 (*pptfd)->Entry = MSFT_ReadString(pcx,
1755 pFuncRec->OptAttr[2]);
1756 }
1757 if( nrattributes > 5 )
1758 {
1759 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1760
1761 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1762 {
1763 MSFT_CustData(pcx,
1764 pFuncRec->OptAttr[6],
1765 &(*pptfd)->pCustData);
1766 }
1767 }
1768 }
1769 }
1770 }
1771
1772 /* fill the FuncDesc Structure */
1773 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1774 offset + infolen + ( i + 1) * sizeof(INT));
1775
1776 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1777 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1778 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1779 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1780 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1781 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1782 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1783
1784 MSFT_GetTdesc(pcx,
1785 pFuncRec->DataType,
1786 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1787 pTI);
1788
1789 /* do the parameters/arguments */
1790 if(pFuncRec->nrargs)
1791 {
1792 int j = 0;
1793 MSFT_ParameterInfo paraminfo;
1794
1795 (*pptfd)->funcdesc.lprgelemdescParam =
1796 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1797
1798 (*pptfd)->pParamDesc =
1799 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1800
1801 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
1802 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1803
1804 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1805 {
1806 TYPEDESC *lpArgTypeDesc;
1807 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1808
1809 MSFT_GetTdesc(pcx,
1810 paraminfo.DataType,
1811 &elemdesc->tdesc,
1812 pTI);
1813
1814 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1815
1816 /* name */
1817 if (paraminfo.oName == -1)
1818 /* this occurs for [propput] or [propget] methods, so
1819 * we should just set the name of the parameter to the
1820 * name of the method. */
1821 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1822 else
1823 (*pptfd)->pParamDesc[j].Name =
1824 MSFT_ReadName( pcx, paraminfo.oName );
1825 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1826
1827 lpArgTypeDesc = &elemdesc->tdesc;
1828
1829 /* resolve referenced type if any */
1830 while ( lpArgTypeDesc != NULL )
1831 {
1832 switch ( lpArgTypeDesc->vt )
1833 {
1834 case VT_PTR:
1835 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1836 break;
1837
1838 case VT_CARRAY:
1839 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1840 break;
1841
1842 case VT_USERDEFINED:
1843 MSFT_DoRefType(pcx, pTI,
1844 lpArgTypeDesc->u.hreftype);
1845
1846 lpArgTypeDesc = NULL;
1847 break;
1848
1849 default:
1850 lpArgTypeDesc = NULL;
1851 }
1852 }
1853
1854 /* default value */
1855 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1856 (pFuncRec->FKCCIC & 0x1000) )
1857 {
1858 INT* pInt = (INT *)((char *)pFuncRec +
1859 reclength -
1860 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1861
1862 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1863
1864 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1865 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1866
1867 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1868 pInt[j], pcx);
1869 }
1870 else
1871 elemdesc->u.paramdesc.pparamdescex = NULL;
1872 /* custom info */
1873 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1874 {
1875 MSFT_CustData(pcx,
1876 pFuncRec->OptAttr[7+j],
1877 &(*pptfd)->pParamDesc[j].pCustData);
1878 }
1879
1880 /* SEEK value = jump to offset,
1881 * from there jump to the end of record,
1882 * go back by (j-1) arguments
1883 */
1884 MSFT_ReadLEDWords( &paraminfo ,
1885 sizeof(MSFT_ParameterInfo), pcx,
1886 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1887 * sizeof(MSFT_ParameterInfo)));
1888 }
1889 }
1890
1891 /* scode is not used: archaic win16 stuff FIXME: right? */
1892 (*pptfd)->funcdesc.cScodes = 0 ;
1893 (*pptfd)->funcdesc.lprgscode = NULL ;
1894
1895 ptfd_prev = *pptfd;
1896 pptfd = & ((*pptfd)->next);
1897 recoffset += reclength;
1898 }
1899 }
1900
1901 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1902 int cVars, int offset, TLBVarDesc ** pptvd)
1903 {
1904 int infolen, nameoffset, reclength;
1905 char recbuf[256];
1906 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1907 int i;
1908 int recoffset;
1909
1910 TRACE_(typelib)("\n");
1911
1912 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1913 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1914 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1915 recoffset += offset+sizeof(INT);
1916 for(i=0;i<cVars;i++){
1917 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1918 /* name, eventually add to a hash table */
1919 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1920 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1921 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1922 /* read the variable information record */
1923 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1924 reclength &=0xff;
1925 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1926 /* Optional data */
1927 if(reclength >(6*sizeof(INT)) )
1928 (*pptvd)->HelpContext=pVarRec->HelpContext;
1929 if(reclength >(7*sizeof(INT)) )
1930 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1931 if(reclength >(8*sizeof(INT)) )
1932 if(reclength >(9*sizeof(INT)) )
1933 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1934 /* fill the VarDesc Structure */
1935 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1936 offset + infolen + ( i + 1) * sizeof(INT));
1937 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1938 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1939 MSFT_GetTdesc(pcx, pVarRec->DataType,
1940 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1941 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1942 if(pVarRec->VarKind == VAR_CONST ){
1943 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1944 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1945 pVarRec->OffsValue, pcx);
1946 } else
1947 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1948 pptvd=&((*pptvd)->next);
1949 recoffset += reclength;
1950 }
1951 }
1952 /* fill in data for a hreftype (offset). When the referenced type is contained
1953 * in the typelib, it's just an (file) offset in the type info base dir.
1954 * If comes from import, it's an offset+1 in the ImpInfo table
1955 * */
1956 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1957 int offset)
1958 {
1959 int j;
1960 TLBRefType **ppRefType = &pTI->reflist;
1961
1962 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1963
1964 while(*ppRefType) {
1965 if((*ppRefType)->reference == offset)
1966 return;
1967 ppRefType = &(*ppRefType)->next;
1968 }
1969
1970 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1971 sizeof(**ppRefType));
1972
1973 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1974 /* external typelib */
1975 MSFT_ImpInfo impinfo;
1976 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1977
1978 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1979
1980 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1981 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1982 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1983 if(pImpLib->offset==impinfo.oImpFile) break;
1984 pImpLib=pImpLib->next;
1985 }
1986 if(pImpLib){
1987 (*ppRefType)->reference=offset;
1988 (*ppRefType)->pImpTLInfo = pImpLib;
1989 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1990 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1991 (*ppRefType)->index = TLB_REF_USE_GUID;
1992 } else
1993 (*ppRefType)->index = impinfo.oGuid;
1994 }else{
1995 ERR("Cannot find a reference\n");
1996 (*ppRefType)->reference=-1;
1997 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1998 }
1999 }else{
2000 /* in this typelib */
2001 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2002 (*ppRefType)->reference=offset;
2003 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2004 }
2005 }
2006
2007 /* process Implemented Interfaces of a com class */
2008 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2009 int offset)
2010 {
2011 int i;
2012 MSFT_RefRecord refrec;
2013 TLBImplType **ppImpl = &pTI->impltypelist;
2014
2015 TRACE_(typelib)("\n");
2016
2017 for(i=0;i<count;i++){
2018 if(offset<0) break; /* paranoia */
2019 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2020 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2021 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2022 (*ppImpl)->hRef = refrec.reftype;
2023 (*ppImpl)->implflags=refrec.flags;
2024 (*ppImpl)->ctCustData=
2025 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2026 offset=refrec.onext;
2027 ppImpl=&((*ppImpl)->next);
2028 }
2029 }
2030 /*
2031 * process a typeinfo record
2032 */
2033 static ITypeInfoImpl * MSFT_DoTypeInfo(
2034 TLBContext *pcx,
2035 int count,
2036 ITypeLibImpl * pLibInfo)
2037 {
2038 MSFT_TypeInfoBase tiBase;
2039 ITypeInfoImpl *ptiRet;
2040
2041 TRACE_(typelib)("count=%u\n", count);
2042
2043 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2044 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2045 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2046
2047 /* this is where we are coming from */
2048 ptiRet->pTypeLib = pLibInfo;
2049 ptiRet->index=count;
2050 /* fill in the typeattr fields */
2051 WARN("Assign constructor/destructor memid\n");
2052
2053 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2054 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2055 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2056 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2057 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2058 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2059 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2060 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2061 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2062 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2063 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2064 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2065 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2066 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2067 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2068 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2069 MSFT_GetTdesc(pcx, tiBase.datatype1,
2070 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2071
2072 /* FIXME: */
2073 /* IDLDESC idldescType; *//* never saw this one != zero */
2074
2075 /* name, eventually add to a hash table */
2076 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2077 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2078 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2079 /* help info */
2080 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2081 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2082 ptiRet->dwHelpContext=tiBase.helpcontext;
2083
2084 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2085 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2086
2087 /* note: InfoType's Help file and HelpStringDll come from the containing
2088 * library. Further HelpString and Docstring appear to be the same thing :(
2089 */
2090 /* functions */
2091 if(ptiRet->TypeAttr.cFuncs >0 )
2092 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2093 ptiRet->TypeAttr.cVars,
2094 tiBase.memoffset, & ptiRet->funclist);
2095 /* variables */
2096 if(ptiRet->TypeAttr.cVars >0 )
2097 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2098 ptiRet->TypeAttr.cVars,
2099 tiBase.memoffset, & ptiRet->varlist);
2100 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2101 switch(ptiRet->TypeAttr.typekind)
2102 {
2103 case TKIND_COCLASS:
2104 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2105 tiBase.datatype1);
2106 break;
2107 case TKIND_DISPATCH:
2108 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2109
2110 if (tiBase.datatype1 != -1)
2111 {
2112 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2113 ptiRet->impltypelist->hRef = tiBase.datatype1;
2114 }
2115 else
2116 { /* FIXME: This is a really bad hack to add IDispatch */
2117 const char* szStdOle = "stdole2.tlb\0";
2118 int nStdOleLen = strlen(szStdOle);
2119 TLBRefType **ppRef = &ptiRet->reflist;
2120
2121 while(*ppRef) {
2122 if((*ppRef)->reference == -1)
2123 break;
2124 ppRef = &(*ppRef)->next;
2125 }
2126 if(!*ppRef) {
2127 *ppRef = TLB_Alloc(sizeof(**ppRef));
2128 (*ppRef)->guid = IID_IDispatch;
2129 (*ppRef)->reference = -1;
2130 (*ppRef)->index = TLB_REF_USE_GUID;
2131 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2132 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2133 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2134 nStdOleLen + 1);
2135
2136 MultiByteToWideChar(CP_ACP,
2137 MB_PRECOMPOSED,
2138 szStdOle,
2139 -1,
2140 (*ppRef)->pImpTLInfo->name,
2141 SysStringLen((*ppRef)->pImpTLInfo->name));
2142
2143 (*ppRef)->pImpTLInfo->lcid = 0;
2144 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2145 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2146 }
2147 }
2148 break;
2149 default:
2150 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2151 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2152 ptiRet->impltypelist->hRef = tiBase.datatype1;
2153 break;
2154 }
2155 }
2156 ptiRet->ctCustData=
2157 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2158
2159 TRACE_(typelib)("%s guid: %s kind:%s\n",
2160 debugstr_w(ptiRet->Name),
2161 debugstr_guid(&ptiRet->TypeAttr.guid),
2162 typekind_desc[ptiRet->TypeAttr.typekind]);
2163
2164 return ptiRet;
2165 }
2166
2167 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2168 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2169 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2170 * tradeoff here.
2171 */
2172 static ITypeLibImpl *tlb_cache_first;
2173 static CRITICAL_SECTION cache_section;
2174 static CRITICAL_SECTION_DEBUG cache_section_debug =
2175 {
2176 0, 0, &cache_section,
2177 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2178 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2179 };
2180 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2181
2182
2183 /****************************************************************************
2184 * TLB_ReadTypeLib
2185 *
2186 * find the type of the typelib file and map the typelib resource into
2187 * the memory
2188 */
2189 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2190 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2191 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2192 {
2193 ITypeLibImpl *entry;
2194 int ret = TYPE_E_CANTLOADLIBRARY;
2195 DWORD dwSignature = 0;
2196 HANDLE hFile;
2197
2198 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2199
2200 *ppTypeLib = NULL;
2201
2202 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2203 EnterCriticalSection(&cache_section);
2204 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2205 {
2206 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2207 {
2208 TRACE("cache hit\n");
2209 *ppTypeLib = (ITypeLib2*)entry;
2210 ITypeLib_AddRef(*ppTypeLib);
2211 LeaveCriticalSection(&cache_section);
2212 return S_OK;
2213 }
2214 }
2215 LeaveCriticalSection(&cache_section);
2216
2217 /* check the signature of the file */
2218 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2219 if (INVALID_HANDLE_VALUE != hFile)
2220 {
2221 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2222 if (hMapping)
2223 {
2224 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2225 if(pBase)
2226 {
2227 /* retrieve file size */
2228 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2229
2230 /* first try to load as *.tlb */
2231 dwSignature = FromLEDWord(*((DWORD*) pBase));
2232 if ( dwSignature == MSFT_SIGNATURE)
2233 {
2234 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2235 }
2236 else if ( dwSignature == SLTG_SIGNATURE)
2237 {
2238 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2239 }
2240 UnmapViewOfFile(pBase);
2241 }
2242 CloseHandle(hMapping);
2243 }
2244 CloseHandle(hFile);
2245 }
2246 else
2247 {
2248 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2249 }
2250
2251 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2252 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2253 {
2254 /* find the typelibrary resource*/
2255 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2256 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2257 if (hinstDLL)
2258 {
2259 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2260 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2261 if (hrsrc)
2262 {
2263 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2264 if (hGlobal)
2265 {
2266 LPVOID pBase = LockResource(hGlobal);
2267 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2268
2269 if (pBase)
2270 {
2271 /* try to load as incore resource */
2272 dwSignature = FromLEDWord(*((DWORD*) pBase));
2273 if ( dwSignature == MSFT_SIGNATURE)
2274 {
2275 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2276 }
2277 else if ( dwSignature == SLTG_SIGNATURE)
2278 {
2279 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2280 }
2281 else
2282 {
2283 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2284 }
2285 }
2286 FreeResource( hGlobal );
2287 }
2288 }
2289 FreeLibrary(hinstDLL);
2290 }
2291 }
2292
2293 if(*ppTypeLib) {
2294 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2295
2296 TRACE("adding to cache\n");
2297 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2298 lstrcpyW(impl->path, pszFileName);
2299 /* We should really canonicalise the path here. */
2300 impl->index = index;
2301
2302 /* FIXME: check if it has added already in the meantime */
2303 EnterCriticalSection(&cache_section);
2304 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2305 impl->prev = NULL;
2306 tlb_cache_first = impl;
2307 LeaveCriticalSection(&cache_section);
2308 ret = S_OK;
2309 } else
2310 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2311
2312 return ret;
2313 }
2314
2315 /*================== ITypeLib(2) Methods ===================================*/
2316
2317 /****************************************************************************
2318 * ITypeLib2_Constructor_MSFT
2319 *
2320 * loading an MSFT typelib from an in-memory image
2321 */
2322 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2323 {
2324 TLBContext cx;
2325 long lPSegDir;
2326 MSFT_Header tlbHeader;
2327 MSFT_SegDir tlbSegDir;
2328 ITypeLibImpl * pTypeLibImpl;
2329
2330 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2331
2332 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2333 if (!pTypeLibImpl) return NULL;
2334
2335 pTypeLibImpl->lpVtbl = &tlbvt;
2336 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2337 pTypeLibImpl->ref = 1;
2338
2339 /* get pointer to beginning of typelib data */
2340 cx.pos = 0;
2341 cx.oStart=0;
2342 cx.mapping = pLib;
2343 cx.pLibInfo = pTypeLibImpl;
2344 cx.length = dwTLBLength;
2345
2346 /* read header */
2347 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2348 TRACE("header:\n");
2349 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2350 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2351 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2352 return NULL;
2353 }
2354 /* there is a small amount of information here until the next important
2355 * part:
2356 * the segment directory . Try to calculate the amount of data */
2357 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2358
2359 /* now read the segment directory */
2360 TRACE("read segment directory (at %ld)\n",lPSegDir);
2361 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2362 cx.pTblDir = &tlbSegDir;
2363
2364 /* just check two entries */
2365 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2366 {
2367 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2368 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2369 return NULL;
2370 }
2371
2372 /* now fill our internal data */
2373 /* TLIBATTR fields */
2374 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2375
2376 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2377 /* Windows seems to have zero here, is this correct? */
2378 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2379 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2380 else
2381 pTypeLibImpl->LibAttr.lcid = 0;
2382
2383 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2384 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2385 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2386 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2387
2388 /* name, eventually add to a hash table */
2389 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2390
2391 /* help info */
2392 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2393 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2394
2395 if( tlbHeader.varflags & HELPDLLFLAG)
2396 {
2397 int offset;
2398 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2399 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2400 }
2401
2402 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2403
2404 /* custom data */
2405 if(tlbHeader.CustomDataOffset >= 0)
2406 {
2407 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2408 }
2409
2410 /* fill in typedescriptions */
2411 if(tlbSegDir.pTypdescTab.length > 0)
2412 {
2413 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2414 INT16 td[4];
2415 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2416 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2417 for(i=0; i<cTD; )
2418 {
2419 /* FIXME: add several sanity checks here */
2420 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2421 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2422 {
2423 /* FIXME: check safearray */
2424 if(td[3] < 0)
2425 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2426 else
2427 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2428 }
2429 else if(td[0] == VT_CARRAY)
2430 {
2431 /* array descr table here */
2432 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2433 }
2434 else if(td[0] == VT_USERDEFINED)
2435 {
2436 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2437 }
2438 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2439 }
2440
2441 /* second time around to fill the array subscript info */
2442 for(i=0;i<cTD;i++)
2443 {
2444 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2445 if(tlbSegDir.pArrayDescriptions.offset>0)
2446 {
2447 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2448 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2449
2450 if(td[1]<0)
2451 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2452 else
2453 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2454
2455 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2456
2457 for(j = 0; j<td[2]; j++)
2458 {
2459 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2460 sizeof(INT), &cx, DO_NOT_SEEK);
2461 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2462 sizeof(INT), &cx, DO_NOT_SEEK);
2463 }
2464 }
2465 else
2466 {
2467 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2468 ERR("didn't find array description data\n");
2469 }
2470 }
2471 }
2472
2473 /* imported type libs */
2474 if(tlbSegDir.pImpFiles.offset>0)
2475 {
2476 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2477 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2478 UINT16 size;
2479
2480 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2481 {
2482 char *name;
2483 DWORD len;
2484
2485 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2486 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2487 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2488
2489 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2490 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2491 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2492 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2493
2494 size >>= 2;
2495 name = TLB_Alloc(size+1);
2496 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2497 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2498 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2499 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2500 TLB_Free(name);
2501
2502 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2503 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2504
2505 ppImpLib = &(*ppImpLib)->next;
2506 }
2507 }
2508
2509 /* type info's */
2510 if(tlbHeader.nrtypeinfos >= 0 )
2511 {
2512 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2513 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2514 int i;
2515
2516 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2517 {
2518 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2519
2520 ppTI = &((*ppTI)->next);
2521 (pTypeLibImpl->TypeInfoCount)++;
2522 }
2523 }
2524
2525 TRACE("(%p)\n", pTypeLibImpl);
2526 return (ITypeLib2*) pTypeLibImpl;
2527 }
2528
2529
2530 static BSTR TLB_MultiByteToBSTR(char *ptr)
2531 {
2532 DWORD len;
2533 WCHAR *nameW;
2534 BSTR ret;
2535
2536 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2537 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2538 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2539 ret = SysAllocString(nameW);
2540 HeapFree(GetProcessHeap(), 0, nameW);
2541 return ret;
2542 }
2543
2544 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2545 {
2546 char b[3];
2547 int i;
2548 short s;
2549
2550 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2551 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2552 return FALSE;
2553 }
2554
2555 guid->Data4[0] = s >> 8;
2556 guid->Data4[1] = s & 0xff;
2557
2558 b[2] = '\0';
2559 for(i = 0; i < 6; i++) {
2560 memcpy(b, str + 24 + 2 * i, 2);
2561 guid->Data4[i + 2] = strtol(b, NULL, 16);
2562 }
2563 return TRUE;
2564 }
2565
2566 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2567 {
2568 WORD bytelen;
2569 DWORD len;
2570 WCHAR *nameW;
2571
2572 *pBstr = NULL;
2573 bytelen = *(WORD*)ptr;
2574 if(bytelen == 0xffff) return 2;
2575 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2576 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2577 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2578 *pBstr = SysAllocStringLen(nameW, len);
2579 HeapFree(GetProcessHeap(), 0, nameW);
2580 return bytelen + 2;
2581 }
2582
2583 static WORD SLTG_ReadStringA(char *ptr, char **str)
2584 {
2585 WORD bytelen;
2586
2587 *str = NULL;
2588 bytelen = *(WORD*)ptr;
2589 if(bytelen == 0xffff) return 2;
2590 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2591 memcpy(*str, ptr + 2, bytelen);
2592 (*str)[bytelen] = '\0';
2593 return bytelen + 2;
2594 }
2595
2596 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2597 {
2598 char *ptr = pLibBlk;
2599 WORD w;
2600
2601 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2602 FIXME("libblk magic = %04x\n", w);
2603 return 0;
2604 }
2605
2606 ptr += 6;
2607 if((w = *(WORD*)ptr) != 0xffff) {
2608 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2609 ptr += w;
2610 }
2611 ptr += 2;
2612
2613 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2614
2615 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2616
2617 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2618 ptr += 4;
2619
2620 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2621 ptr += 2;
2622
2623 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2624 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2625 else
2626 pTypeLibImpl->LibAttr.lcid = 0;
2627 ptr += 2;
2628
2629 ptr += 4; /* skip res12 */
2630
2631 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2632 ptr += 2;
2633
2634 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2635 ptr += 2;
2636
2637 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2638 ptr += 2;
2639
2640 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2641 ptr += sizeof(GUID);
2642
2643 return ptr - (char*)pLibBlk;
2644 }
2645
2646 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2647 {
2648 BOOL done = FALSE;
2649 TYPEDESC *pTD = &pElem->tdesc;
2650
2651 /* Handle [in/out] first */
2652 if((*pType & 0xc000) == 0xc000)
2653 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2654 else if(*pType & 0x8000)
2655 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2656 else if(*pType & 0x4000)
2657 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2658 else
2659 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2660
2661 if(*pType & 0x2000)
2662 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2663
2664 if(*pType & 0x80)
2665 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2666
2667 while(!done) {
2668 if((*pType & 0xe00) == 0xe00) {
2669 pTD->vt = VT_PTR;
2670 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2671 sizeof(TYPEDESC));
2672 pTD = pTD->u.lptdesc;
2673 }
2674 switch(*pType & 0x7f) {
2675 case VT_PTR:
2676 pTD->vt = VT_PTR;
2677 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2678 sizeof(TYPEDESC));
2679 pTD = pTD->u.lptdesc;
2680 break;
2681
2682 case VT_USERDEFINED:
2683 pTD->vt = VT_USERDEFINED;
2684 pTD->u.hreftype = *(++pType) / 4;
2685 done = TRUE;
2686 break;
2687
2688 case VT_CARRAY:
2689 {
2690 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2691 array */
2692
2693 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2694
2695 pTD->vt = VT_CARRAY;
2696 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2697 sizeof(ARRAYDESC) +
2698 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2699 pTD->u.lpadesc->cDims = pSA->cDims;
2700 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2701 pSA->cDims * sizeof(SAFEARRAYBOUND));
2702
2703 pTD = &pTD->u.lpadesc->tdescElem;
2704 break;
2705 }
2706
2707 case VT_SAFEARRAY:
2708 {
2709 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2710 useful? */
2711
2712 pType++;
2713 pTD->vt = VT_SAFEARRAY;
2714 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2715 sizeof(TYPEDESC));
2716 pTD = pTD->u.lptdesc;
2717 break;
2718 }
2719 default:
2720 pTD->vt = *pType & 0x7f;
2721 done = TRUE;
2722 break;
2723 }
2724 pType++;
2725 }
2726 return pType;
2727 }
2728
2729
2730 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2731 char *pNameTable)
2732 {
2733 int ref;
2734 char *name;
2735 TLBRefType **ppRefType;
2736
2737 if(pRef->magic != SLTG_REF_MAGIC) {
2738 FIXME("Ref magic = %x\n", pRef->magic);
2739 return;
2740 }
2741 name = ( (char*)(&pRef->names) + pRef->number);
2742
2743 ppRefType = &pTI->reflist;
2744 for(ref = 0; ref < pRef->number >> 3; ref++) {
2745 char *refname;
2746 unsigned int lib_offs, type_num;
2747
2748 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2749 sizeof(**ppRefType));
2750
2751 name += SLTG_ReadStringA(name, &refname);
2752 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2753 FIXME("Can't sscanf ref\n");
2754 if(lib_offs != 0xffff) {
2755 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2756
2757 while(*import) {
2758 if((*import)->offset == lib_offs)
2759 break;
2760 import = &(*import)->next;
2761 }
2762 if(!*import) {
2763 char fname[MAX_PATH+1];
2764 int len;
2765
2766 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2767 sizeof(**import));
2768 (*import)->offset = lib_offs;
2769 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2770 &(*import)->guid);
2771 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2772 &(*import)->wVersionMajor,
2773 &(*import)->wVersionMinor,
2774 &(*import)->lcid, fname) != 4) {
2775 FIXME("can't sscanf ref %s\n",
2776 pNameTable + lib_offs + 40);
2777 }
2778 len = strlen(fname);
2779 if(fname[len-1] != '#')
2780 FIXME("fname = %s\n", fname);
2781 fname[len-1] = '\0';
2782 (*import)->name = TLB_MultiByteToBSTR(fname);
2783 }
2784 (*ppRefType)->pImpTLInfo = *import;
2785 } else { /* internal ref */
2786 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2787 }
2788 (*ppRefType)->reference = ref;
2789 (*ppRefType)->index = type_num;
2790
2791 HeapFree(GetProcessHeap(), 0, refname);
2792 ppRefType = &(*ppRefType)->next;
2793 }
2794 if((BYTE)*name != SLTG_REF_MAGIC)
2795 FIXME("End of ref block magic = %x\n", *name);
2796 dump_TLBRefType(pTI->reflist);
2797 }
2798
2799 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2800 BOOL OneOnly)
2801 {
2802 SLTG_ImplInfo *info;
2803 TLBImplType **ppImplType = &pTI->impltypelist;
2804 /* I don't really get this structure, usually it's 0x16 bytes
2805 long, but iuser.tlb contains some that are 0x18 bytes long.
2806 That's ok because we can use the next ptr to jump to the next
2807 one. But how do we know the length of the last one? The WORD
2808 at offs 0x8 might be the clue. For now I'm just assuming that
2809 the last one is the regular 0x16 bytes. */
2810
2811 info = (SLTG_ImplInfo*)pBlk;
2812 while(1) {
2813 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2814 sizeof(**ppImplType));
2815 (*ppImplType)->hRef = info->ref;
2816 (*ppImplType)->implflags = info->impltypeflags;
2817 pTI->TypeAttr.cImplTypes++;
2818 ppImplType = &(*ppImplType)->next;
2819
2820 if(info->next == 0xffff)
2821 break;
2822 if(OneOnly)
2823 FIXME("Interface inheriting more than one interface\n");
2824 info = (SLTG_ImplInfo*)(pBlk + info->next);
2825 }
2826 info++; /* see comment at top of function */
2827 return (char*)info;
2828 }
2829
2830 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2831 char *pNameTable)
2832 {
2833 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2834 SLTG_MemberHeader *pMemHeader;
2835 char *pFirstItem, *pNextItem;
2836
2837 if(pTIHeader->href_table != 0xffffffff) {
2838 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2839 pNameTable);
2840 }
2841
2842
2843 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2844
2845 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2846
2847 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2848 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2849 }
2850
2851 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2852 }
2853
2854
2855 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2856 char *pNameTable)
2857 {
2858 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2859 SLTG_MemberHeader *pMemHeader;
2860 SLTG_Function *pFunc;
2861 char *pFirstItem, *pNextItem;
2862 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2863 int num = 0;
2864
2865 if(pTIHeader->href_table != 0xffffffff) {
2866 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2867 pNameTable);
2868 }
2869
2870 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2871
2872 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2873
2874 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2875 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2876 }
2877
2878 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2879 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2880
2881 int param;
2882 WORD *pType, *pArg;
2883
2884 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2885 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2886 FIXME("func magic = %02x\n", pFunc->magic);
2887 return NULL;
2888 }
2889 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2890 sizeof(**ppFuncDesc));
2891 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2892
2893 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2894 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2895 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2896 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2897 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2898 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2899
2900 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2901 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2902
2903 if(pFunc->retnextopt & 0x80)
2904 pType = &pFunc->rettype;
2905 else
2906 pType = (WORD*)(pFirstItem + pFunc->rettype);
2907
2908
2909 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2910
2911 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2912 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2913 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2914 (*ppFuncDesc)->pParamDesc =
2915 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2916 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2917
2918 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2919
2920 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2921 char *paramName = pNameTable + *pArg;
2922 BOOL HaveOffs;
2923 /* If arg type follows then paramName points to the 2nd
2924 letter of the name, else the next WORD is an offset to
2925 the arg type and paramName points to the first letter.
2926 So let's take one char off paramName and see if we're
2927 pointing at an alpha-numeric char. However if *pArg is
2928 0xffff or 0xfffe then the param has no name, the former
2929 meaning that the next WORD is the type, the latter
2930 meaning the the next WORD is an offset to the type. */
2931
2932 HaveOffs = FALSE;
2933 if(*pArg == 0xffff)
2934 paramName = NULL;
2935 else if(*pArg == 0xfffe) {
2936 paramName = NULL;
2937 HaveOffs = TRUE;
2938 }
2939 else if(paramName[-1] && !isalnum(paramName[-1]))
2940 HaveOffs = TRUE;
2941
2942 pArg++;
2943
2944 if(HaveOffs) { /* the next word is an offset to type */
2945 pType = (WORD*)(pFirstItem + *pArg);
2946 SLTG_DoType(pType, pFirstItem,
2947 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2948 pArg++;
2949 } else {
2950 if(paramName)
2951 paramName--;
2952 pArg = SLTG_DoType(pArg, pFirstItem,
2953 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2954 }
2955
2956 /* Are we an optional param ? */
2957 if((*ppFuncDesc)->funcdesc.cParams - param <=
2958 (*ppFuncDesc)->funcdesc.cParamsOpt)
2959 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2960
2961 if(paramName) {
2962 (*ppFuncDesc)->pParamDesc[param].Name =
2963 TLB_MultiByteToBSTR(paramName);
2964 }
2965 }
2966
2967 ppFuncDesc = &((*ppFuncDesc)->next);
2968 if(pFunc->next == 0xffff) break;
2969 }
2970 pTI->TypeAttr.cFuncs = num;
2971 dump_TLBFuncDesc(pTI->funclist);
2972 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2973 }
2974
2975 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2976 char *pNameTable)
2977 {
2978 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2979 SLTG_MemberHeader *pMemHeader;
2980 SLTG_RecordItem *pItem;
2981 char *pFirstItem;
2982 TLBVarDesc **ppVarDesc = &pTI->varlist;
2983 int num = 0;
2984 WORD *pType;
2985 char buf[300];
2986
2987 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2988
2989 pFirstItem = (char*)(pMemHeader + 1);
2990 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2991 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2992 if(pItem->magic != SLTG_RECORD_MAGIC) {
2993 FIXME("record magic = %02x\n"