ReactOS  0.4.14-dev-593-g1793dcc
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 
79 typedef struct
80 {
87 } NE_NAMEINFO;
88 
89 typedef 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  */
97 } NE_TYPEINFO;
98 
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
101 static 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
110 static WORD FromLEWord(WORD p_iVal)
111 {
112  return (((p_iVal & 0x00FF) << 8) |
113  ((p_iVal & 0xFF00) >> 8));
114 }
115 
116 
117 static 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
138 static 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 
152 static 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  */
172 static 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 */
264 static 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 
284 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
285 
286 struct tlibredirect_data
287 {
288  ULONG size;
289  DWORD res;
290  ULONG name_len;
292  LANGID langid;
293  WORD flags;
294  ULONG help_len;
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));
332  *path = SysAllocString( 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 
341  if (res == ERROR_FILE_NOT_FOUND)
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));
349  return TYPE_E_REGISTRYACCESS;
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  {
379  *path = SysAllocString( Path );
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;
428  HRESULT hres;
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  */
458 HRESULT 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 {
478  WCHAR szPath[MAX_PATH+1];
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 */
577 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
578 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
579 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
580 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
581 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
582 
583 static 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 
640  RegCloseKey(key);
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  */
656 HRESULT 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 
762  RegCloseKey(key);
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))) {
771  LPOLESTR name = NULL;
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  {
827  BOOL is_wow64;
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  {
955  BOOL is_wow64;
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 
967 enddeleteloop:
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) {
999  RegCloseKey(key);
1000  key = NULL;
1001 
1002  RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1003  *wcsrchr( keyName, '\\' ) = 0; /* remove last path component */
1004  RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1005  }
1006 
1007 end:
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 
1059 typedef struct tagTLBGuid {
1063  struct list entry;
1064 } TLBGuid;
1065 
1066 typedef struct tagTLBCustData
1067 {
1070  struct list entry;
1071 } TLBCustData;
1072 
1073 /* data structure for import typelibs */
1074 typedef 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;
1091 } TLBImpLib;
1092 
1093 typedef struct tagTLBString {
1096  struct list entry;
1097 } TLBString;
1098 
1099 /* internal ITypeLib data */
1100 typedef 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  */
1119  struct list name_list;
1120  struct list guid_list;
1121 
1122  const TLBString *Name;
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;
1143 } ITypeLibImpl;
1144 
1145 static const ITypeLib2Vtbl tlbvt;
1146 static const ITypeCompVtbl tlbtcvt;
1147 static 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 */
1170 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1171 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1172 
1173 /*======================= ITypeInfo implementation =======================*/
1174 
1175 /* data for referenced types */
1176 typedef 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;
1192 } TLBRefType;
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 */
1200 typedef struct tagTLBParDesc
1201 {
1202  const TLBString *Name;
1204 } TLBParDesc;
1205 
1206 /* internal Function data */
1207 typedef 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 */
1217 } TLBFuncDesc;
1218 
1219 /* internal Variable data */
1220 typedef 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 */
1229 } TLBVarDesc;
1230 
1231 /* internal implemented interface data */
1232 typedef struct tagTLBImplType
1233 {
1234  HREFTYPE hRef; /* hRef of interface */
1235  int implflags; /* IMPLFLAG_*s */
1237 } TLBImplType;
1238 
1239 /* internal TypeInfo data */
1240 typedef 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  */
1259  const TLBString *Name;
1265 
1266  /* functions */
1268 
1269  /* variables */
1271 
1272  /* Implemented Interfaces */
1274 
1277 } ITypeInfoImpl;
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 
1299 static const ITypeInfo2Vtbl tinfvt;
1300 static const ITypeCompVtbl tcompvt;
1301 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1302 
1305 
1306 typedef 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 */
1314 } TLBContext;
1315 
1316 
1317 static inline BSTR TLB_get_bstr(const TLBString *str)
1318 {
1319  return str != NULL ? str->str : NULL;
1320 }
1321 
1322 static 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 
1329 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1330 {
1331  return guid != NULL ? &guid->guid : NULL;
1332 }
1333 
1334 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1335 {
1336  return guid != NULL ? &guid->guid : &GUID_NULL;
1337 }
1338 
1339 static 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 */
1356 static 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 
1405 static 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 }
1421 static 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 
1460 static 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 }
1493 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1494 {
1495  while (n)
1496  {
1498  ++pfd;
1499  --n;
1500  }
1501 }
1502 static 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 
1512 static 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 
1520 static 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)
1528  TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
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 
1540 static 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 
1552 static 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 
1573 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1574 {
1575  TRACE("%p ref=%u\n", pty, pty->ref);
1576  TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
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 
1589 static 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 
1599 static 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 
1612 static 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 */
1619 static 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 */
1641 static 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 */
1669 static 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 
1680 static 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;
1688  MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
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 
1728 static 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 
1749 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
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 
1786 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1787 {
1788  list_init(&func_desc->custdata_list);
1789 }
1790 
1792 {
1793  TLBFuncDesc *ret;
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 {
1814  TLBImplType *ret;
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 
1850 static 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 
1884 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
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 {
1914  ITypeInfo *other;
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 
2030 static 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 */
2046 static 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 
2119 static 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,
2130  pcx->pTblDir->pNametab.offset+offset);
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  */
2213 static 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  */
2300 static 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 
2322 static 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 
2332 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2333 {
2334  return (invkind == INVOKE_PROPERTYGET ||
2335  invkind == INVOKE_PROPERTYPUT ||
2336  invkind == INVOKE_PROPERTYPUTREF);
2337 }
2338 
2339 static 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 
2405  if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
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 
2537 static 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 */
2593 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
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 */
2618 static 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);
2705  ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
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 };
2860 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2861 
2862 
2863 typedef struct TLB_PEFile
2864 {
2871 } TLB_PEFile;
2872 
2874 {
2875  return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2876 }
2877 
2879 {
2880  if (IsEqualIID(riid, &IID_IUnknown))
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 
2911 static const IUnknownVtbl TLB_PEFile_Vtable =
2912 {
2916 };
2917 
2918 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2919 {
2920  TLB_PEFile *This;
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 
2966 typedef struct TLB_NEFile
2967 {
2971 } TLB_NEFile;
2972 
2974 {
2975  return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2976 }
2977 
2979 {
2980  if (IsEqualIID(riid, &IID_IUnknown))
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 
3008 static const IUnknownVtbl TLB_NEFile_Vtable =
3009 {
3013 };
3014 
3015 /***********************************************************************
3016  * read_xx_header [internal]
3017  */
3018 static 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  */
3049 static 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 
3145 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3146 
3147  HFILE lzfd = -1;
3148  OFSTRUCT ofs;
3150  TLB_NEFile *This;
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  {
3162  DWORD reslen, offset;
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 
3186 typedef struct TLB_Mapping
3187 {
3193 } TLB_Mapping;
3194 
3196 {
3197  return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3198 }
3199 
3201 {
3202  if (IsEqualIID(riid, &IID_IUnknown))
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 
3235 static const IUnknownVtbl TLB_Mapping_Vtable =
3236 {
3240 };
3241 
3242 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3243 {
3244  TLB_Mapping *This;
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);
3275  return TYPE_E_CANTLOADLIBRARY;
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" */
3286 static 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 
3328  if(file != pszFileName) heap_free(file);
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 
3342  info = HeapAlloc(GetProcessHeap(), 0, size);
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 
3350  HeapFree(GetProcessHeap(), 0, info);
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);
3376  if (ret == TYPE_E_CANTLOADLIBRARY)
3377  ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3378  if (ret == TYPE_E_CANTLOADLIBRARY)
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 
3642  MSFT_ReadAllRefs(&cx);
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 
3674 static 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 
3703 static 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 
3742 static 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);
3772  SysFreeString(buf);
3773 
3774  return tlbstr;
3775 }
3776 
3777 static 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 
3797 static 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 
3810 static 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 
3827 static 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 
3855  if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
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 */
3879 typedef struct
3880 {
3881  unsigned int num;
3882  HREFTYPE refs[1];
3884 
3886  HREFTYPE *typelib_ref)
3887 {
3888  if(table && typeinfo_ref < table->num)
3889  {
3890  *typelib_ref = table->refs[typeinfo_ref];
3891  return S_OK;
3892  }
3893 
3894  ERR_(typelib)("Unable to find reference\n");
3895  *typelib_ref = -1;
3896  return E_FAIL;
3897 }
3898 
3899 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3900 {
3901  BOOL done = FALSE;
3902 
3903  while(!done) {
3904  if((*pType & 0xe00) == 0xe00) {
3905  pTD->vt = VT_PTR;
3906  pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3907  pTD = pTD->u.lptdesc;
3908  }
3909  switch(*pType & 0x3f) {
3910  case VT_PTR:
3911  pTD->vt = VT_PTR;
3912  pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3913  pTD = pTD->u.lptdesc;
3914  break;
3915 
3916  case VT_USERDEFINED:
3917  pTD->vt = VT_USERDEFINED;
3918  sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3919  done = TRUE;
3920  break;
3921 
3922  case VT_CARRAY:
3923  {
3924  /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3925  array */
3926 
3927  SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3928 
3929  pTD->vt = VT_CARRAY;
3930  pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3931  pTD->u.lpadesc->cDims = pSA->cDims;
3932  memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3933  pSA->cDims * sizeof(SAFEARRAYBOUND));
3934 
3935  pTD = &pTD->u.lpadesc->tdescElem;
3936  break;
3937  }
3938 
3939  case VT_SAFEARRAY:
3940  {
3941  /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3942  useful? */
3943 
3944  pType++;
3945  pTD->vt = VT_SAFEARRAY;
3946  pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3947  pTD = pTD->u.lptdesc;
3948  break;
3949  }
3950  default:
3951  pTD->vt = *pType & 0x3f;
3952  done = TRUE;
3953  break;
3954  }
3955  pType++;
3956  }
3957  return pType;
3958 }
3959 
3960 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3961  ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3962 {
3963  /* Handle [in/out] first */
3964  if((*pType & 0xc000) == 0xc000)
3965  pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3966  else if(*pType & 0x8000)
3967  pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3968  else if(*pType & 0x4000)
3969  pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3970  else
3971  pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3972 
3973  if(*pType & 0x2000)
3974  pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3975 
3976  if(*pType & 0x80)
3977  pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3978 
3979  return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3980 }
3981 
3982 
3984  char *pNameTable)
3985 {
3986  unsigned int ref;
3987  char *name;
3988  TLBRefType *ref_type;
3990  HREFTYPE typelib_ref;
3991 
3992  if(pRef->magic != SLTG_REF_MAGIC) {
3993  FIXME("Ref magic = %x\n", pRef->magic);
3994  return NULL;
3995  }
3996  name = ( (char*)pRef->names + pRef->number);
3997 
3998  table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3999  table->num = pRef->number >> 3;
4000 
4001  /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
4002 
4003  /* We don't want the first href to be 0 */
4004  typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
4005 
4006  for(ref = 0; ref < pRef->number >> 3; ref++) {
4007  char *refname;
4008  unsigned int lib_offs, type_num;
4009 
4010  ref_type = heap_alloc_zero(sizeof(TLBRefType));
4011 
4012  name += SLTG_ReadStringA(name, &refname);
4013  if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
4014  FIXME_(typelib)("Can't sscanf ref\n");
4015  if(lib_offs != 0xffff) {
4016  TLBImpLib *import;
4017 
4019  if(import->offset == lib_offs)
4020  break;
4021 
4022  if(&import->entry == &pTL->implib_list) {
4023  char fname[MAX_PATH+1];
4024  int len;
4025  GUID tmpguid;
4026 
4027  import = heap_alloc_zero(sizeof(*import));
4028  import->offset = lib_offs;
4029  TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
4030  import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
4031  if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
4032  &import->wVersionMajor,
4033  &import->wVersionMinor,
4034  &import->lcid, fname) != 4) {
4035  FIXME_(typelib)("can't sscanf ref %s\n",
4036  pNameTable + lib_offs + 40);
4037  }
4038  len = strlen(fname);
4039  if(fname[len-1] != '#')
4040  FIXME("fname = %s\n", fname);
4041  fname[len-1] = '\0';
4042  import->name = TLB_MultiByteToBSTR(fname);
4043  list_add_tail(&pTL->implib_list, &import->entry);
4044  }
4045  ref_type->pImpTLInfo = import;
4046 
4047  /* Store a reference to IDispatch */
4048  if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4049  pTL->dispatch_href = typelib_ref;
4050 
4051  } else { /* internal ref */
4052  ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4053  }
4054  ref_type->reference = typelib_ref;
4055  ref_type->index = type_num;
4056 
4057  heap_free(refname);
4058  list_add_tail(&pTL->ref_list, &ref_type->entry);
4059 
4060  table->refs[ref] = typelib_ref;
4061  typelib_ref += 4;
4062  }
4063  if((BYTE)*name != SLTG_REF_MAGIC)
4064  FIXME_(typelib)("End of ref block magic = %x\n", *name);
4065  dump_TLBRefType(pTL);
4066  return table;
4067 }
4068 
4069 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4070  BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4071 {
4073  TLBImplType *pImplType;
4074  /* I don't really get this structure, usually it's 0x16 bytes
4075  long, but iuser.tlb contains some that are 0x18 bytes long.
4076  That's ok because we can use the next ptr to jump to the next
4077  one. But how do we know the length of the last one? The WORD
4078  at offs 0x8 might be the clue. For now I'm just assuming that
4079  the last one is the regular 0x16 bytes. */
4080 
4081  info = (SLTG_ImplInfo*)pBlk;
4082  while(1){
4083  pTI->typeattr.cImplTypes++;
4084  if(info->next == 0xffff)
4085  break;
4086  info = (SLTG_ImplInfo*)(pBlk + info->next);
4087  }
4088 
4089  info = (SLTG_ImplInfo*)pBlk;
4090  pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4091  pImplType = pTI->impltypes;
4092  while(1) {
4093  sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4094  pImplType->implflags = info->impltypeflags;
4095  ++pImplType;
4096 
4097  if(info->next == 0xffff)
4098  break;
4099  if(OneOnly)
4100  FIXME_(typelib)("Interface inheriting more than one interface\n");
4101  info = (SLTG_ImplInfo*)(pBlk + info->next);
4102  }
4103  info++; /* see comment at top of function */
4104  return (char*)info;
4105 }
4106 
4107 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4108  const char *pNameTable, const sltg_ref_lookup_t *ref_lookup, const BYTE *hlp_strings)
4109 {
4110  TLBVarDesc *pVarDesc;
4111  const TLBString *prevName = NULL;
4112  SLTG_Variable *pItem;
4113  unsigned short i;
4114  WORD *pType;
4115 
4116  pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4117 
4118  for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4119  pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4120 
4121  pVarDesc->vardesc.memid = pItem->memid;
4122 
4123  if (pItem->magic != SLTG_VAR_MAGIC &&
4124  pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4125  FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4126  return;
4127  }
4128 
4129  if (pItem->name == 0xfffe)
4130  pVarDesc->Name = prevName;
4131  else
4132  pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4133 
4134  TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4135  TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4136  TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4137 
4138  if (pItem->helpstring != 0xffff)
4139  {
4140  pVarDesc->HelpString = decode_string(hlp_strings, pBlk + pItem->helpstring, pNameTable - pBlk, pTI->pTypeLib);
4141  TRACE_(typelib)("helpstring = %s\n", debugstr_w(pVarDesc->HelpString->str));
4142  }
4143 
4144  if(pItem->flags & 0x02)
4145  pType = &pItem->type;
4146  else
4147  pType = (WORD*)(pBlk + pItem->type);
4148 
4149  if (pItem->flags & ~0xda)
4150  FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4151 
4152  SLTG_DoElem(pType, pBlk,
4153  &pVarDesc->vardesc.elemdescVar, ref_lookup);
4154 
4155  if (TRACE_ON(typelib)) {
4156  char buf[300];
4157  dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4158  TRACE_(typelib)("elemdescVar: %s\n", buf);
4159  }
4160 
4161  if (pItem->flags & 0x40) {
4162  TRACE_(typelib)("VAR_DISPATCH\n");
4163  pVarDesc->vardesc.varkind = VAR_DISPATCH;
4164  }
4165  else if (pItem->flags & 0x10) {
4166  TRACE_(typelib)("VAR_CONST\n");
4167  pVarDesc->vardesc.varkind = VAR_CONST;
4168  pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4169  V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4170  if (pItem->flags & 0x08)
4171  V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4172  else {
4173  switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4174  {
4175  case VT_LPSTR:
4176  case VT_LPWSTR:
4177  case VT_BSTR:
4178  {
4179  WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4180  BSTR str;
4181  TRACE_(typelib)("len = %u\n", len);
4182  if (len == 0xffff) {
4183  str = NULL;
4184  } else {
4185  INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4186  str = SysAllocStringLen(NULL, alloc_len);
4187  MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4188  }
4189  V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4190  V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4191  break;
4192  }
4193  case VT_I2:
4194  case VT_UI2:
4195  case VT_I4:
4196  case VT_UI4:
4197  case VT_INT:
4198  case VT_UINT:
4199  V_INT(pVarDesc->vardesc.u.lpvarValue) =
4200  *(INT*)(pBlk + pItem->byte_offs);
4201  break;
4202  default:
4203  FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4204  }
4205  }
4206  }
4207  else {
4208  TRACE_(typelib)("VAR_PERINSTANCE\n");
4209  pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4210  pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4211  }
4212 
4213  if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4214  pVarDesc->vardesc.wVarFlags = pItem->varflags;
4215 
4216  if (pItem->flags & 0x80)
4217  pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4218 
4219  prevName = pVarDesc->Name;
4220  }
4221  pTI->typeattr.cVars = cVars;
4222 }
4223 
4224 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4225  unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup,
4226  const BYTE *hlp_strings)
4227 {
4228  SLTG_Function *pFunc;
4229  unsigned short i;
4230  TLBFuncDesc *pFuncDesc;
4231 
4232  pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4233 
4234  pFuncDesc = pTI->funcdescs;
4235  for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs &&a