ReactOS 0.4.16-dev-340-g0540c21
typelib.c
Go to the documentation of this file.
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 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 *
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
28 *
29 * - Tested using OLEVIEW (Platform SDK tool) only.
30 *
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
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 *
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
41 *
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
47 *
48 */
49
50#include <stdlib.h>
51#include <string.h>
52#include <stdarg.h>
53#include <stdio.h>
54#include <ctype.h>
55
56#define COBJMACROS
57#define NONAMELESSUNION
58
59#include "winerror.h"
60#include "windef.h"
61#include "winbase.h"
62#include "winnls.h"
63#include "winreg.h"
64#include "winuser.h"
65#include "winternl.h"
66#include "lzexpand.h"
67
68#include "objbase.h"
69#include "typelib.h"
70#include "wine/debug.h"
71#include "variant.h"
72#include "wine/asm.h"
73#include "wine/heap.h"
74#include "wine/list.h"
75
78
79typedef struct
80{
88
89typedef struct
90{
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
94 /*
95 * Name info array.
96 */
98
99static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
101static void TLB_FreeVarDesc(VARDESC*);
102
103/****************************************************************************
104 * FromLExxx
105 *
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
108 */
109#ifdef WORDS_BIGENDIAN
110static WORD FromLEWord(WORD p_iVal)
111{
112 return (((p_iVal & 0x00FF) << 8) |
113 ((p_iVal & 0xFF00) >> 8));
114}
115
116
117static DWORD FromLEDWord(DWORD p_iVal)
118{
119 return (((p_iVal & 0x000000FF) << 24) |
120 ((p_iVal & 0x0000FF00) << 8) |
121 ((p_iVal & 0x00FF0000) >> 8) |
122 ((p_iVal & 0xFF000000) >> 24));
123}
124#else
125#define FromLEWord(X) (X)
126#define FromLEDWord(X) (X)
127#endif
128
129#define DISPATCH_HREF_OFFSET 0x01000000
130#define DISPATCH_HREF_MASK 0xff000000
131
132/****************************************************************************
133 * FromLExxx
134 *
135 * Fix byte order in any structure if necessary
136 */
137#ifdef WORDS_BIGENDIAN
138static void FromLEWords(void *p_Val, int p_iSize)
139{
140 WORD *Val = p_Val;
141
142 p_iSize /= sizeof(WORD);
143
144 while (p_iSize) {
145 *Val = FromLEWord(*Val);
146 Val++;
147 p_iSize--;
148 }
149}
150
151
152static void FromLEDWords(void *p_Val, int p_iSize)
153{
154 DWORD *Val = p_Val;
155
156 p_iSize /= sizeof(DWORD);
157
158 while (p_iSize) {
159 *Val = FromLEDWord(*Val);
160 Val++;
161 p_iSize--;
162 }
163}
164#else
165#define FromLEWords(X,Y) /*nothing*/
166#define FromLEDWords(X,Y) /*nothing*/
167#endif
168
169/*
170 * Find a typelib key which matches a requested maj.min version.
171 */
172static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173{
174 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
175 WCHAR buffer[60];
176 char key_name[16];
177 DWORD len, i;
178 INT best_maj = -1, best_min = -1;
179 HKEY hkey;
180
181 memcpy( buffer, typelibW, sizeof(typelibW) );
183
185 return FALSE;
186
187 len = sizeof(key_name);
188 i = 0;
189 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 {
191 INT v_maj, v_min;
192
193 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 {
195 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196
197 if (*wMaj == 0xffff && *wMin == 0xffff)
198 {
199 if (v_maj > best_maj) best_maj = v_maj;
200 if (v_min > best_min) best_min = v_min;
201 }
202 else if (*wMaj == v_maj)
203 {
204 best_maj = v_maj;
205
206 if (*wMin == v_min)
207 {
208 best_min = v_min;
209 break; /* exact match */
210 }
211 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
212 }
213 }
214 len = sizeof(key_name);
215 }
216 RegCloseKey( hkey );
217
218 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219
220 if (*wMaj == 0xffff && *wMin == 0xffff)
221 {
222 if (best_maj >= 0 && best_min >= 0)
223 {
224 *wMaj = best_maj;
225 *wMin = best_min;
226 return TRUE;
227 }
228 }
229
230 if (*wMaj == best_maj && best_min >= 0)
231 {
232 *wMin = best_min;
233 return TRUE;
234 }
235 return FALSE;
236}
237
238/* get the path of a typelib key, in the form "Typelib\<guid>\<maj>.<min>" */
239/* buffer must be at least 60 characters long */
241{
242 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
243 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244
245 memcpy( buffer, TypelibW, sizeof(TypelibW) );
247 swprintf( buffer + lstrlenW(buffer), VersionFormatW, wMaj, wMin );
248 return buffer;
249}
250
251/* get the path of an interface key, in the form "Interface\<guid>" */
252/* buffer must be at least 50 characters long */
254{
255 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256
257 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
259 return buffer;
260}
261
262/* get the lcid subkey for a typelib, in the form "<lcid>\<syskind>" */
263/* buffer must be at least 16 characters long */
264static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265{
266 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
267 static const WCHAR win16W[] = {'w','i','n','1','6',0};
268 static const WCHAR win32W[] = {'w','i','n','3','2',0};
269 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270
271 swprintf( buffer, LcidFormatW, lcid );
272 switch(syskind)
273 {
274 case SYS_WIN16: lstrcatW( buffer, win16W ); break;
275 case SYS_WIN32: lstrcatW( buffer, win32W ); break;
276 case SYS_WIN64: lstrcatW( buffer, win64W ); break;
277 default:
278 TRACE("Typelib is for unsupported syskind %i\n", syskind);
279 return NULL;
280 }
281 return buffer;
282}
283
284static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
285
287{
288 ULONG size;
289 DWORD res;
293 WORD flags;
298};
299
300/* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
302 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
303{
305 LCID myLCID = lcid;
306 HKEY hkey;
307 WCHAR buffer[60];
309 LONG res;
310
311 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
312
313 if (redir)
314 {
315 ACTCTX_SECTION_KEYED_DATA data;
316
317 data.cbSize = sizeof(data);
318 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
319 {
320 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
321 WCHAR *nameW;
322 DWORD len;
323
324 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
326
327 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
329 if (!len) return TYPE_E_LIBNOTREGISTERED;
330
331 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
333 return S_OK;
334 }
335 }
336
337 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
338 get_typelib_key( guid, wMaj, wMin, buffer );
339
342 {
343 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
345 }
346 else if (res != ERROR_SUCCESS)
347 {
348 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
350 }
351
352 while (hr != S_OK)
353 {
354 LONG dwPathLen = sizeof(Path);
355
356 get_lcid_subkey( myLCID, syskind, buffer );
357
358 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
359 {
360 if (!lcid)
361 break;
362 else if (myLCID == lcid)
363 {
364 /* try with sub-langid */
365 myLCID = SUBLANGID(lcid);
366 }
367 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
368 {
369 /* try with system langid */
370 myLCID = 0;
371 }
372 else
373 {
374 break;
375 }
376 }
377 else
378 {
380 hr = S_OK;
381 }
382 }
383 RegCloseKey( hkey );
384 TRACE_(typelib)("-- 0x%08x\n", hr);
385 return hr;
386}
387
388/****************************************************************************
389 * QueryPathOfRegTypeLib [OLEAUT32.164]
390 *
391 * Gets the path to a registered type library.
392 *
393 * PARAMS
394 * guid [I] referenced guid
395 * wMaj [I] major version
396 * wMin [I] minor version
397 * lcid [I] locale id
398 * path [O] path of typelib
399 *
400 * RETURNS
401 * Success: S_OK.
402 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
403 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
404 * opened.
405 */
407{
408 BOOL redir = TRUE;
409#ifdef _WIN64
410 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
411 if(SUCCEEDED(hres))
412 return hres;
413 redir = FALSE;
414#endif
415 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
416}
417
418/******************************************************************************
419 * CreateTypeLib [OLEAUT32.160] creates a typelib
420 *
421 * RETURNS
422 * Success: S_OK
423 * Failure: Status
424 */
426{
427 ICreateTypeLib2 *typelib2;
429
430 FIXME("(%d, %s, %p): forwarding to CreateTypeLib2\n", syskind, debugstr_w(file), ctlib);
431
432 hres = CreateTypeLib2(syskind, file, &typelib2);
433 if(SUCCEEDED(hres))
434 {
435 hres = ICreateTypeLib2_QueryInterface(typelib2, &IID_ICreateTypeLib, (void **)&ctlib);
436 ICreateTypeLib2_Release(typelib2);
437 }
438
439 return hres;
440}
441
442/******************************************************************************
443 * LoadTypeLib [OLEAUT32.161]
444 *
445 * Loads a type library
446 *
447 * PARAMS
448 * szFile [I] Name of file to load from.
449 * pptLib [O] Pointer that receives ITypeLib object on success.
450 *
451 * RETURNS
452 * Success: S_OK
453 * Failure: Status
454 *
455 * SEE
456 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
457 */
458HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
459{
460 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
461 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
462}
463
464/******************************************************************************
465 * LoadTypeLibEx [OLEAUT32.183]
466 *
467 * Loads and optionally registers a type library
468 *
469 * RETURNS
470 * Success: S_OK
471 * Failure: Status
472 */
474 LPCOLESTR szFile, /* [in] Name of file to load from */
475 REGKIND regkind, /* [in] Specify kind of registration */
476 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
477{
479 HRESULT res;
480
481 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
482
483 if (!szFile || !pptLib)
484 return E_INVALIDARG;
485
486 *pptLib = NULL;
487
488 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
489
490 if (SUCCEEDED(res))
491 switch(regkind)
492 {
493 case REGKIND_DEFAULT:
494 /* don't register typelibs supplied with full path. Experimentation confirms the following */
495 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
496 (szFile[0] && (szFile[1] == ':'))) break;
497 /* else fall-through */
498
499 case REGKIND_REGISTER:
500 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
501 {
502 ITypeLib_Release(*pptLib);
503 *pptLib = 0;
504 }
505 break;
506 case REGKIND_NONE:
507 break;
508 }
509
510 TRACE(" returns %08x\n",res);
511 return res;
512}
513
514/******************************************************************************
515 * LoadRegTypeLib [OLEAUT32.162]
516 *
517 * Loads a registered type library.
518 *
519 * PARAMS
520 * rguid [I] GUID of the registered type library.
521 * wVerMajor [I] major version.
522 * wVerMinor [I] minor version.
523 * lcid [I] locale ID.
524 * ppTLib [O] pointer that receives an ITypeLib object on success.
525 *
526 * RETURNS
527 * Success: S_OK.
528 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
529 * LoadTypeLib.
530 */
532 REFGUID rguid,
533 WORD wVerMajor,
534 WORD wVerMinor,
535 LCID lcid,
536 ITypeLib **ppTLib)
537{
538 BSTR bstr=NULL;
539 HRESULT res;
540
541 *ppTLib = NULL;
542
543 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
544
545 if(SUCCEEDED(res))
546 {
547 res= LoadTypeLib(bstr, ppTLib);
548 SysFreeString(bstr);
549
550 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
551 {
552 TLIBATTR *attr;
553
554 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
555 if (res == S_OK)
556 {
557 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
558 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
559
560 if (mismatch)
561 {
562 ITypeLib_Release(*ppTLib);
563 *ppTLib = NULL;
565 }
566 }
567 }
568 }
569
570 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
571
572 return res;
573}
574
575
576/* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
577static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
578static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
579static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
580static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
581static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
582
583static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
584{
585 WCHAR keyName[60];
586 HKEY key, subKey;
587
588 static const WCHAR typelib_proxy_clsid[] = {'{','0','0','0','2','0','4','2','4','-',
589 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
590 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
591 static const WCHAR dispatch_proxy_clsid[] = {'{','0','0','0','2','0','4','2','0','-',
592 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
593 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
594
595 get_interface_key( &tattr->guid, keyName );
596 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
598 {
599 const WCHAR *proxy_clsid;
600
601 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
602 proxy_clsid = typelib_proxy_clsid;
603 else
604 proxy_clsid = dispatch_proxy_clsid;
605
606 if (name)
608 (BYTE *)name, (lstrlenW(name)+1) * sizeof(OLECHAR));
609
611 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
612 RegSetValueExW(subKey, NULL, 0, REG_SZ,
613 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
614 RegCloseKey(subKey);
615 }
616
618 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
619 RegSetValueExW(subKey, NULL, 0, REG_SZ,
620 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
621 RegCloseKey(subKey);
622 }
623
624 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
625 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
626 {
627 WCHAR buffer[40];
628 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
629 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
630
631 StringFromGUID2(&libattr->guid, buffer, 40);
632 RegSetValueExW(subKey, NULL, 0, REG_SZ,
633 (BYTE *)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
634 swprintf(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
635 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
636 (BYTE*)buffer, (lstrlenW(buffer)+1) * sizeof(WCHAR));
637 RegCloseKey(subKey);
638 }
639
641 }
642}
643
644/******************************************************************************
645 * RegisterTypeLib [OLEAUT32.163]
646 * Adds information about a type library to the System Registry
647 * NOTES
648 * Docs: ITypeLib FAR * ptlib
649 * Docs: OLECHAR FAR* szFullPath
650 * Docs: OLECHAR FAR* szHelpDir
651 *
652 * RETURNS
653 * Success: S_OK
654 * Failure: Status
655 */
656HRESULT WINAPI RegisterTypeLib(ITypeLib *ptlib, const WCHAR *szFullPath, const WCHAR *szHelpDir)
657{
658 HRESULT res;
659 TLIBATTR *attr;
660 WCHAR keyName[60];
661 WCHAR tmp[16];
662 HKEY key, subKey;
663 UINT types, tidx;
664 TYPEKIND kind;
665 DWORD disposition;
666
667 if (ptlib == NULL || szFullPath == NULL)
668 return E_INVALIDARG;
669
670 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
671 return E_FAIL;
672
673#ifndef _WIN64
674 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
675#endif
676
677 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
678
679 res = S_OK;
680 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
682 {
683 LPOLESTR doc;
684
685 /* Set the human-readable name of the typelib */
686 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
687 res = E_FAIL;
688 else if (doc)
689 {
690 if (RegSetValueExW(key, NULL, 0, REG_SZ,
691 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
692 res = E_FAIL;
693
694 SysFreeString(doc);
695 }
696
697 /* Make up the name of the typelib path subkey */
698 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
699
700 /* Create the typelib path subkey */
701 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
702 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
703 {
704 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
705 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
706 res = E_FAIL;
707
708 RegCloseKey(subKey);
709 }
710 else
711 res = E_FAIL;
712
713 /* Create the flags subkey */
714 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
715 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
716 {
717 /* FIXME: is %u correct? */
718 static const WCHAR formatW[] = {'%','u',0};
719 WCHAR buf[20];
720 swprintf(buf, formatW, attr->wLibFlags);
721 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
722 (BYTE *)buf, (lstrlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
723 res = E_FAIL;
724
725 RegCloseKey(subKey);
726 }
727 else
728 res = E_FAIL;
729
730 /* create the helpdir subkey */
731 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
732 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
733 {
734 BSTR freeHelpDir = NULL;
735 OLECHAR* pIndexStr;
736
737 /* if we created a new key, and helpDir was null, set the helpdir
738 to the directory which contains the typelib. However,
739 if we just opened an existing key, we leave the helpdir alone */
740 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
741 szHelpDir = freeHelpDir = SysAllocString(szFullPath);
742 pIndexStr = wcsrchr(szHelpDir, '\\');
743 if (pIndexStr) {
744 *pIndexStr = 0;
745 }
746 }
747
748 /* if we have an szHelpDir, set it! */
749 if (szHelpDir != NULL) {
750 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
751 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
752 res = E_FAIL;
753 }
754 }
755
756 SysFreeString(freeHelpDir);
757 RegCloseKey(subKey);
758 } else {
759 res = E_FAIL;
760 }
761
763 }
764 else
765 res = E_FAIL;
766
767 /* register OLE Automation-compatible interfaces for this typelib */
768 types = ITypeLib_GetTypeInfoCount(ptlib);
769 for (tidx=0; tidx<types; tidx++) {
770 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
772 ITypeInfo *tinfo = NULL;
773
774 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
775
776 switch (kind) {
777 case TKIND_INTERFACE:
778 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
779 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
780 break;
781
782 case TKIND_DISPATCH:
783 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
784 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
785 break;
786
787 default:
788 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
789 break;
790 }
791
792 if (tinfo) {
793 TYPEATTR *tattr = NULL;
794 ITypeInfo_GetTypeAttr(tinfo, &tattr);
795
796 if (tattr) {
797 TRACE_(typelib)("guid=%s, flags=%04x (",
798 debugstr_guid(&tattr->guid),
799 tattr->wTypeFlags);
800
801 if (TRACE_ON(typelib)) {
802#define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
803 XX(FAPPOBJECT);
804 XX(FCANCREATE);
805 XX(FLICENSED);
806 XX(FPREDECLID);
807 XX(FHIDDEN);
808 XX(FCONTROL);
809 XX(FDUAL);
810 XX(FNONEXTENSIBLE);
811 XX(FOLEAUTOMATION);
812 XX(FRESTRICTED);
813 XX(FAGGREGATABLE);
814 XX(FREPLACEABLE);
815 XX(FDISPATCHABLE);
816 XX(FREVERSEBIND);
817 XX(FPROXY);
818#undef XX
819 MESSAGE("\n");
820 }
821
822 /* Register all dispinterfaces (which includes dual interfaces) and
823 oleautomation interfaces */
824 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
825 kind == TKIND_DISPATCH)
826 {
828 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
829
830 /* register interface<->typelib coupling */
831 TLB_register_interface(attr, name, tattr, 0);
832
833 /* register TLBs into the opposite registry view, too */
834 if(opposite == KEY_WOW64_32KEY ||
836 TLB_register_interface(attr, name, tattr, opposite);
837 }
838
839 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
840 }
841
842 ITypeInfo_Release(tinfo);
843 }
844
846 }
847 }
848
849 ITypeLib_ReleaseTLibAttr(ptlib, attr);
850
851 return res;
852}
853
855{
856 WCHAR subKeyName[50];
857 HKEY subKey;
858
859 /* the path to the type */
860 get_interface_key( guid, subKeyName );
861
862 /* Delete its bits */
863 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
864 return;
865
868 RegDeleteKeyW(subKey, TypeLibW);
869 RegCloseKey(subKey);
870 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
871}
872
873/******************************************************************************
874 * UnRegisterTypeLib [OLEAUT32.186]
875 * Removes information about a type library from the System Registry
876 * NOTES
877 *
878 * RETURNS
879 * Success: S_OK
880 * Failure: Status
881 */
883 REFGUID libid, /* [in] Guid of the library */
884 WORD wVerMajor, /* [in] major version */
885 WORD wVerMinor, /* [in] minor version */
886 LCID lcid, /* [in] locale id */
887 SYSKIND syskind)
888{
889 BSTR tlibPath = NULL;
890 DWORD tmpLength;
891 WCHAR keyName[60];
892 WCHAR subKeyName[50];
893 int result = S_OK;
894 DWORD i = 0;
895 BOOL deleteOtherStuff;
896 HKEY key = NULL;
897 TYPEATTR* typeAttr = NULL;
898 TYPEKIND kind;
899 ITypeInfo* typeInfo = NULL;
900 ITypeLib* typeLib = NULL;
901 int numTypes;
902
903 TRACE("(IID: %s)\n",debugstr_guid(libid));
904
905 /* Create the path to the key */
906 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
907
908 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
909 {
910 TRACE("Unsupported syskind %i\n", syskind);
912 goto end;
913 }
914
915 /* get the path to the typelib on disk */
916 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
918 goto end;
919 }
920
921 /* Try and open the key to the type library. */
924 goto end;
925 }
926
927 /* Try and load the type library */
928 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
930 goto end;
931 }
932
933 /* remove any types registered with this typelib */
934 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
935 for (i=0; i<numTypes; i++) {
936 /* get the kind of type */
937 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
938 goto enddeleteloop;
939 }
940
941 /* skip non-interfaces, and get type info for the type */
942 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
943 goto enddeleteloop;
944 }
945 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
946 goto enddeleteloop;
947 }
948 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
949 goto enddeleteloop;
950 }
951
952 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
953 kind == TKIND_DISPATCH)
954 {
956 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
957
958 TLB_unregister_interface(&typeAttr->guid, 0);
959
960 /* unregister TLBs into the opposite registry view, too */
961 if(opposite == KEY_WOW64_32KEY ||
963 TLB_unregister_interface(&typeAttr->guid, opposite);
964 }
965 }
966
967enddeleteloop:
968 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
969 typeAttr = NULL;
970 if (typeInfo) ITypeInfo_Release(typeInfo);
971 typeInfo = NULL;
972 }
973
974 /* Now, delete the type library path subkey */
975 get_lcid_subkey( lcid, syskind, subKeyName );
976 RegDeleteKeyW(key, subKeyName);
977 *wcsrchr( subKeyName, '\\' ) = 0; /* remove last path component */
978 RegDeleteKeyW(key, subKeyName);
979
980 /* check if there is anything besides the FLAGS/HELPDIR keys.
981 If there is, we don't delete them */
982 tmpLength = ARRAY_SIZE(subKeyName);
983 deleteOtherStuff = TRUE;
984 i = 0;
985 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
986 tmpLength = ARRAY_SIZE(subKeyName);
987
988 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
989 if (!wcscmp(subKeyName, FLAGSW)) continue;
990 if (!wcscmp(subKeyName, HELPDIRW)) continue;
991 deleteOtherStuff = FALSE;
992 break;
993 }
994
995 /* only delete the other parts of the key if we're absolutely sure */
996 if (deleteOtherStuff) {
1000 key = NULL;
1001
1003 *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
1005 }
1006
1007end:
1008 SysFreeString(tlibPath);
1009 if (typeLib) ITypeLib_Release(typeLib);
1010 if (key) RegCloseKey(key);
1011 return result;
1012}
1013
1014/******************************************************************************
1015 * RegisterTypeLibForUser [OLEAUT32.442]
1016 * Adds information about a type library to the user registry
1017 * NOTES
1018 * Docs: ITypeLib FAR * ptlib
1019 * Docs: OLECHAR FAR* szFullPath
1020 * Docs: OLECHAR FAR* szHelpDir
1021 *
1022 * RETURNS
1023 * Success: S_OK
1024 * Failure: Status
1025 */
1027 ITypeLib * ptlib, /* [in] Pointer to the library*/
1028 OLECHAR * szFullPath, /* [in] full Path of the library*/
1029 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1030 may be NULL*/
1031{
1032 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1033 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1034 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1035}
1036
1037/******************************************************************************
1038 * UnRegisterTypeLibForUser [OLEAUT32.443]
1039 * Removes information about a type library from the user registry
1040 *
1041 * RETURNS
1042 * Success: S_OK
1043 * Failure: Status
1044 */
1046 REFGUID libid, /* [in] GUID of the library */
1047 WORD wVerMajor, /* [in] major version */
1048 WORD wVerMinor, /* [in] minor version */
1049 LCID lcid, /* [in] locale id */
1050 SYSKIND syskind)
1051{
1052 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1053 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1054 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1055}
1056
1057/*======================= ITypeLib implementation =======================*/
1058
1059typedef struct tagTLBGuid {
1063 struct list entry;
1065
1066typedef struct tagTLBCustData
1067{
1070 struct list entry;
1072
1073/* data structure for import typelibs */
1074typedef struct tagTLBImpLib
1075{
1076 int offset; /* offset in the file (MSFT)
1077 offset in nametable (SLTG)
1078 just used to identify library while reading
1079 data from file */
1080 TLBGuid *guid; /* libid */
1081 BSTR name; /* name */
1082
1083 LCID lcid; /* lcid of imported typelib */
1084
1085 WORD wVersionMajor; /* major version number */
1086 WORD wVersionMinor; /* minor version number */
1087
1088 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1089 NULL if not yet loaded */
1090 struct list entry;
1092
1093typedef struct tagTLBString {
1096 struct list entry;
1098
1099/* internal ITypeLib data */
1100typedef struct tagITypeLibImpl
1101{
1114
1115 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1116 * exported to the application as a UNICODE string.
1117 */
1121
1127 int TypeInfoCount; /* nr of typeinfo's in librarry */
1131 int ctTypeDesc; /* number of items in type desc array */
1132 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1133 library. Only used while reading MSFT
1134 typelibs */
1135 struct list ref_list; /* list of ref types in this typelib */
1136 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1137
1138
1139 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1140 struct list entry;
1144
1145static const ITypeLib2Vtbl tlbvt;
1146static const ITypeCompVtbl tlbtcvt;
1147static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1148
1150{
1151 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1152}
1153
1155{
1156 return impl_from_ITypeLib2((ITypeLib2*)iface);
1157}
1158
1160{
1161 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1162}
1163
1165{
1166 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1167}
1168
1169/* ITypeLib methods */
1170static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1171static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1172
1173/*======================= ITypeInfo implementation =======================*/
1174
1175/* data for referenced types */
1176typedef struct tagTLBRefType
1177{
1178 INT index; /* Type index for internal ref or for external ref
1179 it the format is SLTG. -2 indicates to
1180 use guid */
1181
1182 TYPEKIND tkind;
1183 TLBGuid *guid; /* guid of the referenced type */
1184 /* if index == TLB_REF_USE_GUID */
1185
1186 HREFTYPE reference; /* The href of this ref */
1187 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1188 TLB_REF_INTERNAL for internal refs
1189 TLB_REF_NOT_FOUND for broken refs */
1190
1191 struct list entry;
1193
1194#define TLB_REF_USE_GUID -2
1195
1196#define TLB_REF_INTERNAL (void*)-2
1197#define TLB_REF_NOT_FOUND (void*)-1
1198
1199/* internal Parameter data */
1200typedef struct tagTLBParDesc
1201{
1205
1206/* internal Function data */
1207typedef struct tagTLBFuncDesc
1208{
1209 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1210 const TLBString *Name; /* the name of this function */
1211 TLBParDesc *pParamDesc; /* array with param names and custom data */
1215 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1218
1219/* internal Variable data */
1220typedef struct tagTLBVarDesc
1221{
1222 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1223 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1224 const TLBString *Name; /* the name of this variable */
1230
1231/* internal implemented interface data */
1232typedef struct tagTLBImplType
1233{
1234 HREFTYPE hRef; /* hRef of interface */
1235 int implflags; /* IMPLFLAG_*s */
1238
1239/* internal TypeInfo data */
1240typedef struct tagITypeInfoImpl
1241{
1248
1250 TYPEATTR typeattr;
1251 TYPEDESC *tdescAlias;
1252
1253 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1254 int index; /* index in this typelib; */
1255 HREFTYPE hreftype; /* hreftype for app object binding */
1256 /* type libs seem to store the doc strings in ascii
1257 * so why should we do it in unicode?
1258 */
1265
1266 /* functions */
1268
1269 /* variables */
1271
1272 /* Implemented Interfaces */
1274
1278
1280{
1281 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1282}
1283
1285{
1286 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1287}
1288
1290{
1291 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1292}
1293
1295{
1296 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1297}
1298
1299static const ITypeInfo2Vtbl tinfvt;
1300static const ITypeCompVtbl tcompvt;
1301static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1302
1305
1306typedef struct tagTLBContext
1307{
1308 unsigned int oStart; /* start of TLB in file */
1309 unsigned int pos; /* current pos */
1310 unsigned int length; /* total length */
1311 void *mapping; /* memory mapping */
1315
1316
1317static inline BSTR TLB_get_bstr(const TLBString *str)
1318{
1319 return str != NULL ? str->str : NULL;
1320}
1321
1322static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1323{
1324 if(!str)
1325 return 1;
1326 return memcmp(left, str->str, len);
1327}
1328
1329static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1330{
1331 return guid != NULL ? &guid->guid : NULL;
1332}
1333
1334static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1335{
1336 return guid != NULL ? &guid->guid : &GUID_NULL;
1337}
1338
1339static int get_ptr_size(SYSKIND syskind)
1340{
1341 switch(syskind){
1342 case SYS_WIN64:
1343 return 8;
1344 case SYS_WIN32:
1345 case SYS_MAC:
1346 case SYS_WIN16:
1347 return 4;
1348 }
1349 WARN("Unhandled syskind: 0x%x\n", syskind);
1350 return 4;
1351}
1352
1353/*
1354 debug
1355*/
1356static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1357 if (pTD->vt & VT_RESERVED)
1358 szVarType += strlen(strcpy(szVarType, "reserved | "));
1359 if (pTD->vt & VT_BYREF)
1360 szVarType += strlen(strcpy(szVarType, "ref to "));
1361 if (pTD->vt & VT_ARRAY)
1362 szVarType += strlen(strcpy(szVarType, "array of "));
1363 if (pTD->vt & VT_VECTOR)
1364 szVarType += strlen(strcpy(szVarType, "vector of "));
1365 switch(pTD->vt & VT_TYPEMASK) {
1366 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1367 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1368 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1369 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1370 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1371 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1372 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1373 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1374 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1375 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1376 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1377 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1378 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1379 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1380 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1381 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1382 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1383 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1384 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1385 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1386 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1387 pTD->u.hreftype); break;
1388 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1389 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1390 case VT_PTR: sprintf(szVarType, "ptr to ");
1391 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1392 break;
1393 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1394 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1395 break;
1396 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1397 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1398 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1399 break;
1400
1401 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1402 }
1403}
1404
1405static void dump_ELEMDESC(const ELEMDESC *edesc) {
1406 char buf[200];
1407 USHORT flags = edesc->u.paramdesc.wParamFlags;
1408 dump_TypeDesc(&edesc->tdesc,buf);
1409 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1410 MESSAGE("\t\tu.paramdesc.wParamFlags");
1411 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1412 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1413 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1414 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1415 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1416 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1417 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1418 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1419 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1420}
1421static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1422 int i;
1423 MESSAGE("memid is %08x\n",funcdesc->memid);
1424 for (i=0;i<funcdesc->cParams;i++) {
1425 MESSAGE("Param %d:\n",i);
1426 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1427 }
1428 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1429 switch (funcdesc->funckind) {
1430 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1431 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1432 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1433 case FUNC_STATIC: MESSAGE("static");break;
1434 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1435 default: MESSAGE("unknown");break;
1436 }
1437 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1438 switch (funcdesc->invkind) {
1439 case INVOKE_FUNC: MESSAGE("func");break;
1440 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1441 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1442 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1443 }
1444 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1445 switch (funcdesc->callconv) {
1446 case CC_CDECL: MESSAGE("cdecl");break;
1447 case CC_PASCAL: MESSAGE("pascal");break;
1448 case CC_STDCALL: MESSAGE("stdcall");break;
1449 case CC_SYSCALL: MESSAGE("syscall");break;
1450 default:break;
1451 }
1452 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1453 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1454 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1455
1456 MESSAGE("\telemdescFunc (return value type):\n");
1457 dump_ELEMDESC(&funcdesc->elemdescFunc);
1458}
1459
1460static const char * const typekind_desc[] =
1461{
1462 "TKIND_ENUM",
1463 "TKIND_RECORD",
1464 "TKIND_MODULE",
1465 "TKIND_INTERFACE",
1466 "TKIND_DISPATCH",
1467 "TKIND_COCLASS",
1468 "TKIND_ALIAS",
1469 "TKIND_UNION",
1470 "TKIND_MAX"
1471};
1472
1474{
1475 int i;
1476 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1477 for (i=0;i<pfd->funcdesc.cParams;i++)
1478 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1479
1480
1481 dump_FUNCDESC(&(pfd->funcdesc));
1482
1483 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1484 if(pfd->Entry == NULL)
1485 MESSAGE("\tentry: (null)\n");
1486 else if(pfd->Entry == (void*)-1)
1487 MESSAGE("\tentry: invalid\n");
1488 else if(IS_INTRESOURCE(pfd->Entry))
1489 MESSAGE("\tentry: %p\n", pfd->Entry);
1490 else
1491 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1492}
1494{
1495 while (n)
1496 {
1498 ++pfd;
1499 --n;
1500 }
1501}
1502static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1503{
1504 while (n)
1505 {
1506 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1507 ++pvd;
1508 --n;
1509 }
1510}
1511
1512static void dump_TLBImpLib(const TLBImpLib *import)
1513{
1514 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1515 debugstr_w(import->name));
1516 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1517 import->wVersionMinor, import->lcid, import->offset);
1518}
1519
1520static void dump_TLBRefType(const ITypeLibImpl *pTL)
1521{
1522 TLBRefType *ref;
1523
1525 {
1526 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1527 if(ref->index == -1)
1529 else
1530 TRACE_(typelib)("type no: %d\n", ref->index);
1531
1532 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1533 {
1534 TRACE_(typelib)("in lib\n");
1535 dump_TLBImpLib(ref->pImpTLInfo);
1536 }
1537 }
1538}
1539
1540static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1541{
1542 if(!impl)
1543 return;
1544 while (n) {
1545 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1546 impl->hRef, impl->implflags);
1547 ++impl;
1548 --n;
1549 }
1550}
1551
1552static void dump_DispParms(const DISPPARAMS * pdp)
1553{
1554 unsigned int index;
1555
1556 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1557
1558 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1559 {
1560 TRACE("named args:\n");
1561 for (index = 0; index < pdp->cNamedArgs; index++)
1562 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1563 }
1564
1565 if (pdp->cArgs && pdp->rgvarg)
1566 {
1567 TRACE("args:\n");
1568 for (index = 0; index < pdp->cArgs; index++)
1569 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1570 }
1571}
1572
1573static void dump_TypeInfo(const ITypeInfoImpl * pty)
1574{
1575 TRACE("%p ref=%u\n", pty, pty->ref);
1577 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1578 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1579 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1580 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1581 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1582 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1583 if (TRACE_ON(ole))
1584 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1585 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1586 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1587}
1588
1589static void dump_VARDESC(const VARDESC *v)
1590{
1591 MESSAGE("memid %d\n",v->memid);
1592 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1593 MESSAGE("oInst %d\n",v->u.oInst);
1594 dump_ELEMDESC(&(v->elemdescVar));
1595 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1596 MESSAGE("varkind %d\n",v->varkind);
1597}
1598
1599static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1600{
1601 /* VT_LPWSTR is largest type that, may appear in type description */
1602 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1603 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1604 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1605 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1606 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1607 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1608 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1609 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1610};
1611
1612static void TLB_abort(void)
1613{
1614 DebugBreak();
1615}
1616
1617/* returns the size required for a deep copy of a typedesc into a
1618 * flat buffer */
1619static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1620{
1621 SIZE_T size = 0;
1622
1623 if (alloc_initial_space)
1624 size += sizeof(TYPEDESC);
1625
1626 switch (tdesc->vt)
1627 {
1628 case VT_PTR:
1629 case VT_SAFEARRAY:
1630 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1631 break;
1632 case VT_CARRAY:
1633 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1634 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1635 break;
1636 }
1637 return size;
1638}
1639
1640/* deep copy a typedesc into a flat buffer */
1641static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1642{
1643 if (!dest)
1644 {
1645 dest = buffer;
1646 buffer = (char *)buffer + sizeof(TYPEDESC);
1647 }
1648
1649 *dest = *src;
1650
1651 switch (src->vt)
1652 {
1653 case VT_PTR:
1654 case VT_SAFEARRAY:
1655 dest->u.lptdesc = buffer;
1656 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1657 break;
1658 case VT_CARRAY:
1659 dest->u.lpadesc = buffer;
1660 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1661 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1662 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1663 break;
1664 }
1665 return buffer;
1666}
1667
1668/* free custom data allocated by MSFT_CustData */
1669static inline void TLB_FreeCustData(struct list *custdata_list)
1670{
1671 TLBCustData *cd, *cdn;
1672 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1673 {
1674 list_remove(&cd->entry);
1675 VariantClear(&cd->data);
1676 heap_free(cd);
1677 }
1678}
1679
1680static BSTR TLB_MultiByteToBSTR(const char *ptr)
1681{
1682 DWORD len;
1683 BSTR ret;
1684
1685 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1686 ret = SysAllocStringLen(NULL, len - 1);
1687 if (!ret) return ret;
1689 return ret;
1690}
1691
1693 UINT n, MEMBERID memid)
1694{
1695 while(n){
1696 if(funcdescs->funcdesc.memid == memid)
1697 return funcdescs;
1698 ++funcdescs;
1699 --n;
1700 }
1701 return NULL;
1702}
1703
1705 UINT n, MEMBERID memid)
1706{
1707 while(n){
1708 if(vardescs->vardesc.memid == memid)
1709 return vardescs;
1710 ++vardescs;
1711 --n;
1712 }
1713 return NULL;
1714}
1715
1717 UINT n, const OLECHAR *name)
1718{
1719 while(n){
1720 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1721 return vardescs;
1722 ++vardescs;
1723 --n;
1724 }
1725 return NULL;
1726}
1727
1728static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1729{
1730 TLBCustData *cust_data;
1731 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1732 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1733 return cust_data;
1734 return NULL;
1735}
1736
1738 UINT n, const OLECHAR *name)
1739{
1740 while(n){
1741 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1742 return *typeinfos;
1743 ++typeinfos;
1744 --n;
1745 }
1746 return NULL;
1747}
1748
1750{
1751 list_init(&var_desc->custdata_list);
1752}
1753
1755{
1756 TLBVarDesc *ret;
1757
1758 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1759 if(!ret)
1760 return NULL;
1761
1762 while(n){
1764 --n;
1765 }
1766
1767 return ret;
1768}
1769
1771{
1772 TLBParDesc *ret;
1773
1774 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1775 if(!ret)
1776 return NULL;
1777
1778 while(n){
1779 list_init(&ret[n-1].custdata_list);
1780 --n;
1781 }
1782
1783 return ret;
1784}
1785
1787{
1788 list_init(&func_desc->custdata_list);
1789}
1790
1792{
1794
1795 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1796 if(!ret)
1797 return NULL;
1798
1799 while(n){
1801 --n;
1802 }
1803
1804 return ret;
1805}
1806
1808{
1809 list_init(&impl->custdata_list);
1810}
1811
1813{
1815
1816 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1817 if(!ret)
1818 return NULL;
1819
1820 while(n){
1822 --n;
1823 }
1824
1825 return ret;
1826}
1827
1829 const GUID *new_guid, HREFTYPE hreftype)
1830{
1831 TLBGuid *guid;
1832
1834 if (IsEqualGUID(&guid->guid, new_guid))
1835 return guid;
1836 }
1837
1838 guid = heap_alloc(sizeof(TLBGuid));
1839 if (!guid)
1840 return NULL;
1841
1842 memcpy(&guid->guid, new_guid, sizeof(GUID));
1843 guid->hreftype = hreftype;
1844
1845 list_add_tail(guid_list, &guid->entry);
1846
1847 return guid;
1848}
1849
1850static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1851{
1852 TLBCustData *cust_data;
1853
1854 switch(V_VT(var)){
1855 case VT_I4:
1856 case VT_R4:
1857 case VT_UI4:
1858 case VT_INT:
1859 case VT_UINT:
1860 case VT_HRESULT:
1861 case VT_BSTR:
1862 break;
1863 default:
1864 return DISP_E_BADVARTYPE;
1865 }
1866
1867 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1868
1869 if (!cust_data) {
1870 cust_data = heap_alloc(sizeof(TLBCustData));
1871 if (!cust_data)
1872 return E_OUTOFMEMORY;
1873
1874 cust_data->guid = tlbguid;
1875 VariantInit(&cust_data->data);
1876
1877 list_add_tail(custdata_list, &cust_data->entry);
1878 }else
1879 VariantClear(&cust_data->data);
1880
1881 return VariantCopy(&cust_data->data, var);
1882}
1883
1885{
1886 TLBString *str;
1887
1888 if(!new_str)
1889 return NULL;
1890
1892 if (wcscmp(str->str, new_str) == 0)
1893 return str;
1894 }
1895
1896 str = heap_alloc(sizeof(TLBString));
1897 if (!str)
1898 return NULL;
1899
1900 str->str = SysAllocString(new_str);
1901 if (!str->str) {
1902 heap_free(str);
1903 return NULL;
1904 }
1905
1906 list_add_tail(string_list, &str->entry);
1907
1908 return str;
1909}
1910
1912 ULONG *size, WORD *align)
1913{
1915 TYPEATTR *attr;
1916 HRESULT hr;
1917
1918 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1919 if(FAILED(hr))
1920 return hr;
1921
1922 hr = ITypeInfo_GetTypeAttr(other, &attr);
1923 if(FAILED(hr)){
1924 ITypeInfo_Release(other);
1925 return hr;
1926 }
1927
1928 if(size)
1929 *size = attr->cbSizeInstance;
1930 if(align)
1931 *align = attr->cbAlignment;
1932
1933 ITypeInfo_ReleaseTypeAttr(other, attr);
1934 ITypeInfo_Release(other);
1935
1936 return S_OK;
1937}
1938
1940 TYPEDESC *tdesc, ULONG *size, WORD *align)
1941{
1942 ULONG i, sub, ptr_size;
1943 HRESULT hr;
1944
1945 ptr_size = get_ptr_size(sys);
1946
1947 switch(tdesc->vt){
1948 case VT_VOID:
1949 *size = 0;
1950 break;
1951 case VT_I1:
1952 case VT_UI1:
1953 *size = 1;
1954 break;
1955 case VT_I2:
1956 case VT_BOOL:
1957 case VT_UI2:
1958 *size = 2;
1959 break;
1960 case VT_I4:
1961 case VT_R4:
1962 case VT_ERROR:
1963 case VT_UI4:
1964 case VT_INT:
1965 case VT_UINT:
1966 case VT_HRESULT:
1967 *size = 4;
1968 break;
1969 case VT_R8:
1970 case VT_I8:
1971 case VT_UI8:
1972 *size = 8;
1973 break;
1974 case VT_BSTR:
1975 case VT_DISPATCH:
1976 case VT_UNKNOWN:
1977 case VT_PTR:
1978 case VT_SAFEARRAY:
1979 case VT_LPSTR:
1980 case VT_LPWSTR:
1981 *size = ptr_size;
1982 break;
1983 case VT_DATE:
1984 *size = sizeof(DATE);
1985 break;
1986 case VT_VARIANT:
1987 *size = sizeof(VARIANT);
1988#ifdef _WIN64
1989 if(sys == SYS_WIN32)
1990 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1991#endif
1992 break;
1993 case VT_DECIMAL:
1994 *size = sizeof(DECIMAL);
1995 break;
1996 case VT_CY:
1997 *size = sizeof(CY);
1998 break;
1999 case VT_CARRAY:
2000 *size = 0;
2001 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2002 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2003 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2004 if(FAILED(hr))
2005 return hr;
2006 *size *= sub;
2007 return S_OK;
2008 case VT_USERDEFINED:
2009 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2010 default:
2011 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2012 return E_FAIL;
2013 }
2014
2015 if(align){
2016 if(*size < 4)
2017 *align = *size;
2018 else
2019 *align = 4;
2020 }
2021
2022 return S_OK;
2023}
2024
2025/**********************************************************************
2026 *
2027 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2028 */
2029
2030static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2031{
2032 if (where != DO_NOT_SEEK)
2033 {
2034 where += pcx->oStart;
2035 if (where > pcx->length)
2036 {
2037 /* FIXME */
2038 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2039 TLB_abort();
2040 }
2041 pcx->pos = where;
2042 }
2043}
2044
2045/* read function */
2046static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2047{
2048 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2049 pcx->pos, count, pcx->oStart, pcx->length, where);
2050
2051 MSFT_Seek(pcx, where);
2052 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2053 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2054 pcx->pos += count;
2055 return count;
2056}
2057
2059 LONG where )
2060{
2061 DWORD ret;
2062
2063 ret = MSFT_Read(buffer, count, pcx, where);
2065
2066 return ret;
2067}
2068
2070 LONG where )
2071{
2072 DWORD ret;
2073
2074 ret = MSFT_Read(buffer, count, pcx, where);
2076
2077 return ret;
2078}
2079
2081{
2082 TLBGuid *guid;
2084 int offs = 0;
2085
2086 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2087 while (1) {
2088 if (offs >= pcx->pTblDir->pGuidTab.length)
2089 return S_OK;
2090
2092
2093 guid = heap_alloc(sizeof(TLBGuid));
2094
2095 guid->offset = offs;
2096 guid->guid = entry.guid;
2097 guid->hreftype = entry.hreftype;
2098
2099 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2100
2101 offs += sizeof(MSFT_GuidEntry);
2102 }
2103}
2104
2106{
2107 TLBGuid *ret;
2108
2110 if(ret->offset == offset){
2111 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2112 return ret;
2113 }
2114 }
2115
2116 return NULL;
2117}
2118
2119static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2120{
2121 MSFT_NameIntro niName;
2122
2123 if (offset < 0)
2124 {
2125 ERR_(typelib)("bad offset %d\n", offset);
2126 return -1;
2127 }
2128
2129 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2131
2132 return niName.hreftype;
2133}
2134
2136{
2137 char *string;
2138 MSFT_NameIntro intro;
2139 INT16 len_piece;
2140 int offs = 0, lengthInChars;
2141
2142 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2143 while (1) {
2144 TLBString *tlbstr;
2145
2146 if (offs >= pcx->pTblDir->pNametab.length)
2147 return S_OK;
2148
2149 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2150 intro.namelen &= 0xFF;
2151 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2152 if(len_piece % 4)
2153 len_piece = (len_piece + 4) & ~0x3;
2154 if(len_piece < 8)
2155 len_piece = 8;
2156
2157 string = heap_alloc(len_piece + 1);
2158 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2159 string[intro.namelen] = '\0';
2160
2162 string, -1, NULL, 0);
2163 if (!lengthInChars) {
2164 heap_free(string);
2165 return E_UNEXPECTED;
2166 }
2167
2168 tlbstr = heap_alloc(sizeof(TLBString));
2169
2170 tlbstr->offset = offs;
2171 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2172 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2173
2174 heap_free(string);
2175
2176 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2177
2178 offs += len_piece;
2179 }
2180}
2181
2183{
2184 TLBString *tlbstr;
2185
2187 if (tlbstr->offset == offset) {
2188 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2189 return tlbstr;
2190 }
2191 }
2192
2193 return NULL;
2194}
2195
2197{
2198 TLBString *tlbstr;
2199
2201 if (tlbstr->offset == offset) {
2202 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2203 return tlbstr;
2204 }
2205 }
2206
2207 return NULL;
2208}
2209
2210/*
2211 * read a value and fill a VARIANT structure
2212 */
2213static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2214{
2215 int size;
2216
2217 TRACE_(typelib)("\n");
2218
2219 if(offset <0) { /* data are packed in here */
2220 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2221 V_I4(pVar) = offset & 0x3ffffff;
2222 return;
2223 }
2224 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2225 pcx->pTblDir->pCustData.offset + offset );
2226 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2227 switch (V_VT(pVar)){
2228 case VT_EMPTY: /* FIXME: is this right? */
2229 case VT_NULL: /* FIXME: is this right? */
2230 case VT_I2 : /* this should not happen */
2231 case VT_I4 :
2232 case VT_R4 :
2233 case VT_ERROR :
2234 case VT_BOOL :
2235 case VT_I1 :
2236 case VT_UI1 :
2237 case VT_UI2 :
2238 case VT_UI4 :
2239 case VT_INT :
2240 case VT_UINT :
2241 case VT_VOID : /* FIXME: is this right? */
2242 case VT_HRESULT :
2243 size=4; break;
2244 case VT_R8 :
2245 case VT_CY :
2246 case VT_DATE :
2247 case VT_I8 :
2248 case VT_UI8 :
2249 case VT_DECIMAL : /* FIXME: is this right? */
2250 case VT_FILETIME :
2251 size=8;break;
2252 /* pointer types with known behaviour */
2253 case VT_BSTR :{
2254 char * ptr;
2255 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2256 if(size == -1){
2257 V_BSTR(pVar) = NULL;
2258 }else{
2259 ptr = heap_alloc_zero(size);
2260 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2262 /* FIXME: do we need a AtoW conversion here? */
2263 V_UNION(pVar, bstrVal[size])='\0';
2264 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2265 heap_free(ptr);
2266 }
2267 }
2268 size=-4; break;
2269 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2270 case VT_DISPATCH :
2271 case VT_VARIANT :
2272 case VT_UNKNOWN :
2273 case VT_PTR :
2274 case VT_SAFEARRAY :
2275 case VT_CARRAY :
2276 case VT_USERDEFINED :
2277 case VT_LPSTR :
2278 case VT_LPWSTR :
2279 case VT_BLOB :
2280 case VT_STREAM :
2281 case VT_STORAGE :
2282 case VT_STREAMED_OBJECT :
2283 case VT_STORED_OBJECT :
2284 case VT_BLOB_OBJECT :
2285 case VT_CF :
2286 case VT_CLSID :
2287 default:
2288 size=0;
2289 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2290 V_VT(pVar));
2291 }
2292
2293 if(size>0) /* (big|small) endian correct? */
2294 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2295 return;
2296}
2297/*
2298 * create a linked list with custom data
2299 */
2300static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2301{
2303 TLBCustData* pNew;
2304 int count=0;
2305
2306 TRACE_(typelib)("\n");
2307
2308 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2309
2310 while(offset >=0){
2311 count++;
2312 pNew=heap_alloc_zero(sizeof(TLBCustData));
2313 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2314 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2315 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2316 list_add_head(custdata_list, &pNew->entry);
2317 offset = entry.next;
2318 }
2319 return count;
2320}
2321
2322static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2323{
2324 if(type <0)
2325 pTd->vt=type & VT_TYPEMASK;
2326 else
2327 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2328
2329 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2330}
2331
2332static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2333{
2334 return (invkind == INVOKE_PROPERTYGET ||
2335 invkind == INVOKE_PROPERTYPUT ||
2336 invkind == INVOKE_PROPERTYPUTREF);
2337}
2338
2339static void
2341 ITypeInfoImpl* pTI,
2342 int cFuncs,
2343 int cVars,
2344 int offset,
2345 TLBFuncDesc** pptfd)
2346{
2347 /*
2348 * member information is stored in a data structure at offset
2349 * indicated by the memoffset field of the typeinfo structure
2350 * There are several distinctive parts.
2351 * The first part starts with a field that holds the total length
2352 * of this (first) part excluding this field. Then follow the records,
2353 * for each member there is one record.
2354 *
2355 * The first entry is always the length of the record (including this
2356 * length word).
2357 * The rest of the record depends on the type of the member. If there is
2358 * a field indicating the member type (function, variable, interface, etc)
2359 * I have not found it yet. At this time we depend on the information
2360 * in the type info and the usual order how things are stored.
2361 *
2362 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2363 * for each member;
2364 *
2365 * Third is an equal sized array with file offsets to the name entry
2366 * of each member.
2367 *
2368 * The fourth and last (?) part is an array with offsets to the records
2369 * in the first part of this file segment.
2370 */
2371
2372 int infolen, nameoffset, reclength, i;
2373 int recoffset = offset + sizeof(INT);
2374
2375 char *recbuf = heap_alloc(0xffff);
2376 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2377 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2378
2379 TRACE_(typelib)("\n");
2380
2381 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2382
2383 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2384 ptfd = *pptfd;
2385 for ( i = 0; i < cFuncs ; i++ )
2386 {
2387 int optional;
2388
2389 /* name, eventually add to a hash table */
2390 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2391 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2392
2393 /* read the function information record */
2394 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2395
2396 reclength &= 0xffff;
2397
2399
2400 /* size without argument data */
2401 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2402 if (pFuncRec->FKCCIC & 0x1000)
2403 optional -= pFuncRec->nrargs * sizeof(INT);
2404
2406 ptfd->helpcontext = pFuncRec->HelpContext;
2407
2408 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2409 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2410
2411 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2412 {
2413 if (pFuncRec->FKCCIC & 0x2000 )
2414 {
2415 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2416 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2417 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2418 }
2419 else
2420 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2421 }
2422 else
2423 ptfd->Entry = (TLBString*)-1;
2424
2425 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2426 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2427
2428 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2429 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2430
2431 /* fill the FuncDesc Structure */
2432 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2433 offset + infolen + ( i + 1) * sizeof(INT));
2434
2435 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2436 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2437 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2438 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2439 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2440 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2441 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2442
2443 /* nameoffset is sometimes -1 on the second half of a propget/propput
2444 * pair of functions */
2445 if ((nameoffset == -1) && (i > 0) &&
2446 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2447 TLB_is_propgetput(ptfd->funcdesc.invkind))
2448 ptfd->Name = ptfd_prev->Name;
2449 else
2450 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2451
2452 MSFT_GetTdesc(pcx,
2453 pFuncRec->DataType,
2454 &ptfd->funcdesc.elemdescFunc.tdesc);
2455
2456 /* do the parameters/arguments */
2457 if(pFuncRec->nrargs)
2458 {
2459 int j = 0;
2460 MSFT_ParameterInfo paraminfo;
2461
2462 ptfd->funcdesc.lprgelemdescParam =
2463 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2464
2465 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2466
2467 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2468 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2469
2470 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2471 {
2472 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2473
2474 MSFT_GetTdesc(pcx,
2475 paraminfo.DataType,
2476 &elemdesc->tdesc);
2477
2478 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2479
2480 /* name */
2481 if (paraminfo.oName != -1)
2482 ptfd->pParamDesc[j].Name =
2483 MSFT_ReadName( pcx, paraminfo.oName );
2484 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2485
2486 /* default value */
2487 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2488 (pFuncRec->FKCCIC & 0x1000) )
2489 {
2490 INT* pInt = (INT *)((char *)pFuncRec +
2491 reclength -
2492 (pFuncRec->nrargs * 4) * sizeof(INT) );
2493
2494 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2495
2496 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2497 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2498
2499 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2500 pInt[j], pcx);
2501 }
2502 else
2503 elemdesc->u.paramdesc.pparamdescex = NULL;
2504
2505 /* custom info */
2506 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2507 j*sizeof(pFuncRec->oArgCustData[0])) &&
2508 pFuncRec->FKCCIC & 0x80 )
2509 {
2510 MSFT_CustData(pcx,
2511 pFuncRec->oArgCustData[j],
2512 &ptfd->pParamDesc[j].custdata_list);
2513 }
2514
2515 /* SEEK value = jump to offset,
2516 * from there jump to the end of record,
2517 * go back by (j-1) arguments
2518 */
2519 MSFT_ReadLEDWords( &paraminfo ,
2520 sizeof(MSFT_ParameterInfo), pcx,
2521 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2522 * sizeof(MSFT_ParameterInfo)));
2523 }
2524 }
2525
2526 /* scode is not used: archaic win16 stuff FIXME: right? */
2527 ptfd->funcdesc.cScodes = 0 ;
2528 ptfd->funcdesc.lprgscode = NULL ;
2529
2530 ptfd_prev = ptfd;
2531 ++ptfd;
2532 recoffset += reclength;
2533 }
2534 heap_free(recbuf);
2535}
2536
2537static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2538 int cVars, int offset, TLBVarDesc ** pptvd)
2539{
2540 int infolen, nameoffset, reclength;
2541 char recbuf[256];
2542 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2543 TLBVarDesc *ptvd;
2544 int i;
2545 int recoffset;
2546
2547 TRACE_(typelib)("\n");
2548
2549 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2550 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2551 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2552 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2553 recoffset += offset+sizeof(INT);
2554 for(i=0;i<cVars;i++, ++ptvd){
2555 /* name, eventually add to a hash table */
2556 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2557 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2558 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2559 /* read the variable information record */
2560 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2561 reclength &= 0xff;
2563
2564 /* optional data */
2565 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2566 ptvd->HelpContext = pVarRec->HelpContext;
2567
2568 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2569 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2570
2571 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2572 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2573
2574 /* fill the VarDesc Structure */
2575 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2576 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2577 ptvd->vardesc.varkind = pVarRec->VarKind;
2578 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2579 MSFT_GetTdesc(pcx, pVarRec->DataType,
2580 &ptvd->vardesc.elemdescVar.tdesc);
2581/* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2582 if(pVarRec->VarKind == VAR_CONST ){
2583 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2584 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2585 pVarRec->OffsValue, pcx);
2586 } else
2587 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2588 recoffset += reclength;
2589 }
2590}
2591
2592/* process Implemented Interfaces of a com class */
2594 int offset)
2595{
2596 int i;
2597 MSFT_RefRecord refrec;
2598 TLBImplType *pImpl;
2599
2600 TRACE_(typelib)("\n");
2601
2603 pImpl = pTI->impltypes;
2604 for(i=0;i<count;i++){
2605 if(offset<0) break; /* paranoia */
2606 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2607 pImpl->hRef = refrec.reftype;
2608 pImpl->implflags=refrec.flags;
2609 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2610 offset=refrec.onext;
2611 ++pImpl;
2612 }
2613}
2614
2615#ifdef _WIN64
2616/* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2617 * and some structures, and fix the alignment */
2618static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2619{
2620 if(info->typeattr.typekind == TKIND_ALIAS){
2621 switch(info->tdescAlias->vt){
2622 case VT_BSTR:
2623 case VT_DISPATCH:
2624 case VT_UNKNOWN:
2625 case VT_PTR:
2626 case VT_SAFEARRAY:
2627 case VT_LPSTR:
2628 case VT_LPWSTR:
2629 info->typeattr.cbSizeInstance = sizeof(void*);
2630 info->typeattr.cbAlignment = sizeof(void*);
2631 break;
2632 case VT_CARRAY:
2633 case VT_USERDEFINED:
2634 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2635 break;
2636 case VT_VARIANT:
2637 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2638 info->typeattr.cbAlignment = 8;
2639 default:
2640 if(info->typeattr.cbSizeInstance < sizeof(void*))
2641 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2642 else
2643 info->typeattr.cbAlignment = sizeof(void*);
2644 break;
2645 }
2646 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2647 info->typeattr.typekind == TKIND_DISPATCH ||
2648 info->typeattr.typekind == TKIND_COCLASS){
2649 info->typeattr.cbSizeInstance = sizeof(void*);
2650 info->typeattr.cbAlignment = sizeof(void*);
2651 }
2652}
2653#endif
2654
2655/*
2656 * process a typeinfo record
2657 */
2659 TLBContext *pcx,
2660 int count,
2661 ITypeLibImpl * pLibInfo)
2662{
2663 MSFT_TypeInfoBase tiBase;
2664 ITypeInfoImpl *ptiRet;
2665
2666 TRACE_(typelib)("count=%u\n", count);
2667
2668 ptiRet = ITypeInfoImpl_Constructor();
2669 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2670 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2671
2672/* this is where we are coming from */
2673 ptiRet->pTypeLib = pLibInfo;
2674 ptiRet->index=count;
2675
2676 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2677 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2678 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2679 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2680 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2681 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2682 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2683 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2684 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2685 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2686 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2687 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2688 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2689 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2690 TYPEDESC tmp;
2691 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2692 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2693 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2694 }
2695
2696/* FIXME: */
2697/* IDLDESC idldescType; *//* never saw this one != zero */
2698
2699/* name, eventually add to a hash table */
2700 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2701 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2702 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2703 /* help info */
2704 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2706 ptiRet->dwHelpContext=tiBase.helpcontext;
2707
2708 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2709 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2710
2711/* note: InfoType's Help file and HelpStringDll come from the containing
2712 * library. Further HelpString and Docstring appear to be the same thing :(
2713 */
2714 /* functions */
2715 if(ptiRet->typeattr.cFuncs >0 )
2716 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2717 ptiRet->typeattr.cVars,
2718 tiBase.memoffset, &ptiRet->funcdescs);
2719 /* variables */
2720 if(ptiRet->typeattr.cVars >0 )
2721 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2722 ptiRet->typeattr.cVars,
2723 tiBase.memoffset, &ptiRet->vardescs);
2724 if(ptiRet->typeattr.cImplTypes >0 ) {
2725 switch(ptiRet->typeattr.typekind)
2726 {
2727 case TKIND_COCLASS:
2728 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2729 tiBase.datatype1);
2730 break;
2731 case TKIND_DISPATCH:
2732 /* This is not -1 when the interface is a non-base dual interface or
2733 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2734 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2735 not this interface.
2736 */
2737
2738 if (tiBase.datatype1 != -1)
2739 {
2740 ptiRet->impltypes = TLBImplType_Alloc(1);
2741 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2742 }
2743 break;
2744 default:
2745 ptiRet->impltypes = TLBImplType_Alloc(1);
2746 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2747 break;
2748 }
2749 }
2750 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2751
2752 TRACE_(typelib)("%s guid: %s kind:%s\n",
2753 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2755 typekind_desc[ptiRet->typeattr.typekind]);
2756 if (TRACE_ON(typelib))
2757 dump_TypeInfo(ptiRet);
2758
2759 return ptiRet;
2760}
2761
2763{
2764 char *string;
2765 INT16 len_str, len_piece;
2766 int offs = 0, lengthInChars;
2767
2768 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2769 while (1) {
2770 TLBString *tlbstr;
2771
2772 if (offs >= pcx->pTblDir->pStringtab.length)
2773 return S_OK;
2774
2775 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2776 len_piece = len_str + sizeof(INT16);
2777 if(len_piece % 4)
2778 len_piece = (len_piece + 4) & ~0x3;
2779 if(len_piece < 8)
2780 len_piece = 8;
2781
2782 string = heap_alloc(len_piece + 1);
2783 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2784 string[len_str] = '\0';
2785
2787 string, -1, NULL, 0);
2788 if (!lengthInChars) {
2789 heap_free(string);
2790 return E_UNEXPECTED;
2791 }
2792
2793 tlbstr = heap_alloc(sizeof(TLBString));
2794
2795 tlbstr->offset = offs;
2796 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2797 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2798
2799 heap_free(string);
2800
2801 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2802
2803 offs += len_piece;
2804 }
2805}
2806
2808{
2809 TLBRefType *ref;
2810 int offs = 0;
2811
2812 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2813 while (offs < pcx->pTblDir->pImpInfo.length) {
2814 MSFT_ImpInfo impinfo;
2815 TLBImpLib *pImpLib;
2816
2817 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2818
2819 ref = heap_alloc_zero(sizeof(TLBRefType));
2820 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2821
2823 if(pImpLib->offset==impinfo.oImpFile)
2824 break;
2825
2826 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2827 ref->reference = offs;
2828 ref->pImpTLInfo = pImpLib;
2829 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2830 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2831 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2832 ref->index = TLB_REF_USE_GUID;
2833 } else
2834 ref->index = impinfo.oGuid;
2835 }else{
2836 ERR("Cannot find a reference\n");
2837 ref->reference = -1;
2838 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2839 }
2840
2841 offs += sizeof(impinfo);
2842 }
2843
2844 return S_OK;
2845}
2846
2847/* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2848 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2849 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2850 * tradeoff here.
2851 */
2855{
2856 0, 0, &cache_section,
2858 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2859};
2860static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2861
2862
2863typedef struct TLB_PEFile
2864{
2872
2874{
2875 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2876}
2877
2879{
2881 {
2882 *ppv = iface;
2883 IUnknown_AddRef(iface);
2884 return S_OK;
2885 }
2886 *ppv = NULL;
2887 return E_NOINTERFACE;
2888}
2889
2891{
2893 return InterlockedIncrement(&This->refs);
2894}
2895
2897{
2899 ULONG refs = InterlockedDecrement(&This->refs);
2900 if (!refs)
2901 {
2902 if (This->typelib_global)
2903 FreeResource(This->typelib_global);
2904 if (This->dll)
2905 FreeLibrary(This->dll);
2906 heap_free(This);
2907 }
2908 return refs;
2909}
2910
2911static const IUnknownVtbl TLB_PEFile_Vtable =
2912{
2916};
2917
2918static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2919{
2922
2923 This = heap_alloc(sizeof(TLB_PEFile));
2924 if (!This)
2925 return E_OUTOFMEMORY;
2926
2927 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2928 This->refs = 1;
2929 This->dll = NULL;
2930 This->typelib_resource = NULL;
2931 This->typelib_global = NULL;
2932 This->typelib_base = NULL;
2933
2936
2937 if (This->dll)
2938 {
2939 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2940 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2941 if (This->typelib_resource)
2942 {
2943 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2944 if (This->typelib_global)
2945 {
2946 This->typelib_base = LockResource(This->typelib_global);
2947
2948 if (This->typelib_base)
2949 {
2950 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2951 *ppBase = This->typelib_base;
2952 *ppFile = &This->IUnknown_iface;
2953 return S_OK;
2954 }
2955 }
2956 }
2957
2958 TRACE("No TYPELIB resource found\n");
2959 hr = E_FAIL;
2960 }
2961
2962 TLB_PEFile_Release(&This->IUnknown_iface);
2963 return hr;
2964}
2965
2966typedef struct TLB_NEFile
2967{
2972
2974{
2975 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2976}
2977
2979{
2981 {
2982 *ppv = iface;
2983 IUnknown_AddRef(iface);
2984 return S_OK;
2985 }
2986 *ppv = NULL;
2987 return E_NOINTERFACE;
2988}
2989
2991{
2993 return InterlockedIncrement(&This->refs);
2994}
2995
2997{
2999 ULONG refs = InterlockedDecrement(&This->refs);
3000 if (!refs)
3001 {
3002 heap_free(This->typelib_base);
3003 heap_free(This);
3004 }
3005 return refs;
3006}
3007
3008static const IUnknownVtbl TLB_NEFile_Vtable =
3009{
3013};
3014
3015/***********************************************************************
3016 * read_xx_header [internal]
3017 */
3018static int read_xx_header( HFILE lzfd )
3019{
3020 IMAGE_DOS_HEADER mzh;
3021 char magic[3];
3022
3023 LZSeek( lzfd, 0, SEEK_SET );
3024 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3025 return 0;
3026 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3027 return 0;
3028
3029 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3030 if ( 2 != LZRead( lzfd, magic, 2 ) )
3031 return 0;
3032
3033 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3034
3035 if ( magic[0] == 'N' && magic[1] == 'E' )
3036 return IMAGE_OS2_SIGNATURE;
3037 if ( magic[0] == 'P' && magic[1] == 'E' )
3038 return IMAGE_NT_SIGNATURE;
3039
3040 magic[2] = '\0';
3041 WARN("Can't handle %s files.\n", magic );
3042 return 0;
3043}
3044
3045
3046/***********************************************************************
3047 * find_ne_resource [internal]
3048 */
3049static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3050 DWORD *resLen, DWORD *resOff )
3051{
3052 IMAGE_OS2_HEADER nehd;
3053 NE_TYPEINFO *typeInfo;
3054 NE_NAMEINFO *nameInfo;
3055 DWORD nehdoffset;
3056 LPBYTE resTab;
3057 DWORD resTabSize;
3058 int count;
3059
3060 /* Read in NE header */
3061 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3062 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3063
3064 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3065 if ( !resTabSize )
3066 {
3067 TRACE("No resources in NE dll\n" );
3068 return FALSE;
3069 }
3070
3071 /* Read in resource table */
3072 resTab = heap_alloc( resTabSize );
3073 if ( !resTab ) return FALSE;
3074
3075 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3076 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3077 {
3078 heap_free( resTab );
3079 return FALSE;
3080 }
3081
3082 /* Find resource */
3083 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3084
3085 if (!IS_INTRESOURCE(typeid)) /* named type */
3086 {
3087 BYTE len = strlen( typeid );
3088 while (typeInfo->type_id)
3089 {
3090 if (!(typeInfo->type_id & 0x8000))
3091 {
3092 BYTE *p = resTab + typeInfo->type_id;
3093 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3094 }
3095 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3096 typeInfo->count * sizeof(NE_NAMEINFO));
3097 }
3098 }
3099 else /* numeric type id */
3100 {
3101 WORD id = LOWORD(typeid) | 0x8000;
3102 while (typeInfo->type_id)
3103 {
3104 if (typeInfo->type_id == id) goto found_type;
3105 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3106 typeInfo->count * sizeof(NE_NAMEINFO));
3107 }
3108 }
3109 TRACE("No typeid entry found for %p\n", typeid );
3110 heap_free( resTab );
3111 return FALSE;
3112
3113 found_type:
3114 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3115
3116 if (!IS_INTRESOURCE(resid)) /* named resource */
3117 {
3118 BYTE len = strlen( resid );
3119 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3120 {
3121 BYTE *p = resTab + nameInfo->id;
3122 if (nameInfo->id & 0x8000) continue;
3123 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3124 }
3125 }
3126 else /* numeric resource id */
3127 {
3128 WORD id = LOWORD(resid) | 0x8000;
3129 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3130 if (nameInfo->id == id) goto found_name;
3131 }
3132 TRACE("No resid entry found for %p\n", typeid );
3133 heap_free( resTab );
3134 return FALSE;
3135
3136 found_name:
3137 /* Return resource data */
3138 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3139 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3140
3141 heap_free( resTab );
3142 return TRUE;
3143}
3144
3145static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3146
3147 HFILE lzfd = -1;
3148 OFSTRUCT ofs;
3151
3152 This = heap_alloc(sizeof(TLB_NEFile));
3153 if (!This) return E_OUTOFMEMORY;
3154
3155 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3156 This->refs = 1;
3157 This->typelib_base = NULL;
3158
3159 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3160 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3161 {
3163 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3164 {
3165 This->typelib_base = heap_alloc(reslen);
3166 if( !This->typelib_base )
3167 hr = E_OUTOFMEMORY;
3168 else
3169 {
3170 LZSeek( lzfd, offset, SEEK_SET );
3171 reslen = LZRead( lzfd, This->typelib_base, reslen );
3172 LZClose( lzfd );
3173 *ppBase = This->typelib_base;
3174 *pdwTLBLength = reslen;
3175 *ppFile = &This->IUnknown_iface;
3176 return S_OK;
3177 }
3178 }
3179 }
3180
3181 if( lzfd >= 0) LZClose( lzfd );
3182 TLB_NEFile_Release(&This->IUnknown_iface);
3183 return hr;
3184}
3185
3186typedef struct TLB_Mapping
3187{
3194
3196{
3197 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3198}
3199
3201{
3203 {
3204 *ppv = iface;
3205 IUnknown_AddRef(iface);
3206 return S_OK;
3207 }
3208 *ppv = NULL;
3209 return E_NOINTERFACE;
3210}
3211
3213{
3215 return InterlockedIncrement(&This->refs);
3216}
3217
3219{
3221 ULONG refs = InterlockedDecrement(&This->refs);
3222 if (!refs)
3223 {
3224 if (This->typelib_base)
3225 UnmapViewOfFile(This->typelib_base);
3226 if (This->mapping)
3227 CloseHandle(This->mapping);
3228 if (This->file != INVALID_HANDLE_VALUE)
3229 CloseHandle(This->file);
3230 heap_free(This);
3231 }
3232 return refs;
3233}
3234
3235static const IUnknownVtbl TLB_Mapping_Vtable =
3236{
3240};
3241
3242static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3243{
3245
3246 This = heap_alloc(sizeof(TLB_Mapping));
3247 if (!This)
3248 return E_OUTOFMEMORY;
3249
3250 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3251 This->refs = 1;
3252 This->file = INVALID_HANDLE_VALUE;
3253 This->mapping = NULL;
3254 This->typelib_base = NULL;
3255
3257 if (INVALID_HANDLE_VALUE != This->file)
3258 {
3259 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3260 if (This->mapping)
3261 {
3262 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3263 if(This->typelib_base)
3264 {
3265 /* retrieve file size */
3266 *pdwTLBLength = GetFileSize(This->file, NULL);
3267 *ppBase = This->typelib_base;
3268 *ppFile = &This->IUnknown_iface;
3269 return S_OK;
3270 }
3271 }
3272 }
3273
3274 IUnknown_Release(&This->IUnknown_iface);
3276}
3277
3278/****************************************************************************
3279 * TLB_ReadTypeLib
3280 *
3281 * find the type of the typelib file and map the typelib resource into
3282 * the memory
3283 */
3284
3285#define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3286static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3287{
3289 HRESULT ret;
3290 INT index = 1;
3291 LPWSTR index_str, file = (LPWSTR)pszFileName;
3292 LPVOID pBase = NULL;
3293 DWORD dwTLBLength = 0;
3294 IUnknown *pFile = NULL;
3295 HANDLE h;
3296
3297 *ppTypeLib = NULL;
3298
3299 index_str = wcsrchr(pszFileName, '\\');
3300 if(index_str && *++index_str != '\0')
3301 {
3302 LPWSTR end_ptr;
3303 LONG idx = wcstol(index_str, &end_ptr, 10);
3304 if(*end_ptr == '\0')
3305 {
3306 int str_len = index_str - pszFileName - 1;
3307 index = idx;
3308 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3309 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3310 file[str_len] = 0;
3311 }
3312 }
3313
3314 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3315 {
3316 if(wcschr(file, '\\'))
3317 {
3318 lstrcpyW(pszPath, file);
3319 }
3320 else
3321 {
3322 int len = GetSystemDirectoryW(pszPath, cchPath);
3323 pszPath[len] = '\\';
3324 memcpy(pszPath + len + 1, file, (lstrlenW(file) + 1) * sizeof(WCHAR));
3325 }
3326 }
3327
3329
3331 if(h != INVALID_HANDLE_VALUE){
3332 FILE_NAME_INFORMATION size_info;
3333 BOOL br;
3334
3335 /* GetFileInformationByHandleEx returns the path of the file without
3336 * WOW64 redirection */
3337 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3338 if(br || GetLastError() == ERROR_MORE_DATA){
3340 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3341
3343
3344 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3345 if(br){
3346 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3347 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3348 }
3349
3351 }
3352
3353 CloseHandle(h);
3354 }
3355
3356 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3357
3358 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3361 {
3362 if (!wcsicmp(entry->path, pszPath) && entry->index == index)
3363 {
3364 TRACE("cache hit\n");
3365 *ppTypeLib = &entry->ITypeLib2_iface;
3366 ITypeLib2_AddRef(*ppTypeLib);
3368 return S_OK;
3369 }
3370 }
3372
3373 /* now actually load and parse the typelib */
3374
3375 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3377 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3379 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3380 if (SUCCEEDED(ret))
3381 {
3382 if (dwTLBLength >= 4)
3383 {
3384 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3385 if (dwSignature == MSFT_SIGNATURE)
3386 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3387 else if (dwSignature == SLTG_SIGNATURE)
3388 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3389 else
3390 {
3391 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3393 }
3394 }
3395 else
3397 IUnknown_Release(pFile);
3398 }
3399
3400 if(*ppTypeLib) {
3401 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3402
3403 TRACE("adding to cache\n");
3404 impl->path = heap_alloc((lstrlenW(pszPath)+1) * sizeof(WCHAR));
3405 lstrcpyW(impl->path, pszPath);
3406 /* We should really canonicalise the path here. */
3407 impl->index = index;
3408
3409 /* FIXME: check if it has added already in the meantime */
3411 list_add_head(&tlb_cache, &impl->entry);
3413 ret = S_OK;
3414 }
3415 else
3416 {
3417 if(ret != E_FAIL)
3418 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3419
3421 }
3422
3423
3424 return ret;
3425}
3426
3427/*================== ITypeLib(2) Methods ===================================*/
3428
3430{
3431 ITypeLibImpl* pTypeLibImpl;
3432
3433 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3434 if (!pTypeLibImpl) return NULL;
3435
3436 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3437 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3438 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3439 pTypeLibImpl->ref = 1;
3440
3441 list_init(&pTypeLibImpl->implib_list);
3442 list_init(&pTypeLibImpl->custdata_list);
3443 list_init(&pTypeLibImpl->name_list);
3444 list_init(&pTypeLibImpl->string_list);
3445 list_init(&pTypeLibImpl->guid_list);
3446 list_init(&pTypeLibImpl->ref_list);
3447 pTypeLibImpl->dispatch_href = -1;
3448
3449 return pTypeLibImpl;
3450}
3451
3452/****************************************************************************
3453 * ITypeLib2_Constructor_MSFT
3454 *
3455 * loading an MSFT typelib from an in-memory image
3456 */
3458{
3459 TLBContext cx;
3460 LONG lPSegDir;
3461 MSFT_Header tlbHeader;
3462 MSFT_SegDir tlbSegDir;
3463 ITypeLibImpl * pTypeLibImpl;
3464 int i;
3465
3466 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3467
3468 pTypeLibImpl = TypeLibImpl_Constructor();
3469 if (!pTypeLibImpl) return NULL;
3470
3471 /* get pointer to beginning of typelib data */
3472 cx.pos = 0;
3473 cx.oStart=0;
3474 cx.mapping = pLib;
3475 cx.pLibInfo = pTypeLibImpl;
3476 cx.length = dwTLBLength;
3477
3478 /* read header */
3479 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3480 TRACE_(typelib)("header:\n");
3481 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3482 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3483 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3484 return NULL;
3485 }
3486 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3487
3488 /* there is a small amount of information here until the next important
3489 * part:
3490 * the segment directory . Try to calculate the amount of data */
3491 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3492
3493 /* now read the segment directory */
3494 TRACE("read segment directory (at %d)\n",lPSegDir);
3495 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3496 cx.pTblDir = &tlbSegDir;
3497
3498 /* just check two entries */
3499 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3500 {
3501 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3502 heap_free(pTypeLibImpl);
3503 return NULL;
3504 }
3505
3509
3510 /* now fill our internal data */
3511 /* TLIBATTR fields */
3512 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3513
3514 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3515 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3516 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3517 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3518 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3519
3520 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3521 pTypeLibImpl->lcid = tlbHeader.lcid;
3522
3523 /* name, eventually add to a hash table */
3524 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3525
3526 /* help info */
3527 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3528 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3529
3530 if( tlbHeader.varflags & HELPDLLFLAG)
3531 {
3532 int offset;
3533 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3534 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3535 }
3536
3537 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3538
3539 /* custom data */
3540 if(tlbHeader.CustomDataOffset >= 0)
3541 {
3542 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3543 }
3544
3545 /* fill in type descriptions */
3546 if(tlbSegDir.pTypdescTab.length > 0)
3547 {
3548 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3549 INT16 td[4];
3550 pTypeLibImpl->ctTypeDesc = cTD;
3551 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3552 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3553 for(i=0; i<cTD; )
3554 {
3555 /* FIXME: add several sanity checks here */
3556 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3557 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3558 {
3559 /* FIXME: check safearray */
3560 if(td[3] < 0)
3561 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3562 else
3563 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3564 }
3565 else if(td[0] == VT_CARRAY)
3566 {
3567 /* array descr table here */
3568 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3569 }
3570 else if(td[0] == VT_USERDEFINED)
3571 {
3572 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3573 }
3574 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3575 }
3576
3577 /* second time around to fill the array subscript info */
3578 for(i=0;i<cTD;i++)
3579 {
3580 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3581 if(tlbSegDir.pArrayDescriptions.offset>0)
3582 {
3583 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3585
3586 if(td[1]<0)
3587 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3588 else
3589 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3590
3591 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3592
3593 for(j = 0; j<td[2]; j++)
3594 {
3595 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3596 sizeof(INT), &cx, DO_NOT_SEEK);
3597 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3598 sizeof(INT), &cx, DO_NOT_SEEK);
3599 }
3600 }
3601 else
3602 {
3603 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3604 ERR("didn't find array description data\n");
3605 }
3606 }
3607 }
3608
3609 /* imported type libs */
3610 if(tlbSegDir.pImpFiles.offset>0)
3611 {
3612 TLBImpLib *pImpLib;
3613 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3614 UINT16 size;
3615
3616 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3617 {
3618 char *name;
3619
3620 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3621 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3622 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3623
3624 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3625 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3626 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3627 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3628
3629 size >>= 2;
3630 name = heap_alloc_zero(size+1);
3632 pImpLib->name = TLB_MultiByteToBSTR(name);
3633 heap_free(name);
3634
3635 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3636 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3637
3638 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3639 }
3640 }
3641
3643
3644 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3645
3646 /* type infos */
3647 if(tlbHeader.nrtypeinfos >= 0 )
3648 {
3649 ITypeInfoImpl **ppTI;
3650
3651 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3652
3653 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3654 {
3655 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3656
3657 ++ppTI;
3658 (pTypeLibImpl->TypeInfoCount)++;
3659 }
3660 }
3661
3662#ifdef _WIN64
3663 if(pTypeLibImpl->syskind == SYS_WIN32){
3664 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3665 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3666 }
3667#endif
3668
3669 TRACE("(%p)\n", pTypeLibImpl);
3670 return &pTypeLibImpl->ITypeLib2_iface;
3671}
3672
3673
3674static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3675{
3676 char b[3];
3677 int i;
3678 short s;
3679
3680 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3681 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3682 return FALSE;
3683 }
3684
3685 guid->Data4[0] = s >> 8;
3686 guid->Data4[1] = s & 0xff;
3687
3688 b[2] = '\0';
3689 for(i = 0; i < 6; i++) {
3690 memcpy(b, str + 24 + 2 * i, 2);
3691 guid->Data4[i + 2] = strtol(b, NULL, 16);
3692 }
3693 return TRUE;
3694}
3695
3697{
3698 const BYTE *buffer;
3701};
3702
3703static const char *lookup_code(const BYTE *table, DWORD table_size, struct bitstream *bits)
3704{
3705 const BYTE *p = table;
3706
3707 while (p < table + table_size && *p == 0x80)
3708 {
3709 if (p + 2 >= table + table_size) return NULL;
3710
3711 if (!(bits->current & 0xff))
3712 {
3713 if (!bits->length) return NULL;
3714 bits->current = (*bits->buffer << 8) | 1;
3715 bits->buffer++;
3716 bits->length--;
3717 }
3718
3719 if (bits->current & 0x8000)
3720 {
3721 p += 3;
3722 }
3723 else
3724 {
3725 p = table + (*(p + 2) | (*(p + 1) << 8));
3726 }
3727
3728 bits->current <<= 1;
3729 }
3730
3731 if (p + 1 < table + table_size && *(p + 1))
3732 {
3733 /* FIXME: Whats the meaning of *p? */
3734 const BYTE *q = p + 1;
3735 while (q < table + table_size && *q) q++;
3736 return (q < table + table_size) ? (const char *)(p + 1) : NULL;
3737 }
3738
3739 return NULL;
3740}
3741
3742static const TLBString *decode_string(const BYTE *table, const char *stream, DWORD stream_length, ITypeLibImpl *lib)
3743{
3744 DWORD buf_size, table_size;
3745 const char *p;
3746 struct bitstream bits;
3747 BSTR buf;
3748 TLBString *tlbstr;
3749
3750 if (!stream_length) return NULL;
3751
3752 bits.buffer = (const BYTE *)stream;
3753 bits.length = stream_length;
3754 bits.current = 0;
3755
3756 buf_size = *(const WORD *)table;
3757 table += sizeof(WORD);
3758 table_size = *(const DWORD *)table;
3759 table += sizeof(DWORD);
3760
3761 buf = SysAllocStringLen(NULL, buf_size);
3762 buf[0] = 0;
3763
3764 while ((p = lookup_code(table, table_size, &bits)))
3765 {
3766 static const WCHAR spaceW[] = { ' ',0 };
3767 if (buf[0]) lstrcatW(buf, spaceW);
3768 MultiByteToWideChar(CP_ACP, 0, p, -1, buf + lstrlenW(buf), buf_size - lstrlenW(buf));
3769 }
3770
3771 tlbstr = TLB_append_str(&lib->string_list, buf);
3773
3774 return tlbstr;
3775}
3776
3777static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3778{
3779 WORD bytelen;
3780 DWORD len;
3781 BSTR tmp_str;
3782
3783 *pStr = NULL;
3784 bytelen = *(const WORD*)ptr;
3785 if(bytelen == 0xffff) return 2;
3786
3787 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3788 tmp_str = SysAllocStringLen(NULL, len);
3789 if (tmp_str) {
3790 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3791 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3792 SysFreeString(tmp_str);
3793 }
3794 return bytelen + 2;
3795}
3796
3797static WORD SLTG_ReadStringA(const char *ptr, char **str)
3798{
3799 WORD bytelen;
3800
3801 *str = NULL;
3802 bytelen = *(const WORD*)ptr;
3803 if(bytelen == 0xffff) return 2;
3804 *str = heap_alloc(bytelen + 1);
3805 memcpy(*str, ptr + 2, bytelen);
3806 (*str)[bytelen] = '\0';
3807 return bytelen + 2;
3808}
3809
3810static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3811{
3812 BSTR tmp_str;
3813 TLBString *tlbstr;
3814
3815 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3816 if (tlbstr->offset == offset)
3817 return tlbstr;
3818 }
3819
3820 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3821 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3822 SysFreeString(tmp_str);
3823
3824 return tlbstr;
3825}
3826
3827static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3828{
3829 char *ptr = pLibBlk;
3830 WORD w;
3831
3832 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3833 FIXME("libblk magic = %04x\n", w);
3834 return 0;
3835 }
3836
3837 ptr += 6;
3838 if((w = *(WORD*)ptr) != 0xffff) {
3839 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3840 ptr += w;
3841 }
3842 ptr += 2;
3843
3844 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3845
3846 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3847
3848 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3849 ptr += 4;
3850
3851 pTypeLibImpl->syskind = *(WORD*)ptr;
3852 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3853 ptr += 2;
3854
3856 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3857 else
3858 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3859 ptr += 2;
3860
3861 ptr += 4; /* skip res12 */
3862
3863 pTypeLibImpl->libflags = *(WORD*)ptr;
3864 ptr += 2;
3865
3866 pTypeLibImpl->ver_major = *(WORD*)ptr;
3867 ptr += 2;
3868
3869 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3870 ptr += 2;
3871
3872 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3873 ptr += sizeof(GUID);
3874
3875 return ptr - (char*)pLibBlk;
3876}
3877
3878/* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3879typedef struct
3880{
3881 unsigned int num;
3882 HREFTYPE refs[1];
3884
3886 HREFTYPE *typelib_ref)
3887{
3888 if(table && typeinfo_ref < table->num)
3889 {
<