Sync with trunk revision 63128.
[reactos.git] / dll / win32 / oleaut32 / typelib.c
1 /*
2 * TYPELIB
3 *
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 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 "precomp.h"
51
52 #include <winternl.h>
53 #include <lzexpand.h>
54
55 #include "typelib.h"
56
57 WINE_DEFAULT_DEBUG_CHANNEL(ole);
58 WINE_DECLARE_DEBUG_CHANNEL(typelib);
59
60 #ifdef __REACTOS__
61 /* FIXME: Vista+ */
62 #define STATUS_SUCCESS ((NTSTATUS)0x00000000)
63 static BOOL WINAPI GetFileInformationByHandleEx( HANDLE handle, FILE_INFO_BY_HANDLE_CLASS class,
64 LPVOID info, DWORD size )
65 {
66 NTSTATUS status;
67 IO_STATUS_BLOCK io;
68
69 switch (class)
70 {
71 case FileBasicInfo:
72 case FileStandardInfo:
73 case FileRenameInfo:
74 case FileDispositionInfo:
75 case FileAllocationInfo:
76 case FileEndOfFileInfo:
77 case FileStreamInfo:
78 case FileCompressionInfo:
79 case FileAttributeTagInfo:
80 case FileIoPriorityHintInfo:
81 case FileRemoteProtocolInfo:
82 case FileFullDirectoryInfo:
83 case FileFullDirectoryRestartInfo:
84 case FileStorageInfo:
85 case FileAlignmentInfo:
86 case FileIdInfo:
87 case FileIdExtdDirectoryInfo:
88 case FileIdExtdDirectoryRestartInfo:
89 FIXME( "%p, %u, %p, %u\n", handle, class, info, size );
90 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
91 return FALSE;
92
93 case FileNameInfo:
94 status = NtQueryInformationFile( handle, &io, info, size, FileNameInformation );
95 if (status != STATUS_SUCCESS)
96 {
97 SetLastError( RtlNtStatusToDosError( status ) );
98 return FALSE;
99 }
100 return TRUE;
101
102 case FileIdBothDirectoryRestartInfo:
103 case FileIdBothDirectoryInfo:
104 status = NtQueryDirectoryFile( handle, NULL, NULL, NULL, &io, info, size,
105 FileIdBothDirectoryInformation, FALSE, NULL,
106 (class == FileIdBothDirectoryRestartInfo) );
107 if (status != STATUS_SUCCESS)
108 {
109 SetLastError( RtlNtStatusToDosError( status ) );
110 return FALSE;
111 }
112 return TRUE;
113
114 default:
115 SetLastError( ERROR_INVALID_PARAMETER );
116 return FALSE;
117 }
118 }
119 #endif
120
121 typedef struct
122 {
123 WORD offset;
124 WORD length;
125 WORD flags;
126 WORD id;
127 WORD handle;
128 WORD usage;
129 } NE_NAMEINFO;
130
131 typedef struct
132 {
133 WORD type_id; /* Type identifier */
134 WORD count; /* Number of resources of this type */
135 DWORD resloader; /* SetResourceHandler() */
136 /*
137 * Name info array.
138 */
139 } NE_TYPEINFO;
140
141 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
142 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
143 static void TLB_FreeVarDesc(VARDESC*);
144
145 /****************************************************************************
146 * FromLExxx
147 *
148 * Takes p_iVal (which is in little endian) and returns it
149 * in the host machine's byte order.
150 */
151 #ifdef WORDS_BIGENDIAN
152 static WORD FromLEWord(WORD p_iVal)
153 {
154 return (((p_iVal & 0x00FF) << 8) |
155 ((p_iVal & 0xFF00) >> 8));
156 }
157
158
159 static DWORD FromLEDWord(DWORD p_iVal)
160 {
161 return (((p_iVal & 0x000000FF) << 24) |
162 ((p_iVal & 0x0000FF00) << 8) |
163 ((p_iVal & 0x00FF0000) >> 8) |
164 ((p_iVal & 0xFF000000) >> 24));
165 }
166 #else
167 #define FromLEWord(X) (X)
168 #define FromLEDWord(X) (X)
169 #endif
170
171 #define DISPATCH_HREF_OFFSET 0x01000000
172 #define DISPATCH_HREF_MASK 0xff000000
173
174 /****************************************************************************
175 * FromLExxx
176 *
177 * Fix byte order in any structure if necessary
178 */
179 #ifdef WORDS_BIGENDIAN
180 static void FromLEWords(void *p_Val, int p_iSize)
181 {
182 WORD *Val = p_Val;
183
184 p_iSize /= sizeof(WORD);
185
186 while (p_iSize) {
187 *Val = FromLEWord(*Val);
188 Val++;
189 p_iSize--;
190 }
191 }
192
193
194 static void FromLEDWords(void *p_Val, int p_iSize)
195 {
196 DWORD *Val = p_Val;
197
198 p_iSize /= sizeof(DWORD);
199
200 while (p_iSize) {
201 *Val = FromLEDWord(*Val);
202 Val++;
203 p_iSize--;
204 }
205 }
206 #else
207 #define FromLEWords(X,Y) /*nothing*/
208 #define FromLEDWords(X,Y) /*nothing*/
209 #endif
210
211 /*
212 * Find a typelib key which matches a requested maj.min version.
213 */
214 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
215 {
216 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
217 WCHAR buffer[60];
218 char key_name[16];
219 DWORD len, i;
220 INT best_maj = -1, best_min = -1;
221 HKEY hkey;
222
223 memcpy( buffer, typelibW, sizeof(typelibW) );
224 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
225
226 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
227 return FALSE;
228
229 len = sizeof(key_name);
230 i = 0;
231 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
232 {
233 INT v_maj, v_min;
234
235 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
236 {
237 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
238
239 if (*wMaj == 0xffff && *wMin == 0xffff)
240 {
241 if (v_maj > best_maj) best_maj = v_maj;
242 if (v_min > best_min) best_min = v_min;
243 }
244 else if (*wMaj == v_maj)
245 {
246 best_maj = v_maj;
247
248 if (*wMin == v_min)
249 {
250 best_min = v_min;
251 break; /* exact match */
252 }
253 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
254 }
255 }
256 len = sizeof(key_name);
257 }
258 RegCloseKey( hkey );
259
260 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
261
262 if (*wMaj == 0xffff && *wMin == 0xffff)
263 {
264 if (best_maj >= 0 && best_min >= 0)
265 {
266 *wMaj = best_maj;
267 *wMin = best_min;
268 return TRUE;
269 }
270 }
271
272 if (*wMaj == best_maj && best_min >= 0)
273 {
274 *wMin = best_min;
275 return TRUE;
276 }
277 return FALSE;
278 }
279
280 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
281 /* buffer must be at least 60 characters long */
282 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
283 {
284 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
285 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
286
287 memcpy( buffer, TypelibW, sizeof(TypelibW) );
288 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
289 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
290 return buffer;
291 }
292
293 /* get the path of an interface key, in the form "Interface\\<guid>" */
294 /* buffer must be at least 50 characters long */
295 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
296 {
297 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
298
299 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
300 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
301 return buffer;
302 }
303
304 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
305 /* buffer must be at least 16 characters long */
306 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
307 {
308 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
309 static const WCHAR win16W[] = {'w','i','n','1','6',0};
310 static const WCHAR win32W[] = {'w','i','n','3','2',0};
311 static const WCHAR win64W[] = {'w','i','n','6','4',0};
312
313 sprintfW( buffer, LcidFormatW, lcid );
314 switch(syskind)
315 {
316 case SYS_WIN16: strcatW( buffer, win16W ); break;
317 case SYS_WIN32: strcatW( buffer, win32W ); break;
318 case SYS_WIN64: strcatW( buffer, win64W ); break;
319 default:
320 TRACE("Typelib is for unsupported syskind %i\n", syskind);
321 return NULL;
322 }
323 return buffer;
324 }
325
326 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
327
328 struct tlibredirect_data
329 {
330 ULONG size;
331 DWORD res;
332 ULONG name_len;
333 ULONG name_offset;
334 LANGID langid;
335 WORD flags;
336 ULONG help_len;
337 ULONG help_offset;
338 WORD major_version;
339 WORD minor_version;
340 };
341
342 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
343 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
344 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
345 {
346 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
347 LCID myLCID = lcid;
348 HKEY hkey;
349 WCHAR buffer[60];
350 WCHAR Path[MAX_PATH];
351 LONG res;
352
353 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
354
355 if (redir)
356 {
357 ACTCTX_SECTION_KEYED_DATA data;
358
359 data.cbSize = sizeof(data);
360 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
361 {
362 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
363 WCHAR *nameW;
364 DWORD len;
365
366 if (tlib->major_version != wMaj || tlib->minor_version < wMin)
367 return TYPE_E_LIBNOTREGISTERED;
368
369 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
370 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL );
371 if (!len) return TYPE_E_LIBNOTREGISTERED;
372
373 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
374 *path = SysAllocString( Path );
375 return S_OK;
376 }
377 }
378
379 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
380 get_typelib_key( guid, wMaj, wMin, buffer );
381
382 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
383 if (res == ERROR_FILE_NOT_FOUND)
384 {
385 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
386 return TYPE_E_LIBNOTREGISTERED;
387 }
388 else if (res != ERROR_SUCCESS)
389 {
390 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
391 return TYPE_E_REGISTRYACCESS;
392 }
393
394 while (hr != S_OK)
395 {
396 LONG dwPathLen = sizeof(Path);
397
398 get_lcid_subkey( myLCID, syskind, buffer );
399
400 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
401 {
402 if (!lcid)
403 break;
404 else if (myLCID == lcid)
405 {
406 /* try with sub-langid */
407 myLCID = SUBLANGID(lcid);
408 }
409 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
410 {
411 /* try with system langid */
412 myLCID = 0;
413 }
414 else
415 {
416 break;
417 }
418 }
419 else
420 {
421 *path = SysAllocString( Path );
422 hr = S_OK;
423 }
424 }
425 RegCloseKey( hkey );
426 TRACE_(typelib)("-- 0x%08x\n", hr);
427 return hr;
428 }
429
430 /****************************************************************************
431 * QueryPathOfRegTypeLib [OLEAUT32.164]
432 *
433 * Gets the path to a registered type library.
434 *
435 * PARAMS
436 * guid [I] referenced guid
437 * wMaj [I] major version
438 * wMin [I] minor version
439 * lcid [I] locale id
440 * path [O] path of typelib
441 *
442 * RETURNS
443 * Success: S_OK.
444 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
445 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
446 * opened.
447 */
448 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
449 {
450 BOOL redir = TRUE;
451 #ifdef _WIN64
452 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
453 if(SUCCEEDED(hres))
454 return hres;
455 redir = FALSE;
456 #endif
457 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
458 }
459
460 /******************************************************************************
461 * CreateTypeLib [OLEAUT32.160] creates a typelib
462 *
463 * RETURNS
464 * Success: S_OK
465 * Failure: Status
466 */
467 HRESULT WINAPI CreateTypeLib(
468 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
469 ) {
470 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
471 return E_FAIL;
472 }
473
474 /******************************************************************************
475 * LoadTypeLib [OLEAUT32.161]
476 *
477 * Loads a type library
478 *
479 * PARAMS
480 * szFile [I] Name of file to load from.
481 * pptLib [O] Pointer that receives ITypeLib object on success.
482 *
483 * RETURNS
484 * Success: S_OK
485 * Failure: Status
486 *
487 * SEE
488 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
489 */
490 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
491 {
492 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
493 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
494 }
495
496 /******************************************************************************
497 * LoadTypeLibEx [OLEAUT32.183]
498 *
499 * Loads and optionally registers a type library
500 *
501 * RETURNS
502 * Success: S_OK
503 * Failure: Status
504 */
505 HRESULT WINAPI LoadTypeLibEx(
506 LPCOLESTR szFile, /* [in] Name of file to load from */
507 REGKIND regkind, /* [in] Specify kind of registration */
508 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
509 {
510 WCHAR szPath[MAX_PATH+1];
511 HRESULT res;
512
513 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
514
515 *pptLib = NULL;
516
517 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
518
519 if (SUCCEEDED(res))
520 switch(regkind)
521 {
522 case REGKIND_DEFAULT:
523 /* don't register typelibs supplied with full path. Experimentation confirms the following */
524 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
525 (szFile[0] && (szFile[1] == ':'))) break;
526 /* else fall-through */
527
528 case REGKIND_REGISTER:
529 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
530 {
531 ITypeLib_Release(*pptLib);
532 *pptLib = 0;
533 }
534 break;
535 case REGKIND_NONE:
536 break;
537 }
538
539 TRACE(" returns %08x\n",res);
540 return res;
541 }
542
543 /******************************************************************************
544 * LoadRegTypeLib [OLEAUT32.162]
545 *
546 * Loads a registered type library.
547 *
548 * PARAMS
549 * rguid [I] GUID of the registered type library.
550 * wVerMajor [I] major version.
551 * wVerMinor [I] minor version.
552 * lcid [I] locale ID.
553 * ppTLib [O] pointer that receives an ITypeLib object on success.
554 *
555 * RETURNS
556 * Success: S_OK.
557 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
558 * LoadTypeLib.
559 */
560 HRESULT WINAPI LoadRegTypeLib(
561 REFGUID rguid,
562 WORD wVerMajor,
563 WORD wVerMinor,
564 LCID lcid,
565 ITypeLib **ppTLib)
566 {
567 BSTR bstr=NULL;
568 HRESULT res;
569
570 *ppTLib = NULL;
571
572 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
573
574 if(SUCCEEDED(res))
575 {
576 res= LoadTypeLib(bstr, ppTLib);
577 SysFreeString(bstr);
578
579 if (*ppTLib)
580 {
581 TLIBATTR *attr;
582
583 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
584 if (res == S_OK && (attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor))
585 {
586 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
587 ITypeLib_Release(*ppTLib);
588 *ppTLib = NULL;
589 res = TYPE_E_LIBNOTREGISTERED;
590 }
591 }
592 }
593
594 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
595
596 return res;
597 }
598
599
600 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
601 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
602 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
603 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
604 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
605 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
606
607 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
608 {
609 WCHAR keyName[60];
610 HKEY key, subKey;
611
612 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
613 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
614 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
615
616 get_interface_key( &tattr->guid, keyName );
617 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
618 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
619 {
620 if (name)
621 RegSetValueExW(key, NULL, 0, REG_SZ,
622 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
623
624 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
625 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
626 RegSetValueExW(subKey, NULL, 0, REG_SZ,
627 (const BYTE *)PSOA, sizeof PSOA);
628 RegCloseKey(subKey);
629 }
630
631 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
632 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
633 RegSetValueExW(subKey, NULL, 0, REG_SZ,
634 (const BYTE *)PSOA, sizeof PSOA);
635 RegCloseKey(subKey);
636 }
637
638 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
639 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
640 {
641 WCHAR buffer[40];
642 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
643 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
644
645 StringFromGUID2(&libattr->guid, buffer, 40);
646 RegSetValueExW(subKey, NULL, 0, REG_SZ,
647 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
648 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
649 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
650 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
651 RegCloseKey(subKey);
652 }
653
654 RegCloseKey(key);
655 }
656 }
657
658 /******************************************************************************
659 * RegisterTypeLib [OLEAUT32.163]
660 * Adds information about a type library to the System Registry
661 * NOTES
662 * Docs: ITypeLib FAR * ptlib
663 * Docs: OLECHAR FAR* szFullPath
664 * Docs: OLECHAR FAR* szHelpDir
665 *
666 * RETURNS
667 * Success: S_OK
668 * Failure: Status
669 */
670 HRESULT WINAPI RegisterTypeLib(
671 ITypeLib * ptlib, /* [in] Pointer to the library*/
672 OLECHAR * szFullPath, /* [in] full Path of the library*/
673 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
674 may be NULL*/
675 {
676 HRESULT res;
677 TLIBATTR *attr;
678 WCHAR keyName[60];
679 WCHAR tmp[16];
680 HKEY key, subKey;
681 UINT types, tidx;
682 TYPEKIND kind;
683 DWORD disposition;
684
685 if (ptlib == NULL || szFullPath == NULL)
686 return E_INVALIDARG;
687
688 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
689 return E_FAIL;
690
691 #ifndef _WIN64
692 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
693 #endif
694
695 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
696
697 res = S_OK;
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
700 {
701 LPOLESTR doc;
702
703 /* Set the human-readable name of the typelib */
704 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
705 res = E_FAIL;
706 else if (doc)
707 {
708 if (RegSetValueExW(key, NULL, 0, REG_SZ,
709 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
710 res = E_FAIL;
711
712 SysFreeString(doc);
713 }
714
715 /* Make up the name of the typelib path subkey */
716 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
717
718 /* Create the typelib path subkey */
719 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
721 {
722 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
723 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
724 res = E_FAIL;
725
726 RegCloseKey(subKey);
727 }
728 else
729 res = E_FAIL;
730
731 /* Create the flags subkey */
732 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
733 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
734 {
735 /* FIXME: is %u correct? */
736 static const WCHAR formatW[] = {'%','u',0};
737 WCHAR buf[20];
738 sprintfW(buf, formatW, attr->wLibFlags);
739 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
740 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
741 res = E_FAIL;
742
743 RegCloseKey(subKey);
744 }
745 else
746 res = E_FAIL;
747
748 /* create the helpdir subkey */
749 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
750 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
751 {
752 BOOL freeHelpDir = FALSE;
753 OLECHAR* pIndexStr;
754
755 /* if we created a new key, and helpDir was null, set the helpdir
756 to the directory which contains the typelib. However,
757 if we just opened an existing key, we leave the helpdir alone */
758 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
759 szHelpDir = SysAllocString(szFullPath);
760 pIndexStr = strrchrW(szHelpDir, '\\');
761 if (pIndexStr) {
762 *pIndexStr = 0;
763 }
764 freeHelpDir = TRUE;
765 }
766
767 /* if we have an szHelpDir, set it! */
768 if (szHelpDir != NULL) {
769 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
770 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
771 res = E_FAIL;
772 }
773 }
774
775 /* tidy up */
776 if (freeHelpDir) SysFreeString(szHelpDir);
777 RegCloseKey(subKey);
778
779 } else {
780 res = E_FAIL;
781 }
782
783 RegCloseKey(key);
784 }
785 else
786 res = E_FAIL;
787
788 /* register OLE Automation-compatible interfaces for this typelib */
789 types = ITypeLib_GetTypeInfoCount(ptlib);
790 for (tidx=0; tidx<types; tidx++) {
791 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
792 LPOLESTR name = NULL;
793 ITypeInfo *tinfo = NULL;
794
795 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
796
797 switch (kind) {
798 case TKIND_INTERFACE:
799 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
800 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
801 break;
802
803 case TKIND_DISPATCH:
804 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
805 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
806 break;
807
808 default:
809 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
810 break;
811 }
812
813 if (tinfo) {
814 TYPEATTR *tattr = NULL;
815 ITypeInfo_GetTypeAttr(tinfo, &tattr);
816
817 if (tattr) {
818 TRACE_(typelib)("guid=%s, flags=%04x (",
819 debugstr_guid(&tattr->guid),
820 tattr->wTypeFlags);
821
822 if (TRACE_ON(typelib)) {
823 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
824 XX(FAPPOBJECT);
825 XX(FCANCREATE);
826 XX(FLICENSED);
827 XX(FPREDECLID);
828 XX(FHIDDEN);
829 XX(FCONTROL);
830 XX(FDUAL);
831 XX(FNONEXTENSIBLE);
832 XX(FOLEAUTOMATION);
833 XX(FRESTRICTED);
834 XX(FAGGREGATABLE);
835 XX(FREPLACEABLE);
836 XX(FDISPATCHABLE);
837 XX(FREVERSEBIND);
838 XX(FPROXY);
839 #undef XX
840 MESSAGE("\n");
841 }
842
843 /* Register all dispinterfaces (which includes dual interfaces) and
844 oleautomation interfaces */
845 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
846 kind == TKIND_DISPATCH)
847 {
848 BOOL is_wow64;
849 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
850
851 /* register interface<->typelib coupling */
852 TLB_register_interface(attr, name, tattr, 0);
853
854 /* register TLBs into the opposite registry view, too */
855 if(opposite == KEY_WOW64_32KEY ||
856 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
857 TLB_register_interface(attr, name, tattr, opposite);
858 }
859
860 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
861 }
862
863 ITypeInfo_Release(tinfo);
864 }
865
866 SysFreeString(name);
867 }
868 }
869
870 ITypeLib_ReleaseTLibAttr(ptlib, attr);
871
872 return res;
873 }
874
875
876 /******************************************************************************
877 * UnRegisterTypeLib [OLEAUT32.186]
878 * Removes information about a type library from the System Registry
879 * NOTES
880 *
881 * RETURNS
882 * Success: S_OK
883 * Failure: Status
884 */
885 HRESULT WINAPI UnRegisterTypeLib(
886 REFGUID libid, /* [in] Guid of the library */
887 WORD wVerMajor, /* [in] major version */
888 WORD wVerMinor, /* [in] minor version */
889 LCID lcid, /* [in] locale id */
890 SYSKIND syskind)
891 {
892 BSTR tlibPath = NULL;
893 DWORD tmpLength;
894 WCHAR keyName[60];
895 WCHAR subKeyName[50];
896 int result = S_OK;
897 DWORD i = 0;
898 BOOL deleteOtherStuff;
899 HKEY key = NULL;
900 HKEY subKey = NULL;
901 TYPEATTR* typeAttr = NULL;
902 TYPEKIND kind;
903 ITypeInfo* typeInfo = NULL;
904 ITypeLib* typeLib = NULL;
905 int numTypes;
906
907 TRACE("(IID: %s)\n",debugstr_guid(libid));
908
909 /* Create the path to the key */
910 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
911
912 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
913 {
914 TRACE("Unsupported syskind %i\n", syskind);
915 result = E_INVALIDARG;
916 goto end;
917 }
918
919 /* get the path to the typelib on disk */
920 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
921 result = E_INVALIDARG;
922 goto end;
923 }
924
925 /* Try and open the key to the type library. */
926 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
927 result = E_INVALIDARG;
928 goto end;
929 }
930
931 /* Try and load the type library */
932 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
933 result = TYPE_E_INVALIDSTATE;
934 goto end;
935 }
936
937 /* remove any types registered with this typelib */
938 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
939 for (i=0; i<numTypes; i++) {
940 /* get the kind of type */
941 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
942 goto enddeleteloop;
943 }
944
945 /* skip non-interfaces, and get type info for the type */
946 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
947 goto enddeleteloop;
948 }
949 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
950 goto enddeleteloop;
951 }
952 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
953 goto enddeleteloop;
954 }
955
956 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
957 kind == TKIND_DISPATCH)
958 {
959 /* the path to the type */
960 get_interface_key( &typeAttr->guid, subKeyName );
961
962 /* Delete its bits */
963 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
964 goto enddeleteloop;
965
966 RegDeleteKeyW(subKey, ProxyStubClsidW);
967 RegDeleteKeyW(subKey, ProxyStubClsid32W);
968 RegDeleteKeyW(subKey, TypeLibW);
969 RegCloseKey(subKey);
970 subKey = NULL;
971 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
972 }
973
974 enddeleteloop:
975 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
976 typeAttr = NULL;
977 if (typeInfo) ITypeInfo_Release(typeInfo);
978 typeInfo = NULL;
979 }
980
981 /* Now, delete the type library path subkey */
982 get_lcid_subkey( lcid, syskind, subKeyName );
983 RegDeleteKeyW(key, subKeyName);
984 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
985 RegDeleteKeyW(key, subKeyName);
986
987 /* check if there is anything besides the FLAGS/HELPDIR keys.
988 If there is, we don't delete them */
989 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
990 deleteOtherStuff = TRUE;
991 i = 0;
992 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
993 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
994
995 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
996 if (!strcmpW(subKeyName, FLAGSW)) continue;
997 if (!strcmpW(subKeyName, HELPDIRW)) continue;
998 deleteOtherStuff = FALSE;
999 break;
1000 }
1001
1002 /* only delete the other parts of the key if we're absolutely sure */
1003 if (deleteOtherStuff) {
1004 RegDeleteKeyW(key, FLAGSW);
1005 RegDeleteKeyW(key, HELPDIRW);
1006 RegCloseKey(key);
1007 key = NULL;
1008
1009 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1010 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
1011 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1012 }
1013
1014 end:
1015 SysFreeString(tlibPath);
1016 if (typeLib) ITypeLib_Release(typeLib);
1017 if (subKey) RegCloseKey(subKey);
1018 if (key) RegCloseKey(key);
1019 return result;
1020 }
1021
1022 /******************************************************************************
1023 * RegisterTypeLibForUser [OLEAUT32.442]
1024 * Adds information about a type library to the user registry
1025 * NOTES
1026 * Docs: ITypeLib FAR * ptlib
1027 * Docs: OLECHAR FAR* szFullPath
1028 * Docs: OLECHAR FAR* szHelpDir
1029 *
1030 * RETURNS
1031 * Success: S_OK
1032 * Failure: Status
1033 */
1034 HRESULT WINAPI RegisterTypeLibForUser(
1035 ITypeLib * ptlib, /* [in] Pointer to the library*/
1036 OLECHAR * szFullPath, /* [in] full Path of the library*/
1037 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1038 may be NULL*/
1039 {
1040 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1041 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1042 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1043 }
1044
1045 /******************************************************************************
1046 * UnRegisterTypeLibForUser [OLEAUT32.443]
1047 * Removes information about a type library from the user registry
1048 *
1049 * RETURNS
1050 * Success: S_OK
1051 * Failure: Status
1052 */
1053 HRESULT WINAPI UnRegisterTypeLibForUser(
1054 REFGUID libid, /* [in] GUID of the library */
1055 WORD wVerMajor, /* [in] major version */
1056 WORD wVerMinor, /* [in] minor version */
1057 LCID lcid, /* [in] locale id */
1058 SYSKIND syskind)
1059 {
1060 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1061 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1062 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1063 }
1064
1065 /*======================= ITypeLib implementation =======================*/
1066
1067 typedef struct tagTLBGuid {
1068 GUID guid;
1069 INT hreftype;
1070 UINT offset;
1071 struct list entry;
1072 } TLBGuid;
1073
1074 typedef struct tagTLBCustData
1075 {
1076 TLBGuid *guid;
1077 VARIANT data;
1078 struct list entry;
1079 } TLBCustData;
1080
1081 /* data structure for import typelibs */
1082 typedef struct tagTLBImpLib
1083 {
1084 int offset; /* offset in the file (MSFT)
1085 offset in nametable (SLTG)
1086 just used to identify library while reading
1087 data from file */
1088 TLBGuid *guid; /* libid */
1089 BSTR name; /* name */
1090
1091 LCID lcid; /* lcid of imported typelib */
1092
1093 WORD wVersionMajor; /* major version number */
1094 WORD wVersionMinor; /* minor version number */
1095
1096 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1097 NULL if not yet loaded */
1098 struct list entry;
1099 } TLBImpLib;
1100
1101 typedef struct tagTLBString {
1102 BSTR str;
1103 UINT offset;
1104 struct list entry;
1105 } TLBString;
1106
1107 /* internal ITypeLib data */
1108 typedef struct tagITypeLibImpl
1109 {
1110 ITypeLib2 ITypeLib2_iface;
1111 ITypeComp ITypeComp_iface;
1112 ICreateTypeLib2 ICreateTypeLib2_iface;
1113 LONG ref;
1114 TLBGuid *guid;
1115 LCID lcid;
1116 SYSKIND syskind;
1117 int ptr_size;
1118 WORD ver_major;
1119 WORD ver_minor;
1120 WORD libflags;
1121 LCID set_lcid;
1122
1123 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1124 * exported to the application as a UNICODE string.
1125 */
1126 struct list string_list;
1127 struct list name_list;
1128 struct list guid_list;
1129
1130 const TLBString *Name;
1131 const TLBString *DocString;
1132 const TLBString *HelpFile;
1133 const TLBString *HelpStringDll;
1134 DWORD dwHelpContext;
1135 int TypeInfoCount; /* nr of typeinfo's in librarry */
1136 struct tagITypeInfoImpl **typeinfos;
1137 struct list custdata_list;
1138 struct list implib_list;
1139 int ctTypeDesc; /* number of items in type desc array */
1140 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1141 library. Only used while reading MSFT
1142 typelibs */
1143 struct list ref_list; /* list of ref types in this typelib */
1144 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1145
1146
1147 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1148 struct list entry;
1149 WCHAR *path;
1150 INT index;
1151 } ITypeLibImpl;
1152
1153 static const ITypeLib2Vtbl tlbvt;
1154 static const ITypeCompVtbl tlbtcvt;
1155 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1156
1157 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1158 {
1159 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1160 }
1161
1162 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1163 {
1164 return impl_from_ITypeLib2((ITypeLib2*)iface);
1165 }
1166
1167 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1168 {
1169 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1170 }
1171
1172 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1173 {
1174 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1175 }
1176
1177 /* ITypeLib methods */
1178 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1179 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1180
1181 /*======================= ITypeInfo implementation =======================*/
1182
1183 /* data for referenced types */
1184 typedef struct tagTLBRefType
1185 {
1186 INT index; /* Type index for internal ref or for external ref
1187 it the format is SLTG. -2 indicates to
1188 use guid */
1189
1190 TYPEKIND tkind;
1191 TLBGuid *guid; /* guid of the referenced type */
1192 /* if index == TLB_REF_USE_GUID */
1193
1194 HREFTYPE reference; /* The href of this ref */
1195 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1196 TLB_REF_INTERNAL for internal refs
1197 TLB_REF_NOT_FOUND for broken refs */
1198
1199 struct list entry;
1200 } TLBRefType;
1201
1202 #define TLB_REF_USE_GUID -2
1203
1204 #define TLB_REF_INTERNAL (void*)-2
1205 #define TLB_REF_NOT_FOUND (void*)-1
1206
1207 /* internal Parameter data */
1208 typedef struct tagTLBParDesc
1209 {
1210 const TLBString *Name;
1211 struct list custdata_list;
1212 } TLBParDesc;
1213
1214 /* internal Function data */
1215 typedef struct tagTLBFuncDesc
1216 {
1217 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1218 const TLBString *Name; /* the name of this function */
1219 TLBParDesc *pParamDesc; /* array with param names and custom data */
1220 int helpcontext;
1221 int HelpStringContext;
1222 const TLBString *HelpString;
1223 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1224 struct list custdata_list;
1225 } TLBFuncDesc;
1226
1227 /* internal Variable data */
1228 typedef struct tagTLBVarDesc
1229 {
1230 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1231 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1232 const TLBString *Name; /* the name of this variable */
1233 int HelpContext;
1234 int HelpStringContext;
1235 const TLBString *HelpString;
1236 struct list custdata_list;
1237 } TLBVarDesc;
1238
1239 /* internal implemented interface data */
1240 typedef struct tagTLBImplType
1241 {
1242 HREFTYPE hRef; /* hRef of interface */
1243 int implflags; /* IMPLFLAG_*s */
1244 struct list custdata_list;
1245 } TLBImplType;
1246
1247 /* internal TypeInfo data */
1248 typedef struct tagITypeInfoImpl
1249 {
1250 ITypeInfo2 ITypeInfo2_iface;
1251 ITypeComp ITypeComp_iface;
1252 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1253 LONG ref;
1254 BOOL not_attached_to_typelib;
1255 BOOL needs_layout;
1256
1257 TLBGuid *guid;
1258 LCID lcid;
1259 MEMBERID memidConstructor;
1260 MEMBERID memidDestructor;
1261 LPOLESTR lpstrSchema;
1262 ULONG cbSizeInstance;
1263 TYPEKIND typekind;
1264 WORD cFuncs;
1265 WORD cVars;
1266 WORD cImplTypes;
1267 WORD cbSizeVft;
1268 WORD cbAlignment;
1269 WORD wTypeFlags;
1270 WORD wMajorVerNum;
1271 WORD wMinorVerNum;
1272 TYPEDESC *tdescAlias;
1273 IDLDESC idldescType;
1274
1275 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1276 int index; /* index in this typelib; */
1277 HREFTYPE hreftype; /* hreftype for app object binding */
1278 /* type libs seem to store the doc strings in ascii
1279 * so why should we do it in unicode?
1280 */
1281 const TLBString *Name;
1282 const TLBString *DocString;
1283 const TLBString *DllName;
1284 const TLBString *Schema;
1285 DWORD dwHelpContext;
1286 DWORD dwHelpStringContext;
1287
1288 /* functions */
1289 TLBFuncDesc *funcdescs;
1290
1291 /* variables */
1292 TLBVarDesc *vardescs;
1293
1294 /* Implemented Interfaces */
1295 TLBImplType *impltypes;
1296
1297 struct list *pcustdata_list;
1298 struct list custdata_list;
1299 } ITypeInfoImpl;
1300
1301 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1302 {
1303 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1304 }
1305
1306 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1307 {
1308 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1309 }
1310
1311 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1312 {
1313 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1314 }
1315
1316 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1317 {
1318 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1319 }
1320
1321 static const ITypeInfo2Vtbl tinfvt;
1322 static const ITypeCompVtbl tcompvt;
1323 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1324
1325 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1326 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1327
1328 typedef struct tagTLBContext
1329 {
1330 unsigned int oStart; /* start of TLB in file */
1331 unsigned int pos; /* current pos */
1332 unsigned int length; /* total length */
1333 void *mapping; /* memory mapping */
1334 MSFT_SegDir * pTblDir;
1335 ITypeLibImpl* pLibInfo;
1336 } TLBContext;
1337
1338
1339 static inline BSTR TLB_get_bstr(const TLBString *str)
1340 {
1341 return str != NULL ? str->str : NULL;
1342 }
1343
1344 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1345 {
1346 if(!str)
1347 return 1;
1348 return memcmp(left, str->str, len);
1349 }
1350
1351 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1352 {
1353 return guid != NULL ? &guid->guid : NULL;
1354 }
1355
1356 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1357 {
1358 return guid != NULL ? &guid->guid : &GUID_NULL;
1359 }
1360
1361 static int get_ptr_size(SYSKIND syskind)
1362 {
1363 switch(syskind){
1364 case SYS_WIN64:
1365 return 8;
1366 case SYS_WIN32:
1367 case SYS_MAC:
1368 case SYS_WIN16:
1369 return 4;
1370 }
1371 WARN("Unhandled syskind: 0x%x\n", syskind);
1372 return 4;
1373 }
1374
1375 /*
1376 debug
1377 */
1378 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1379 if (pTD->vt & VT_RESERVED)
1380 szVarType += strlen(strcpy(szVarType, "reserved | "));
1381 if (pTD->vt & VT_BYREF)
1382 szVarType += strlen(strcpy(szVarType, "ref to "));
1383 if (pTD->vt & VT_ARRAY)
1384 szVarType += strlen(strcpy(szVarType, "array of "));
1385 if (pTD->vt & VT_VECTOR)
1386 szVarType += strlen(strcpy(szVarType, "vector of "));
1387 switch(pTD->vt & VT_TYPEMASK) {
1388 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1389 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1390 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1391 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1392 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1393 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1394 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1395 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1396 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1397 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1398 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1399 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1400 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1401 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1402 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1403 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1404 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1405 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1406 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1407 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1408 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1409 pTD->u.hreftype); break;
1410 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1411 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1412 case VT_PTR: sprintf(szVarType, "ptr to ");
1413 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1414 break;
1415 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1416 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1417 break;
1418 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1419 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1420 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1421 break;
1422
1423 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1424 }
1425 }
1426
1427 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1428 char buf[200];
1429 USHORT flags = edesc->u.paramdesc.wParamFlags;
1430 dump_TypeDesc(&edesc->tdesc,buf);
1431 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1432 MESSAGE("\t\tu.paramdesc.wParamFlags");
1433 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1434 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1435 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1436 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1437 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1438 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1439 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1440 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1441 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1442 }
1443 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1444 int i;
1445 MESSAGE("memid is %08x\n",funcdesc->memid);
1446 for (i=0;i<funcdesc->cParams;i++) {
1447 MESSAGE("Param %d:\n",i);
1448 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1449 }
1450 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1451 switch (funcdesc->funckind) {
1452 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1453 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1454 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1455 case FUNC_STATIC: MESSAGE("static");break;
1456 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1457 default: MESSAGE("unknown");break;
1458 }
1459 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1460 switch (funcdesc->invkind) {
1461 case INVOKE_FUNC: MESSAGE("func");break;
1462 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1463 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1464 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1465 }
1466 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1467 switch (funcdesc->callconv) {
1468 case CC_CDECL: MESSAGE("cdecl");break;
1469 case CC_PASCAL: MESSAGE("pascal");break;
1470 case CC_STDCALL: MESSAGE("stdcall");break;
1471 case CC_SYSCALL: MESSAGE("syscall");break;
1472 default:break;
1473 }
1474 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1475 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1476 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1477
1478 MESSAGE("\telemdescFunc (return value type):\n");
1479 dump_ELEMDESC(&funcdesc->elemdescFunc);
1480 }
1481
1482 static const char * const typekind_desc[] =
1483 {
1484 "TKIND_ENUM",
1485 "TKIND_RECORD",
1486 "TKIND_MODULE",
1487 "TKIND_INTERFACE",
1488 "TKIND_DISPATCH",
1489 "TKIND_COCLASS",
1490 "TKIND_ALIAS",
1491 "TKIND_UNION",
1492 "TKIND_MAX"
1493 };
1494
1495 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1496 {
1497 int i;
1498 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1499 for (i=0;i<pfd->funcdesc.cParams;i++)
1500 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1501
1502
1503 dump_FUNCDESC(&(pfd->funcdesc));
1504
1505 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1506 if(pfd->Entry == NULL)
1507 MESSAGE("\tentry: (null)\n");
1508 else if(pfd->Entry == (void*)-1)
1509 MESSAGE("\tentry: invalid\n");
1510 else if(IS_INTRESOURCE(pfd->Entry))
1511 MESSAGE("\tentry: %p\n", pfd->Entry);
1512 else
1513 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1514 }
1515 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1516 {
1517 while (n)
1518 {
1519 dump_TLBFuncDescOne(pfd);
1520 ++pfd;
1521 --n;
1522 }
1523 }
1524 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1525 {
1526 while (n)
1527 {
1528 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1529 ++pvd;
1530 --n;
1531 }
1532 }
1533
1534 static void dump_TLBImpLib(const TLBImpLib *import)
1535 {
1536 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1537 debugstr_w(import->name));
1538 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1539 import->wVersionMinor, import->lcid, import->offset);
1540 }
1541
1542 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1543 {
1544 TLBRefType *ref;
1545
1546 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1547 {
1548 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1549 if(ref->index == -1)
1550 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1551 else
1552 TRACE_(typelib)("type no: %d\n", ref->index);
1553
1554 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1555 {
1556 TRACE_(typelib)("in lib\n");
1557 dump_TLBImpLib(ref->pImpTLInfo);
1558 }
1559 }
1560 }
1561
1562 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1563 {
1564 if(!impl)
1565 return;
1566 while (n) {
1567 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1568 impl->hRef, impl->implflags);
1569 ++impl;
1570 --n;
1571 }
1572 }
1573
1574 static void dump_Variant(const VARIANT * pvar)
1575 {
1576 SYSTEMTIME st;
1577
1578 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1579
1580 if (pvar)
1581 {
1582 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1583 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1584 {
1585 TRACE(",%p", V_BYREF(pvar));
1586 }
1587 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1588 {
1589 TRACE(",%p", V_ARRAY(pvar));
1590 }
1591 else switch (V_TYPE(pvar))
1592 {
1593 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1594 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1595 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1596 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1597 case VT_INT:
1598 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1599 case VT_UINT:
1600 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1601 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1602 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1603 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1604 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1605 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1606 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1607 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1608 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1609 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1610 V_CY(pvar).s.Lo); break;
1611 case VT_DATE:
1612 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1613 TRACE(",<invalid>");
1614 else
1615 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1616 st.wHour, st.wMinute, st.wSecond);
1617 break;
1618 case VT_ERROR:
1619 case VT_VOID:
1620 case VT_USERDEFINED:
1621 case VT_EMPTY:
1622 case VT_NULL: break;
1623 default: TRACE(",?"); break;
1624 }
1625 }
1626 TRACE("}\n");
1627 }
1628
1629 static void dump_DispParms(const DISPPARAMS * pdp)
1630 {
1631 unsigned int index;
1632
1633 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1634
1635 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1636 {
1637 TRACE("named args:\n");
1638 for (index = 0; index < pdp->cNamedArgs; index++)
1639 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1640 }
1641
1642 if (pdp->cArgs && pdp->rgvarg)
1643 {
1644 TRACE("args:\n");
1645 for (index = 0; index < pdp->cArgs; index++)
1646 dump_Variant( &pdp->rgvarg[index] );
1647 }
1648 }
1649
1650 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1651 {
1652 TRACE("%p ref=%u\n", pty, pty->ref);
1653 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1654 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1655 TRACE("kind:%s\n", typekind_desc[pty->typekind]);
1656 TRACE("fct:%u var:%u impl:%u\n", pty->cFuncs, pty->cVars, pty->cImplTypes);
1657 TRACE("wTypeFlags: 0x%04x\n", pty->wTypeFlags);
1658 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1659 if (pty->typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1660 if (TRACE_ON(ole))
1661 dump_TLBFuncDesc(pty->funcdescs, pty->cFuncs);
1662 dump_TLBVarDesc(pty->vardescs, pty->cVars);
1663 dump_TLBImplType(pty->impltypes, pty->cImplTypes);
1664 }
1665
1666 static void dump_VARDESC(const VARDESC *v)
1667 {
1668 MESSAGE("memid %d\n",v->memid);
1669 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1670 MESSAGE("oInst %d\n",v->u.oInst);
1671 dump_ELEMDESC(&(v->elemdescVar));
1672 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1673 MESSAGE("varkind %d\n",v->varkind);
1674 }
1675
1676 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1677 {
1678 /* VT_LPWSTR is largest type that, may appear in type description */
1679 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1680 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1681 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1682 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1683 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1684 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1685 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1686 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1687 };
1688
1689 static void TLB_abort(void)
1690 {
1691 DebugBreak();
1692 }
1693
1694 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1695 {
1696 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1697 if (!ret) ERR("cannot allocate memory\n");
1698 return ret;
1699 }
1700
1701 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1702 {
1703 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1704 if (!ret) ERR("cannot allocate memory\n");
1705 return ret;
1706 }
1707
1708 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1709 {
1710 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1711 }
1712
1713 void heap_free(void *ptr)
1714 {
1715 HeapFree(GetProcessHeap(), 0, ptr);
1716 }
1717
1718 /* returns the size required for a deep copy of a typedesc into a
1719 * flat buffer */
1720 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1721 {
1722 SIZE_T size = 0;
1723
1724 if (alloc_initial_space)
1725 size += sizeof(TYPEDESC);
1726
1727 switch (tdesc->vt)
1728 {
1729 case VT_PTR:
1730 case VT_SAFEARRAY:
1731 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1732 break;
1733 case VT_CARRAY:
1734 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1735 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1736 break;
1737 }
1738 return size;
1739 }
1740
1741 /* deep copy a typedesc into a flat buffer */
1742 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1743 {
1744 if (!dest)
1745 {
1746 dest = buffer;
1747 buffer = (char *)buffer + sizeof(TYPEDESC);
1748 }
1749
1750 *dest = *src;
1751
1752 switch (src->vt)
1753 {
1754 case VT_PTR:
1755 case VT_SAFEARRAY:
1756 dest->u.lptdesc = buffer;
1757 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1758 break;
1759 case VT_CARRAY:
1760 dest->u.lpadesc = buffer;
1761 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1762 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1763 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1764 break;
1765 }
1766 return buffer;
1767 }
1768
1769 /* free custom data allocated by MSFT_CustData */
1770 static inline void TLB_FreeCustData(struct list *custdata_list)
1771 {
1772 TLBCustData *cd, *cdn;
1773 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1774 {
1775 list_remove(&cd->entry);
1776 VariantClear(&cd->data);
1777 heap_free(cd);
1778 }
1779 }
1780
1781 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1782 {
1783 DWORD len;
1784 BSTR ret;
1785
1786 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1787 ret = SysAllocStringLen(NULL, len - 1);
1788 if (!ret) return ret;
1789 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1790 return ret;
1791 }
1792
1793 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1794 UINT n, MEMBERID memid)
1795 {
1796 while(n){
1797 if(funcdescs->funcdesc.memid == memid)
1798 return funcdescs;
1799 ++funcdescs;
1800 --n;
1801 }
1802 return NULL;
1803 }
1804
1805 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1806 UINT n, const OLECHAR *name)
1807 {
1808 while(n){
1809 if(!lstrcmpiW(TLB_get_bstr(funcdescs->Name), name))
1810 return funcdescs;
1811 ++funcdescs;
1812 --n;
1813 }
1814 return NULL;
1815 }
1816
1817 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1818 UINT n, MEMBERID memid)
1819 {
1820 while(n){
1821 if(vardescs->vardesc.memid == memid)
1822 return vardescs;
1823 ++vardescs;
1824 --n;
1825 }
1826 return NULL;
1827 }
1828
1829 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1830 UINT n, const OLECHAR *name)
1831 {
1832 while(n){
1833 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1834 return vardescs;
1835 ++vardescs;
1836 --n;
1837 }
1838 return NULL;
1839 }
1840
1841 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1842 {
1843 TLBCustData *cust_data;
1844 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1845 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1846 return cust_data;
1847 return NULL;
1848 }
1849
1850 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1851 UINT n, const OLECHAR *name)
1852 {
1853 while(n){
1854 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1855 return *typeinfos;
1856 ++typeinfos;
1857 --n;
1858 }
1859 return NULL;
1860 }
1861
1862 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1863 {
1864 list_init(&var_desc->custdata_list);
1865 }
1866
1867 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1868 {
1869 TLBVarDesc *ret;
1870
1871 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1872 if(!ret)
1873 return NULL;
1874
1875 while(n){
1876 TLBVarDesc_Constructor(&ret[n-1]);
1877 --n;
1878 }
1879
1880 return ret;
1881 }
1882
1883 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1884 {
1885 TLBParDesc *ret;
1886
1887 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1888 if(!ret)
1889 return NULL;
1890
1891 while(n){
1892 list_init(&ret[n-1].custdata_list);
1893 --n;
1894 }
1895
1896 return ret;
1897 }
1898
1899 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1900 {
1901 list_init(&func_desc->custdata_list);
1902 }
1903
1904 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1905 {
1906 TLBFuncDesc *ret;
1907
1908 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1909 if(!ret)
1910 return NULL;
1911
1912 while(n){
1913 TLBFuncDesc_Constructor(&ret[n-1]);
1914 --n;
1915 }
1916
1917 return ret;
1918 }
1919
1920 static void TLBImplType_Constructor(TLBImplType *impl)
1921 {
1922 list_init(&impl->custdata_list);
1923 }
1924
1925 static TLBImplType *TLBImplType_Alloc(UINT n)
1926 {
1927 TLBImplType *ret;
1928
1929 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1930 if(!ret)
1931 return NULL;
1932
1933 while(n){
1934 TLBImplType_Constructor(&ret[n-1]);
1935 --n;
1936 }
1937
1938 return ret;
1939 }
1940
1941 static TLBGuid *TLB_append_guid(struct list *guid_list,
1942 const GUID *new_guid, HREFTYPE hreftype)
1943 {
1944 TLBGuid *guid;
1945
1946 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1947 if (IsEqualGUID(&guid->guid, new_guid))
1948 return guid;
1949 }
1950
1951 guid = heap_alloc(sizeof(TLBGuid));
1952 if (!guid)
1953 return NULL;
1954
1955 memcpy(&guid->guid, new_guid, sizeof(GUID));
1956 guid->hreftype = hreftype;
1957
1958 list_add_tail(guid_list, &guid->entry);
1959
1960 return guid;
1961 }
1962
1963 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1964 {
1965 TLBCustData *cust_data;
1966
1967 switch(V_VT(var)){
1968 case VT_I4:
1969 case VT_R4:
1970 case VT_UI4:
1971 case VT_INT:
1972 case VT_UINT:
1973 case VT_HRESULT:
1974 case VT_BSTR:
1975 break;
1976 default:
1977 return DISP_E_BADVARTYPE;
1978 }
1979
1980 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1981
1982 if (!cust_data) {
1983 cust_data = heap_alloc(sizeof(TLBCustData));
1984 if (!cust_data)
1985 return E_OUTOFMEMORY;
1986
1987 cust_data->guid = tlbguid;
1988 VariantInit(&cust_data->data);
1989
1990 list_add_tail(custdata_list, &cust_data->entry);
1991 }else
1992 VariantClear(&cust_data->data);
1993
1994 return VariantCopy(&cust_data->data, var);
1995 }
1996
1997 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1998 {
1999 TLBString *str;
2000
2001 if(!new_str)
2002 return NULL;
2003
2004 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
2005 if (strcmpW(str->str, new_str) == 0)
2006 return str;
2007 }
2008
2009 str = heap_alloc(sizeof(TLBString));
2010 if (!str)
2011 return NULL;
2012
2013 str->str = SysAllocString(new_str);
2014 if (!str->str) {
2015 heap_free(str);
2016 return NULL;
2017 }
2018
2019 list_add_tail(string_list, &str->entry);
2020
2021 return str;
2022 }
2023
2024 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
2025 ULONG *size, WORD *align)
2026 {
2027 ITypeInfo *other;
2028 TYPEATTR *attr;
2029 HRESULT hr;
2030
2031 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
2032 if(FAILED(hr))
2033 return hr;
2034
2035 hr = ITypeInfo_GetTypeAttr(other, &attr);
2036 if(FAILED(hr)){
2037 ITypeInfo_Release(other);
2038 return hr;
2039 }
2040
2041 if(size)
2042 *size = attr->cbSizeInstance;
2043 if(align)
2044 *align = attr->cbAlignment;
2045
2046 ITypeInfo_ReleaseTypeAttr(other, attr);
2047 ITypeInfo_Release(other);
2048
2049 return S_OK;
2050 }
2051
2052 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
2053 TYPEDESC *tdesc, ULONG *size, WORD *align)
2054 {
2055 ULONG i, sub, ptr_size;
2056 HRESULT hr;
2057
2058 ptr_size = get_ptr_size(sys);
2059
2060 switch(tdesc->vt){
2061 case VT_VOID:
2062 *size = 0;
2063 break;
2064 case VT_I1:
2065 case VT_UI1:
2066 *size = 1;
2067 break;
2068 case VT_I2:
2069 case VT_BOOL:
2070 case VT_UI2:
2071 *size = 2;
2072 break;
2073 case VT_I4:
2074 case VT_R4:
2075 case VT_ERROR:
2076 case VT_UI4:
2077 case VT_INT:
2078 case VT_UINT:
2079 case VT_HRESULT:
2080 *size = 4;
2081 break;
2082 case VT_R8:
2083 case VT_I8:
2084 case VT_UI8:
2085 *size = 8;
2086 break;
2087 case VT_BSTR:
2088 case VT_DISPATCH:
2089 case VT_UNKNOWN:
2090 case VT_PTR:
2091 case VT_SAFEARRAY:
2092 case VT_LPSTR:
2093 case VT_LPWSTR:
2094 *size = ptr_size;
2095 break;
2096 case VT_DATE:
2097 *size = sizeof(DATE);
2098 break;
2099 case VT_VARIANT:
2100 *size = sizeof(VARIANT);
2101 #ifdef _WIN64
2102 if(sys == SYS_WIN32)
2103 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2104 #endif
2105 break;
2106 case VT_DECIMAL:
2107 *size = sizeof(DECIMAL);
2108 break;
2109 case VT_CY:
2110 *size = sizeof(CY);
2111 break;
2112 case VT_CARRAY:
2113 *size = 0;
2114 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2115 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2116 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2117 if(FAILED(hr))
2118 return hr;
2119 *size *= sub;
2120 return S_OK;
2121 case VT_USERDEFINED:
2122 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2123 default:
2124 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2125 return E_FAIL;
2126 }
2127
2128 if(align){
2129 if(*size < 4)
2130 *align = *size;
2131 else
2132 *align = 4;
2133 }
2134
2135 return S_OK;
2136 }
2137
2138 /**********************************************************************
2139 *
2140 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2141 */
2142 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
2143 {
2144 return pcx->pos;
2145 }
2146
2147 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2148 {
2149 if (where != DO_NOT_SEEK)
2150 {
2151 where += pcx->oStart;
2152 if (where > pcx->length)
2153 {
2154 /* FIXME */
2155 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2156 TLB_abort();
2157 }
2158 pcx->pos = where;
2159 }
2160 }
2161
2162 /* read function */
2163 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2164 {
2165 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2166 pcx->pos, count, pcx->oStart, pcx->length, where);
2167
2168 MSFT_Seek(pcx, where);
2169 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2170 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2171 pcx->pos += count;
2172 return count;
2173 }
2174
2175 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2176 LONG where )
2177 {
2178 DWORD ret;
2179
2180 ret = MSFT_Read(buffer, count, pcx, where);
2181 FromLEDWords(buffer, ret);
2182
2183 return ret;
2184 }
2185
2186 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2187 LONG where )
2188 {
2189 DWORD ret;
2190
2191 ret = MSFT_Read(buffer, count, pcx, where);
2192 FromLEWords(buffer, ret);
2193
2194 return ret;
2195 }
2196
2197 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2198 {
2199 TLBGuid *guid;
2200 MSFT_GuidEntry entry;
2201 int offs = 0;
2202
2203 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2204 while (1) {
2205 if (offs >= pcx->pTblDir->pGuidTab.length)
2206 return S_OK;
2207
2208 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2209
2210 guid = heap_alloc(sizeof(TLBGuid));
2211
2212 guid->offset = offs;
2213 guid->guid = entry.guid;
2214 guid->hreftype = entry.hreftype;
2215
2216 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2217
2218 offs += sizeof(MSFT_GuidEntry);
2219 }
2220 }
2221
2222 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2223 {
2224 TLBGuid *ret;
2225
2226 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2227 if(ret->offset == offset){
2228 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2229 return ret;
2230 }
2231 }
2232
2233 return NULL;
2234 }
2235
2236 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2237 {
2238 MSFT_NameIntro niName;
2239
2240 if (offset < 0)
2241 {
2242 ERR_(typelib)("bad offset %d\n", offset);
2243 return -1;
2244 }
2245
2246 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2247 pcx->pTblDir->pNametab.offset+offset);
2248
2249 return niName.hreftype;
2250 }
2251
2252 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2253 {
2254 char *string;
2255 MSFT_NameIntro intro;
2256 INT16 len_piece;
2257 int offs = 0, lengthInChars;
2258
2259 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2260 while (1) {
2261 TLBString *tlbstr;
2262
2263 if (offs >= pcx->pTblDir->pNametab.length)
2264 return S_OK;
2265
2266 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2267 intro.namelen &= 0xFF;
2268 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2269 if(len_piece % 4)
2270 len_piece = (len_piece + 4) & ~0x3;
2271 if(len_piece < 8)
2272 len_piece = 8;
2273
2274 string = heap_alloc(len_piece + 1);
2275 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2276 string[intro.namelen] = '\0';
2277
2278 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2279 string, -1, NULL, 0);
2280 if (!lengthInChars) {
2281 heap_free(string);
2282 return E_UNEXPECTED;
2283 }
2284
2285 tlbstr = heap_alloc(sizeof(TLBString));
2286
2287 tlbstr->offset = offs;
2288 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2289 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2290
2291 heap_free(string);
2292
2293 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2294
2295 offs += len_piece;
2296 }
2297 }
2298
2299 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2300 {
2301 TLBString *tlbstr;
2302
2303 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2304 if (tlbstr->offset == offset) {
2305 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2306 return tlbstr;
2307 }
2308 }
2309
2310 return NULL;
2311 }
2312
2313 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2314 {
2315 TLBString *tlbstr;
2316
2317 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2318 if (tlbstr->offset == offset) {
2319 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2320 return tlbstr;
2321 }
2322 }
2323
2324 return NULL;
2325 }
2326
2327 /*
2328 * read a value and fill a VARIANT structure
2329 */
2330 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2331 {
2332 int size;
2333
2334 TRACE_(typelib)("\n");
2335
2336 if(offset <0) { /* data are packed in here */
2337 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2338 V_I4(pVar) = offset & 0x3ffffff;
2339 return;
2340 }
2341 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2342 pcx->pTblDir->pCustData.offset + offset );
2343 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2344 switch (V_VT(pVar)){
2345 case VT_EMPTY: /* FIXME: is this right? */
2346 case VT_NULL: /* FIXME: is this right? */
2347 case VT_I2 : /* this should not happen */
2348 case VT_I4 :
2349 case VT_R4 :
2350 case VT_ERROR :
2351 case VT_BOOL :
2352 case VT_I1 :
2353 case VT_UI1 :
2354 case VT_UI2 :
2355 case VT_UI4 :
2356 case VT_INT :
2357 case VT_UINT :
2358 case VT_VOID : /* FIXME: is this right? */
2359 case VT_HRESULT :
2360 size=4; break;
2361 case VT_R8 :
2362 case VT_CY :
2363 case VT_DATE :
2364 case VT_I8 :
2365 case VT_UI8 :
2366 case VT_DECIMAL : /* FIXME: is this right? */
2367 case VT_FILETIME :
2368 size=8;break;
2369 /* pointer types with known behaviour */
2370 case VT_BSTR :{
2371 char * ptr;
2372 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2373 if(size == -1){
2374 V_BSTR(pVar) = NULL;
2375 }else{
2376 ptr = heap_alloc_zero(size);
2377 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2378 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2379 /* FIXME: do we need a AtoW conversion here? */
2380 V_UNION(pVar, bstrVal[size])='\0';
2381 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2382 heap_free(ptr);
2383 }
2384 }
2385 size=-4; break;
2386 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2387 case VT_DISPATCH :
2388 case VT_VARIANT :
2389 case VT_UNKNOWN :
2390 case VT_PTR :
2391 case VT_SAFEARRAY :
2392 case VT_CARRAY :
2393 case VT_USERDEFINED :
2394 case VT_LPSTR :
2395 case VT_LPWSTR :
2396 case VT_BLOB :
2397 case VT_STREAM :
2398 case VT_STORAGE :
2399 case VT_STREAMED_OBJECT :
2400 case VT_STORED_OBJECT :
2401 case VT_BLOB_OBJECT :
2402 case VT_CF :
2403 case VT_CLSID :
2404 default:
2405 size=0;
2406 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2407 V_VT(pVar));
2408 }
2409
2410 if(size>0) /* (big|small) endian correct? */
2411 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2412 return;
2413 }
2414 /*
2415 * create a linked list with custom data
2416 */
2417 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2418 {
2419 MSFT_CDGuid entry;
2420 TLBCustData* pNew;
2421 int count=0;
2422
2423 TRACE_(typelib)("\n");
2424
2425 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2426
2427 while(offset >=0){
2428 count++;
2429 pNew=heap_alloc_zero(sizeof(TLBCustData));
2430 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2431 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2432 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2433 list_add_head(custdata_list, &pNew->entry);
2434 offset = entry.next;
2435 }
2436 return count;
2437 }
2438
2439 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2440 {
2441 if(type <0)
2442 pTd->vt=type & VT_TYPEMASK;
2443 else
2444 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2445
2446 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2447 }
2448
2449 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2450 {
2451 return (invkind == INVOKE_PROPERTYGET ||
2452 invkind == INVOKE_PROPERTYPUT ||
2453 invkind == INVOKE_PROPERTYPUTREF);
2454 }
2455
2456 static void
2457 MSFT_DoFuncs(TLBContext* pcx,
2458 ITypeInfoImpl* pTI,
2459 int cFuncs,
2460 int cVars,
2461 int offset,
2462 TLBFuncDesc** pptfd)
2463 {
2464 /*
2465 * member information is stored in a data structure at offset
2466 * indicated by the memoffset field of the typeinfo structure
2467 * There are several distinctive parts.
2468 * The first part starts with a field that holds the total length
2469 * of this (first) part excluding this field. Then follow the records,
2470 * for each member there is one record.
2471 *
2472 * The first entry is always the length of the record (including this
2473 * length word).
2474 * The rest of the record depends on the type of the member. If there is
2475 * a field indicating the member type (function, variable, interface, etc)
2476 * I have not found it yet. At this time we depend on the information
2477 * in the type info and the usual order how things are stored.
2478 *
2479 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2480 * for each member;
2481 *
2482 * Third is an equal sized array with file offsets to the name entry
2483 * of each member.
2484 *
2485 * The fourth and last (?) part is an array with offsets to the records
2486 * in the first part of this file segment.
2487 */
2488
2489 int infolen, nameoffset, reclength, i;
2490 int recoffset = offset + sizeof(INT);
2491
2492 char *recbuf = heap_alloc(0xffff);
2493 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2494 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2495
2496 TRACE_(typelib)("\n");
2497
2498 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2499
2500 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2501 ptfd = *pptfd;
2502 for ( i = 0; i < cFuncs ; i++ )
2503 {
2504 int optional;
2505
2506 /* name, eventually add to a hash table */
2507 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2508 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2509
2510 /* read the function information record */
2511 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2512
2513 reclength &= 0xffff;
2514
2515 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2516
2517 /* size without argument data */
2518 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2519 if (pFuncRec->FKCCIC & 0x1000)
2520 optional -= pFuncRec->nrargs * sizeof(INT);
2521
2522 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2523 ptfd->helpcontext = pFuncRec->HelpContext;
2524
2525 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2526 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2527
2528 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2529 {
2530 if (pFuncRec->FKCCIC & 0x2000 )
2531 {
2532 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2533 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2534 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2535 }
2536 else
2537 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2538 }
2539 else
2540 ptfd->Entry = (TLBString*)-1;
2541
2542 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2543 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2544
2545 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2546 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2547
2548 /* fill the FuncDesc Structure */
2549 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2550 offset + infolen + ( i + 1) * sizeof(INT));
2551
2552 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2553 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2554 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2555 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2556 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2557 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2558 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2559
2560 /* nameoffset is sometimes -1 on the second half of a propget/propput
2561 * pair of functions */
2562 if ((nameoffset == -1) && (i > 0) &&
2563 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2564 TLB_is_propgetput(ptfd->funcdesc.invkind))
2565 ptfd->Name = ptfd_prev->Name;
2566 else
2567 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2568
2569 MSFT_GetTdesc(pcx,
2570 pFuncRec->DataType,
2571 &ptfd->funcdesc.elemdescFunc.tdesc);
2572
2573 /* do the parameters/arguments */
2574 if(pFuncRec->nrargs)
2575 {
2576 int j = 0;
2577 MSFT_ParameterInfo paraminfo;
2578
2579 ptfd->funcdesc.lprgelemdescParam =
2580 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2581
2582 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2583
2584 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2585 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2586
2587 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2588 {
2589 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2590
2591 MSFT_GetTdesc(pcx,
2592 paraminfo.DataType,
2593 &elemdesc->tdesc);
2594
2595 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2596
2597 /* name */
2598 if (paraminfo.oName != -1)
2599 ptfd->pParamDesc[j].Name =
2600 MSFT_ReadName( pcx, paraminfo.oName );
2601 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2602
2603 /* default value */
2604 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2605 (pFuncRec->FKCCIC & 0x1000) )
2606 {
2607 INT* pInt = (INT *)((char *)pFuncRec +
2608 reclength -
2609 (pFuncRec->nrargs * 4) * sizeof(INT) );
2610
2611 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2612
2613 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2614 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2615
2616 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2617 pInt[j], pcx);
2618 }
2619 else
2620 elemdesc->u.paramdesc.pparamdescex = NULL;
2621
2622 /* custom info */
2623 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2624 j*sizeof(pFuncRec->oArgCustData[0])) &&
2625 pFuncRec->FKCCIC & 0x80 )
2626 {
2627 MSFT_CustData(pcx,
2628 pFuncRec->oArgCustData[j],
2629 &ptfd->pParamDesc[j].custdata_list);
2630 }
2631
2632 /* SEEK value = jump to offset,
2633 * from there jump to the end of record,
2634 * go back by (j-1) arguments
2635 */
2636 MSFT_ReadLEDWords( &paraminfo ,
2637 sizeof(MSFT_ParameterInfo), pcx,
2638 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2639 * sizeof(MSFT_ParameterInfo)));
2640 }
2641 }
2642
2643 /* scode is not used: archaic win16 stuff FIXME: right? */
2644 ptfd->funcdesc.cScodes = 0 ;
2645 ptfd->funcdesc.lprgscode = NULL ;
2646
2647 ptfd_prev = ptfd;
2648 ++ptfd;
2649 recoffset += reclength;
2650 }
2651 heap_free(recbuf);
2652 }
2653
2654 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2655 int cVars, int offset, TLBVarDesc ** pptvd)
2656 {
2657 int infolen, nameoffset, reclength;
2658 char recbuf[256];
2659 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2660 TLBVarDesc *ptvd;
2661 int i;
2662 int recoffset;
2663
2664 TRACE_(typelib)("\n");
2665
2666 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2667 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2668 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2669 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2670 recoffset += offset+sizeof(INT);
2671 for(i=0;i<cVars;i++, ++ptvd){
2672 /* name, eventually add to a hash table */
2673 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2674 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2675 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2676 /* read the variable information record */
2677 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2678 reclength &= 0xff;
2679 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2680
2681 /* optional data */
2682 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2683 ptvd->HelpContext = pVarRec->HelpContext;
2684
2685 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2686 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2687
2688 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2689 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2690
2691 /* fill the VarDesc Structure */
2692 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2693 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2694 ptvd->vardesc.varkind = pVarRec->VarKind;
2695 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2696 MSFT_GetTdesc(pcx, pVarRec->DataType,
2697 &ptvd->vardesc.elemdescVar.tdesc);
2698 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2699 if(pVarRec->VarKind == VAR_CONST ){
2700 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2701 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2702 pVarRec->OffsValue, pcx);
2703 } else
2704 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2705 recoffset += reclength;
2706 }
2707 }
2708
2709 /* process Implemented Interfaces of a com class */
2710 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2711 int offset)
2712 {
2713 int i;
2714 MSFT_RefRecord refrec;
2715 TLBImplType *pImpl;
2716
2717 TRACE_(typelib)("\n");
2718
2719 pTI->impltypes = TLBImplType_Alloc(count);
2720 pImpl = pTI->impltypes;
2721 for(i=0;i<count;i++){
2722 if(offset<0) break; /* paranoia */
2723 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2724 pImpl->hRef = refrec.reftype;
2725 pImpl->implflags=refrec.flags;
2726 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2727 offset=refrec.onext;
2728 ++pImpl;
2729 }
2730 }
2731
2732 #ifdef _WIN64
2733 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2734 * and some structures, and fix the alignment */
2735 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2736 {
2737 if(info->typekind == TKIND_ALIAS){
2738 switch(info->tdescAlias->vt){
2739 case VT_BSTR:
2740 case VT_DISPATCH:
2741 case VT_UNKNOWN:
2742 case VT_PTR:
2743 case VT_SAFEARRAY:
2744 case VT_LPSTR:
2745 case VT_LPWSTR:
2746 info->cbSizeInstance = sizeof(void*);
2747 info->cbAlignment = sizeof(void*);
2748 break;
2749 case VT_CARRAY:
2750 case VT_USERDEFINED:
2751 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->cbSizeInstance, &info->cbAlignment);
2752 break;
2753 case VT_VARIANT:
2754 info->cbSizeInstance = sizeof(VARIANT);
2755 info->cbAlignment = 8;
2756 default:
2757 if(info->cbSizeInstance < sizeof(void*))
2758 info->cbAlignment = info->cbSizeInstance;
2759 else
2760 info->cbAlignment = sizeof(void*);
2761 break;
2762 }
2763 }else if(info->typekind == TKIND_INTERFACE ||
2764 info->typekind == TKIND_DISPATCH ||
2765 info->typekind == TKIND_COCLASS){
2766 info->cbSizeInstance = sizeof(void*);
2767 info->cbAlignment = sizeof(void*);
2768 }
2769 }
2770 #endif
2771
2772 /*
2773 * process a typeinfo record
2774 */
2775 static ITypeInfoImpl * MSFT_DoTypeInfo(
2776 TLBContext *pcx,
2777 int count,
2778 ITypeLibImpl * pLibInfo)
2779 {
2780 MSFT_TypeInfoBase tiBase;
2781 ITypeInfoImpl *ptiRet;
2782
2783 TRACE_(typelib)("count=%u\n", count);
2784
2785 ptiRet = ITypeInfoImpl_Constructor();
2786 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2787 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2788
2789 /* this is where we are coming from */
2790 ptiRet->pTypeLib = pLibInfo;
2791 ptiRet->index=count;
2792
2793 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2794 ptiRet->lcid=pLibInfo->set_lcid; /* FIXME: correct? */
2795 ptiRet->lpstrSchema=NULL; /* reserved */
2796 ptiRet->cbSizeInstance=tiBase.size;
2797 ptiRet->typekind=tiBase.typekind & 0xF;
2798 ptiRet->cFuncs=LOWORD(tiBase.cElement);
2799 ptiRet->cVars=HIWORD(tiBase.cElement);
2800 ptiRet->cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2801 ptiRet->wTypeFlags=tiBase.flags;
2802 ptiRet->wMajorVerNum=LOWORD(tiBase.version);
2803 ptiRet->wMinorVerNum=HIWORD(tiBase.version);
2804 ptiRet->cImplTypes=tiBase.cImplTypes;
2805 ptiRet->cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2806 if(ptiRet->typekind == TKIND_ALIAS){
2807 TYPEDESC tmp;
2808 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2809 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2810 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2811 }
2812
2813 /* FIXME: */
2814 /* IDLDESC idldescType; *//* never saw this one != zero */
2815
2816 /* name, eventually add to a hash table */
2817 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2818 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2819 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2820 /* help info */
2821 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2822 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2823 ptiRet->dwHelpContext=tiBase.helpcontext;
2824
2825 if (ptiRet->typekind == TKIND_MODULE)
2826 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2827
2828 /* note: InfoType's Help file and HelpStringDll come from the containing
2829 * library. Further HelpString and Docstring appear to be the same thing :(
2830 */
2831 /* functions */
2832 if(ptiRet->cFuncs >0 )
2833 MSFT_DoFuncs(pcx, ptiRet, ptiRet->cFuncs,
2834 ptiRet->cVars,
2835 tiBase.memoffset, &ptiRet->funcdescs);
2836 /* variables */
2837 if(ptiRet->cVars >0 )
2838 MSFT_DoVars(pcx, ptiRet, ptiRet->cFuncs,
2839 ptiRet->cVars,
2840 tiBase.memoffset, &ptiRet->vardescs);
2841 if(ptiRet->cImplTypes >0 ) {
2842 switch(ptiRet->typekind)
2843 {
2844 case TKIND_COCLASS:
2845 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->cImplTypes,
2846 tiBase.datatype1);
2847 break;
2848 case TKIND_DISPATCH:
2849 /* This is not -1 when the interface is a non-base dual interface or
2850 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2851 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2852 not this interface.
2853 */
2854
2855 if (tiBase.datatype1 != -1)
2856 {
2857 ptiRet->impltypes = TLBImplType_Alloc(1);
2858 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2859 }
2860 break;
2861 default:
2862 ptiRet->impltypes = TLBImplType_Alloc(1);
2863 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2864 break;
2865 }
2866 }
2867 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2868
2869 TRACE_(typelib)("%s guid: %s kind:%s\n",
2870 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2871 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2872 typekind_desc[ptiRet->typekind]);
2873 if (TRACE_ON(typelib))
2874 dump_TypeInfo(ptiRet);
2875
2876 return ptiRet;
2877 }
2878
2879 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2880 {
2881 char *string;
2882 INT16 len_str, len_piece;
2883 int offs = 0, lengthInChars;
2884
2885 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2886 while (1) {
2887 TLBString *tlbstr;
2888
2889 if (offs >= pcx->pTblDir->pStringtab.length)
2890 return S_OK;
2891
2892 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2893 len_piece = len_str + sizeof(INT16);
2894 if(len_piece % 4)
2895 len_piece = (len_piece + 4) & ~0x3;
2896 if(len_piece < 8)
2897 len_piece = 8;
2898
2899 string = heap_alloc(len_piece + 1);
2900 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2901 string[len_str] = '\0';
2902
2903 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2904 string, -1, NULL, 0);
2905 if (!lengthInChars) {
2906 heap_free(string);
2907 return E_UNEXPECTED;
2908 }
2909
2910 tlbstr = heap_alloc(sizeof(TLBString));
2911
2912 tlbstr->offset = offs;
2913 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2914 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2915
2916 heap_free(string);
2917
2918 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2919
2920 offs += len_piece;
2921 }
2922 }
2923
2924 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2925 {
2926 TLBRefType *ref;
2927 int offs = 0;
2928
2929 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2930 while (offs < pcx->pTblDir->pImpInfo.length) {
2931 MSFT_ImpInfo impinfo;
2932 TLBImpLib *pImpLib;
2933
2934 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2935
2936 ref = heap_alloc_zero(sizeof(TLBRefType));
2937 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2938
2939 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2940 if(pImpLib->offset==impinfo.oImpFile)
2941 break;
2942
2943 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2944 ref->reference = offs;
2945 ref->pImpTLInfo = pImpLib;
2946 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2947 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2948 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2949 ref->index = TLB_REF_USE_GUID;
2950 } else
2951 ref->index = impinfo.oGuid;
2952 }else{
2953 ERR("Cannot find a reference\n");
2954 ref->reference = -1;
2955 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2956 }
2957
2958 offs += sizeof(impinfo);
2959 }
2960
2961 return S_OK;
2962 }
2963
2964 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2965 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2966 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2967 * tradeoff here.
2968 */
2969 static struct list tlb_cache = LIST_INIT(tlb_cache);
2970 static CRITICAL_SECTION cache_section;
2971 static CRITICAL_SECTION_DEBUG cache_section_debug =
2972 {
2973 0, 0, &cache_section,
2974 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2975 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2976 };
2977 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2978
2979
2980 typedef struct TLB_PEFile
2981 {
2982 IUnknown IUnknown_iface;
2983 LONG refs;
2984 HMODULE dll;
2985 HRSRC typelib_resource;
2986 HGLOBAL typelib_global;
2987 LPVOID typelib_base;
2988 } TLB_PEFile;
2989
2990 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2991 {
2992 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2993 }
2994
2995 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2996 {
2997 if (IsEqualIID(riid, &IID_IUnknown))
2998 {
2999 *ppv = iface;
3000 IUnknown_AddRef(iface);
3001 return S_OK;
3002 }
3003 *ppv = NULL;
3004 return E_NOINTERFACE;
3005 }
3006
3007 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
3008 {
3009 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
3010 return InterlockedIncrement(&This->refs);
3011 }
3012
3013 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
3014 {
3015 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
3016 ULONG refs = InterlockedDecrement(&This->refs);
3017 if (!refs)
3018 {
3019 if (This->typelib_global)
3020 FreeResource(This->typelib_global);
3021 if (This->dll)
3022 FreeLibrary(This->dll);
3023 heap_free(This);
3024 }
3025 return refs;
3026 }
3027
3028 static const IUnknownVtbl TLB_PEFile_Vtable =
3029 {
3030 TLB_PEFile_QueryInterface,
3031 TLB_PEFile_AddRef,
3032 TLB_PEFile_Release
3033 };
3034
3035 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3036 {
3037 TLB_PEFile *This;
3038 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3039
3040 This = heap_alloc(sizeof(TLB_PEFile));
3041 if (!This)
3042 return E_OUTOFMEMORY;
3043
3044 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
3045 This->refs = 1;
3046 This->dll = NULL;
3047 This->typelib_resource = NULL;
3048 This->typelib_global = NULL;
3049 This->typelib_base = NULL;
3050
3051 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
3052 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
3053
3054 if (This->dll)
3055 {
3056 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
3057 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
3058 if (This->typelib_resource)
3059 {
3060 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
3061 if (This->typelib_global)
3062 {
3063 This->typelib_base = LockResource(This->typelib_global);
3064
3065 if (This->typelib_base)
3066 {
3067 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
3068 *ppBase = This->typelib_base;
3069 *ppFile = &This->IUnknown_iface;
3070 return S_OK;
3071 }
3072 }
3073 }
3074
3075 TRACE("No TYPELIB resource found\n");
3076 hr = E_FAIL;
3077 }
3078
3079 TLB_PEFile_Release(&This->IUnknown_iface);
3080 return hr;
3081 }
3082
3083 typedef struct TLB_NEFile
3084 {
3085 IUnknown IUnknown_iface;
3086 LONG refs;
3087 LPVOID typelib_base;
3088 } TLB_NEFile;
3089
3090 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
3091 {
3092 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
3093 }
3094
3095 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3096 {
3097 if (IsEqualIID(riid, &IID_IUnknown))
3098 {
3099 *ppv = iface;
3100 IUnknown_AddRef(iface);
3101 return S_OK;
3102 }
3103 *ppv = NULL;
3104 return E_NOINTERFACE;
3105 }
3106
3107 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
3108 {
3109 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3110 return InterlockedIncrement(&This->refs);
3111 }
3112
3113 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
3114 {
3115 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3116 ULONG refs = InterlockedDecrement(&This->refs);
3117 if (!refs)
3118 {
3119 heap_free(This->typelib_base);
3120 heap_free(This);
3121 }
3122 return refs;
3123 }
3124
3125 static const IUnknownVtbl TLB_NEFile_Vtable =
3126 {
3127 TLB_NEFile_QueryInterface,
3128 TLB_NEFile_AddRef,
3129 TLB_NEFile_Release
3130 };
3131
3132 /***********************************************************************
3133 * read_xx_header [internal]
3134 */
3135 static int read_xx_header( HFILE lzfd )
3136 {
3137 IMAGE_DOS_HEADER mzh;
3138 char magic[3];
3139
3140 LZSeek( lzfd, 0, SEEK_SET );
3141 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3142 return 0;
3143 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3144 return 0;
3145
3146 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3147 if ( 2 != LZRead( lzfd, magic, 2 ) )
3148 return 0;
3149
3150 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3151
3152 if ( magic[0] == 'N' && magic[1] == 'E' )
3153 return IMAGE_OS2_SIGNATURE;
3154 if ( magic[0] == 'P' && magic[1] == 'E' )
3155 return IMAGE_NT_SIGNATURE;
3156
3157 magic[2] = '\0';
3158 WARN("Can't handle %s files.\n", magic );
3159 return 0;
3160 }
3161
3162
3163 /***********************************************************************
3164 * find_ne_resource [internal]
3165 */
3166 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3167 DWORD *resLen, DWORD *resOff )
3168 {
3169 IMAGE_OS2_HEADER nehd;
3170 NE_TYPEINFO *typeInfo;
3171 NE_NAMEINFO *nameInfo;
3172 DWORD nehdoffset;
3173 LPBYTE resTab;
3174 DWORD resTabSize;
3175 int count;
3176
3177 /* Read in NE header */
3178 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3179 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3180
3181 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3182 if ( !resTabSize )
3183 {
3184 TRACE("No resources in NE dll\n" );
3185 return FALSE;
3186 }
3187
3188 /* Read in resource table */
3189 resTab = heap_alloc( resTabSize );
3190 if ( !resTab ) return FALSE;
3191
3192 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3193 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3194 {
3195 heap_free( resTab );
3196 return FALSE;
3197 }
3198
3199 /* Find resource */
3200 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3201
3202 if (!IS_INTRESOURCE(typeid)) /* named type */
3203 {
3204 BYTE len = strlen( typeid );
3205 while (typeInfo->type_id)
3206 {
3207 if (!(typeInfo->type_id & 0x8000))
3208 {
3209 BYTE *p = resTab + typeInfo->type_id;
3210 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3211 }
3212 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3213 typeInfo->count * sizeof(NE_NAMEINFO));
3214 }
3215 }
3216 else /* numeric type id */
3217 {
3218 WORD id = LOWORD(typeid) | 0x8000;
3219 while (typeInfo->type_id)
3220 {
3221 if (typeInfo->type_id == id) goto found_type;
3222 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3223 typeInfo->count * sizeof(NE_NAMEINFO));
3224 }
3225 }
3226 TRACE("No typeid entry found for %p\n", typeid );
3227 heap_free( resTab );
3228 return FALSE;
3229
3230 found_type:
3231 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3232
3233 if (!IS_INTRESOURCE(resid)) /* named resource */
3234 {
3235 BYTE len = strlen( resid );
3236 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3237 {
3238 BYTE *p = resTab + nameInfo->id;
3239 if (nameInfo->id & 0x8000) continue;
3240 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3241 }
3242 }
3243 else /* numeric resource id */
3244 {
3245 WORD id = LOWORD(resid) | 0x8000;
3246 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3247 if (nameInfo->id == id) goto found_name;
3248 }
3249 TRACE("No resid entry found for %p\n", typeid );
3250 heap_free( resTab );
3251 return FALSE;
3252
3253 found_name:
3254 /* Return resource data */
3255 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3256 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3257
3258 heap_free( resTab );
3259 return TRUE;
3260 }
3261
3262 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3263
3264 HFILE lzfd = -1;
3265 OFSTRUCT ofs;
3266 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3267 TLB_NEFile *This;
3268
3269 This = heap_alloc(sizeof(TLB_NEFile));
3270 if (!This) return E_OUTOFMEMORY;
3271
3272 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3273 This->refs = 1;
3274 This->typelib_base = NULL;
3275
3276 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3277 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3278 {
3279 DWORD reslen, offset;
3280 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3281 {
3282 This->typelib_base = heap_alloc(reslen);
3283 if( !This->typelib_base )
3284 hr = E_OUTOFMEMORY;
3285 else
3286 {
3287 LZSeek( lzfd, offset, SEEK_SET );
3288 reslen = LZRead( lzfd, This->typelib_base, reslen );
3289 LZClose( lzfd );
3290 *ppBase = This->typelib_base;
3291 *pdwTLBLength = reslen;
3292 *ppFile = &This->IUnknown_iface;
3293 return S_OK;
3294 }
3295 }
3296 }
3297
3298 if( lzfd >= 0) LZClose( lzfd );
3299 TLB_NEFile_Release(&This->IUnknown_iface);
3300 return hr;
3301 }
3302
3303 typedef struct TLB_Mapping
3304 {
3305 IUnknown IUnknown_iface;
3306 LONG refs;
3307 HANDLE file;
3308 HANDLE mapping;
3309 LPVOID typelib_base;
3310 } TLB_Mapping;
3311
3312 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3313 {
3314 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3315 }
3316
3317 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3318 {
3319 if (IsEqualIID(riid, &IID_IUnknown))
3320 {
3321 *ppv = iface;
3322 IUnknown_AddRef(iface);
3323 return S_OK;
3324 }
3325 *ppv = NULL;
3326 return E_NOINTERFACE;
3327 }
3328
3329 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3330 {
3331 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3332 return InterlockedIncrement(&This->refs);
3333 }
3334
3335 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3336 {
3337 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3338 ULONG refs = InterlockedDecrement(&This->refs);
3339 if (!refs)
3340 {
3341 if (This->typelib_base)
3342 UnmapViewOfFile(This->typelib_base);
3343 if (This->mapping)
3344 CloseHandle(This->mapping);
3345 if (This->file != INVALID_HANDLE_VALUE)
3346 CloseHandle(This->file);
3347 heap_free(This);
3348 }
3349 return refs;
3350 }
3351
3352 static const IUnknownVtbl TLB_Mapping_Vtable =
3353 {
3354 TLB_Mapping_QueryInterface,
3355 TLB_Mapping_AddRef,
3356 TLB_Mapping_Release
3357 };
3358
3359 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3360 {
3361 TLB_Mapping *This;
3362
3363 This = heap_alloc(sizeof(TLB_Mapping));
3364 if (!This)
3365 return E_OUTOFMEMORY;
3366
3367 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3368 This->refs = 1;
3369 This->file = INVALID_HANDLE_VALUE;
3370 This->mapping = NULL;
3371 This->typelib_base = NULL;
3372
3373 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3374 if (INVALID_HANDLE_VALUE != This->file)
3375 {
3376 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3377 if (This->mapping)
3378 {
3379 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3380 if(This->typelib_base)
3381 {
3382 /* retrieve file size */
3383 *pdwTLBLength = GetFileSize(This->file, NULL);
3384 *ppBase = This->typelib_base;
3385 *ppFile = &This->IUnknown_iface;
3386 return S_OK;
3387 }
3388 }
3389 }
3390
3391 IUnknown_Release(&This->IUnknown_iface);
3392 return TYPE_E_CANTLOADLIBRARY;
3393 }
3394
3395 /****************************************************************************
3396 * TLB_ReadTypeLib
3397 *
3398 * find the type of the typelib file and map the typelib resource into
3399 * the memory
3400 */
3401
3402 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3403 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3404 {
3405 ITypeLibImpl *entry;
3406 HRESULT ret;
3407 INT index = 1;
3408 LPWSTR index_str, file = (LPWSTR)pszFileName;
3409 LPVOID pBase = NULL;
3410 DWORD dwTLBLength = 0;
3411 IUnknown *pFile = NULL;
3412 HANDLE h;
3413
3414 *ppTypeLib = NULL;
3415
3416 index_str = strrchrW(pszFileName, '\\');
3417 if(index_str && *++index_str != '\0')
3418 {
3419 LPWSTR end_ptr;
3420 LONG idx = strtolW(index_str, &end_ptr, 10);
3421 if(*end_ptr == '\0')
3422 {
3423 int str_len = index_str - pszFileName - 1;
3424 index = idx;
3425 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3426 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3427 file[str_len] = 0;
3428 }
3429 }
3430
3431 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3432 {
3433 if(strchrW(file, '\\'))
3434 {
3435 lstrcpyW(pszPath, file);
3436 }
3437 else
3438 {
3439 int len = GetSystemDirectoryW(pszPath, cchPath);
3440 pszPath[len] = '\\';
3441 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3442 }
3443 }
3444
3445 if(file != pszFileName) heap_free(file);
3446
3447 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3448 if(h != INVALID_HANDLE_VALUE){
3449 FILE_NAME_INFORMATION *info;
3450 char data[MAX_PATH * sizeof(WCHAR) + sizeof(info->FileNameLength)];
3451 BOOL br;
3452
3453 info = (FILE_NAME_INFORMATION*)data;
3454 /* GetFileInformationByHandleEx returns the path of the file without
3455 * WOW64 redirection */
3456 br = GetFileInformationByHandleEx(h, FileNameInfo, data, sizeof(data));
3457 if(br){
3458 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3459 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3460 }
3461 CloseHandle(h);
3462 }
3463
3464 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3465
3466 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3467 EnterCriticalSection(&cache_section);
3468 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3469 {
3470 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3471 {
3472 TRACE("cache hit\n");
3473 *ppTypeLib = &entry->ITypeLib2_iface;
3474 ITypeLib2_AddRef(*ppTypeLib);
3475 LeaveCriticalSection(&cache_section);
3476 return S_OK;
3477 }
3478 }
3479 LeaveCriticalSection(&cache_section);
3480
3481 /* now actually load and parse the typelib */
3482
3483 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3484 if (ret == TYPE_E_CANTLOADLIBRARY)
3485 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3486 if (ret == TYPE_E_CANTLOADLIBRARY)
3487 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3488 if (SUCCEEDED(ret))
3489 {
3490 if (dwTLBLength >= 4)
3491 {
3492 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3493 if (dwSignature == MSFT_SIGNATURE)
3494 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3495 else if (dwSignature == SLTG_SIGNATURE)
3496 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3497 else
3498 {
3499 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3500 ret = TYPE_E_CANTLOADLIBRARY;
3501 }
3502 }
3503 else
3504 ret = TYPE_E_CANTLOADLIBRARY;
3505 IUnknown_Release(pFile);
3506 }
3507
3508 if(*ppTypeLib) {
3509 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3510
3511 TRACE("adding to cache\n");
3512 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3513 lstrcpyW(impl->path, pszPath);
3514 /* We should really canonicalise the path here. */
3515 impl->index = index;
3516
3517 /* FIXME: check if it has added already in the meantime */
3518 EnterCriticalSection(&cache_section);
3519 list_add_head(&tlb_cache, &impl->entry);
3520 LeaveCriticalSection(&cache_section);
3521 ret = S_OK;
3522 }
3523 else
3524 {
3525 if(ret != E_FAIL)
3526 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3527
3528 ret = TYPE_E_CANTLOADLIBRARY;
3529 }
3530
3531
3532 return ret;
3533 }
3534
3535 /*================== ITypeLib(2) Methods ===================================*/
3536
3537 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3538 {
3539 ITypeLibImpl* pTypeLibImpl;
3540
3541 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3542 if (!pTypeLibImpl) return NULL;
3543
3544 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3545 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3546 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3547 pTypeLibImpl->ref = 1;
3548
3549 list_init(&pTypeLibImpl->implib_list);
3550 list_init(&pTypeLibImpl->custdata_list);
3551 list_init(&pTypeLibImpl->name_list);
3552 list_init(&pTypeLibImpl->string_list);
3553 list_init(&pTypeLibImpl->guid_list);
3554 list_init(&pTypeLibImpl->ref_list);
3555 pTypeLibImpl->dispatch_href = -1;
3556
3557 return pTypeLibImpl;
3558 }
3559
3560 /****************************************************************************
3561 * ITypeLib2_Constructor_MSFT
3562 *
3563 * loading an MSFT typelib from an in-memory image
3564 */
3565 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3566 {
3567 TLBContext cx;
3568 LONG lPSegDir;
3569 MSFT_Header tlbHeader;
3570 MSFT_SegDir tlbSegDir;
3571 ITypeLibImpl * pTypeLibImpl;
3572 int i;
3573
3574 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3575
3576 pTypeLibImpl = TypeLibImpl_Constructor();
3577 if (!pTypeLibImpl) return NULL;
3578
3579 /* get pointer to beginning of typelib data */
3580 cx.pos = 0;
3581 cx.oStart=0;
3582 cx.mapping = pLib;
3583 cx.pLibInfo = pTypeLibImpl;
3584 cx.length = dwTLBLength;
3585
3586 /* read header */
3587 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3588 TRACE_(typelib)("header:\n");
3589 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3590 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3591 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3592 return NULL;
3593 }
3594 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3595
3596 /* there is a small amount of information here until the next important
3597 * part:
3598 * the segment directory . Try to calculate the amount of data */
3599 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3600
3601 /* now read the segment directory */
3602 TRACE("read segment directory (at %d)\n",lPSegDir);
3603 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3604 cx.pTblDir = &tlbSegDir;
3605
3606 /* just check two entries */
3607 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3608 {
3609 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3610 heap_free(pTypeLibImpl);
3611 return NULL;
3612 }
3613
3614 MSFT_ReadAllNames(&cx);
3615 MSFT_ReadAllStrings(&cx);
3616 MSFT_ReadAllGuids(&cx);
3617
3618 /* now fill our internal data */
3619 /* TLIBATTR fields */
3620 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3621
3622 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3623 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3624 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3625 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3626 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3627
3628 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3629 pTypeLibImpl->lcid = tlbHeader.lcid;
3630
3631 /* name, eventually add to a hash table */
3632 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3633
3634 /* help info */
3635 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3636 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3637
3638 if( tlbHeader.varflags & HELPDLLFLAG)
3639 {
3640 int offset;
3641 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3642 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3643 }
3644
3645 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3646
3647 /* custom data */
3648 if(tlbHeader.CustomDataOffset >= 0)
3649 {
3650 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3651 }
3652
3653 /* fill in type descriptions */
3654 if(tlbSegDir.pTypdescTab.length > 0)
3655 {
3656 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3657 INT16 td[4];
3658 pTypeLibImpl->ctTypeDesc = cTD;
3659 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3660 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3661 for(i=0; i<cTD; )
3662 {
3663 /* FIXME: add several sanity checks here */
3664 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3665 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3666 {
3667 /* FIXME: check safearray */
3668 if(td[3] < 0)
3669 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3670 else
3671 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3672 }
3673 else if(td[0] == VT_CARRAY)
3674 {
3675 /* array descr table here */
3676 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3677 }
3678 else if(td[0] == VT_USERDEFINED)
3679 {
3680 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3681 }
3682 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3683 }
3684
3685 /* second time around to fill the array subscript info */
3686 for(i=0;i<cTD;i++)
3687 {
3688 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3689 if(tlbSegDir.pArrayDescriptions.offset>0)
3690 {
3691 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3692 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3693
3694 if(td[1]<0)
3695 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3696 else
3697 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3698
3699 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3700
3701 for(j = 0; j<td[2]; j++)
3702 {
3703 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3704 sizeof(INT), &cx, DO_NOT_SEEK);
3705 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3706 sizeof(INT), &cx, DO_NOT_SEEK);
3707 }
3708 }
3709 else
3710 {
3711 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3712 ERR("didn't find array description data\n");
3713 }
3714 }
3715 }
3716
3717 /* imported type libs */
3718 if(tlbSegDir.pImpFiles.offset>0)
3719 {
3720 TLBImpLib *pImpLib;
3721 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3722 UINT16 size;
3723
3724 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3725 {
3726 char *name;
3727
3728 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3729 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3730 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3731
3732 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3733 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3734 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3735 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3736
3737 size >>= 2;
3738 name = heap_alloc_zero(size+1);
3739 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3740 pImpLib->name = TLB_MultiByteToBSTR(name);
3741 heap_free(name);
3742
3743 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3744 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3745
3746 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3747 }
3748 }
3749
3750 MSFT_ReadAllRefs(&cx);
3751
3752 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3753
3754 /* type infos */
3755 if(tlbHeader.nrtypeinfos >= 0 )
3756 {
3757 ITypeInfoImpl **ppTI;
3758
3759 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3760
3761 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3762 {
3763 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3764
3765 ++ppTI;
3766 (pTypeLibImpl->TypeInfoCount)++;
3767 }
3768 }
3769
3770 #ifdef _WIN64
3771 if(pTypeLibImpl->syskind == SYS_WIN32){
3772 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3773 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3774 }
3775 #endif
3776
3777 TRACE("(%p)\n", pTypeLibImpl);
3778 return &pTypeLibImpl->ITypeLib2_iface;
3779 }
3780
3781
3782 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3783 {
3784 char b[3];
3785 int i;
3786 short s;
3787
3788 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3789 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3790 return FALSE;
3791 }
3792
3793 guid->Data4[0] = s >> 8;
3794 guid->Data4[1] = s & 0xff;
3795
3796 b[2] = '\0';
3797 for(i = 0; i < 6; i++) {
3798 memcpy(b, str + 24 + 2 * i, 2);
3799 guid->Data4[i + 2] = strtol(b, NULL, 16);
3800 }
3801 return TRUE;
3802 }
3803
3804 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3805 {
3806 WORD bytelen;
3807 DWORD len;
3808 BSTR tmp_str;
3809
3810 *pStr = NULL;
3811 bytelen = *(const WORD*)ptr;
3812 if(bytelen == 0xffff) return 2;
3813
3814 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3815 tmp_str = SysAllocStringLen(NULL, len);
3816 if (tmp_str) {
3817 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3818 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3819 SysFreeString(tmp_str);
3820 }
3821 return bytelen + 2;
3822 }
3823
3824 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3825 {
3826 WORD bytelen;
3827
3828 *str = NULL;
3829 bytelen = *(const WORD*)ptr;
3830 if(bytelen == 0xffff) return 2;
3831 *str = heap_alloc(bytelen + 1);
3832 memcpy(*str, ptr + 2, bytelen);
3833 (*str)[bytelen] = '\0';
3834 return bytelen + 2;
3835 }
3836
3837 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3838 {
3839 BSTR tmp_str;
3840 TLBString *tlbstr;
3841
3842 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3843 if (tlbstr->offset == offset)
3844 return tlbstr;
3845 }
3846
3847 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3848 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3849 SysFreeString(tmp_str);
3850
3851 return tlbstr;
3852 }
3853
3854 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3855 {
3856 char *ptr = pLibBlk;
3857 WORD w;
3858
3859 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3860 FIXME("libblk magic = %04x\n", w);
3861 return 0;
3862 }
3863
3864 ptr += 6;
3865 if((w = *(WORD*)ptr) != 0xffff) {
3866 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3867 ptr += w;
3868 }
3869 ptr += 2;
3870
3871 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3872
3873 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3874
3875 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3876 ptr += 4;
3877
3878 pTypeLibImpl->syskind = *(WORD*)ptr;
3879 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3880 ptr += 2;
3881
3882 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3883 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3884 else
3885 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3886 ptr += 2;
3887
3888 ptr += 4; /* skip res12 */
3889
3890 pTypeLibImpl->libflags = *(WORD*)ptr;
3891 ptr += 2;
3892
3893 pTypeLibImpl->ver_major = *(WORD*)ptr;
3894 ptr += 2;
3895
3896 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3897 ptr += 2;
3898
3899 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3900 ptr += sizeof(GUID);
3901
3902 return ptr - (char*)pLibBlk;
3903 }
3904
3905 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3906 typedef struct
3907 {
3908 unsigned int num;
3909 HREFTYPE refs[1];
3910 } sltg_ref_lookup_t;
3911
3912 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3913 HREFTYPE *typelib_ref)
3914 {
3915 if(table && typeinfo_ref < table->num)
3916 {
3917 *typelib_ref = table->refs[typeinfo_ref];
3918 return S_OK;
3919 }
3920
3921 ERR_(typelib)("Unable to find reference\n");
3922 *typelib_ref = -1;
3923 return E_FAIL;
3924 }
3925
3926 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3927 {
3928 BOOL done = FALSE;
3929
3930 while(!done) {
3931 if((*pType & 0xe00) == 0xe00) {
3932 pTD->vt = VT_PTR;
3933 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3934 pTD = pTD->u.lptdesc;
3935 }
3936 switch(*pType & 0x3f) {
3937 case VT_PTR:
3938 pTD->vt = VT_PTR;
3939 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3940 pTD = pTD->u.lptdesc;
3941 break;
3942
3943 case VT_USERDEFINED:
3944 pTD->vt = VT_USERDEFINED;
3945 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3946 done = TRUE;
3947 break;
3948
3949 case VT_CARRAY:
3950 {
3951 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3952 array */
3953
3954 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3955
3956 pTD->vt = VT_CARRAY;
3957 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3958 pTD->u.lpadesc->cDims = pSA->cDims;
3959 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3960 pSA->cDims * sizeof(SAFEARRAYBOUND));
3961
3962 pTD = &pTD->u.lpadesc->tdescElem;
3963 break;
3964 }
3965
3966 case VT_SAFEARRAY:
3967 {
3968 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3969 useful? */
3970
3971 pType++;
3972 pTD->vt = VT_SAFEARRAY;
3973 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3974 pTD = pTD->u.lptdesc;
3975 break;
3976 }
3977 default:
3978 pTD->vt = *pType & 0x3f;
3979 done = TRUE;
3980 break;
3981 }
3982 pType++;
3983 }
3984 return pType;
3985 }
3986
3987 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3988 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3989 {
3990 /* Handle [in/out] first */
3991 if((*pType & 0xc000) == 0xc000)
3992 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3993 else if(*pType & 0x8000)
3994 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3995 else if(*pType & 0x4000)
3996 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3997 else
3998 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3999
4000 if(*pType & 0x2000)
4001 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
4002
4003 if(*pType & 0x80)
4004 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
4005
4006 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
4007 }
4008
4009
4010 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
4011 char *pNameTable)
4012 {
4013 unsigned int ref;
4014 char *name;
4015 TLBRefType *ref_type;
4016 sltg_ref_lookup_t *table;
4017 HREFTYPE typelib_ref;
4018
4019 if(pRef->magic != SLTG_REF_MAGIC) {
4020 FIXME("Ref magic = %x\n", pRef->magic);
4021 return NULL;
4022 }
4023 name = ( (char*)pRef->names + pRef->number);
4024
4025 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
4026 table->num = pRef->number >> 3;
4027
4028 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
4029
4030 /* We don't want the first href to be 0 */
4031 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
4032
4033 for(ref = 0; ref < pRef->number >> 3; ref++) {
4034 char *refname;
4035 unsigned int lib_offs, type_num;
4036
4037 ref_type = heap_alloc_zero(sizeof(TLBRefType));
4038
4039 name += SLTG_ReadStringA(name, &refname);
4040 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
4041 FIXME_(typelib)("Can't sscanf ref\n");
4042 if(lib_offs != 0xffff) {
4043 TLBImpLib *import;
4044
4045 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
4046 if(import->offset == lib_offs)
4047 break;
4048
4049 if(&import->entry == &pTL->implib_list) {
4050 char fname[MAX_PATH+1];
4051 int len;
4052 GUID tmpguid;
4053
4054 import = heap_alloc_zero(sizeof(*import));
4055 import->offset = lib_offs;
4056 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
4057 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
4058 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
4059 &import->wVersionMajor,
4060 &import->wVersionMinor,
4061 &import->lcid, fname) != 4) {
4062 FIXME_(typelib)("can't sscanf ref %s\n",
4063 pNameTable + lib_offs + 40);
4064 }
4065 len = strlen(fname);
4066 if(fname[len-1] != '#')
4067 FIXME("fname = %s\n", fname);
4068 fname[len-1] = '\0';
4069 import->name = TLB_MultiByteToBSTR(fname);
4070 list_add_tail(&pTL->implib_list, &import->entry);
4071 }
4072 ref_type->pImpTLInfo = import;
4073
4074 /* Store a reference to IDispatch */
4075 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
4076 pTL->dispatch_href = typelib_ref;
4077
4078 } else { /* internal ref */
4079 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
4080 }
4081 ref_type->reference = typelib_ref;
4082 ref_type->index = type_num;
4083
4084 heap_free(refname);
4085 list_add_tail(&pTL->ref_list, &ref_type->entry);
4086
4087 table->refs[ref] = typelib_ref;
4088 typelib_ref += 4;
4089 }
4090 if((BYTE)*name != SLTG_REF_MAGIC)
4091 FIXME_(typelib)("End of ref block magic = %x\n", *name);
4092 dump_TLBRefType(pTL);
4093 return table;
4094 }
4095
4096 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
4097 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
4098 {
4099 SLTG_ImplInfo *info;
4100 TLBImplType *pImplType;
4101 /* I don't really get this structure, usually it's 0x16 bytes
4102 long, but iuser.tlb contains some that are 0x18 bytes long.
4103 That's ok because we can use the next ptr to jump to the next
4104 one. But how do we know the length of the last one? The WORD
4105 at offs 0x8 might be the clue. For now I'm just assuming that
4106 the last one is the regular 0x16 bytes. */
4107
4108 info = (SLTG_ImplInfo*)pBlk;
4109 while(1){
4110 pTI->cImplTypes++;
4111 if(info->next == 0xffff)
4112 break;
4113 info = (SLTG_ImplInfo*)(pBlk + info->next);
4114 }
4115
4116 info = (SLTG_ImplInfo*)pBlk;
4117 pTI->impltypes = TLBImplType_Alloc(pTI->cImplTypes);
4118 pImplType = pTI->impltypes;
4119 while(1) {
4120 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4121 pImplType->implflags = info->impltypeflags;
4122 ++pImplType;
4123
4124 if(info->next == 0xffff)
4125 break;
4126 if(OneOnly)
4127 FIXME_(typelib)("Interface inheriting more than one interface\n");
4128 info = (SLTG_ImplInfo*)(pBlk + info->next);
4129 }
4130 info++; /* see comment at top of function */
4131 return (char*)info;
4132 }
4133
4134 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4135 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4136 {
4137 TLBVarDesc *pVarDesc;
4138 const TLBString *prevName = NULL;
4139 SLTG_Variable *pItem;
4140 unsigned short i;
4141 WORD *pType;
4142
4143 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4144
4145 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4146 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4147
4148 pVarDesc->vardesc.memid = pItem->memid;
4149
4150 if (pItem->magic != SLTG_VAR_MAGIC &&
4151 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4152 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4153 return;
4154 }
4155
4156 if (pItem->name == 0xfffe)
4157 pVarDesc->Name = prevName;
4158 else
4159 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4160
4161 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4162 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4163 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4164
4165 if(pItem->flags & 0x02)
4166 pType = &pItem->type;
4167 else
4168 pType = (WORD*)(pBlk + pItem->type);
4169
4170 if (pItem->flags & ~0xda)
4171 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4172
4173 SLTG_DoElem(pType, pBlk,
4174 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4175
4176 if (TRACE_ON(typelib)) {
4177 char buf[300];
4178 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4179 TRACE_(typelib)("elemdescVar: %s\n", buf);
4180 }
4181
4182 if (pItem->flags & 0x40) {
4183 TRACE_(typelib)("VAR_DISPATCH\n");
4184 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4185 }
4186 else if (pItem->flags & 0x10) {
4187 TRACE_(typelib)("VAR_CONST\n");
4188 pVarDesc->vardesc.varkind = VAR_CONST;
4189 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4190 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4191 if (pItem->flags & 0x08)
4192 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4193 else {
4194 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4195 {
4196 case VT_LPSTR:
4197 case VT_LPWSTR:
4198 case VT_BSTR:
4199 {
4200 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4201 BSTR str;
4202 TRACE_(typelib)("len = %u\n", len);
4203 if (len == 0xffff) {
4204 str = NULL;
4205 } else {
4206 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4207 str = SysAllocStringLen(NULL, alloc_len);
4208 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4209 }
4210 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4211 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4212 break;
4213 }
4214 case VT_I2:
4215 case VT_UI2:
4216 case VT_I4:
4217 case VT_UI4:
4218 case VT_INT:
4219 case VT_UINT:
4220 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4221 *(INT*)(pBlk + pItem->byte_offs);
4222 break;
4223 default:
4224 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4225 }
4226 }
4227 }
4228 else {
4229 TRACE_(typelib)("VAR_PERINSTANCE\n");
4230 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4231 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4232 }
4233
4234 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4235 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4236
4237 if (pItem->flags & 0x80)
4238 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4239
4240 prevName = pVarDesc->Name;
4241 }
4242 pTI->cVars = cVars;
4243 }
4244
4245 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4246 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4247 {
4248 SLTG_Function *pFunc;
4249 unsigned short i;
4250 TLBFuncDesc *pFuncDesc;
4251
4252 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4253
4254 pFuncDesc = pTI->funcdescs;
4255 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4256 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4257
4258 int param;
4259 WORD *pType, *pArg;
4260
4261 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4262 case SLTG_FUNCTION_MAGIC:
4263 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4264 break;
4265 case SLTG_DISPATCH_FUNCTION_MAGIC:
4266 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4267 break;
4268 case SLTG_STATIC_FUNCTION_MAGIC:
4269 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4270 break;
4271 default:
4272 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4273 continue;
4274 }
4275 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4276
4277 pFuncDesc->funcdesc.memid = pFunc->dispid;
4278 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4279 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4280 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4281 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4282 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4283
4284 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4285 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4286
4287 if(pFunc->retnextopt & 0x80)
4288 pType = &pFunc->rettype;
4289 else
4290 pType = (WORD*)(pBlk + pFunc->rettype);
4291
4292 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4293
4294 pFuncDesc->funcdesc.lprgelemdescParam =
4295 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4296 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4297
4298 pArg = (WORD*)(pBlk + pFunc->arg_off);
4299
4300 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4301 char *paramName = pNameTable + *pArg;
4302 BOOL HaveOffs;
4303 /* If arg type follows then paramName points to the 2nd
4304 letter of the name, else the next WORD is an offset to
4305 the arg type and paramName points to the first letter.
4306 So let's take one char off paramName and see if we're
4307 pointing at an alpha-numeric char. However if *pArg is
4308 0xffff or 0xfffe then the param has no name, the former
4309 meaning that the next WORD is the type, the latter
4310 meaning that the next WORD is an offset to the type. */
4311
4312 HaveOffs = FALSE;
4313 if(*pArg == 0xffff)
4314 paramName = NULL;
4315 else if(*pArg == 0xfffe) {
4316 paramName = NULL;
4317 HaveOffs = TRUE;
4318 }
4319 else if(paramName[-1] && !isalnum(paramName[-1]))
4320 HaveOffs = TRUE;
4321
4322 pArg++;
4323
4324 if(HaveOffs) { /* the next word is an offset to type */
4325 pType = (WORD*)(pBlk + *pArg);
4326 SLTG_DoElem(pType, pBlk,
4327 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4328 pArg++;
4329 } else {
4330 if(paramName)
4331 paramName--;
4332 pArg = SLTG_DoElem(pArg, pBlk,
4333 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4334 }
4335
4336 /* Are we an optional param ? */
4337 if(pFuncDesc->funcdesc.cParams - param <=
4338 pFuncDesc->funcdesc.cParamsOpt)
4339 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4340
4341 if(paramName) {
4342 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4343 paramName - pNameTable, pTI->pTypeLib);
4344 } else {
4345 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4346 }
4347 }
4348 }
4349 pTI->cFuncs = cFuncs;
4350 }
4351
4352 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4353 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4354 SLTG_TypeInfoTail *pTITail)
4355 {
4356 char *pFirstItem;
4357 sltg_ref_lookup_t *ref_lookup = NULL;
4358
4359 if(pTIHeader->href_table != 0xffffffff) {
4360 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4361 pNameTable);
4362 }
4363
4364 pFirstItem = pBlk;
4365
4366 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4367 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4368 }
4369 heap_free(ref_lookup);
4370 }
4371
4372
4373 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4374 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4375 const SLTG_TypeInfoTail *pTITail)
4376 {
4377 char *pFirstItem;
4378 sltg_ref_lookup_t *ref_lookup = NULL;
4379
4380 if(pTIHeader->href_table != 0xffffffff) {
4381 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4382 pNameTable);
4383 }
4384
4385 pFirstItem = pBlk;
4386
4387 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4388 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4389 }
4390
4391 if (pTITail->funcs_off != 0xffff)
4392 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4393
4394 heap_free(ref_lookup);
4395
4396 if (TRACE_ON(typelib))
4397 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4398 }
4399
4400 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4401 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4402 const SLTG_TypeInfoTail *pTITail)
4403 {
4404 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4405 }
4406
4407 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4408 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4409 const SLTG_TypeInfoTail *pTITail)
4410 {
4411 WORD *pType;
4412 sltg_ref_lookup_t *ref_lookup = NULL;
4413
4414 if (pTITail->simple_alias) {
4415 /* if simple alias, no more processing required */
4416 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4417 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4418 return;
4419 }
4420
4421 if(pTIHeader->href_table != 0xffffffff) {
4422 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4423 pNameTable);
4424 }
4425
4426 /* otherwise it is an offset to a type */
4427 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4428
4429 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4430 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4431
4432 heap_free(ref_lookup);
4433 }
4434
4435 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4436 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4437 const SLTG_TypeInfoTail *pTITail)
4438 {
4439 sltg_ref_lookup_t *ref_lookup = NULL;
4440 if (pTIHeader->href_table != 0xffffffff)
4441 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4442 pNameTable);
4443
4444 if (pTITail->vars_off != 0xffff)
4445 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4446
4447 if (pTITail->funcs_off != 0xffff)
4448 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4449
4450 if (pTITail->impls_off != 0xffff)
4451 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4452
4453 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4454 * of dispinterface functions including the IDispatch ones, so
4455 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4456 pTI->cbSizeVft = pTI->cFuncs * pTI->pTypeLib->ptr_size;
4457
4458 heap_free(ref_lookup);
4459 if (TRACE_ON(typelib))
4460 dump_TLBFuncDesc(pTI->funcdescs, pTI->cFuncs);
4461 }
4462
4463 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4464 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4465 const SLTG_TypeInfoTail *pTITail)
4466 {
4467 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4468 }
4469
4470 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4471 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4472 const SLTG_TypeInfoTail *pTITail)
4473 {
4474 sltg_ref_lookup_t *ref_lookup = NULL;
4475 if (pTIHeader->href_table != 0xffffffff)
4476 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4477 pNameTable);
4478
4479 if (pTITail->vars_off != 0xffff)
4480 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4481
4482 if (pTITail->funcs_off != 0xffff)
4483 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4484 heap_free(ref_lookup);
4485 if (TRACE_ON(typelib))
4486 dump_TypeInfo(pTI);
4487 }
4488
4489 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4490 manageable copy of it into this */
4491 typedef struct {
4492 WORD small_no;
4493 char *index_name;
4494 char *other_name;
4495 WORD res1a;
4496 WORD name_offs;
4497 WORD more_bytes;
4498 char *extra;
4499 WORD res20;
4500 DWORD helpcontext;
4501 WORD res26;
4502 GUID uuid;
4503 } SLTG_InternalOtherTypeInfo;
4504
4505 /****************************************************************************
4506 * ITypeLib2_Constructor_SLTG
4507 *
4508 * loading a SLTG typelib from an in-memory image
4509 */
4510 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4511 {
4512 ITypeLibImpl *pTypeLibImpl;
4513 SLTG_Header *pHeader;
4514 SLTG_BlkEntry *pBlkEntry;
4515 SLTG_Magic *pMagic;
4516 SLTG_Index *pIndex;
4517 SLTG_Pad9 *pPad9;
4518 LPVOID pBlk, pFirstBlk;
4519 SLTG_LibBlk *pLibBlk;
4520 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4521 char *pAfterOTIBlks = NULL;
4522 char *pNameTable, *ptr;
4523 int i;
4524 DWORD len, order;
4525 ITypeInfoImpl **ppTypeInfoImpl;
4526
4527 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4528
4529
4530 pTypeLibImpl = TypeLibImpl_Constructor();
4531 if (!pTypeLibImpl) return NULL;
4532
4533 pHeader = pLib;
4534
4535 TRACE_(typelib)("header:\n");
4536 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4537 pHeader->nrOfFileBlks );
4538 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4539 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4540 pHeader->SLTG_magic);
4541 return NULL;
4542 }
4543
4544 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4545 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4546
4547 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4548 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4549
4550 /* Next we have a magic block */
4551 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4552
4553 /* Let's see if we're still in sync */
4554 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4555 sizeof(SLTG_COMPOBJ_MAGIC))) {
4556 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4557 return NULL;
4558 }
4559 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4560 sizeof(SLTG_DIR_MAGIC))) {
4561 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4562 return NULL;
4563 }
4564
4565 pIndex = (SLTG_Index*)(pMagic+1);
4566
4567 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4568
4569 pFirstBlk = pPad9 + 1;
4570
4571 /* We'll set up a ptr to the main library block, which is the last one. */
4572
4573 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4574 pBlkEntry[order].next != 0;
4575 order = pBlkEntry[order].next - 1, i++) {
4576 pBlk = (char*)pBlk + pBlkEntry[order].len;
4577 }
4578 pLibBlk = pBlk;
4579
4580 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4581
4582 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4583 interspersed */
4584
4585 len += 0x40;
4586
4587 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4588
4589 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4590
4591
4592 ptr = (char*)pLibBlk + len;
4593
4594 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4595 WORD w, extra;
4596 len = 0;
4597
4598 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4599
4600 w = *(WORD*)(ptr + 2);
4601 if(w != 0xffff) {
4602 len += w;
4603 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4604 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4605 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4606 }
4607 w = *(WORD*)(ptr + 4 + len);
4608 if(w != 0xffff) {
4609 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4610 len += w;
4611 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4612 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4613 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4614 }
4615 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4616 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4617 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4618 if(extra) {
4619 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4620 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4621 len += extra;
4622 }
4623 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4624 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4625 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4626 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4627 len += sizeof(SLTG_OtherTypeInfo);
4628 ptr += len;
4629 }
4630
4631 pAfterOTIBlks = ptr;
4632
4633 /* Skip this WORD and get the next DWORD */
4634 len = *(DWORD*)(pAfterOTIBlks + 2);
4635
4636 /* Now add this to pLibBLk look at what we're pointing at and
4637 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4638 dust and we should be pointing at the beginning of the name
4639 table */
4640
4641 pNameTable = (char*)pLibBlk + len;
4642
4643 switch(*(WORD*)pNameTable) {
4644 case 0xffff:
4645 break;
4646 case 0x0200:
4647 pNameTable += 0x20;
4648 break;
4649 default:
4650 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4651 break;
4652 }
4653
4654 pNameTable += 0x216;
4655
4656 pNameTable += 2;
4657
4658 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4659
4660 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4661
4662
4663 /* Hopefully we now have enough ptrs set up to actually read in
4664 some TypeInfos. It's not clear which order to do them in, so
4665 I'll just follow the links along the BlkEntry chain and read
4666 them in the order in which they are in the file */
4667
4668 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4669 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4670
4671 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4672 pBlkEntry[order].next != 0;
4673 order = pBlkEntry[order].next - 1, i++) {
4674
4675 SLTG_TypeInfoHeader *pTIHeader;
4676 SLTG_TypeInfoTail *pTITail;
4677 SLTG_MemberHeader *pMemHeader;
4678
4679 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4680 FIXME_(typelib)("Index strings don't match\n");
4681 heap_free(pOtherTypeInfoBlks);
4682 return NULL;
4683 }
4684
4685 pTIHeader = pBlk;
4686 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4687 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4688 heap_free(pOtherTypeInfoBlks);
4689 return NULL;
4690 }
4691 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4692 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4693 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4694
4695 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4696 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4697 (*ppTypeInfoImpl)->index = i;
4698 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4699 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4700 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4701 (*ppTypeInfoImpl)->typekind = pTIHeader->typekind;
4702 (*ppTypeInfoImpl)->wMajorVerNum = pTIHeader->major_version;
4703 (*ppTypeInfoImpl)->wMinorVerNum = pTIHeader->minor_version;
4704 (*ppTypeInfoImpl)->wTypeFlags =
4705 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4706
4707 if((*ppTypeInfoImpl)->wTypeFlags & TYPEFLAG_FDUAL)
4708 (*ppTypeInfoImpl)->typekind = TKIND_DISPATCH;
4709
4710 if((pTIHeader->typeflags1 & 7) != 2)
4711 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4712 if(pTIHeader->typeflags3 != 2)
4713 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4714
4715 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4716 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4717 typekind_desc[pTIHeader->typekind],
4718 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4719 (*ppTypeInfoImpl)->wTypeFlags);
4720
4721 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4722
4723 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4724
4725 (*ppTypeInfoImpl)->cbAlignment = pTITail->cbAlignment;
4726 (*ppTypeInfoImpl)->cbSizeInstance = pTITail->cbSizeInstance;
4727 (*ppTypeInfoImpl)->cbSizeVft = pTITail->cbSizeVft;
4728
4729 switch(pTIHeader->typekind) {
4730 case TKIND_ENUM:
4731 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4732 pTIHeader, pTITail);
4733 break;
4734
4735 case TKIND_RECORD:
4736 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4737 pTIHeader, pTITail);
4738 break;
4739
4740 case TKIND_INTERFACE:
4741 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4742 pTIHeader, pTITail);
4743 break;
4744
4745 case TKIND_COCLASS:
4746 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4747 pTIHeader, pTITail);
4748 break;
4749
4750 case TKIND_ALIAS:
4751 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4752 pTIHeader, pTITail);
4753 break;
4754
4755 case TKIND_DISPATCH:
4756 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4757 pTIHeader, pTITail);
4758 break;
4759
4760 case TKIND_MODULE:
4761 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4762 pTIHeader, pTITail);
4763 break;
4764
4765 default:
4766 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4767 break;
4768
4769 }
4770
4771 /* could get cFuncs, cVars and cImplTypes from here
4772 but we've already set those */
4773 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4774 X(06);
4775 X(16);
4776 X(18);
4777 X(1a);
4778 X(1e);
4779 X(24);
4780 X(26);
4781 X(2a);
4782 X(2c);
4783 X(2e);
4784 X(30);
4785 X(32);
4786 X(34);
4787 #undef X
4788 ++ppTypeInfoImpl;
4789 pBlk = (char*)pBlk + pBlkEntry[order].len;
4790 }
4791
4792 if(i != pTypeLibImpl->TypeInfoCount) {
4793 FIXME("Somehow processed %d TypeInfos\n", i);
4794 heap_free(pOtherTypeInfoBlks);
4795 return NULL;
4796 }
4797
4798 heap_free(pOtherTypeInfoBlks);
4799 return &pTypeLibImpl->ITypeLib2_iface;
4800 }
4801
4802 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4803 {
4804 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4805
4806 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4807
4808 if(IsEqualIID(riid, &IID_IUnknown) ||
4809 IsEqualIID(riid,&IID_ITypeLib)||
4810 IsEqualIID(riid,&IID_ITypeLib2))
4811 {
4812 *ppv = &This->ITypeLib2_iface;
4813 }
4814 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4815 IsEqualIID(riid, &IID_ICreateTypeLib2))
4816 {
4817 *ppv = &This->ICreateTypeLib2_iface;
4818 }
4819 else
4820 {
4821 *ppv = NULL;
4822 TRACE("-- Interface: E_NOINTERFACE\n");
4823 return E_NOINTERFACE;
4824 }
4825
4826 IUnknown_AddRef((IUnknown*)*ppv);
4827 return S_OK;
4828 }
4829
4830 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4831 {
4832 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4833 ULONG ref = InterlockedIncrement(&This->ref);
4834
4835 TRACE("(%p) ref=%u\n", This, ref);
4836
4837 return ref;
4838 }
4839
4840 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4841 {
4842 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4843 ULONG ref = InterlockedDecrement(&This->ref);
4844
4845 TRACE("(%p) ref=%u\n",This, ref);
4846
4847 if (!ref)
4848 {
4849 TLBImpLib *pImpLib, *pImpLibNext;
4850 TLBRefType *ref_type;
4851 TLBString *tlbstr, *tlbstr_next;
4852 TLBGuid *tlbguid, *tlbguid_next;
4853 void *cursor2;
4854 int i;
4855
4856 /* remove cache entry */
4857 if(This->path)
4858 {
4859 TRACE("removing from cache list\n");
4860 EnterCriticalSection(&cache_section);
4861 if(This->entry.next)
4862 list_remove(&This->entry);
4863 LeaveCriticalSection(&cache_section);
4864 heap_free(This->path);
4865 }
4866 TRACE(" destroying ITypeLib(%p)\n",This);
4867
4868 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4869 list_remove(&tlbstr->entry);
4870 SysFreeString(tlbstr->str);
4871 heap_free(tlbstr);
4872 }
4873
4874 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4875 list_remove(&tlbstr->entry);
4876 SysFreeString(tlbstr->str);
4877 heap_free(tlbstr);
4878 }
4879
4880 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4881 list_remove(&tlbguid->entry);
4882 heap_free(tlbguid);
4883 }
4884
4885 TLB_FreeCustData(&This->custdata_list);
4886
4887 for (i = 0; i < This->ctTypeDesc; i++)
4888 if (This->pTypeDesc[i].vt == VT_CARRAY)
4889 heap_free(This->pTypeDesc[i].u.lpadesc);
4890
4891 heap_free(This->pTypeDesc);
4892
4893 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4894 {
4895 if (pImpLib->pImpTypeLib)
4896 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4897 SysFreeString(pImpLib->name);
4898
4899 list_remove(&pImpLib->entry);
4900 heap_free(pImpLib);
4901 }
4902
4903 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4904 {
4905 list_remove(&ref_type->entry);
4906 heap_free(ref_type);
4907 }
4908
4909 for (i = 0; i < This->TypeInfoCount; ++i){
4910 heap_free(This->typeinfos[i]->tdescAlias);
4911 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4912 }
4913 heap_free(This->typeinfos);
4914 heap_free(This);
4915 return 0;
4916 }
4917
4918 return ref;
4919 }
4920
4921 /* ITypeLib::GetTypeInfoCount
4922 *
4923 * Returns the number of type descriptions in the type library
4924 */
4925 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4926 {
4927 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4928 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4929 return This->TypeInfoCount;
4930 }
4931
4932 /* ITypeLib::GetTypeInfo
4933 *
4934 * retrieves the specified type description in the library.
4935 */
4936 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4937 ITypeLib2 *iface,
4938 UINT index,
4939 ITypeInfo **ppTInfo)
4940 {
4941 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4942
4943 TRACE("%p %u %p\n", This, index, ppTInfo);
4944
4945 if(!ppTInfo)
4946 return E_INVALIDARG;
4947
4948 if(index >= This->TypeInfoCount)
4949 return TYPE_E_ELEMENTNOTFOUND;
4950
4951 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4952 ITypeInfo_AddRef(*ppTInfo);
4953
4954 return S_OK;
4955 }
4956
4957
4958 /* ITypeLibs::GetTypeInfoType
4959 *
4960 * Retrieves the type of a type description.
4961 */
4962 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4963 ITypeLib2 *iface,
4964 UINT index,
4965 TYPEKIND *pTKind)
4966 {
4967 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4968
4969 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4970
4971 if(!pTKind)
4972 return E_INVALIDARG;
4973
4974 if(index >= This->TypeInfoCount)
4975 return TYPE_E_ELEMENTNOTFOUND;
4976
4977 *pTKind = This->typeinfos[index]->typekind;
4978
4979 return S_OK;
4980 }
4981
4982 /* ITypeLib::GetTypeInfoOfGuid
4983 *
4984 * Retrieves the type description that corresponds to the specified GUID.
4985 *
4986 */
4987 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4988 ITypeLib2 *iface,
4989 REFGUID guid,
4990 ITypeInfo **ppTInfo)
4991 {
4992 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4993 int i;
4994
4995 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4996
4997 for(i = 0; i < This->TypeInfoCount; ++i){
4998 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4999 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
5000 ITypeInfo_AddRef(*ppTInfo);
5001 return S_OK;
5002 }
5003 }
5004
5005 return TYPE_E_ELEMENTNOTFOUND;
5006 }
5007
5008 /* ITypeLib::GetLibAttr
5009 *
5010 * Retrieves the structure that contains the library's attributes.
5011 *
5012 */
5013 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
5014 ITypeLib2 *iface,
5015 LPTLIBATTR *attr)
5016 {
5017 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5018
5019 TRACE("(%p, %p)\n", This, attr);
5020
5021 if (!attr) return E_INVALIDARG;
5022
5023 *attr = heap_alloc(sizeof(**attr));
5024 if (!*attr) return E_OUTOFMEMORY;
5025
5026 (*attr)->guid = *TLB_get_guid_null(This->guid);
5027 (*attr)->lcid = This->set_lcid;
5028 (*attr)->syskind = This->syskind;
5029 (*attr)->wMajorVerNum = This->ver_major;
5030 (*attr)->wMinorVerNum = This->ver_minor;
5031 (*attr)->wLibFlags = This->libflags;
5032
5033 return S_OK;
5034 }
5035
5036 /* ITypeLib::GetTypeComp
5037 *
5038 * Enables a client compiler to bind to a library's types, variables,
5039 * constants, and global functions.
5040 *
5041 */
5042 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
5043 ITypeLib2 *iface,
5044 ITypeComp **ppTComp)
5045 {
5046 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5047
5048 TRACE("(%p)->(%p)\n",This,ppTComp);
5049 *ppTComp = &This->ITypeComp_iface;
5050 ITypeComp_AddRef(*ppTComp);
5051
5052 return S_OK;
5053 }
5054
5055 /* ITypeLib::GetDocumentation
5056 *
5057 * Retrieves the library's documentation string, the complete Help file name
5058 * and path, and the context identifier for the library Help topic in the Help
5059 * file.
5060 *
5061 * On a successful return all non-null BSTR pointers will have been set,
5062 * possibly to NULL.
5063 */
5064 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
5065 ITypeLib2 *iface,
5066 INT index,
5067 BSTR *pBstrName,
5068 BSTR *pBstrDocString,
5069 DWORD *pdwHelpContext,
5070 BSTR *pBstrHelpFile)
5071 {
5072 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5073 HRESULT result = E_INVALIDARG;
5074 ITypeInfo *pTInfo;
5075
5076 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
5077 This, index,
5078 pBstrName, pBstrDocString,
5079 pdwHelpContext, pBstrHelpFile);
5080
5081 if(index<0)
5082 {
5083 /* documentation for the typelib */
5084 if(pBstrName)
5085 {
5086 if (This->Name)
5087 {
5088 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
5089 goto memerr1;
5090 }
5091 else
5092 *pBstrName = NULL;
5093 }
5094 if(pBstrDocString)
5095 {
5096 if (This->DocString)
5097 {
5098 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
5099 goto memerr2;
5100 }
5101 else
5102 *pBstrDocString = NULL;
5103 }
5104 if(pdwHelpContext)
5105 {
5106 *pdwHelpContext = This->dwHelpContext;
5107 }
5108 if(pBstrHelpFile)
5109 {
5110 if (This->HelpFile)
5111 {
5112 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5113 goto memerr3;
5114 }
5115 else
5116 *pBstrHelpFile = NULL;
5117 }
5118
5119 result = S_OK;
5120 }
5121 else
5122 {
5123 /* for a typeinfo */
5124 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5125
5126 if(SUCCEEDED(result))
5127 {
5128 result = ITypeInfo_GetDocumentation(pTInfo,
5129 MEMBERID_NIL,
5130 pBstrName,
5131 pBstrDocString,
5132 pdwHelpContext, pBstrHelpFile);
5133
5134 ITypeInfo_Release(pTInfo);
5135 }
5136 }
5137 return result;
5138 memerr3:
5139 if (pBstrDocString) SysFreeString (*pBstrDocString);
5140 memerr2:
5141 if (pBstrName) SysFreeString (*pBstrName);
5142 memerr1:
5143 return STG_E_INSUFFICIENTMEMORY;
5144 }
5145
5146 /* ITypeLib::IsName
5147 *
5148 * Indicates whether a passed-in string contains the name of a type or member
5149 * described in the library.
5150 *
5151 */
5152 static HRESULT WINAPI ITypeLib2_fnIsName(
5153 ITypeLib2 *iface,
5154 LPOLESTR szNameBuf,
5155 ULONG lHashVal,
5156 BOOL *pfName)
5157 {
5158 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5159 int tic;
5160 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5161
5162 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5163 pfName);
5164
5165 *pfName=TRUE;
5166 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5167 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5168 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5169 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5170 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5171 int pc;
5172 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5173 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5174 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5175 goto ITypeLib2_fnIsName_exit;
5176 }
5177 }
5178 for(vrc = 0; vrc < pTInfo->cVars; ++vrc){
5179 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5180 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5181 }
5182
5183 }
5184 *pfName=FALSE;
5185
5186 ITypeLib2_fnIsName_exit:
5187 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5188 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5189
5190 return S_OK;
5191 }
5192
5193 /* ITypeLib::FindName
5194 *
5195 * Finds occurrences of a type description in a type library. This may be used
5196 * to quickly verify that a name exists in a type library.
5197 *
5198 */
5199 static HRESULT WINAPI ITypeLib2_fnFindName(
5200 ITypeLib2 *iface,
5201 LPOLESTR name,
5202 ULONG hash,
5203 ITypeInfo **ppTInfo,
5204 MEMBERID *memid,
5205 UINT16 *found)
5206 {
5207 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5208 int tic;
5209 UINT count = 0;
5210 UINT len;
5211
5212 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5213
5214 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5215 return E_INVALIDARG;
5216
5217 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5218 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5219 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5220 TLBVarDesc *var;
5221 UINT fdc;
5222
5223 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5224 memid[count] = MEMBERID_NIL;
5225 goto ITypeLib2_fnFindName_exit;
5226 }
5227
5228 for(fdc = 0; fdc < pTInfo->cFuncs; ++fdc) {
5229 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5230
5231 if(!TLB_str_memcmp(name, func->Name, len)) {
5232 memid[count] = func->funcdesc.memid;
5233 goto ITypeLib2_fnFindName_exit;
5234 }
5235 }
5236
5237 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->cVars, name);
5238 if (var) {
5239 memid[count] = var->vardesc.memid;
5240 goto ITypeLib2_fnFindName_exit;
5241 }
5242
5243 continue;
5244 ITypeLib2_fnFindName_exit:
5245 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5246 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5247 count++;
5248 }
5249 TRACE("found %d typeinfos\n", count);
5250
5251 *found = count;
5252
5253 return S_OK;
5254 }
5255
5256 /* ITypeLib::ReleaseTLibAttr
5257 *
5258 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5259 *
5260 */
5261 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5262 ITypeLib2 *iface,
5263 TLIBATTR *pTLibAttr)
5264 {
5265 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5266 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5267 heap_free(pTLibAttr);
5268 }
5269
5270 /* ITypeLib2::GetCustData
5271 *
5272 * gets the custom data
5273 */
5274 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5275 ITypeLib2 * iface,
5276 REFGUID guid,
5277 VARIANT *pVarVal)
5278 {
5279 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5280 TLBCustData *pCData;
5281
5282 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5283
5284 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5285 if(!pCData)
5286 return TYPE_E_ELEMENTNOTFOUND;
5287
5288 VariantInit(pVarVal);
5289 VariantCopy(pVarVal, &pCData->data);
5290
5291 return S_OK;
5292 }
5293
5294 /* ITypeLib2::GetLibStatistics
5295 *
5296 * Returns statistics about a type library that are required for efficient
5297 * sizing of hash tables.
5298 *
5299 */
5300 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5301 ITypeLib2 * iface,
5302 ULONG *pcUniqueNames,
5303 ULONG *pcchUniqueNames)
5304 {
5305 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5306
5307 FIXME("(%p): stub!\n", This);
5308
5309 if(pcUniqueNames) *pcUniqueNames=1;
5310 if(pcchUniqueNames) *pcchUniqueNames=1;
5311 return S_OK;
5312 }
5313
5314 /* ITypeLib2::GetDocumentation2
5315 *
5316 * Retrieves the library's documentation string, the complete Help file name
5317 * and path, the localization context to use, and the context ID for the
5318 * library Help topic in the Help file.
5319 *
5320 */
5321 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5322 ITypeLib2 * iface,
5323 INT index,
5324 LCID lcid,
5325 BSTR *pbstrHelpString,
5326 DWORD *pdwHelpStringContext,
5327 BSTR *pbstrHelpStringDll)
5328 {
5329 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5330 HRESULT result;
5331 ITypeInfo *pTInfo;
5332
5333 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5334
5335 /* the help string should be obtained from the helpstringdll,
5336 * using the _DLLGetDocumentation function, based on the supplied
5337 * lcid. Nice to do sometime...
5338 */
5339 if(index<0)
5340 {
5341 /* documentation for the typelib */
5342 if(pbstrHelpString)
5343 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5344 if(pdwHelpStringContext)
5345 *pdwHelpStringContext=This->dwHelpContext;
5346 if(pbstrHelpStringDll)
5347 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5348
5349 result = S_OK;
5350 }
5351 else
5352 {
5353 /* for a typeinfo */
5354 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5355
5356 if(SUCCEEDED(result))
5357 {
5358 ITypeInfo2 * pTInfo2;
5359 result = ITypeInfo_QueryInterface(pTInfo,
5360 &IID_ITypeInfo2,
5361 (LPVOID*) &pTInfo2);
5362
5363 if(SUCCEEDED(result))
5364 {
5365 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5366 MEMBERID_NIL,
5367 lcid,
5368 pbstrHelpString,
5369 pdwHelpStringContext,
5370 pbstrHelpStringDll);
5371
5372 ITypeInfo2_Release(pTInfo2);
5373 }
5374
5375 ITypeInfo_Release(pTInfo);
5376 }
5377 }
5378 return result;
5379 }
5380
5381 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5382 {
5383 TLBCustData *pCData;
5384 unsigned int ct;
5385 CUSTDATAITEM *cdi;
5386
5387 ct = list_count(custdata_list);
5388
5389 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5390 if(!pCustData->prgCustData)
5391 return E_OUTOFMEMORY;
5392
5393 pCustData->cCustData = ct;
5394
5395 cdi = pCustData->prgCustData;
5396 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5397 cdi->guid = *TLB_get_guid_null(pCData->guid);
5398 VariantCopy(&cdi->varValue, &pCData->data);
5399 ++cdi;
5400 }
5401
5402 return S_OK;
5403 }
5404
5405
5406 /* ITypeLib2::GetAllCustData
5407 *
5408 * Gets all custom data items for the library.
5409 *
5410 */
5411 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5412 ITypeLib2 * iface,
5413 CUSTDATA *pCustData)
5414 {
5415 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5416 TRACE("(%p)->(%p)\n", This, pCustData);
5417 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5418 }
5419
5420 static const ITypeLib2Vtbl tlbvt = {
5421 ITypeLib2_fnQueryInterface,
5422 ITypeLib2_fnAddRef,
5423 ITypeLib2_fnRelease,
5424 ITypeLib2_fnGetTypeInfoCount,
5425 ITypeLib2_fnGetTypeInfo,
5426 ITypeLib2_fnGetTypeInfoType,
5427 ITypeLib2_fnGetTypeInfoOfGuid,
5428 ITypeLib2_fnGetLibAttr,
5429 ITypeLib2_fnGetTypeComp,
5430 ITypeLib2_fnGetDocumentation,
5431 ITypeLib2_fnIsName,
5432 ITypeLib2_fnFindName,
5433 ITypeLib2_fnReleaseTLibAttr,
5434
5435 ITypeLib2_fnGetCustData,
5436 ITypeLib2_fnGetLibStatistics,
5437 ITypeLib2_fnGetDocumentation2,
5438 ITypeLib2_fnGetAllCustData
5439 };
5440
5441
5442 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5443 {
5444 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5445
5446 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5447 }
5448
5449 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5450 {
5451 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5452
5453 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5454 }
5455
5456 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5457 {
5458 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5459
5460 return ITypeLib2_Release(&This->ITypeLib2_iface);
5461 }
5462
5463 static HRESULT WINAPI ITypeLibComp_fnBind(
5464 ITypeComp * iface,
5465 OLECHAR * szName,
5466 ULONG lHash,
5467 WORD wFlags,
5468 ITypeInfo ** ppTInfo,
5469 DESCKIND * pDescKind,
5470 BINDPTR * pBindPtr)
5471 {
5472 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5473 BOOL typemismatch = FALSE;
5474 int i;
5475
5476 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5477
5478 *pDescKind = DESCKIND_NONE;
5479 pBindPtr->lptcomp = NULL;
5480 *ppTInfo = NULL;
5481
5482 for(i = 0; i < This->TypeInfoCount; ++i){
5483 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5484 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5485
5486 /* FIXME: check wFlags here? */
5487 /* FIXME: we should use a hash table to look this info up using lHash
5488 * instead of an O(n) search */
5489 if ((pTypeInfo->typekind == TKIND_ENUM) ||
5490 (pTypeInfo->typekind == TKIND_MODULE))
5491 {
5492 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5493 {
5494 *pDescKind = DESCKIND_TYPECOMP;
5495 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5496 ITypeComp_AddRef(pBindPtr->lptcomp);
5497 TRACE("module or enum: %s\n", debugstr_w(szName));
5498 return S_OK;
5499 }
5500 }
5501
5502 if ((pTypeInfo->typekind == TKIND_MODULE) ||
5503 (pTypeInfo->typekind == TKIND_ENUM))
5504 {
5505 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5506 HRESULT hr;
5507
5508 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5509 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5510 {
5511 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5512 return S_OK;
5513 }
5514 else if (hr == TYPE_E_TYPEMISMATCH)
5515 typemismatch = TRUE;
5516 }
5517
5518 if ((pTypeInfo->typekind == TKIND_COCLASS) &&
5519 (pTypeInfo->wTypeFlags & TYPEFLAG_FAPPOBJECT))
5520 {
5521 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5522 HRESULT hr;
5523 ITypeInfo *subtypeinfo;
5524 BINDPTR subbindptr;
5525 DESCKIND subdesckind;
5526
5527 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5528 &subtypeinfo, &subdesckind, &subbindptr);
5529 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5530 {
5531 TYPEDESC tdesc_appobject;
5532 const VARDESC vardesc_appobject =
5533 {
5534 -2, /* memid */
5535 NULL, /* lpstrSchema */
5536 {
5537 0 /* oInst */
5538 },
5539 {
5540 /* ELEMDESC */
5541 {
5542 /* TYPEDESC */
5543 {
5544 &tdesc_appobject
5545 },
5546 VT_PTR
5547 },
5548 },
5549 0, /* wVarFlags */
5550 VAR_STATIC /* varkind */
5551 };
5552
5553 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5554 tdesc_appobject.vt = VT_USERDEFINED;
5555
5556 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5557
5558 /* cleanup things filled in by Bind call so we can put our
5559 * application object data in there instead */
5560 switch (subdesckind)
5561 {
5562 case DESCKIND_FUNCDESC:
5563 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5564 break;
5565 case DESCKIND_VARDESC:
5566 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5567 break;
5568 default:
5569 break;
5570 }
5571 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5572
5573 if (pTypeInfo->hreftype == -1)
5574 FIXME("no hreftype for interface %p\n", pTypeInfo);
5575
5576 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5577 if (FAILED(hr))
5578 return hr;
5579
5580 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5581 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5582 ITypeInfo_AddRef(*ppTInfo);
5583 return S_OK;
5584 }
5585 else if (hr == TYPE_E_TYPEMISMATCH)
5586 typemismatch = TRUE;
5587 }
5588 }
5589
5590 if (typemismatch)
5591 {
5592 TRACE("type mismatch %s\n", debugstr_w(szName));
5593 return TYPE_E_TYPEMISMATCH;
5594 }
5595 else
5596 {
5597 TRACE("name not found %s\n", debugstr_w(szName));
5598 return S_OK;
5599 }
5600 }
5601
5602 static HRESULT WINAPI ITypeLibComp_fnBindType(
5603 ITypeComp * iface,
5604 OLECHAR * szName,
5605 ULONG lHash,
5606 ITypeInfo ** ppTInfo,
5607 ITypeComp ** ppTComp)
5608 {
5609 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5610 ITypeInfoImpl *info;
5611
5612 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5613
5614 if(!szName || !ppTInfo || !ppTComp)
5615 return E_INVALIDARG;
5616
5617 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5618 if(!info){
5619 *ppTInfo = NULL;
5620 *ppTComp = NULL;
5621 return S_OK;
5622 }
5623
5624 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5625 ITypeInfo_AddRef(*ppTInfo);
5626 *ppTComp = &info->ITypeComp_iface;
5627 ITypeComp_AddRef(*ppTComp);
5628
5629 return S_OK;
5630 }
5631
5632 static const ITypeCompVtbl tlbtcvt =
5633 {
5634
5635 ITypeLibComp_fnQueryInterface,
5636 ITypeLibComp_fnAddRef,
5637 ITypeLibComp_fnRelease,
5638
5639 ITypeLibComp_fnBind,
5640 ITypeLibComp_fnBindType
5641 };
5642
5643 /*================== ITypeInfo(2) Methods ===================================*/
5644 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5645 {
5646 ITypeInfoImpl *pTypeInfoImpl;
5647
5648 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5649 if (pTypeInfoImpl)
5650 {
5651 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5652 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5653 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5654 pTypeInfoImpl->ref = 0;
5655 pTypeInfoImpl->hreftype = -1;
5656 pTypeInfoImpl->memidConstructor = MEMBERID_NIL;
5657 pTypeInfoImpl->memidDestructor = MEMBERID_NIL;
5658 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5659 list_init(pTypeInfoImpl->pcustdata_list);
5660 }
5661 TRACE("(%p)\n", pTypeInfoImpl);
5662 return pTypeInfoImpl;
5663 }
5664
5665 /* ITypeInfo::QueryInterface
5666 */
5667 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5668 ITypeInfo2 *iface,
5669 REFIID riid,
5670 VOID **ppvObject)
5671 {
5672 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5673
5674 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5675
5676 *ppvObject=NULL;
5677 if(IsEqualIID(riid, &IID_IUnknown) ||
5678 IsEqualIID(riid,&IID_ITypeInfo)||
5679 IsEqualIID(riid,&IID_ITypeInfo2))
5680 *ppvObject = This;
5681 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5682 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5683 *ppvObject = &This->ICreateTypeInfo2_iface;
5684
5685 if(*ppvObject){
5686 ITypeInfo2_AddRef(iface);
5687 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5688 return S_OK;
5689 }
5690 TRACE("-- Interface: E_NOINTERFACE\n");
5691 return E_NOINTERFACE;
5692 }
5693
5694 /* ITypeInfo::AddRef
5695 */
5696 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5697 {
5698 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5699 ULONG ref = InterlockedIncrement(&This->ref);
5700
5701 TRACE("(%p)->ref is %u\n",This, ref);
5702
5703 if (ref == 1 /* incremented from 0 */)
5704 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5705
5706 return ref;
5707 }
5708
5709 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5710 {
5711 UINT i;
5712
5713 TRACE("destroying ITypeInfo(%p)\n",This);
5714
5715 for (i = 0; i < This->cFuncs; ++i)
5716 {
5717 int j;
5718 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5719 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5720 {
5721 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5722 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5723 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5724 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5725 }
5726 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5727 heap_free(pFInfo->pParamDesc);
5728 TLB_FreeCustData(&pFInfo->custdata_list);
5729 }
5730 heap_free(This->funcdescs);
5731
5732 for(i = 0; i < This->cVars; ++i)
5733 {
5734 TLBVarDesc *pVInfo = &This->vardescs[i];
5735 if (pVInfo->vardesc_create) {
5736 TLB_FreeVarDesc(pVInfo->vardesc_create);
5737 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5738 VariantClear(pVInfo->vardesc.u.lpvarValue);
5739 heap_free(pVInfo->vardesc.u.lpvarValue);
5740 }
5741 TLB_FreeCustData(&pVInfo->custdata_list);
5742 }
5743 heap_free(This->vardescs);
5744
5745 if(This->impltypes){
5746 for (i = 0; i < This->cImplTypes; ++i){
5747 TLBImplType *pImpl = &This->impltypes[i];
5748 TLB_FreeCustData(&pImpl->custdata_list);
5749 }
5750 heap_free(This->impltypes);
5751 }
5752
5753 TLB_FreeCustData(&This->custdata_list);
5754
5755 heap_free(This);
5756 }
5757
5758 /* ITypeInfo::Release
5759 */
5760 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5761 {
5762 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5763 ULONG ref = InterlockedDecrement(&This->ref);
5764
5765 TRACE("(%p)->(%u)\n",This, ref);
5766
5767 if (!ref)
5768 {
5769 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5770 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5771 if (not_attached_to_typelib)
5772 heap_free(This);
5773 /* otherwise This will be freed when typelib is freed */
5774 }
5775
5776 return ref;
5777 }
5778
5779 /* ITypeInfo::GetTypeAttr
5780 *
5781 * Retrieves a TYPEATTR structure that contains the attributes of the type
5782 * description.
5783 *
5784 */
5785 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5786 LPTYPEATTR *ppTypeAttr)
5787 {
5788 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5789 SIZE_T size;
5790
5791 TRACE("(%p)\n",This);
5792
5793 size = sizeof(**ppTypeAttr);
5794 if (This->typekind == TKIND_ALIAS && This->tdescAlias)
5795 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5796
5797 *ppTypeAttr = heap_alloc(size);
5798 if (!*ppTypeAttr)
5799 return E_OUTOFMEMORY;
5800
5801 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5802 (*ppTypeAttr)->lcid = This->lcid;
5803 (*ppTypeAttr)->memidConstructor = This->memidConstructor;
5804 (*ppTypeAttr)->memidDestructor = This->memidDestructor;
5805 (*ppTypeAttr)->lpstrSchema = This->lpstrSchema;
5806 (*ppTypeAttr)->cbSizeInstance = This->cbSizeInstance;
5807 (*ppTypeAttr)->typekind = This->typekind;
5808 (*ppTypeAttr)->cFuncs = This->cFuncs;
5809 (*ppTypeAttr)->cVars = This->cVars;
5810 (*ppTypeAttr)->cImplTypes = This->cImplTypes;
5811 (*ppTypeAttr)->cbSizeVft = This->cbSizeVft;
5812 (*ppTypeAttr)->cbAlignment = This->cbAlignment;
5813 (*ppTypeAttr)->wTypeFlags = This->wTypeFlags;
5814 (*ppTypeAttr)->wMajorVerNum = This->wMajorVerNum;
5815 (*ppTypeAttr)->wMinorVerNum = This->wMinorVerNum;
5816 (*ppTypeAttr)->idldescType = This->idldescType;
5817
5818 if (This->tdescAlias)
5819 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5820 This->tdescAlias, *ppTypeAttr + 1);
5821 else{
5822 (*ppTypeAttr)->tdescAlias.vt = VT_EMPTY;
5823 (*ppTypeAttr)->tdescAlias.u.lptdesc = NULL;
5824 }
5825
5826 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5827 /* This should include all the inherited funcs */
5828 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5829 /* This is always the size of IDispatch's vtbl */
5830 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5831 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5832 }
5833 return S_OK;
5834 }
5835
5836 /* ITypeInfo::GetTypeComp
5837 *
5838 * Retrieves the ITypeComp interface for the type description, which enables a
5839 * client compiler to bind to the type description's members.
5840 *
5841 */
5842 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5843 ITypeComp * *ppTComp)
5844 {
5845 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5846
5847 TRACE("(%p)->(%p)\n", This, ppTComp);
5848
5849 *ppTComp = &This->ITypeComp_iface;
5850 ITypeComp_AddRef(*ppTComp);
5851 return S_OK;
5852 }
5853
5854 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5855 {
5856 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5857 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5858 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5859 return size;
5860 }
5861
5862 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5863 {
5864 *dest = *src;
5865 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5866 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5867 {
5868 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5869 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5870 *buffer += sizeof(PARAMDESCEX);
5871 *pparamdescex_dest = *pparamdescex_src;
5872 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5873 VariantInit(&pparamdescex_dest->varDefaultValue);
5874 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5875 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5876 }
5877 else
5878 dest->u.paramdesc.pparamdescex = NULL;
5879 return S_OK;
5880 }
5881
5882 static HRESULT TLB_SanitizeBSTR(BSTR str)
5883 {
5884 UINT len = SysStringLen(str), i;
5885 for (i = 0; i < len; ++i)
5886 if (str[i] > 0x7f)
5887 str[i] = '?';
5888 return S_OK;
5889 }
5890
5891 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5892 {
5893 if (V_VT(var) == VT_INT)
5894 return VariantChangeType(var, var, 0, VT_I4);
5895 else if (V_VT(var) == VT_UINT)
5896 return VariantChangeType(var, var, 0, VT_UI4);
5897 else if (V_VT(var) == VT_BSTR)
5898 return TLB_SanitizeBSTR(V_BSTR(var));
5899
5900 return S_OK;
5901 }
5902
5903 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5904 {
5905 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5906 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5907 }
5908
5909 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5910 {
5911 FUNCDESC *dest;
5912 char *buffer;
5913 SIZE_T size = sizeof(*src);
5914 SHORT i;
5915 HRESULT hr;
5916
5917 size += sizeof(*src->lprgscode) * src->cScodes;
5918 size += TLB_SizeElemDesc(&src->elemdescFunc);
5919 for (i = 0; i < src->cParams; i++)
5920 {
5921 size += sizeof(ELEMDESC);
5922 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5923 }
5924
5925 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5926 if (!dest) return E_OUTOFMEMORY;
5927
5928 *dest = *src;
5929 if (dispinterface) /* overwrite funckind */
5930 dest->funckind = FUNC_DISPATCH;
5931 buffer = (char *)(dest + 1);
5932
5933 dest->oVft = dest->oVft & 0xFFFC;
5934
5935 if (dest->cScodes) {
5936 dest->lprgscode = (SCODE *)buffer;
5937 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5938 buffer += sizeof(*src->lprgscode) * src->cScodes;
5939 } else
5940 dest->lprgscode = NULL;
5941
5942 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5943 if (FAILED(hr))
5944 {
5945 SysFreeString((BSTR)dest);
5946 return hr;
5947 }
5948
5949 if (dest->cParams) {
5950 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5951 buffer += sizeof(ELEMDESC) * src->cParams;
5952 for (i = 0; i < src->cParams; i++)
5953 {
5954 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5955 if (FAILED(hr))
5956 break;
5957 }
5958 if (FAILED(hr))
5959 {
5960 /* undo the above actions */
5961 for (i = i - 1; i >= 0; i--)
5962 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5963 TLB_FreeElemDesc(&dest->elemdescFunc);
5964 SysFreeString((BSTR)dest);
5965 return hr;
5966 }
5967 } else
5968 dest->lprgelemdescParam = NULL;
5969
5970 /* special treatment for dispinterfaces: this makes functions appear
5971 * to return their [retval] value when it is really returning an
5972 * HRESULT */
5973 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5974 {
5975 if (dest->cParams &&
5976 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5977 {
5978 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5979 if (elemdesc->tdesc.vt != VT_PTR)
5980 {
5981 ERR("elemdesc should have started with VT_PTR instead of:\n");
5982 if (ERR_ON(ole))
5983 dump_ELEMDESC(elemdesc);
5984 return E_UNEXPECTED;
5985 }
5986
5987 /* copy last parameter to the return value. we are using a flat
5988 * buffer so there is no danger of leaking memory in
5989 * elemdescFunc */
5990 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5991
5992 /* remove the last parameter */
5993 dest->cParams--;
5994 }
5995 else
5996 /* otherwise this function is made to appear to have no return
5997 * value */
5998 dest->elemdescFunc.tdesc.vt = VT_VOID;
5999
6000 }
6001
6002 *dest_ptr = dest;
6003 return S_OK;
6004 }
6005
6006 static void TLB_FreeVarDesc(VARDESC *var_desc)
6007 {
6008 TLB_FreeElemDesc(&var_desc->elemdescVar);
6009 if (var_desc->varkind == VAR_CONST)
6010 VariantClear(var_desc->u.lpvarValue);
6011 SysFreeString((BSTR)var_desc);
6012 }
6013
6014 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
6015 {
6016 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6017
6018 if (index >= This->cFuncs)
6019 return TYPE_E_ELEMENTNOTFOUND;
6020
6021 *ppFuncDesc = &This->funcdescs[index].funcdesc;
6022 return S_OK;
6023 }
6024
6025 /* internal function to make the inherited interfaces' methods appear
6026 * part of the interface */
6027 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
6028 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
6029 {
6030 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6031 HRESULT hr;
6032 UINT implemented_funcs = 0;
6033
6034 if (funcs)
6035 *funcs = 0;
6036 else
6037 *hrefoffset = DISPATCH_HREF_OFFSET;
6038
6039 if(This->impltypes)
6040 {
6041 ITypeInfo *pSubTypeInfo;
6042 UINT sub_funcs;
6043
6044 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6045 if (FAILED(hr))
6046 return hr;
6047
6048 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
6049 index,
6050 ppFuncDesc,
6051 &sub_funcs, hrefoffset);
6052 implemented_funcs += sub_funcs;
6053 ITypeInfo_Release(pSubTypeInfo);
6054 if (SUCCEEDED(hr))
6055 return hr;
6056 *hrefoffset += DISPATCH_HREF_OFFSET;
6057 }
6058
6059 if (funcs)
6060 *funcs = implemented_funcs + This->cFuncs;
6061 else
6062 *hrefoffset = 0;
6063
6064 if (index < implemented_funcs)
6065 return E_INVALIDARG;
6066 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
6067 ppFuncDesc);
6068 }
6069
6070 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
6071 {
6072 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
6073 while (TRUE)
6074 {
6075 switch (pTypeDesc->vt)
6076 {
6077 case VT_USERDEFINED:
6078 pTypeDesc->u.hreftype += hrefoffset;
6079 return;
6080 case VT_PTR:
6081 case VT_SAFEARRAY:
6082 pTypeDesc = pTypeDesc->u.lptdesc;
6083 break;
6084 case VT_CARRAY:
6085 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
6086 break;
6087 default:
6088 return;
6089 }
6090 }
6091 }
6092
6093 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
6094 {
6095 SHORT i;
6096 for (i = 0; i < pFuncDesc->cParams; i++)
6097 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
6098 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
6099 }
6100
6101 /* ITypeInfo::GetFuncDesc
6102 *
6103 * Retrieves the FUNCDESC structure that contains information about a
6104 * specified function.
6105 *
6106 */
6107 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
6108 LPFUNCDESC *ppFuncDesc)
6109 {
6110 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6111 const FUNCDESC *internal_funcdesc;
6112 HRESULT hr;
6113 UINT hrefoffset = 0;
6114
6115 TRACE("(%p) index %d\n", This, index);
6116
6117 if (!ppFuncDesc)
6118 return E_INVALIDARG;
6119
6120 if (This->needs_layout)
6121 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6122
6123 if (This->typekind == TKIND_DISPATCH)
6124 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6125 &internal_funcdesc, NULL,
6126 &hrefoffset);
6127 else
6128 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6129 &internal_funcdesc);
6130 if (FAILED(hr))
6131 {
6132 WARN("description for function %d not found\n", index);
6133 return hr;
6134 }
6135
6136 hr = TLB_AllocAndInitFuncDesc(
6137 internal_funcdesc,
6138 ppFuncDesc,
6139 This->typekind == TKIND_DISPATCH);
6140
6141 if ((This->typekind == TKIND_DISPATCH) && hrefoffset)
6142 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6143
6144 TRACE("-- 0x%08x\n", hr);
6145 return hr;
6146 }
6147
6148 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6149 {
6150 VARDESC *dest;
6151 char *buffer;
6152 SIZE_T size = sizeof(*src);
6153 HRESULT hr;
6154
6155 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6156 if (src->varkind == VAR_CONST)
6157 size += sizeof(VARIANT);
6158 size += TLB_SizeElemDesc(&src->elemdescVar);
6159
6160 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6161 if (!dest) return E_OUTOFMEMORY;
6162
6163 *dest = *src;
6164 buffer = (char *)(dest + 1);
6165 if (src->lpstrSchema)
6166 {
6167 int len;
6168 dest->lpstrSchema = (LPOLESTR)buffer;
6169 len = strlenW(src->lpstrSchema);
6170 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6171 buffer += (len + 1) * sizeof(WCHAR);
6172 }
6173
6174 if (src->varkind == VAR_CONST)
6175 {
6176 HRESULT hr;
6177
6178 dest->u.lpvarValue = (VARIANT *)buffer;
6179 *dest->u.lpvarValue = *src->u.lpvarValue;
6180 buffer += sizeof(VARIANT);
6181 VariantInit(dest->u.lpvarValue);
6182 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6183 if (FAILED(hr))
6184 {
6185 SysFreeString((BSTR)dest);
6186 return hr;
6187 }
6188 }
6189 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6190 if (FAILED(hr))
6191 {
6192 if (src->varkind == VAR_CONST)
6193 VariantClear(dest->u.lpvarValue);
6194 SysFreeString((BSTR)dest);
6195 return hr;
6196 }
6197 *dest_ptr = dest;
6198 return S_OK;
6199 }
6200
6201 /* ITypeInfo::GetVarDesc
6202 *
6203 * Retrieves a VARDESC structure that describes the specified variable.
6204 *
6205 */
6206 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6207 LPVARDESC *ppVarDesc)
6208 {
6209 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6210 const TLBVarDesc *pVDesc = &This->vardescs[index];
6211
6212 TRACE("(%p) index %d\n", This, index);
6213
6214 if(index >= This->cVars)
6215 return TYPE_E_ELEMENTNOTFOUND;
6216
6217 if (This->needs_layout)
6218 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6219
6220 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6221 }
6222
6223 /* ITypeInfo_GetNames
6224 *
6225 * Retrieves the variable with the specified member ID (or the name of the
6226 * property or method and its parameters) that correspond to the specified
6227 * function ID.
6228 */
6229 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6230 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6231 {
6232 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6233 const TLBFuncDesc *pFDesc;
6234 const TLBVarDesc *pVDesc;
6235 int i;
6236 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6237
6238 if(!rgBstrNames)
6239 return E_INVALIDARG;
6240
6241 *pcNames = 0;
6242
6243 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
6244 if(pFDesc)
6245 {
6246 if(!cMaxNames || !pFDesc->Name)
6247 return S_OK;
6248
6249 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6250 ++(*pcNames);
6251
6252 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6253 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6254 return S_OK;
6255 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6256 ++(*pcNames);
6257 }
6258 return S_OK;
6259 }
6260
6261 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
6262 if(pVDesc)
6263 {
6264 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6265 *pcNames=1;
6266 }
6267 else
6268 {
6269 if(This->impltypes &&
6270 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
6271 /* recursive search */
6272 ITypeInfo *pTInfo;
6273 HRESULT result;
6274 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6275 if(SUCCEEDED(result))
6276 {
6277 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6278 ITypeInfo_Release(pTInfo);
6279 return result;
6280 }
6281 WARN("Could not search inherited interface!\n");
6282 }
6283 else
6284 {
6285 WARN("no names found\n");
6286 }
6287 *pcNames=0;
6288 return TYPE_E_ELEMENTNOTFOUND;
6289 }
6290 return S_OK;
6291 }
6292
6293
6294 /* ITypeInfo::GetRefTypeOfImplType
6295 *
6296 * If a type description describes a COM class, it retrieves the type
6297 * description of the implemented interface types. For an interface,
6298 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6299 * if any exist.
6300 *
6301 */
6302 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6303 ITypeInfo2 *iface,
6304 UINT index,
6305 HREFTYPE *pRefType)
6306 {
6307 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6308 HRESULT hr = S_OK;
6309
6310 TRACE("(%p) index %d\n", This, index);
6311 if (TRACE_ON(ole)) dump_TypeInfo(This);
6312
6313 if(index==(UINT)-1)
6314 {
6315 /* only valid on dual interfaces;
6316 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6317 */
6318
6319 if (This->wTypeFlags & TYPEFLAG_FDUAL)
6320 {
6321 *pRefType = -2;
6322 }
6323 else
6324 {
6325 hr = TYPE_E_ELEMENTNOTFOUND;
6326 }
6327 }
6328 else if(index == 0 && This->typekind == TKIND_DISPATCH)
6329 {
6330 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6331 *pRefType = This->pTypeLib->dispatch_href;
6332 }
6333 else
6334 {
6335 if(index >= This->cImplTypes)
6336 hr = TYPE_E_ELEMENTNOTFOUND;
6337 else{
6338 *pRefType = This->impltypes[index].hRef;
6339 if(This->typekind == TKIND_INTERFACE)
6340 *pRefType |= 0x2;
6341 }
6342 }
6343
6344 if(TRACE_ON(ole))
6345 {
6346 if(SUCCEEDED(hr))
6347 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6348 else
6349 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6350 }
6351
6352 return hr;
6353 }
6354
6355 /* ITypeInfo::GetImplTypeFlags
6356 *
6357 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6358 * or base interface in a type description.
6359 */
6360 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6361 UINT index, INT *pImplTypeFlags)
6362 {
6363 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6364
6365 TRACE("(%p) index %d\n", This, index);
6366
6367 if(!pImplTypeFlags)
6368 return E_INVALIDARG;
6369
6370 if(This->typekind == TKIND_DISPATCH && index == 0){
6371 *pImplTypeFlags = 0;
6372 return S_OK;
6373 }
6374
6375 if(index >= This->cImplTypes)
6376 return TYPE_E_ELEMENTNOTFOUND;
6377
6378 *pImplTypeFlags = This->impltypes[index].implflags;
6379
6380 return S_OK;
6381 }
6382
6383 /* GetIDsOfNames
6384 * Maps between member names and member IDs, and parameter names and
6385 * parameter IDs.
6386 */
6387 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6388 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6389 {
6390 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6391 const TLBVarDesc *pVDesc;
6392 HRESULT ret=S_OK;
6393 UINT i, fdc;
6394
6395 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6396 cNames);
6397
6398 /* init out parameters in case of failure */
6399 for (i = 0; i < cNames; i++)
6400 pMemId[i] = MEMBERID_NIL;
6401
6402 for (fdc = 0; fdc < This->cFuncs; ++fdc) {
6403 int j;
6404 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6405 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6406 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6407 for(i=1; i < cNames; i++){
6408 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6409 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6410 break;
6411 if( j<pFDesc->funcdesc.cParams)
6412 pMemId[i]=j;
6413 else
6414 ret=DISP_E_UNKNOWNNAME;
6415 };
6416 TRACE("-- 0x%08x\n", ret);
6417 return ret;
6418 }
6419 }
6420 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, *rgszNames);
6421 if(pVDesc){
6422 if(cNames)
6423 *pMemId = pVDesc->vardesc.memid;
6424 return ret;
6425 }
6426 /* not found, see if it can be found in an inherited interface */
6427 if(This->impltypes) {
6428 /* recursive search */
6429 ITypeInfo *pTInfo;
6430 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6431 if(SUCCEEDED(ret)){
6432 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6433 ITypeInfo_Release(pTInfo);
6434 return ret;
6435 }
6436 WARN("Could not search inherited interface!\n");
6437 } else
6438 WARN("no names found\n");
6439 return DISP_E_UNKNOWNNAME;
6440 }
6441
6442
6443 #ifdef __i386__
6444
6445 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6446 __ASM_GLOBAL_FUNC( call_method,
6447 "pushl %ebp\n\t"
6448 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6449 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6450 "movl %esp,%ebp\n\t"
6451 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6452 "pushl %esi\n\t"
6453 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6454 "pushl %edi\n\t"
6455 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6456 "movl 12(%ebp),%edx\n\t"
6457 "movl %esp,%edi\n\t"
6458 "shll $2,%edx\n\t"
6459 "jz 1f\n\t"
6460 "subl %edx,%edi\n\t"
6461 "andl $~15,%edi\n\t"
6462 "movl %edi,%esp\n\t"
6463 "movl 12(%ebp),%ecx\n\t"
6464 "movl 16(%ebp),%esi\n\t"
6465 "cld\n\t"
6466 "rep; movsl\n"
6467 "1:\tcall *8(%ebp)\n\t"
6468 "subl %esp,%edi\n\t"
6469 "movl 20(%ebp),%ecx\n\t"
6470 "movl %edi,(%ecx)\n\t"
6471 "leal -8(%ebp),%esp\n\t"
6472 "popl %edi\n\t"
6473 __ASM_CFI(".cfi_same_value %edi\n\t")
6474 "popl %esi\n\t"
6475 __ASM_CFI(".cfi_same_value %esi\n\t")
6476 "popl %ebp\n\t"
6477 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6478 __ASM_CFI(".cfi_same_value %ebp\n\t")
6479 "ret" )
6480
6481 /* same function but returning floating point */
6482 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6483
6484 /* ITypeInfo::Invoke
6485 *
6486 * Invokes a method, or accesses a property of an object, that implements the
6487 * interface described by the type description.
6488 */
6489 DWORD
6490 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6491 DWORD res;
6492 int stack_offset;
6493
6494 if (TRACE_ON(ole)) {
6495 int i;
6496 TRACE("Calling %p(",func);
6497 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6498 if (nrargs > 30) TRACE("...");
6499 TRACE(")\n");
6500 }
6501
6502 switch (callconv) {
6503 case CC_STDCALL:
6504 case CC_CDECL:
6505 res = call_method( func, nrargs, args, &stack_offset );
6506 break;
6507 default:
6508 FIXME("unsupported calling convention %d\n",callconv);
6509 res = -1;
6510 break;
6511 }
6512 TRACE("returns %08x\n",res);
6513 return res;
6514 }
6515
6516 #elif defined(__x86_64__)
6517
6518 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6519 __ASM_GLOBAL_FUNC( call_method,
6520 "pushq %rbp\n\t"
6521 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6522 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6523 "movq %rsp,%rbp\n\t"
6524 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6525 "pushq %rsi\n\t"
6526 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6527 "pushq %rdi\n\t"
6528 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6529 "movq %rcx,%rax\n\t"
6530 "movq $4,%rcx\n\t"
6531 "cmp %rcx,%rdx\n\t"
6532 "cmovgq %rdx,%rcx\n\t"
6533 "leaq 0(,%rcx,8),%rdx\n\t"
6534 "subq %rdx,%rsp\n\t"
6535 "andq $~15,%rsp\n\t"
6536 "movq %rsp,%rdi\n\t"
6537 "movq %r8,%rsi\n\t"
6538 "rep; movsq\n\t"
6539 "movq 0(%rsp),%rcx\n\t"
6540 "movq 8(%rsp),%rdx\n\t"
6541 "movq 16(%rsp),%r8\n\t"
6542 "movq 24(%rsp),%r9\n\t"
6543 "movq %rcx,%xmm0\n\t"
6544 "movq %rdx,%xmm1\n\t"
6545 "movq %r8,%xmm2\n\t"
6546 "movq %r9,%xmm3\n\t"
6547 "callq *%rax\n\t"
6548 "leaq -16(%rbp),%rsp\n\t"
6549 "popq %rdi\n\t"
6550 __ASM_CFI(".cfi_same_value %rdi\n\t")
6551 "popq %rsi\n\t"
6552 __ASM_CFI(".cfi_same_value %rsi\n\t")
6553 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6554 "popq %rbp\n\t"
6555 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6556 __ASM_CFI(".cfi_same_value %rbp\n\t")
6557 "ret")
6558
6559 /* same function but returning floating point */
6560 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6561
6562 #endif /* __x86_64__ */
6563
6564 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6565 {
6566 HRESULT hr = S_OK;
6567 ITypeInfo *tinfo2 = NULL;
6568 TYPEATTR *tattr = NULL;
6569
6570 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6571 if (hr)
6572 {
6573 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6574 "hr = 0x%08x\n",
6575 tdesc->u.hreftype, hr);
6576 return hr;
6577 }
6578 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6579 if (hr)
6580 {
6581 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6582 ITypeInfo_Release(tinfo2);
6583 return hr;
6584 }
6585
6586 switch (tattr->typekind)
6587 {
6588 case TKIND_ENUM:
6589 *vt |= VT_I4;
6590 break;
6591
6592 case TKIND_ALIAS:
6593 tdesc = &tattr->tdescAlias;
6594 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6595 break;
6596
6597 case TKIND_INTERFACE:
6598 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6599 *vt |= VT_DISPATCH;
6600 else
6601 *vt |= VT_UNKNOWN;
6602 break;
6603
6604 case TKIND_DISPATCH:
6605 *vt |= VT_DISPATCH;
6606 break;
6607
6608 case TKIND_COCLASS:
6609 *vt |= VT_DISPATCH;
6610 break;
6611
6612 case TKIND_RECORD:
6613 FIXME("TKIND_RECORD unhandled.\n");
6614 hr = E_NOTIMPL;
6615 break;
6616
6617 case TKIND_UNION:
6618 FIXME("TKIND_UNION unhandled.\n");
6619 hr = E_NOTIMPL;
6620 break;
6621
6622 default:
6623 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6624 hr = E_NOTIMPL;
6625 break;
6626 }
6627 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6628 ITypeInfo_Release(tinfo2);
6629 return hr;
6630 }
6631
6632 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6633 {
6634 HRESULT hr = S_OK;
6635
6636 /* enforce only one level of pointer indirection */
6637 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6638 {
6639 tdesc = tdesc->u.lptdesc;
6640
6641 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6642 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6643 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6644 if ((tdesc->vt == VT_USERDEFINED) ||
6645 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6646 {
6647 VARTYPE vt_userdefined = 0;
6648 const TYPEDESC *tdesc_userdefined = tdesc;
6649 if (tdesc->vt == VT_PTR)
6650 {
6651 vt_userdefined = VT_BYREF;
6652 tdesc_userdefined = tdesc->u.lptdesc;
6653 }
6654 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6655 if ((hr == S_OK) &&
6656 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6657 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6658 {
6659 *vt |= vt_userdefined;
6660 return S_OK;
6661 }
6662 }
6663 *vt = VT_BYREF;
6664 }
6665
6666 switch (tdesc->vt)
6667 {
6668 case VT_HRESULT:
6669 *vt |= VT_ERROR;
6670 break;
6671 case VT_USERDEFINED:
6672 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6673 break;
6674 case VT_VOID:
6675 case VT_CARRAY:
6676 case VT_PTR:
6677 case VT_LPSTR:
6678 case VT_LPWSTR:
6679 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6680 hr = DISP_E_BADVARTYPE;
6681 break;
6682 case VT_SAFEARRAY:
6683 *vt |= VT_ARRAY;
6684 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6685 break;
6686 case VT_INT:
6687 *vt |= VT_I4;
6688 break;
6689 case VT_UINT:
6690 *vt |= VT_UI4;
6691 break;
6692 default:
6693 *vt |= tdesc->vt;
6694 break;
6695 }
6696 return hr;
6697 }
6698
6699 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6700 {
6701 ITypeInfo *tinfo2;
6702 TYPEATTR *tattr;
6703 HRESULT hres;
6704
6705 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6706 if(FAILED(hres))
6707 return hres;
6708
6709 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6710 if(FAILED(hres)) {
6711 ITypeInfo_Release(tinfo2);
6712 return hres;
6713 }
6714
6715 switch(tattr->typekind) {
6716 case TKIND_ALIAS:
6717 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6718 break;
6719
6720 case TKIND_INTERFACE:
6721 case TKIND_DISPATCH:
6722 *guid = tattr->guid;
6723 break;
6724
6725 default:
6726 ERR("Unexpected typekind %d\n", tattr->typekind);
6727 hres = E_UNEXPECTED;
6728 }
6729
6730 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6731 ITypeInfo_Release(tinfo2);
6732 return hres;
6733 }
6734
6735 /***********************************************************************
6736 * DispCallFunc (OLEAUT32.@)
6737 *
6738 * Invokes a function of the specified calling convention, passing the
6739 * specified arguments and returns the result.
6740 *
6741 * PARAMS
6742 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6743 * oVft [I] The offset in the vtable. See notes.
6744 * cc [I] Calling convention of the function to call.
6745 * vtReturn [I] The return type of the function.
6746 * cActuals [I] Number of parameters.
6747 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6748 * prgpvarg [I] The arguments to pass.
6749 * pvargResult [O] The return value of the function. Can be NULL.
6750 *
6751 * RETURNS
6752 * Success: S_OK.
6753 * Failure: HRESULT code.
6754 *
6755 * NOTES
6756 * The HRESULT return value of this function is not affected by the return
6757 * value of the user supplied function, which is returned in pvargResult.
6758 *
6759 * If pvInstance is NULL then a non-object function is to be called and oVft
6760 * is the address of the function to call.
6761 *
6762 * The cc parameter can be one of the following values:
6763 *|CC_FASTCALL
6764 *|CC_CDECL
6765 *|CC_PASCAL
6766 *|CC_STDCALL
6767 *|CC_FPFASTCALL
6768 *|CC_SYSCALL
6769 *|CC_MPWCDECL
6770 *|CC_MPWPASCAL
6771 *
6772 */
6773 HRESULT WINAPI
6774 DispCallFunc(
6775 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6776 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6777 {
6778 #ifdef __i386__
6779 int argspos, stack_offset;
6780 void *func;
6781 UINT i;
6782 DWORD *args;
6783
6784 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6785 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6786 pvargResult, V_VT(pvargResult));
6787
6788 if (cc != CC_STDCALL && cc != CC_CDECL)
6789 {
6790 FIXME("unsupported calling convention %d\n",cc);
6791 return E_INVALIDARG;
6792 }
6793
6794 /* maximum size for an argument is sizeof(VARIANT) */
6795 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6796
6797 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6798 argspos = 1;
6799 if (pvInstance)
6800 {
6801 const FARPROC *vtable = *(FARPROC **)pvInstance;
6802 func = vtable[oVft/sizeof(void *)];
6803 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6804 }
6805 else func = (void *)oVft;
6806
6807 for (i = 0; i < cActuals; i++)
6808 {
6809 VARIANT *arg = prgpvarg[i];
6810
6811 switch (prgvt[i])
6812 {
6813 case VT_EMPTY:
6814 break;
6815 case VT_I8:
6816 case VT_UI8:
6817 case VT_R8:
6818 case VT_DATE:
6819 case VT_CY:
6820 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6821 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6822 break;
6823 case VT_DECIMAL:
6824 case VT_VARIANT:
6825 memcpy( &args[argspos], arg, sizeof(*arg) );
6826 argspos += sizeof(*arg) / sizeof(DWORD);
6827 break;
6828 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6829 args[argspos++] = V_BOOL(arg);
6830 break;
6831 default:
6832 args[argspos++] = V_UI4(arg);
6833 break;
6834 }
6835 TRACE("arg %u: type %d\n",i,prgvt[i]);
6836 dump_Variant(arg);
6837 }
6838
6839 switch (vtReturn)
6840 {
6841 case VT_EMPTY:
6842 call_method( func, argspos - 1, args + 1, &stack_offset );
6843 break;
6844 case VT_R4:
6845 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6846 break;
6847 case VT_R8:
6848 case VT_DATE:
6849 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6850 break;
6851 case VT_DECIMAL:
6852 case VT_VARIANT:
6853 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6854 call_method( func, argspos, args, &stack_offset );
6855 break;
6856 case VT_I8:
6857 case VT_UI8:
6858 case VT_CY:
6859 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6860 break;
6861 case VT_HRESULT:
6862 WARN("invalid return type %u\n", vtReturn);
6863 heap_free( args );
6864 return E_INVALIDARG;
6865 default:
6866 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6867 break;
6868 }
6869 heap_free( args );
6870 if (stack_offset && cc == CC_STDCALL)
6871 {
6872 WARN( "stack pointer off by %d\n", stack_offset );
6873 return DISP_E_BADCALLEE;
6874 }
6875 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6876 TRACE("retval: "); dump_Variant(pvargResult);
6877 return S_OK;
6878
6879 #elif defined(__x86_64__)
6880 int argspos;
6881 UINT i;
6882 DWORD_PTR *args;
6883 void *func;
6884
6885 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6886 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6887 pvargResult, V_VT(pvargResult));
6888
6889 if (cc != CC_STDCALL && cc != CC_CDECL)
6890 {
6891 FIXME("unsupported calling convention %d\n",cc);
6892 return E_INVALIDARG;
6893 }
6894
6895 /* maximum size for an argument is sizeof(DWORD_PTR) */
6896 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6897
6898 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6899 argspos = 1;
6900 if (pvInstance)
6901 {
6902 const FARPROC *vtable = *(FARPROC **)pvInstance;
6903 func = vtable[oVft/sizeof(void *)];
6904 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6905 }
6906 else func = (void *)oVft;
6907
6908 for (i = 0; i < cActuals; i++)
6909 {
6910 VARIANT *arg = prgpvarg[i];
6911
6912 switch (prgvt[i])
6913 {
6914 case VT_DECIMAL:
6915 case VT_VARIANT:
6916 args[argspos++] = (ULONG_PTR)arg;
6917 break;
6918 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6919 args[argspos++] = V_BOOL(arg);
6920 break;
6921 default:
6922 args[argspos++] = V_UI8(arg);
6923 break;
6924 }
6925 TRACE("arg %u: type %d\n",i,prgvt[i]);
6926 dump_Variant(arg);
6927 }
6928
6929 switch (vtReturn)
6930 {
6931 case VT_R4:
6932 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6933 break;
6934 case VT_R8:
6935 case VT_DATE:
6936 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6937 break;
6938 case VT_DECIMAL:
6939 case VT_VARIANT:
6940 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6941 call_method( func, argspos, args );
6942 break;
6943 case VT_HRESULT:
6944 WARN("invalid return type %u\n", vtReturn);
6945 heap_free( args );
6946 return E_INVALIDARG;
6947 default:
6948 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6949 break;
6950 }
6951 heap_free( args );
6952 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6953 TRACE("retval: "); dump_Variant(pvargResult);
6954 return S_OK;
6955
6956 #else
6957 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6958 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6959 return E_NOTIMPL;
6960 #endif
6961 }
6962
6963 static inline BOOL func_restricted( const FUNCDESC *desc )
6964 {
6965 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6966 }
6967
6968 #define INVBUF_ELEMENT_SIZE \
6969 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6970 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6971 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6972 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6973 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6974 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6975 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6976 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6977
6978 static HRESULT WINAPI ITypeInfo_fnInvoke(
6979 ITypeInfo2 *iface,
6980 VOID *pIUnk,
6981 MEMBERID memid,
6982 UINT16 wFlags,
6983 DISPPARAMS *pDispParams,
6984 VARIANT *pVarResult,
6985 EXCEPINFO *pExcepInfo,
6986 UINT *pArgErr)
6987 {
6988 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6989 int i;
6990 unsigned int var_index;
6991 TYPEKIND type_kind;
6992 HRESULT hres;
6993 const TLBFuncDesc *pFuncInfo;
6994 UINT fdc;
6995
6996 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6997 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6998 );
6999
7000 if( This->wTypeFlags & TYPEFLAG_FRESTRICTED )
7001 return DISP_E_MEMBERNOTFOUND;
7002
7003 if (!pDispParams)
7004 {
7005 ERR("NULL pDispParams not allowed\n");
7006 return E_INVALIDARG;
7007 }
7008
7009 dump_DispParms(pDispParams);
7010
7011 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7012 {
7013 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7014 pDispParams->cNamedArgs, pDispParams->cArgs);
7015 return E_INVALIDARG;
7016 }
7017
7018 /* we do this instead of using GetFuncDesc since it will return a fake
7019 * FUNCDESC for dispinterfaces and we want the real function description */
7020 for (fdc = 0; fdc < This->cFuncs; ++fdc){
7021 pFuncInfo = &This->funcdescs[fdc];
7022 if ((memid == pFuncInfo->funcdesc.memid) &&
7023 (wFlags & pFuncInfo->funcdesc.invkind) &&
7024 !func_restricted( &pFuncInfo->funcdesc ))
7025 break;
7026 }
7027
7028 if (fdc < This->cFuncs) {
7029 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7030
7031 if (TRACE_ON(ole))
7032 {
7033 TRACE("invoking:\n");
7034 dump_TLBFuncDescOne(pFuncInfo);
7035 }
7036
7037 switch (func_desc->funckind) {
7038 case FUNC_PUREVIRTUAL:
7039 case FUNC_VIRTUAL: {
7040 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7041 VARIANT varresult;
7042 VARIANT retval; /* pointer for storing byref retvals in */
7043 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7044 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7045 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7046 UINT cNamedArgs = pDispParams->cNamedArgs;
7047 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7048 UINT vargs_converted=0;
7049
7050 hres = S_OK;
7051
7052 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7053 {
7054 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7055 {
7056 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7057 hres = DISP_E_PARAMNOTFOUND;
7058 goto func_fail;
7059 }
7060 }
7061
7062 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7063 {
7064 ERR("functions with the vararg attribute do not support named arguments\n");
7065 hres = DISP_E_NONAMEDARGS;
7066 goto func_fail;
7067 }
7068
7069 for (i = 0; i < func_desc->cParams; i++)
7070 {
7071 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7072 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7073 if (FAILED(hres))
7074 goto func_fail;
7075 }
7076
7077 TRACE("changing args\n");
7078 for (i = 0; i < func_desc->cParams; i++)
7079 {
7080 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7081 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7082 VARIANTARG *src_arg;
7083
7084 if (wParamFlags & PARAMFLAG_FLCID)
7085 {
7086 VARIANTARG *arg;
7087 arg = prgpvarg[i] = &rgvarg[i];
7088 V_VT(arg) = VT_I4;
7089 V_I4(arg) = This->pTypeLib->lcid;
7090 continue;
7091 }
7092
7093 src_arg = NULL;
7094
7095 if (cNamedArgs)
7096 {
7097 USHORT j;
7098 for (j = 0; j < cNamedArgs; j++)
7099 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7100 {
7101 src_arg = &pDispParams->rgvarg[j];
7102 break;
7103 }
7104 }
7105
7106 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7107 {
7108 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7109 vargs_converted++;
7110 }
7111
7112 if (wParamFlags & PARAMFLAG_FRETVAL)
7113 {
7114 /* under most conditions the caller is not allowed to
7115 * pass in a dispparam arg in the index of what would be
7116 * the retval parameter. however, there is an exception
7117 * where the extra parameter is used in an extra
7118 * IDispatch::Invoke below */
7119 if ((i < pDispParams->cArgs) &&
7120 ((func_desc->cParams != 1) || !pVarResult ||
7121 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7122 {
7123 hres = DISP_E_BADPARAMCOUNT;
7124 break;
7125 }
7126
7127 /* note: this check is placed so that if the caller passes
7128 * in a VARIANTARG for the retval we just ignore it, like
7129 * native does */
7130 if (i == func_desc->cParams - 1)
7131 {
7132 VARIANTARG *arg;
7133 arg = prgpvarg[i] = &rgvarg[i];
7134 memset(arg, 0, sizeof(*arg));
7135 V_VT(arg) = rgvt[i];
7136 memset(&retval, 0, sizeof(retval));
7137 V_BYREF(arg) = &retval;
7138 }
7139 else
7140 {
7141 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7142 hres = E_UNEXPECTED;
7143 break;
7144 }
7145 }
7146 else if (src_arg)
7147 {
7148 dump_Variant(src_arg);
7149
7150 if(rgvt[i]!=V_VT(src_arg))
7151 {
7152 if (rgvt[i] == VT_VARIANT)
7153 hres = VariantCopy(&rgvarg[i], src_arg);
7154 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7155 {
7156 if (rgvt[i] == V_VT(src_arg))
7157 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7158 else
7159 {
7160 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7161 if (wParamFlags & PARAMFLAG_FIN)
7162 hres = VariantCopy(&missing_arg[i], src_arg);
7163 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7164 }
7165 V_VT(&rgvarg[i]) = rgvt[i];
7166 }
7167 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
7168 {
7169 SAFEARRAY *a;
7170 SAFEARRAYBOUND bound;
7171 VARIANT *v;
7172 LONG j;
7173 bound.lLbound = 0;
7174 bound.cElements = pDispParams->cArgs-i;
7175 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7176 {
7177 ERR("SafeArrayCreate failed\n");
7178 break;
7179 }
7180 hres = SafeArrayAccessData(a, (LPVOID)&v);
7181 if (hres != S_OK)
7182 {
7183 ERR("SafeArrayAccessData failed with %x\n", hres);
7184 SafeArrayDestroy(a);
7185 break;
7186 }
7187 for (j = 0; j < bound.cElements; j++)
7188 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7189 hres = SafeArrayUnaccessData(a);
7190 if (hres != S_OK)
7191 {
7192 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7193 SafeArrayDestroy(a);
7194 break;
7195 }
7196 V_ARRAY(&rgvarg[i]) = a;
7197 V_VT(&rgvarg[i]) = rgvt[i];
7198 }
7199 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7200 {
7201 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7202 if (wParamFlags & PARAMFLAG_FIN)
7203 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7204 else
7205 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7206 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7207 V_VT(&rgvarg[i]) = rgvt[i];
7208 }
7209 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7210 {
7211 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7212 V_VT(&rgvarg[i]) = rgvt[i];
7213 }
7214 else
7215 {
7216 /* FIXME: this doesn't work for VT_BYREF arguments if
7217 * they are not the same type as in the paramdesc */
7218 V_VT(&rgvarg[i]) = V_VT(src_arg);
7219 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7220 V_VT(&rgvarg[i]) = rgvt[i];
7221 }
7222
7223 if (FAILED(hres))
7224 {
7225 ERR("failed to convert param %d to %s%s from %s%s\n", i,
7226 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
7227 debugstr_VT(src_arg), debugstr_VF(src_arg));
7228 break;
7229 }
7230 prgpvarg[i] = &rgvarg[i];
7231 }
7232 else
7233 {
7234 prgpvarg[i] = src_arg;
7235 }
7236
7237 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7238 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7239 && V_UNKNOWN(prgpvarg[i])) {
7240 IUnknown *userdefined_iface;
7241 GUID guid;
7242
7243 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7244 if(FAILED(hres))
7245 break;
7246
7247 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7248 if(FAILED(hres)) {
7249 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7250 break;
7251 }
7252
7253 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7254 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7255 }
7256 }
7257 else if (wParamFlags & PARAMFLAG_FOPT)
7258 {
7259 VARIANTARG *arg;
7260 arg = prgpvarg[i] = &rgvarg[i];
7261 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7262 {
7263 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7264 if (FAILED(hres))
7265 break;
7266 }
7267 else
7268 {
7269 VARIANTARG *missing_arg;
7270 /* if the function wants a pointer to a variant then
7271 * set that up, otherwise just pass the VT_ERROR in
7272 * the argument by value */
7273 if (rgvt[i] & VT_BYREF)
7274 {
7275 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7276 V_VT(arg) = VT_VARIANT | VT_BYREF;
7277 V_VARIANTREF(arg) = missing_arg;
7278 }
7279 else
7280 missing_arg = arg;
7281 V_VT(missing_arg) = VT_ERROR;
7282 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7283 }
7284 }
7285 else
7286 {
7287 hres = DISP_E_BADPARAMCOUNT;
7288 break;
7289 }
7290 }
7291 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7292
7293 /* VT_VOID is a special case for return types, so it is not
7294 * handled in the general function */
7295 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7296 V_VT(&varresult) = VT_EMPTY;
7297 else
7298 {
7299 V_VT(&varresult) = 0;
7300 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7301 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7302 }
7303
7304 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7305 V_VT(&varresult), func_desc->cParams, rgvt,
7306 prgpvarg, &varresult);
7307
7308 vargs_converted = 0;
7309
7310 for (i = 0; i < func_desc->cParams; i++)
7311 {
7312 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7313 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7314
7315 if (wParamFlags & PARAMFLAG_FLCID)
7316 continue;
7317 else if (wParamFlags & PARAMFLAG_FRETVAL)
7318 {
7319 if (TRACE_ON(ole))
7320 {
7321 TRACE("[retval] value: ");
7322 dump_Variant(prgpvarg[i]);
7323 }
7324
7325 if (pVarResult)
7326 {
7327 VariantInit(pVarResult);
7328 /* deref return value */
7329 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7330 }
7331
7332 VARIANT_ClearInd(prgpvarg[i]);
7333 }
7334 else if (vargs_converted < pDispParams->cArgs)
7335 {
7336 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7337 if (wParamFlags & PARAMFLAG_FOUT)
7338 {
7339 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7340 {
7341 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7342
7343 if (FAILED(hres))
7344 {
7345 ERR("failed to convert param %d to vt %d\n", i,
7346 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7347 break;
7348 }
7349 }
7350 }
7351 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7352 func_desc->cParamsOpt < 0 &&
7353 i == func_desc->cParams-1)
7354 {
7355 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7356 LONG j, ubound;
7357 VARIANT *v;
7358 hres = SafeArrayGetUBound(a, 1, &ubound);
7359 if (hres != S_OK)
7360 {
7361 ERR("SafeArrayGetUBound failed with %x\n", hres);
7362 break;
7363 }
7364 hres = SafeArrayAccessData(a, (LPVOID)&v);
7365 if (hres != S_OK)
7366 {
7367 ERR("SafeArrayAccessData failed with %x\n", hres);
7368 break;
7369 }
7370 for (j = 0; j <= ubound; j++)
7371 VariantClear(&v[j]);
7372 hres = SafeArrayUnaccessData(a);
7373 if (hres != S_OK)
7374 {
7375 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7376 break;
7377 }
7378 }
7379 VariantClear(&rgvarg[i]);
7380 vargs_converted++;
7381 }
7382 else if (wParamFlags & PARAMFLAG_FOPT)
7383 {
7384 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7385 VariantClear(&rgvarg[i]);
7386 }
7387
7388 VariantClear(&missing_arg[i]);
7389 }
7390
7391 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7392 {
7393 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7394 hres = DISP_E_EXCEPTION;
7395 if (pExcepInfo)
7396 {
7397 IErrorInfo *pErrorInfo;
7398 pExcepInfo->scode = V_ERROR(&varresult);
7399 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7400 {
7401 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7402 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7403 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7404 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7405
7406 IErrorInfo_Release(pErrorInfo);
7407 }
7408 }
7409 }
7410 if (V_VT(&varresult) != VT_ERROR)
7411 {
7412 TRACE("varresult value: ");
7413 dump_Variant(&varresult);
7414
7415 if (pVarResult)
7416 {
7417 VariantClear(pVarResult);
7418 *pVarResult = varresult;
7419 }
7420 else
7421 VariantClear(&varresult);
7422 }
7423
7424 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7425 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7426 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7427 (pDispParams->cArgs != 0))
7428 {
7429 if (V_VT(pVarResult) == VT_DISPATCH)
7430 {
7431 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7432 /* Note: not VariantClear; we still need the dispatch
7433 * pointer to be valid */
7434 VariantInit(pVarResult);
7435 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7436 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7437 pDispParams, pVarResult, pExcepInfo, pArgErr);
7438 IDispatch_Release(pDispatch);
7439 }
7440 else
7441 {
7442 VariantClear(pVarResult);
7443 hres = DISP_E_NOTACOLLECTION;
7444 }
7445 }
7446
7447 func_fail:
7448 heap_free(buffer);
7449 break;
7450 }
7451 case FUNC_DISPATCH: {
7452 IDispatch *disp;
7453
7454 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7455 if (SUCCEEDED(hres)) {
7456 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7457 hres = IDispatch_Invoke(
7458 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7459 pVarResult,pExcepInfo,pArgErr
7460 );
7461 if (FAILED(hres))
7462 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7463 IDispatch_Release(disp);
7464 } else
7465 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7466 break;
7467 }
7468 default:
7469 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7470 hres = E_FAIL;
7471 break;
7472 }
7473
7474 TRACE("-- 0x%08x\n", hres);
7475 return hres;
7476
7477 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7478 VARDESC *var_desc;
7479
7480 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7481 if(FAILED(hres)) return hres;
7482
7483 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7484 dump_VARDESC(var_desc);
7485 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7486 return E_NOTIMPL;
7487 }
7488
7489 /* not found, look for it in inherited interfaces */
7490 ITypeInfo2_GetTypeKind(iface, &type_kind);
7491 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7492 if(This->impltypes) {
7493 /* recursive search */
7494 ITypeInfo *pTInfo;
7495 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7496 if(SUCCEEDED(hres)){
7497 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7498 ITypeInfo_Release(pTInfo);
7499 return hres;
7500 }
7501 WARN("Could not search inherited interface!\n");
7502 }
7503 }
7504 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7505 return DISP_E_MEMBERNOTFOUND;
7506 }
7507
7508 /* ITypeInfo::GetDocumentation
7509 *
7510 * Retrieves the documentation string, the complete Help file name and path,
7511 * and the context ID for the Help topic for a specified type description.
7512 *
7513 * (Can be tested by the Visual Basic Editor in Word for instance.)
7514 */
7515 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7516 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7517 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7518 {
7519 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7520 const TLBFuncDesc *pFDesc;
7521 const TLBVarDesc *pVDesc;
7522 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7523 " HelpContext(%p) HelpFile(%p)\n",
7524 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7525 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7526 if(pBstrName)
7527 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7528 if(pBstrDocString)
7529 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7530 if(pdwHelpContext)
7531 *pdwHelpContext=This->dwHelpContext;
7532 if(pBstrHelpFile)
7533 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7534 return S_OK;
7535 }else {/* for a member */
7536 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7537 if(pFDesc){
7538 if(pBstrName)
7539 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7540 if(pBstrDocString)
7541 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7542 if(pdwHelpContext)
7543 *pdwHelpContext=pFDesc->helpcontext;
7544 if(pBstrHelpFile)
7545 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7546 return S_OK;
7547 }
7548 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
7549 if(pVDesc){
7550 if(pBstrName)
7551 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7552 if(pBstrDocString)
7553 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7554 if(pdwHelpContext)
7555 *pdwHelpContext=pVDesc->HelpContext;
7556 if(pBstrHelpFile)
7557 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7558 return S_OK;
7559 }
7560 }
7561
7562 if(This->impltypes &&
7563 (This->typekind==TKIND_INTERFACE || This->typekind==TKIND_DISPATCH)) {
7564 /* recursive search */
7565 ITypeInfo *pTInfo;
7566 HRESULT result;
7567 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7568 if(SUCCEEDED(result)) {
7569 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7570 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7571 ITypeInfo_Release(pTInfo);
7572 return result;
7573 }
7574 WARN("Could not search inherited interface!\n");
7575 }
7576
7577 WARN("member %d not found\n", memid);
7578 return TYPE_E_ELEMENTNOTFOUND;
7579 }
7580
7581 /* ITypeInfo::GetDllEntry
7582 *
7583 * Retrieves a description or specification of an entry point for a function
7584 * in a DLL.
7585 */
7586 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7587 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7588 WORD *pwOrdinal)
7589 {
7590 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7591 const TLBFuncDesc *pFDesc;
7592
7593 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7594
7595 if (pBstrDllName) *pBstrDllName = NULL;
7596 if (pBstrName) *pBstrName = NULL;
7597 if (pwOrdinal) *pwOrdinal = 0;
7598
7599 if (This->typekind != TKIND_MODULE)
7600 return TYPE_E_BADMODULEKIND;
7601
7602 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
7603 if(pFDesc){
7604 dump_TypeInfo(This);
7605 if (TRACE_ON(ole))
7606 dump_TLBFuncDescOne(pFDesc);
7607
7608 if (pBstrDllName)
7609 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7610
7611 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7612 if (pBstrName)
7613 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7614 if (pwOrdinal)
7615 *pwOrdinal = -1;
7616 return S_OK;
7617 }
7618 if (pBstrName)
7619 *pBstrName = NULL;
7620 if (pwOrdinal)
7621 *pwOrdinal = LOWORD(pFDesc->Entry);
7622 return S_OK;
7623 }
7624 return TYPE_E_ELEMENTNOTFOUND;
7625 }
7626
7627 /* internal function to make the inherited interfaces' methods appear
7628 * part of the interface */
7629 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7630 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7631 {
7632 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7633 HRESULT hr;
7634
7635 TRACE("%p, 0x%x\n", iface, *hRefType);
7636
7637 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7638 {
7639 ITypeInfo *pSubTypeInfo;
7640
7641 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7642 if (FAILED(hr))
7643 return hr;
7644
7645 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7646 hRefType, ppTInfo);
7647 ITypeInfo_Release(pSubTypeInfo);
7648 if (SUCCEEDED(hr))
7649 return hr;
7650 }
7651 *hRefType -= DISPATCH_HREF_OFFSET;
7652
7653 if (!(*hRefType & DISPATCH_HREF_MASK))
7654 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7655 else
7656 return E_FAIL;
7657 }
7658
7659 /* ITypeInfo::GetRefTypeInfo
7660 *
7661 * If a type description references other type descriptions, it retrieves
7662 * the referenced type descriptions.
7663 */
7664 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7665 ITypeInfo2 *iface,
7666 HREFTYPE hRefType,
7667 ITypeInfo **ppTInfo)
7668 {
7669 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7670 HRESULT result = E_FAIL;
7671
7672 if(!ppTInfo)
7673 return E_INVALIDARG;
7674
7675 if ((INT)hRefType < 0) {
7676 ITypeInfoImpl *pTypeInfoImpl;
7677
7678 if (!(This->wTypeFlags & TYPEFLAG_FDUAL) ||
7679 !(This->typekind == TKIND_INTERFACE ||
7680 This->typekind == TKIND_DISPATCH))
7681 return TYPE_E_ELEMENTNOTFOUND;
7682
7683 /* when we meet a DUAL typeinfo, we must create the alternate
7684 * version of it.
7685 */
7686 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7687
7688 *pTypeInfoImpl = *This;
7689 pTypeInfoImpl->ref = 0;
7690 list_init(&pTypeInfoImpl->custdata_list);
7691
7692 if (This->typekind == TKIND_INTERFACE)
7693 pTypeInfoImpl->typekind = TKIND_DISPATCH;
7694 else
7695 pTypeInfoImpl->typekind = TKIND_INTERFACE;
7696
7697 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7698 /* the AddRef implicitly adds a reference to the parent typelib, which
7699 * stops the copied data from being destroyed until the new typeinfo's
7700 * refcount goes to zero, but we need to signal to the new instance to
7701 * not free its data structures when it is destroyed */
7702 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7703
7704 ITypeInfo_AddRef(*ppTInfo);
7705
7706 result = S_OK;
7707 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7708 (This->typekind == TKIND_DISPATCH))
7709 {
7710 HREFTYPE href_dispatch = hRefType;
7711 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7712 } else {
7713 TLBRefType *ref_type;
7714 ITypeLib *pTLib = NULL;
7715 UINT i;
7716
7717 if(!(hRefType & 0x1)){
7718 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7719 {
7720 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7721 {
7722 result = S_OK;
7723 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7724 ITypeInfo_AddRef(*ppTInfo);
7725 goto end;
7726 }
7727 }
7728 }
7729
7730 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7731 {
7732 if(ref_type->reference == (hRefType & (~0x3)))
7733 break;
7734 }
7735 if(&ref_type->entry == &This->pTypeLib->ref_list)
7736 {
7737 FIXME("Can't find pRefType for ref %x\n", hRefType);
7738 goto end;
7739 }
7740
7741 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7742 UINT Index;
7743 TRACE("internal reference\n");
7744 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7745 } else {
7746 if(ref_type->pImpTLInfo->pImpTypeLib) {
7747 TRACE("typeinfo in imported typelib that is already loaded\n");
7748 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7749 ITypeLib_AddRef(pTLib);
7750 result = S_OK;
7751 } else {
7752 BSTR libnam;
7753
7754 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7755
7756 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7757 ref_type->pImpTLInfo->wVersionMajor,
7758 ref_type->pImpTLInfo->wVersionMinor,
7759 This->pTypeLib->syskind,
7760 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7761 if(FAILED(result))
7762 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7763
7764 result = LoadTypeLib(libnam, &pTLib);
7765 SysFreeString(libnam);
7766
7767 if(SUCCEEDED(result)) {
7768 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7769 ITypeLib_AddRef(pTLib);
7770 }
7771 }
7772 }
7773 if(SUCCEEDED(result)) {
7774 if(ref_type->index == TLB_REF_USE_GUID)
7775 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7776 else
7777 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7778 }
7779 if (pTLib != NULL)
7780 ITypeLib_Release(pTLib);
7781 }
7782
7783 end:
7784 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7785 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7786 return result;
7787 }
7788
7789 /* ITypeInfo::AddressOfMember
7790 *
7791 * Retrieves the addresses of static functions or variables, such as those
7792 * defined in a DLL.
7793 */
7794 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7795 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7796 {
7797 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7798 HRESULT hr;
7799 BSTR dll, entry;
7800 WORD ordinal;
7801 HMODULE module;
7802
7803 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7804
7805 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7806 if (FAILED(hr))
7807 return hr;
7808
7809 module = LoadLibraryW(dll);
7810 if (!module)
7811 {
7812 ERR("couldn't load %s\n", debugstr_w(dll));
7813 SysFreeString(dll);
7814 SysFreeString(entry);
7815 return STG_E_FILENOTFOUND;
7816 }
7817 /* FIXME: store library somewhere where we can free it */
7818
7819 if (entry)
7820 {
7821 LPSTR entryA;
7822 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7823 entryA = heap_alloc(len);
7824 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7825
7826 *ppv = GetProcAddress(module, entryA);
7827 if (!*ppv)
7828 ERR("function not found %s\n", debugstr_a(entryA));
7829
7830 heap_free(entryA);
7831 }
7832 else
7833 {
7834 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7835 if (!*ppv)
7836 ERR("function not found %d\n", ordinal);
7837 }
7838
7839 SysFreeString(dll);
7840 SysFreeString(entry);
7841
7842 if (!*ppv)
7843 return TYPE_E_DLLFUNCTIONNOTFOUND;
7844
7845 return S_OK;
7846 }
7847
7848 /* ITypeInfo::CreateInstance
7849 *
7850 * Creates a new instance of a type that describes a component object class
7851 * (coclass).
7852 */
7853 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7854 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7855 {
7856 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7857 HRESULT hr;
7858 TYPEATTR *pTA;
7859
7860 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7861
7862 *ppvObj = NULL;
7863
7864 if(pOuterUnk)
7865 {
7866 WARN("Not able to aggregate\n");
7867 return CLASS_E_NOAGGREGATION;
7868 }
7869
7870 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7871 if(FAILED(hr)) return hr;
7872
7873 if(pTA->typekind != TKIND_COCLASS)
7874 {
7875 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7876 hr = E_INVALIDARG;
7877 goto end;
7878 }
7879
7880 hr = S_FALSE;
7881 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7882 {
7883 IUnknown *pUnk;
7884 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7885 TRACE("GetActiveObject rets %08x\n", hr);
7886 if(hr == S_OK)
7887 {
7888 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7889 IUnknown_Release(pUnk);
7890 }
7891 }
7892
7893 if(hr != S_OK)
7894 hr = CoCreateInstance(&pTA->guid, NULL,
7895 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7896 riid, ppvObj);
7897
7898 end:
7899 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7900 return hr;
7901 }
7902
7903 /* ITypeInfo::GetMops
7904 *
7905 * Retrieves marshalling information.
7906 */
7907 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7908 BSTR *pBstrMops)
7909 {
7910 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7911 FIXME("(%p %d) stub!\n", This, memid);
7912 *pBstrMops = NULL;
7913 return S_OK;
7914 }
7915
7916 /* ITypeInfo::GetContainingTypeLib
7917 *
7918 * Retrieves the containing type library and the index of the type description
7919 * within that type library.
7920 */
7921 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7922 ITypeLib * *ppTLib, UINT *pIndex)
7923 {
7924 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7925
7926 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7927 if (pIndex) {
7928 *pIndex=This->index;
7929 TRACE("returning pIndex=%d\n", *pIndex);
7930 }
7931
7932 if (ppTLib) {
7933 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7934 ITypeLib_AddRef(*ppTLib);
7935 TRACE("returning ppTLib=%p\n", *ppTLib);
7936 }
7937
7938 return S_OK;
7939 }
7940
7941 /* ITypeInfo::ReleaseTypeAttr
7942 *
7943 * Releases a TYPEATTR previously returned by Get
7944 *
7945 */
7946 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7947 TYPEATTR* pTypeAttr)
7948 {
7949 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7950 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7951 heap_free(pTypeAttr);
7952 }
7953
7954 /* ITypeInfo::ReleaseFuncDesc
7955 *
7956 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7957 */
7958 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7959 ITypeInfo2 *iface,
7960 FUNCDESC *pFuncDesc)
7961 {
7962 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7963 SHORT i;
7964
7965 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7966
7967 for (i = 0; i < pFuncDesc->cParams; i++)
7968 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7969 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7970
7971 SysFreeString((BSTR)pFuncDesc);
7972 }
7973
7974 /* ITypeInfo::ReleaseVarDesc
7975 *
7976 * Releases a VARDESC previously returned by GetVarDesc.
7977 */
7978 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7979 VARDESC *pVarDesc)
7980 {
7981 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7982 TRACE("(%p)->(%p)\n", This, pVarDesc);
7983
7984 TLB_FreeVarDesc(pVarDesc);
7985 }
7986
7987 /* ITypeInfo2::GetTypeKind
7988 *
7989 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7990 *
7991 */
7992 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7993 TYPEKIND *pTypeKind)
7994 {
7995 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7996 *pTypeKind=This->typekind;
7997 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7998 return S_OK;
7999 }
8000
8001 /* ITypeInfo2::GetTypeFlags
8002 *
8003 * Returns the type flags without any allocations. This returns a DWORD type
8004 * flag, which expands the type flags without growing the TYPEATTR (type
8005 * attribute).
8006 *
8007 */
8008 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8009 {
8010 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8011 *pTypeFlags=This->wTypeFlags;
8012 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8013 return S_OK;
8014 }
8015
8016 /* ITypeInfo2::GetFuncIndexOfMemId
8017 * Binds to a specific member based on a known DISPID, where the member name
8018 * is not known (for example, when binding to a default member).
8019 *
8020 */
8021 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8022 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8023 {
8024 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8025 UINT fdc;
8026 HRESULT result;
8027
8028 for (fdc = 0; fdc < This->cFuncs; ++fdc){
8029 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8030 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8031 break;
8032 }
8033 if(fdc < This->cFuncs) {
8034 *pFuncIndex = fdc;
8035 result = S_OK;
8036 } else
8037 result = TYPE_E_ELEMENTNOTFOUND;
8038
8039 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8040 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8041 return result;
8042 }
8043
8044 /* TypeInfo2::GetVarIndexOfMemId
8045 *
8046 * Binds to a specific member based on a known DISPID, where the member name
8047 * is not known (for example, when binding to a default member).
8048 *
8049 */
8050 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8051 MEMBERID memid, UINT *pVarIndex)
8052 {
8053 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8054 TLBVarDesc *pVarInfo;
8055
8056 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8057
8058 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8059 if(!pVarInfo)
8060 return TYPE_E_ELEMENTNOTFOUND;
8061
8062 *pVarIndex = (pVarInfo - This->vardescs);
8063
8064 return S_OK;
8065 }
8066
8067 /* ITypeInfo2::GetCustData
8068 *
8069 * Gets the custom data
8070 */
8071 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8072 ITypeInfo2 * iface,
8073 REFGUID guid,
8074 VARIANT *pVarVal)
8075 {
8076 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8077 TLBCustData *pCData;
8078
8079 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8080
8081 if(!guid || !pVarVal)
8082 return E_INVALIDARG;
8083
8084 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8085
8086 VariantInit( pVarVal);
8087 if (pCData)
8088 VariantCopy( pVarVal, &pCData->data);
8089 else
8090 VariantClear( pVarVal );
8091 return S_OK;
8092 }
8093
8094 /* ITypeInfo2::GetFuncCustData
8095 *
8096 * Gets the custom data
8097 */
8098 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8099 ITypeInfo2 * iface,
8100 UINT index,
8101 REFGUID guid,
8102 VARIANT *pVarVal)
8103 {
8104 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8105 TLBCustData *pCData;
8106 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8107
8108 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8109
8110 if(index >= This->cFuncs)
8111 return TYPE_E_ELEMENTNOTFOUND;
8112
8113 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8114 if(!pCData)
8115 return TYPE_E_ELEMENTNOTFOUND;
8116
8117 VariantInit(pVarVal);
8118 VariantCopy(pVarVal, &pCData->data);
8119
8120 return S_OK;
8121 }
8122
8123 /* ITypeInfo2::GetParamCustData
8124 *
8125 * Gets the custom data
8126 */
8127 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8128 ITypeInfo2 * iface,
8129 UINT indexFunc,
8130 UINT indexParam,
8131 REFGUID guid,
8132 VARIANT *pVarVal)
8133 {
8134 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8135 TLBCustData *pCData;
8136 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8137
8138 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8139 debugstr_guid(guid), pVarVal);
8140
8141 if(indexFunc >= This->cFuncs)
8142 return TYPE_E_ELEMENTNOTFOUND;
8143
8144 if(indexParam >= pFDesc->funcdesc.cParams)
8145 return TYPE_E_ELEMENTNOTFOUND;
8146
8147 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8148 if(!pCData)
8149 return TYPE_E_ELEMENTNOTFOUND;
8150
8151 VariantInit(pVarVal);
8152 VariantCopy(pVarVal, &pCData->data);
8153
8154 return S_OK;
8155 }
8156
8157 /* ITypeInfo2::GetVarCustData
8158 *
8159 * Gets the custom data
8160 */
8161 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8162 ITypeInfo2 * iface,
8163 UINT index,
8164 REFGUID guid,
8165 VARIANT *pVarVal)
8166 {
8167 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8168 TLBCustData *pCData;
8169 TLBVarDesc *pVDesc = &This->vardescs[index];
8170
8171 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8172
8173 if(index >= This->cVars)
8174 return TYPE_E_ELEMENTNOTFOUND;
8175
8176 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8177 if(!pCData)
8178 return TYPE_E_ELEMENTNOTFOUND;
8179
8180 VariantInit(pVarVal);
8181 VariantCopy(pVarVal, &pCData->data);
8182
8183 return S_OK;
8184 }
8185
8186 /* ITypeInfo2::GetImplCustData
8187 *
8188 * Gets the custom data
8189 */
8190 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8191 ITypeInfo2 * iface,
8192 UINT index,
8193 REFGUID guid,
8194 VARIANT *pVarVal)
8195 {
8196 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8197 TLBCustData *pCData;
8198 TLBImplType *pRDesc = &This->impltypes[index];
8199
8200 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8201
8202 if(index >= This->cImplTypes)
8203 return TYPE_E_ELEMENTNOTFOUND;
8204
8205 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8206 if(!pCData)
8207 return TYPE_E_ELEMENTNOTFOUND;
8208
8209 VariantInit(pVarVal);
8210 VariantCopy(pVarVal, &pCData->data);
8211
8212 return S_OK;
8213 }
8214
8215 /* ITypeInfo2::GetDocumentation2
8216 *
8217 * Retrieves the documentation string, the complete Help file name and path,
8218 * the localization context to use, and the context ID for the library Help
8219 * topic in the Help file.
8220 *
8221 */
8222 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8223 ITypeInfo2 * iface,
8224 MEMBERID memid,
8225 LCID lcid,
8226 BSTR *pbstrHelpString,
8227 DWORD *pdwHelpStringContext,
8228 BSTR *pbstrHelpStringDll)
8229 {
8230 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8231 const TLBFuncDesc *pFDesc;
8232 const TLBVarDesc *pVDesc;
8233 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8234 "HelpStringContext(%p) HelpStringDll(%p)\n",
8235 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8236 pbstrHelpStringDll );
8237 /* the help string should be obtained from the helpstringdll,
8238 * using the _DLLGetDocumentation function, based on the supplied
8239 * lcid. Nice to do sometime...
8240 */
8241 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8242 if(pbstrHelpString)
8243 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8244 if(pdwHelpStringContext)
8245 *pdwHelpStringContext=This->dwHelpStringContext;
8246 if(pbstrHelpStringDll)
8247 *pbstrHelpStringDll=
8248 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8249 return S_OK;
8250 }else {/* for a member */
8251 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->cFuncs, memid);
8252 if(pFDesc){
8253 if(pbstrHelpString)
8254 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8255 if(pdwHelpStringContext)
8256 *pdwHelpStringContext=pFDesc->HelpStringContext;
8257 if(pbstrHelpStringDll)
8258 *pbstrHelpStringDll=
8259 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8260 return S_OK;
8261 }
8262 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->cVars, memid);
8263 if(pVDesc){
8264 if(pbstrHelpString)
8265 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8266 if(pdwHelpStringContext)
8267 *pdwHelpStringContext=pVDesc->HelpStringContext;
8268 if(pbstrHelpStringDll)
8269 *pbstrHelpStringDll=
8270 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8271 return S_OK;
8272 }
8273 }
8274 return TYPE_E_ELEMENTNOTFOUND;
8275 }
8276
8277 /* ITypeInfo2::GetAllCustData
8278 *
8279 * Gets all custom data items for the Type info.
8280 *
8281 */
8282 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8283 ITypeInfo2 * iface,
8284 CUSTDATA *pCustData)
8285 {
8286 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8287
8288 TRACE("%p %p\n", This, pCustData);
8289
8290 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8291 }
8292
8293 /* ITypeInfo2::GetAllFuncCustData
8294 *
8295 * Gets all custom data items for the specified Function
8296 *
8297 */
8298 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8299 ITypeInfo2 * iface,
8300 UINT index,
8301 CUSTDATA *pCustData)
8302 {
8303 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8304 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8305
8306 TRACE("%p %u %p\n", This, index, pCustData);
8307
8308 if(index >= This->cFuncs)
8309 return TYPE_E_ELEMENTNOTFOUND;
8310
8311 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8312 }
8313
8314 /* ITypeInfo2::GetAllParamCustData
8315 *
8316 * Gets all custom data items for the Functions
8317 *
8318 */
8319 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8320 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8321 {
8322 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8323 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8324
8325 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8326
8327 if(indexFunc >= This->cFuncs)
8328 return TYPE_E_ELEMENTNOTFOUND;
8329
8330 if(indexParam >= pFDesc->funcdesc.cParams)
8331 return TYPE_E_ELEMENTNOTFOUND;
8332
8333 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8334 }
8335
8336 /* ITypeInfo2::GetAllVarCustData
8337 *
8338 * Gets all custom data items for the specified Variable
8339 *
8340 */
8341 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8342 UINT index, CUSTDATA *pCustData)
8343 {
8344 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8345 TLBVarDesc * pVDesc = &This->vardescs[index];
8346
8347 TRACE("%p %u %p\n", This, index, pCustData);
8348
8349 if(index >= This->cVars)
8350 return TYPE_E_ELEMENTNOTFOUND;
8351
8352 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8353 }
8354
8355 /* ITypeInfo2::GetAllImplCustData
8356 *
8357 * Gets all custom data items for the specified implementation type
8358 *
8359 */
8360 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8361 ITypeInfo2 * iface,
8362 UINT index,
8363 CUSTDATA *pCustData)
8364 {
8365 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8366 TLBImplType *pRDesc = &This->impltypes[index];
8367
8368 TRACE("%p %u %p\n", This, index, pCustData);
8369
8370 if(index >= This->cImplTypes)
8371 return TYPE_E_ELEMENTNOTFOUND;
8372
8373 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8374 }
8375
8376 static const ITypeInfo2Vtbl tinfvt =
8377 {
8378
8379 ITypeInfo_fnQueryInterface,
8380 ITypeInfo_fnAddRef,
8381 ITypeInfo_fnRelease,
8382
8383 ITypeInfo_fnGetTypeAttr,
8384 ITypeInfo_fnGetTypeComp,
8385 ITypeInfo_fnGetFuncDesc,
8386 ITypeInfo_fnGetVarDesc,
8387 ITypeInfo_fnGetNames,
8388 ITypeInfo_fnGetRefTypeOfImplType,
8389 ITypeInfo_fnGetImplTypeFlags,
8390 ITypeInfo_fnGetIDsOfNames,
8391 ITypeInfo_fnInvoke,
8392 ITypeInfo_fnGetDocumentation,
8393 ITypeInfo_fnGetDllEntry,
8394 ITypeInfo_fnGetRefTypeInfo,
8395 ITypeInfo_fnAddressOfMember,
8396 ITypeInfo_fnCreateInstance,
8397 ITypeInfo_fnGetMops,
8398 ITypeInfo_fnGetContainingTypeLib,
8399 ITypeInfo_fnReleaseTypeAttr,
8400 ITypeInfo_fnReleaseFuncDesc,
8401 ITypeInfo_fnReleaseVarDesc,
8402
8403 ITypeInfo2_fnGetTypeKind,
8404 ITypeInfo2_fnGetTypeFlags,
8405 ITypeInfo2_fnGetFuncIndexOfMemId,
8406 ITypeInfo2_fnGetVarIndexOfMemId,
8407 ITypeInfo2_fnGetCustData,
8408 ITypeInfo2_fnGetFuncCustData,
8409 ITypeInfo2_fnGetParamCustData,
8410 ITypeInfo2_fnGetVarCustData,
8411 ITypeInfo2_fnGetImplTypeCustData,
8412 ITypeInfo2_fnGetDocumentation2,
8413 ITypeInfo2_fnGetAllCustData,
8414 ITypeInfo2_fnGetAllFuncCustData,
8415 ITypeInfo2_fnGetAllParamCustData,
8416 ITypeInfo2_fnGetAllVarCustData,
8417 ITypeInfo2_fnGetAllImplTypeCustData,
8418 };
8419
8420 /******************************************************************************
8421 * CreateDispTypeInfo [OLEAUT32.31]
8422 *
8423 * Build type information for an object so it can be called through an
8424 * IDispatch interface.
8425 *
8426 * RETURNS
8427 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8428 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8429 *
8430 * NOTES
8431 * This call allows an objects methods to be accessed through IDispatch, by
8432 * building an ITypeInfo object that IDispatch can use to call through.
8433 */
8434 HRESULT WINAPI CreateDispTypeInfo(
8435 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8436 LCID lcid, /* [I] Locale Id */
8437 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8438 {
8439 ITypeInfoImpl *pTIClass, *pTIIface;
8440 ITypeLibImpl *pTypeLibImpl;
8441 unsigned int param, func;
8442 TLBFuncDesc *pFuncDesc;
8443 TLBRefType *ref;
8444
8445 TRACE("\n");
8446 pTypeLibImpl = TypeLibImpl_Constructor();
8447 if (!pTypeLibImpl) return E_FAIL;
8448
8449 pTypeLibImpl->TypeInfoCount = 2;
8450 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8451
8452 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8453 pTIIface->pTypeLib = pTypeLibImpl;
8454 pTIIface->index = 0;
8455 pTIIface->Name = NULL;
8456 pTIIface->dwHelpContext = -1;
8457 pTIIface->guid = NULL;
8458 pTIIface->lcid = lcid;
8459 pTIIface->typekind = TKIND_INTERFACE;
8460 pTIIface->wMajorVerNum = 0;
8461 pTIIface->wMinorVerNum = 0;
8462 pTIIface->cbAlignment = 2;
8463 pTIIface->cbSizeInstance = -1;
8464 pTIIface->cbSizeVft = -1;
8465 pTIIface->cFuncs = 0;
8466 pTIIface->cImplTypes = 0;
8467 pTIIface->cVars = 0;
8468 pTIIface->wTypeFlags = 0;
8469 pTIIface->hreftype = 0;
8470
8471 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8472 pFuncDesc = pTIIface->funcdescs;
8473 for(func = 0; func < pidata->cMembers; func++) {
8474 METHODDATA *md = pidata->pmethdata + func;
8475 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8476 pFuncDesc->funcdesc.memid = md->dispid;
8477 pFuncDesc->funcdesc.lprgscode = NULL;
8478 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8479 pFuncDesc->funcdesc.invkind = md->wFlags;
8480 pFuncDesc->funcdesc.callconv = md->cc;
8481 pFuncDesc->funcdesc.cParams = md->cArgs;
8482 pFuncDesc->funcdesc.cParamsOpt = 0;
8483 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8484 pFuncDesc->funcdesc.cScodes = 0;
8485 pFuncDesc->funcdesc.wFuncFlags = 0;
8486 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8487 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8488 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8489 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8490 md->cArgs * sizeof(ELEMDESC));
8491 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8492 for(param = 0; param < md->cArgs; param++) {
8493 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8494 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8495 }
8496 pFuncDesc->helpcontext = 0;
8497 pFuncDesc->HelpStringContext = 0;
8498 pFuncDesc->HelpString = NULL;
8499 pFuncDesc->Entry = NULL;
8500 list_init(&pFuncDesc->custdata_list);
8501 pTIIface->cFuncs++;
8502 ++pFuncDesc;
8503 }
8504
8505 dump_TypeInfo(pTIIface);
8506
8507 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8508 pTIClass->pTypeLib = pTypeLibImpl;
8509 pTIClass->index = 1;
8510 pTIClass->Name = NULL;
8511 pTIClass->dwHelpContext = -1;
8512 pTIClass->guid = NULL;
8513 pTIClass->lcid = lcid;
8514 pTIClass->typekind = TKIND_COCLASS;
8515 pTIClass->wMajorVerNum = 0;
8516 pTIClass->wMinorVerNum = 0;
8517 pTIClass->cbAlignment = 2;
8518 pTIClass->cbSizeInstance = -1;
8519 pTIClass->cbSizeVft = -1;
8520 pTIClass->cFuncs = 0;
8521 pTIClass->cImplTypes = 1;
8522 pTIClass->cVars = 0;
8523 pTIClass->wTypeFlags = 0;
8524 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8525
8526 pTIClass->impltypes = TLBImplType_Alloc(1);
8527
8528 ref = heap_alloc_zero(sizeof(*ref));
8529 ref->pImpTLInfo = TLB_REF_INTERNAL;
8530 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8531
8532 dump_TypeInfo(pTIClass);
8533
8534 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8535
8536 ITypeInfo_AddRef(*pptinfo);
8537 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8538
8539 return S_OK;
8540
8541 }
8542
8543 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8544 {
8545 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8546
8547 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8548 }
8549
8550 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8551 {
8552 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8553
8554 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8555 }
8556
8557 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8558 {
8559 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8560
8561 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8562 }
8563
8564 static HRESULT WINAPI ITypeComp_fnBind(
8565 ITypeComp * iface,
8566 OLECHAR * szName,
8567 ULONG lHash,
8568 WORD wFlags,
8569 ITypeInfo ** ppTInfo,
8570 DESCKIND * pDescKind,
8571 BINDPTR * pBindPtr)
8572 {
8573 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8574 const TLBFuncDesc *pFDesc;
8575 const TLBVarDesc *pVDesc;
8576 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8577 UINT fdc;
8578
8579 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8580
8581 *pDescKind = DESCKIND_NONE;
8582 pBindPtr->lpfuncdesc = NULL;
8583 *ppTInfo = NULL;
8584
8585 for(fdc = 0; fdc < This->cFuncs; ++fdc){
8586 pFDesc = &This->funcdescs[fdc];
8587 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8588 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8589 break;
8590 else
8591 /* name found, but wrong flags */
8592 hr = TYPE_E_TYPEMISMATCH;
8593 }
8594 }
8595
8596 if (fdc < This->cFuncs)
8597 {
8598 HRESULT hr = TLB_AllocAndInitFuncDesc(
8599 &pFDesc->funcdesc,
8600 &pBindPtr->lpfuncdesc,
8601 This->typekind == TKIND_DISPATCH);
8602 if (FAILED(hr))
8603 return hr;
8604 *pDescKind = DESCKIND_FUNCDESC;
8605 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8606 ITypeInfo_AddRef(*ppTInfo);
8607 return S_OK;
8608 } else {
8609 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->cVars, szName);
8610 if(pVDesc){
8611 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8612 if (FAILED(hr))
8613 return hr;
8614 *pDescKind = DESCKIND_VARDESC;
8615 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8616 ITypeInfo_AddRef(*ppTInfo);
8617 return S_OK;
8618 }
8619 }
8620
8621 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8622 /* recursive search */
8623 ITypeInfo *pTInfo;
8624 ITypeComp *pTComp;
8625 HRESULT hr;
8626 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8627 if (SUCCEEDED(hr))
8628 {
8629 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8630 ITypeInfo_Release(pTInfo);
8631 }
8632 if (SUCCEEDED(hr))
8633 {
8634 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8635 ITypeComp_Release(pTComp);
8636 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8637 This->typekind == TKIND_DISPATCH)
8638 {
8639 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8640 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8641 SysFreeString((BSTR)tmp);
8642 }
8643 return hr;
8644 }
8645 WARN("Could not search inherited interface!\n");
8646 }
8647 if (hr == DISP_E_MEMBERNOTFOUND)
8648 hr = S_OK;
8649 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8650 return hr;
8651 }
8652
8653 static HRESULT WINAPI ITypeComp_fnBindType(
8654 ITypeComp * iface,
8655 OLECHAR * szName,
8656 ULONG lHash,
8657 ITypeInfo ** ppTInfo,
8658 ITypeComp ** ppTComp)
8659 {
8660 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8661
8662 /* strange behaviour (does nothing) but like the
8663 * original */
8664
8665 if (!ppTInfo || !ppTComp)
8666 return E_POINTER;
8667
8668 *ppTInfo = NULL;
8669 *ppTComp = NULL;
8670
8671 return S_OK;
8672 }
8673
8674 static const ITypeCompVtbl tcompvt =
8675 {
8676
8677 ITypeComp_fnQueryInterface,
8678 ITypeComp_fnAddRef,
8679 ITypeComp_fnRelease,
8680
8681 ITypeComp_fnBind,
8682 ITypeComp_fnBindType
8683 };
8684
8685 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8686 ICreateTypeLib2** ppctlib)
8687 {
8688 ITypeLibImpl *This;
8689 HRESULT hres;
8690
8691 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8692
8693 if (!szFile) return E_INVALIDARG;
8694
8695 This = TypeLibImpl_Constructor();
8696 if (!This)
8697 return E_OUTOFMEMORY;
8698
8699 This->lcid = GetSystemDefaultLCID();
8700 This->syskind = syskind;
8701 This->ptr_size = get_ptr_size(syskind);
8702
8703 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8704 if (!This->path) {
8705 ITypeLib2_Release(&This->ITypeLib2_iface);
8706 return E_OUTOFMEMORY;
8707 }
8708 lstrcpyW(This->path, szFile);
8709
8710 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8711 ITypeLib2_Release(&This->ITypeLib2_iface);
8712 return hres;
8713 }
8714
8715 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8716 REFIID riid, void **object)
8717 {
8718 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8719
8720 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8721 }
8722
8723 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8724 {
8725 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8726
8727 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8728 }
8729
8730 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8731 {
8732 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8733
8734 return ITypeLib2_Release(&This->ITypeLib2_iface);
8735 }
8736
8737 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8738 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8739 {
8740 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8741 ITypeInfoImpl *info;
8742 HRESULT hres;
8743
8744 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8745
8746 if (!ctinfo || !name)
8747 return E_INVALIDARG;
8748
8749 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8750 if (info)
8751 return TYPE_E_NAMECONFLICT;
8752
8753 if (This->typeinfos)
8754 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8755 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8756 else
8757 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8758
8759 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8760
8761 info->pTypeLib = This;
8762 info->Name = TLB_append_str(&This->name_list, name);
8763 info->index = This->TypeInfoCount;
8764 info->typekind = kind;
8765 info->cbAlignment = 4;
8766
8767 switch(info->typekind) {
8768 case TKIND_ENUM:
8769 case TKIND_INTERFACE:
8770 case TKIND_DISPATCH:
8771 case TKIND_COCLASS:
8772 info->cbSizeInstance = This->ptr_size;
8773 break;
8774 case TKIND_RECORD:
8775 case TKIND_UNION:
8776 info->cbSizeInstance = 0;
8777 break;
8778 case TKIND_MODULE:
8779 info->cbSizeInstance = 2;
8780 break;
8781 case TKIND_ALIAS:
8782 info->cbSizeInstance = -0x75;
8783 break;
8784 default:
8785 FIXME("unrecognized typekind %d\n", info->typekind);
8786 info->cbSizeInstance = 0xdeadbeef;
8787 break;
8788 }
8789
8790 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8791 &IID_ICreateTypeInfo, (void **)ctinfo);
8792 if (FAILED(hres)) {
8793 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8794 return hres;
8795 }
8796
8797 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8798
8799 ++This->TypeInfoCount;
8800
8801 return S_OK;
8802 }
8803
8804 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8805 LPOLESTR name)
8806 {
8807 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8808
8809 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8810
8811 if (!name)
8812 return E_INVALIDARG;
8813
8814 This->Name = TLB_append_str(&This->name_list, name);
8815
8816 return S_OK;
8817 }
8818
8819 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8820 WORD majorVerNum, WORD minorVerNum)
8821 {
8822 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8823
8824 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8825
8826 This->ver_major = majorVerNum;
8827 This->ver_minor = minorVerNum;
8828
8829 return S_OK;
8830 }
8831
8832 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8833 REFGUID guid)
8834 {
8835 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8836
8837 TRACE("%p %s\n", This, debugstr_guid(guid));
8838
8839 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8840
8841 return S_OK;
8842 }
8843
8844 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8845 LPOLESTR doc)
8846 {
8847 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8848
8849 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8850
8851 if (!doc)
8852 return E_INVALIDARG;
8853
8854 This->DocString = TLB_append_str(&This->string_list, doc);
8855
8856 return S_OK;
8857 }
8858
8859 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8860 LPOLESTR helpFileName)
8861 {
8862 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8863
8864 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8865
8866 if (!helpFileName)
8867 return E_INVALIDARG;
8868
8869 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8870
8871 return S_OK;
8872 }
8873
8874 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8875 DWORD helpContext)
8876 {
8877 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8878
8879 TRACE("%p %d\n", This, helpContext);
8880
8881 This->dwHelpContext = helpContext;
8882
8883 return S_OK;
8884 }
8885
8886 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8887 LCID lcid)
8888 {
8889 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8890
8891 TRACE("%p %x\n", This, lcid);
8892
8893 This->set_lcid = lcid;
8894
8895 return S_OK;
8896 }
8897
8898 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8899 UINT libFlags)
8900 {
8901 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8902
8903 TRACE("%p %x\n", This, libFlags);
8904
8905 This->libflags = libFlags;
8906
8907 return S_OK;
8908 }
8909
8910 typedef struct tagWMSFT_SegContents {
8911 DWORD len;
8912 void *data;
8913 } WMSFT_SegContents;
8914
8915 typedef struct tagWMSFT_TLBFile {
8916 MSFT_Header header;
8917 WMSFT_SegContents typeinfo_seg;
8918 WMSFT_SegContents impfile_seg;
8919 WMSFT_SegContents impinfo_seg;
8920 WMSFT_SegContents ref_seg;
8921 WMSFT_SegContents guidhash_seg;
8922 WMSFT_SegContents guid_seg;
8923 WMSFT_SegContents namehash_seg;
8924 WMSFT_SegContents name_seg;
8925 WMSFT_SegContents string_seg;
8926 WMSFT_SegContents typdesc_seg;
8927 WMSFT_SegContents arraydesc_seg;
8928 WMSFT_SegContents custdata_seg;
8929 WMSFT_SegContents cdguids_seg;
8930 MSFT_SegDir segdir;
8931 WMSFT_SegContents aux_seg;
8932 } WMSFT_TLBFile;
8933
8934 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8935 WMSFT_TLBFile *file)
8936 {
8937 TLBString *str;
8938 UINT last_offs;
8939 char *data;
8940
8941 file->string_seg.len = 0;
8942 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8943 int size;
8944
8945 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8946 if (size == 0)
8947 return E_UNEXPECTED;
8948
8949 size += sizeof(INT16);
8950 if (size % 4)
8951 size = (size + 4) & ~0x3;
8952 if (size < 8)
8953 size = 8;
8954
8955 file->string_seg.len += size;
8956
8957 /* temporarily use str->offset to store the length of the aligned,
8958 * converted string */
8959 str->offset = size;
8960 }
8961
8962 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8963
8964 last_offs = 0;
8965 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8966 int size;
8967
8968 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8969 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8970 if (size == 0) {
8971 heap_free(file->string_seg.data);
8972 return E_UNEXPECTED;
8973 }
8974
8975 *((INT16*)data) = size;
8976
8977 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8978
8979 size = str->offset;
8980 data += size;
8981 str->offset = last_offs;
8982 last_offs += size;
8983 }
8984
8985 return S_OK;
8986 }
8987
8988 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8989 WMSFT_TLBFile *file)
8990 {
8991 TLBString *str;
8992 UINT last_offs;
8993 char *data;
8994 MSFT_NameIntro *last_intro = NULL;
8995
8996 file->header.nametablecount = 0;
8997 file->header.nametablechars = 0;
8998
8999 file->name_seg.len = 0;
9000 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9001 int size;
9002
9003 size = strlenW(str->str);
9004 file->header.nametablechars += size;
9005 file->header.nametablecount++;
9006
9007 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9008 if (size == 0)
9009 return E_UNEXPECTED;
9010
9011 size += sizeof(MSFT_NameIntro);
9012 if (size % 4)
9013 size = (size + 4) & ~0x3;
9014 if (size < 8)
9015 size = 8;
9016
9017 file->name_seg.len += size;
9018
9019 /* temporarily use str->offset to store the length of the aligned,
9020 * converted string */
9021 str->offset = size;
9022 }
9023
9024 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9025 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9026
9027 last_offs = 0;
9028 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9029 int size, hash;
9030 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9031
9032 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9033 data + sizeof(MSFT_NameIntro),
9034 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9035 if (size == 0) {
9036 heap_free(file->name_seg.data);
9037 return E_UNEXPECTED;
9038 }
9039 data[sizeof(MSFT_NameIntro) + size] = '\0';
9040
9041 intro->hreftype = -1; /* TODO? */
9042 intro->namelen = size & 0xFF;
9043 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9044 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9045 intro->namelen |= hash << 16;
9046 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9047 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9048
9049 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9050 str->offset - size - sizeof(MSFT_NameIntro));
9051
9052 /* update str->offset to actual value to use in other
9053 * compilation functions that require positions within
9054 * the string table */
9055 last_intro = intro;
9056 size = str->offset;
9057 data += size;
9058 str->offset = last_offs;
9059 last_offs += size;
9060 }
9061
9062 if(last_intro)
9063 last_intro->hreftype = 0; /* last one is 0? */
9064
9065 return S_OK;
9066 }
9067
9068 static inline int hash_guid(GUID *guid)
9069 {
9070 int i, hash = 0;
9071
9072 for (i = 0; i < 8; i ++)
9073 hash ^= ((const short *)guid)[i];
9074
9075 return hash & 0x1f;
9076 }
9077
9078 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9079 {
9080 TLBGuid *guid;
9081 MSFT_GuidEntry *entry;
9082 DWORD offs;
9083 int hash_key, *guidhashtab;
9084
9085 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9086 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9087
9088 entry = file->guid_seg.data;
9089 offs = 0;
9090 guidhashtab = file->guidhash_seg.data;
9091 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9092 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9093 entry->hreftype = guid->hreftype;
9094
9095 hash_key = hash_guid(&guid->guid);
9096 entry->next_hash = guidhashtab[hash_key];
9097 guidhashtab[hash_key] = offs;
9098
9099 guid->offset = offs;
9100 offs += sizeof(MSFT_GuidEntry);
9101 ++entry;
9102 }
9103
9104 return S_OK;
9105 }
9106
9107 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9108 {
9109 VARIANT v = *value;
9110 VARTYPE arg_type = V_VT(value);
9111 int mask = 0;
9112 HRESULT hres;
9113 DWORD ret = file->custdata_seg.len;
9114
9115 if(arg_type == VT_INT)
9116 arg_type = VT_I4;
9117 if(arg_type == VT_UINT)
9118 arg_type = VT_UI4;
9119
9120 v = *value;
9121 if(V_VT(value) != arg_type) {
9122 hres = VariantChangeType(&v, value, 0, arg_type);
9123 if(FAILED(hres)){
9124 ERR("VariantChangeType failed: %08x\n", hres);
9125 return -1;
9126 }
9127 }
9128
9129 /* Check if default value can be stored in-place */
9130 switch(arg_type){
9131 case VT_I4:
9132 case VT_UI4:
9133 mask = 0x3ffffff;
9134 if(V_UI4(&v) > 0x3ffffff)
9135 break;
9136 /* fall through */
9137 case VT_I1:
9138 case VT_UI1:
9139 case VT_BOOL:
9140 if(!mask)
9141 mask = 0xff;
9142 /* fall through */
9143 case VT_I2:
9144 case VT_UI2:
9145 if(!mask)
9146 mask = 0xffff;
9147 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9148 }
9149
9150 /* have to allocate space in custdata_seg */
9151 switch(arg_type) {
9152 case VT_I4:
9153 case VT_R4:
9154 case VT_UI4:
9155 case VT_INT:
9156 case VT_UINT:
9157 case VT_HRESULT:
9158 case VT_PTR: {
9159 /* Construct the data to be allocated */
9160 int *data;
9161
9162 if(file->custdata_seg.data){
9163 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9164 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9165 file->custdata_seg.len += sizeof(int) * 2;
9166 }else{
9167 file->custdata_seg.len = sizeof(int) * 2;
9168 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9169 }
9170
9171 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9172 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9173
9174 /* TODO: Check if the encoded data is already present in custdata_seg */
9175
9176 return ret;
9177 }
9178
9179 case VT_BSTR: {
9180 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9181 char *data;
9182
9183 if(file->custdata_seg.data){
9184 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9185 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9186 file->custdata_seg.len += len;
9187 }else{
9188 file->custdata_seg.len = len;
9189 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9190 }
9191
9192 *((unsigned short *)data) = V_VT(value);
9193 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9194 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9195 if(V_BSTR(&v)[i] <= 0x7f)
9196 data[i+6] = V_BSTR(&v)[i];
9197 else
9198 data[i+6] = '?';
9199 }
9200 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9201 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9202 data[i] = 0x57;
9203
9204 /* TODO: Check if the encoded data is already present in custdata_seg */
9205
9206 return ret;
9207 }
9208 default:
9209 FIXME("Argument type not yet handled\n");
9210 return -1;
9211 }
9212 }
9213
9214 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9215
9216 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9217 {
9218 DWORD offs = file->arraydesc_seg.len;
9219 DWORD *encoded;
9220 USHORT i;
9221
9222 /* TODO: we should check for duplicates, but that's harder because each
9223 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9224 * at the library-level) */
9225
9226 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9227 if(!file->arraydesc_seg.data)
9228 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9229 else
9230 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9231 encoded = (DWORD*)((char *)file->arraydesc_seg.data) + offs;
9232
9233 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9234 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9235 for(i = 0; i < desc->cDims; ++i){
9236 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9237 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9238 }
9239
9240 return offs;
9241 }
9242
9243 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9244 {
9245 DWORD junk;
9246 INT16 junk2;
9247 DWORD offs = 0;
9248 DWORD encoded[2];
9249 VARTYPE vt, subtype;
9250 char *data;
9251
9252 if(!desc)
9253 return -1;
9254
9255 if(!out_mix)
9256 out_mix = &junk;
9257 if(!out_size)
9258 out_size = &junk2;
9259
9260 vt = desc->vt & VT_TYPEMASK;
9261
9262 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9263 DWORD mix;
9264 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9265 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9266 *out_mix = 0x7FFF;
9267 *out_size += 2 * sizeof(DWORD);
9268 }else if(vt == VT_CARRAY){
9269 encoded[0] = desc->vt | (0x7FFE << 16);
9270 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9271 *out_mix = 0x7FFE;
9272 }else if(vt == VT_USERDEFINED){
9273 encoded[0] = desc->vt | (0x7FFF << 16);
9274 encoded[1] = desc->u.hreftype;
9275 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9276 }else{
9277 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9278
9279 switch(vt){
9280 case VT_INT:
9281 subtype = VT_I4;
9282 break;
9283 case VT_UINT:
9284 subtype = VT_UI4;
9285 break;
9286 case VT_VOID:
9287 subtype = VT_EMPTY;
9288 break;
9289 default:
9290 subtype = vt;
9291 break;
9292 }
9293
9294 *out_mix = subtype;
9295 return 0x80000000 | (subtype << 16) | desc->vt;
9296 }
9297
9298 data = file->typdesc_seg.data;
9299 while(offs < file->typdesc_seg.len){
9300 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9301 return offs;
9302 offs += sizeof(encoded);
9303 }
9304
9305 file->typdesc_seg.len += sizeof(encoded);
9306 if(!file->typdesc_seg.data)
9307 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9308 else
9309 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9310
9311 memcpy(&data[offs], encoded, sizeof(encoded));
9312
9313 return offs;
9314 }
9315
9316 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9317 {
9318 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9319 DWORD ret = cdguids_seg->len, offs;
9320 MSFT_CDGuid *cdguid = cdguids_seg->data;
9321 TLBCustData *cd;
9322
9323 if(list_empty(custdata_list))
9324 return -1;
9325
9326 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9327 if(!cdguids_seg->data){
9328 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9329 }else
9330 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9331
9332 offs = ret + sizeof(MSFT_CDGuid);
9333 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9334 cdguid->GuidOffset = cd->guid->offset;
9335 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9336 cdguid->next = offs;
9337 offs += sizeof(MSFT_CDGuid);
9338 ++cdguid;
9339 }
9340
9341 --cdguid;
9342 cdguid->next = -1;
9343
9344 return ret;
9345 }
9346
9347 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9348 WMSFT_TLBFile *file)
9349 {
9350 WMSFT_SegContents *aux_seg = &file->aux_seg;
9351 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9352 MSFT_VarRecord *varrecord;
9353 MSFT_FuncRecord *funcrecord;
9354 MEMBERID *memid;
9355 DWORD *name, *offsets, offs;
9356
9357 for(i = 0; i < info->cFuncs; ++i){
9358 TLBFuncDesc *desc = &info->funcdescs[i];
9359
9360 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9361
9362 /* optional fields */
9363 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9364 if(!list_empty(&desc->custdata_list))
9365 recorded_size += 7 * sizeof(INT);
9366 else if(desc->HelpStringContext != 0)
9367 recorded_size += 6 * sizeof(INT);
9368 /* res9? resA? */
9369 else if(desc->Entry)
9370 recorded_size += 3 * sizeof(INT);
9371 else if(desc->HelpString)
9372 recorded_size += 2 * sizeof(INT);
9373 else if(desc->helpcontext)
9374 recorded_size += sizeof(INT);
9375
9376 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9377
9378 for(j = 0; j < desc->funcdesc.cParams; ++j){
9379 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9380 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9381 break;
9382 }
9383 }
9384
9385 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9386 }
9387
9388 for(i = 0; i < info->cVars; ++i){
9389 TLBVarDesc *desc = &info->vardescs[i];
9390
9391 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9392
9393 /* optional fields */
9394 if(desc->HelpStringContext != 0)
9395 recorded_size += 5 * sizeof(INT);
9396 else if(!list_empty(&desc->custdata_list))
9397 recorded_size += 4 * sizeof(INT);
9398 /* res9? */
9399 else if(desc->HelpString)
9400 recorded_size += 2 * sizeof(INT);
9401 else if(desc->HelpContext != 0)
9402 recorded_size += sizeof(INT);
9403
9404 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9405 }
9406
9407 if(!recorded_size && !extra_size)
9408 return ret;
9409
9410 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9411
9412 aux_seg->len += recorded_size + extra_size;
9413
9414 aux_seg->len += sizeof(INT) * (info->cVars + info->cFuncs); /* offsets at the end */
9415
9416 if(aux_seg->data)
9417 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9418 else
9419 aux_seg->data = heap_alloc(aux_seg->len);
9420
9421 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9422
9423 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9424 offs = 0;
9425
9426 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9427 for(i = 0; i < info->cFuncs; ++i){
9428 TLBFuncDesc *desc = &info->funcdescs[i];
9429 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9430
9431 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9432 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9433 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9434 funcrecord->VtableOffset = desc->funcdesc.oVft;
9435
9436 /* FKCCIC:
9437 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9438 * ^^^funckind
9439 * ^^^ ^invkind
9440 * ^has_cust_data
9441 * ^^^^callconv
9442 * ^has_param_defaults
9443 * ^oEntry_is_intresource
9444 */
9445 funcrecord->FKCCIC =
9446 desc->funcdesc.funckind |
9447 (desc->funcdesc.invkind << 3) |
9448 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9449 (desc->funcdesc.callconv << 8);
9450
9451 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9452 funcrecord->FKCCIC |= 0x2000;
9453
9454 for(j = 0; j < desc->funcdesc.cParams; ++j){
9455 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9456 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9457 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9458 }
9459 }
9460 if(paramdefault_size > 0)
9461 funcrecord->FKCCIC |= 0x1000;
9462
9463 funcrecord->nrargs = desc->funcdesc.cParams;
9464 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9465
9466 /* optional fields */
9467 /* res9? resA? */
9468 if(!list_empty(&desc->custdata_list)){
9469 size += 7 * sizeof(INT);
9470 funcrecord->HelpContext = desc->helpcontext;
9471 if(desc->HelpString)
9472 funcrecord->oHelpString = desc->HelpString->offset;
9473 else
9474 funcrecord->oHelpString = -1;
9475 if(!desc->Entry)
9476 funcrecord->oEntry = -1;
9477 else if(IS_INTRESOURCE(desc->Entry))
9478 funcrecord->oEntry = LOWORD(desc->Entry);
9479 else
9480 funcrecord->oEntry = desc->Entry->offset;
9481 funcrecord->res9 = -1;
9482 funcrecord->resA = -1;
9483 funcrecord->HelpStringContext = desc->HelpStringContext;
9484 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9485 }else if(desc->HelpStringContext != 0){
9486 size += 6 * sizeof(INT);
9487 funcrecord->HelpContext = desc->helpcontext;
9488 if(desc->HelpString)
9489 funcrecord->oHelpString = desc->HelpString->offset;
9490 else
9491 funcrecord->oHelpString = -1;
9492 if(!desc->Entry)
9493 funcrecord->oEntry = -1;
9494 else if(IS_INTRESOURCE(desc->Entry))
9495 funcrecord->oEntry = LOWORD(desc->Entry);
9496 else
9497 funcrecord->oEntry = desc->Entry->offset;
9498 funcrecord->res9 = -1;
9499 funcrecord->resA = -1;
9500 funcrecord->HelpStringContext = desc->HelpStringContext;
9501 }else if(desc->Entry){
9502 size += 3 * sizeof(INT);
9503 funcrecord->HelpContext = desc->helpcontext;
9504 if(desc->HelpString)
9505 funcrecord->oHelpString = desc->HelpString->offset;
9506 else
9507 funcrecord->oHelpString = -1;
9508 if(!desc->Entry)
9509 funcrecord->oEntry = -1;
9510 else if(IS_INTRESOURCE(desc->Entry))
9511 funcrecord->oEntry = LOWORD(desc->Entry);
9512 else
9513 funcrecord->oEntry = desc->Entry->offset;
9514 }else if(desc->HelpString){
9515 size += 2 * sizeof(INT);
9516 funcrecord->HelpContext = desc->helpcontext;
9517 funcrecord->oHelpString = desc->HelpString->offset;
9518 }else if(desc->helpcontext){
9519 size += sizeof(INT);
9520 funcrecord->HelpContext = desc->helpcontext;
9521 }
9522
9523 paramdefault = (DWORD*)((char *)funcrecord + size);
9524 size += paramdefault_size;
9525
9526 for(j = 0; j < desc->funcdesc.cParams; ++j){
9527 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9528
9529 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9530 if(desc->pParamDesc[j].Name)
9531 info->oName = desc->pParamDesc[j].Name->offset;
9532 else
9533 info->oName = -1;
9534 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9535
9536 if(paramdefault_size){
9537 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9538 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9539 else if(paramdefault_size)
9540 *paramdefault = -1;
9541 ++paramdefault;
9542 }
9543
9544 size += sizeof(MSFT_ParameterInfo);
9545 }
9546
9547 funcrecord->Info = size | (i << 16); /* is it just the index? */
9548
9549 *offsets = offs;
9550 offs += size;
9551 ++offsets;
9552
9553 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9554 }
9555
9556 varrecord = (MSFT_VarRecord*)funcrecord;
9557 for(i = 0; i < info->cVars; ++i){
9558 TLBVarDesc *desc = &info->vardescs[i];
9559 DWORD size = 5 * sizeof(INT);
9560
9561 varrecord->vardescsize = sizeof(desc->vardesc);
9562 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9563 varrecord->Flags = desc->vardesc.wVarFlags;
9564 varrecord->VarKind = desc->vardesc.varkind;
9565
9566 if(desc->vardesc.varkind == VAR_CONST){
9567 varrecord->vardescsize += sizeof(VARIANT);
9568 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9569 }else
9570 varrecord->OffsValue = desc->vardesc.u.oInst;
9571
9572 /* res9? */
9573 if(desc->HelpStringContext != 0){
9574 size += 5 * sizeof(INT);
9575 varrecord->HelpContext = desc->HelpContext;
9576 if(desc->HelpString)
9577 varrecord->HelpString = desc->HelpString->offset;
9578 else
9579 varrecord->HelpString = -1;
9580 varrecord->res9 = -1;
9581 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9582 varrecord->HelpStringContext = desc->HelpStringContext;
9583 }else if(!list_empty(&desc->custdata_list)){
9584 size += 4 * sizeof(INT);
9585 varrecord->HelpContext = desc->HelpContext;
9586 if(desc->HelpString)
9587 varrecord->HelpString = desc->HelpString->offset;
9588 else
9589 varrecord->HelpString = -1;
9590 varrecord->res9 = -1;
9591 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9592 }else if(desc->HelpString){
9593 size += 2 * sizeof(INT);
9594 varrecord->HelpContext = desc->HelpContext;
9595 if(desc->HelpString)
9596 varrecord->HelpString = desc->HelpString->offset;
9597 else
9598 varrecord->HelpString = -1;
9599 }else if(desc->HelpContext != 0){
9600 size += sizeof(INT);
9601 varrecord->HelpContext = desc->HelpContext;
9602 }
9603
9604 varrecord->Info = size | (i << 16);
9605
9606 *offsets = offs;
9607 offs += size;
9608 ++offsets;
9609
9610 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9611 }
9612
9613 memid = (MEMBERID*)varrecord;
9614 for(i = 0; i < info->cFuncs; ++i){
9615 TLBFuncDesc *desc = &info->funcdescs[i];
9616 *memid = desc->funcdesc.memid;
9617 ++memid;
9618 }
9619 for(i = 0; i < info->cVars; ++i){
9620 TLBVarDesc *desc = &info->vardescs[i];
9621 *memid = desc->vardesc.memid;
9622 ++memid;
9623 }
9624
9625 name = (UINT*)memid;
9626 for(i = 0; i < info->cFuncs; ++i){
9627 TLBFuncDesc *desc = &info->funcdescs[i];
9628 if(desc->Name)
9629 *name = desc->Name->offset;
9630 else
9631 *name = -1;
9632 ++name;
9633 }
9634 for(i = 0; i < info->cVars; ++i){
9635 TLBVarDesc *desc = &info->vardescs[i];
9636 if(desc->Name)
9637 *name = desc->Name->offset;
9638 else
9639 *name = -1;
9640 ++name;
9641 }
9642
9643 return ret;
9644 }
9645
9646 typedef struct tagWMSFT_RefChunk {
9647 DWORD href;
9648 DWORD res04;
9649 DWORD res08;
9650 DWORD next;
9651 } WMSFT_RefChunk;
9652
9653 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9654 {
9655 DWORD offs = file->ref_seg.len, i;
9656 WMSFT_RefChunk *chunk;
9657
9658 file->ref_seg.len += info->cImplTypes * sizeof(WMSFT_RefChunk);
9659 if(!file->ref_seg.data)
9660 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9661 else
9662 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9663
9664 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9665
9666 for(i = 0; i < info->cImplTypes; ++i){
9667 chunk->href = info->impltypes[i].hRef;
9668 chunk->res04 = info->impltypes[i].implflags;
9669 chunk->res08 = -1;
9670 if(i < info->cImplTypes - 1)
9671 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9672 else
9673 chunk->next = -1;
9674 ++chunk;
9675 }
9676
9677 return offs;
9678 }
9679
9680 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9681 {
9682 DWORD size;
9683
9684 size = sizeof(MSFT_TypeInfoBase);
9685
9686 if(data){
9687 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9688 if(info->wTypeFlags & TYPEFLAG_FDUAL)
9689 base->typekind = TKIND_DISPATCH;
9690 else
9691 base->typekind = info->typekind;
9692 base->typekind |= index << 16; /* TODO: There are some other flags here */
9693 base->typekind |= (info->cbAlignment << 11) | (info->cbAlignment << 6);
9694 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9695 base->res2 = 0;
9696 base->res3 = 0;
9697 base->res4 = 3;
9698 base->res5 = 0;
9699 base->cElement = (info->cVars << 16) | info->cFuncs;
9700 base->res7 = 0;
9701 base->res8 = 0;
9702 base->res9 = 0;
9703 base->resA = 0;
9704 if(info->guid)
9705 base->posguid = info->guid->offset;
9706 else
9707 base->posguid = -1;
9708 base->flags = info->wTypeFlags;
9709 if(info->Name) {
9710 base->NameOffset = info->Name->offset;
9711
9712 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9713 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9714 }else {
9715 base->NameOffset = -1;
9716 }
9717 base->version = (info->wMinorVerNum << 16) | info->wMajorVerNum;
9718 if(info->DocString)
9719 base->docstringoffs = info->DocString->offset;
9720 else
9721 base->docstringoffs = -1;
9722 base->helpstringcontext = info->dwHelpStringContext;
9723 base->helpcontext = info->dwHelpContext;
9724 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9725 base->cImplTypes = info->cImplTypes;
9726 base->cbSizeVft = info->cbSizeVft;
9727 base->size = info->cbSizeInstance;
9728 if(info->typekind == TKIND_COCLASS){
9729 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9730 }else if(info->typekind == TKIND_ALIAS){
9731 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9732 }else if(info->typekind == TKIND_MODULE){
9733 if(info->DllName)
9734 base->datatype1 = info->DllName->offset;
9735 else
9736 base->datatype1 = -1;
9737 }else{
9738 if(info->cImplTypes > 0)
9739 base->datatype1 = info->impltypes[0].hRef;
9740 else
9741 base->datatype1 = -1;
9742 }
9743 base->datatype2 = index; /* FIXME: i think there's more here */
9744 base->res18 = 0;
9745 base->res19 = -1;
9746 }
9747
9748 return size;
9749 }
9750
9751 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9752 {
9753 UINT i;
9754
9755 file->typeinfo_seg.len = 0;
9756 for(i = 0; i < This->TypeInfoCount; ++i){
9757 ITypeInfoImpl *info = This->typeinfos[i];
9758 *junk = file->typeinfo_seg.len;
9759 ++junk;
9760 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9761 }
9762
9763 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9764 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9765
9766 file->aux_seg.len = 0;
9767 file->aux_seg.data = NULL;
9768
9769 file->typeinfo_seg.len = 0;
9770 for(i = 0; i < This->TypeInfoCount; ++i){
9771 ITypeInfoImpl *info = This->typeinfos[i];
9772 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9773 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9774 }
9775 }
9776
9777 typedef struct tagWMSFT_ImpFile {
9778 INT guid_offs;
9779 LCID lcid;
9780 DWORD version;
9781 } WMSFT_ImpFile;
9782
9783 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9784 {
9785 TLBImpLib *implib;
9786 WMSFT_ImpFile *impfile;
9787 char *data;
9788 DWORD last_offs = 0;
9789
9790 file->impfile_seg.len = 0;
9791 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9792 int size = 0;
9793
9794 if(implib->name){
9795 WCHAR *path = strrchrW(implib->name, '\\');
9796 if(path)
9797 ++path;
9798 else
9799 path = implib->name;
9800 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9801 if (size == 0)
9802 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9803 }
9804
9805 size += sizeof(INT16);
9806 if (size % 4)
9807 size = (size + 4) & ~0x3;
9808 if (size < 8)
9809 size = 8;
9810
9811 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9812 }
9813
9814 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9815
9816 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9817 int strlen = 0, size;
9818
9819 impfile = (WMSFT_ImpFile*)data;
9820 impfile->guid_offs = implib->guid->offset;
9821 impfile->lcid = implib->lcid;
9822 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9823
9824 data += sizeof(WMSFT_ImpFile);
9825
9826 if(implib->name){
9827 WCHAR *path= strrchrW(implib->name, '\\');
9828 if(path)
9829 ++path;
9830 else
9831 path = implib->name;
9832 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9833 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9834 if (strlen == 0)
9835 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9836 }
9837
9838 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9839
9840 size = strlen + sizeof(INT16);
9841 if (size % 4)
9842 size = (size + 4) & ~0x3;
9843 if (size < 8)
9844 size = 8;
9845 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9846
9847 data += size;
9848 implib->offset = last_offs;
9849 last_offs += size + sizeof(WMSFT_ImpFile);
9850 }
9851 }
9852
9853 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9854 {
9855 MSFT_ImpInfo *info;
9856 TLBRefType *ref_type;
9857 UINT i = 0;
9858
9859 WMSFT_compile_impfile(This, file);
9860
9861 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9862 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9863
9864 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9865 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9866 if(ref_type->index == TLB_REF_USE_GUID){
9867 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9868 info->oGuid = ref_type->guid->offset;
9869 }else
9870 info->oGuid = ref_type->index;
9871 info->oImpFile = ref_type->pImpTLInfo->offset;
9872 ++i;
9873 ++info;
9874 }
9875 }
9876
9877 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9878 {
9879 file->guidhash_seg.len = 0x80;
9880 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9881 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9882 }
9883
9884 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9885 {
9886 file->namehash_seg.len = 0x200;
9887 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9888 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9889 }
9890
9891 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9892 {
9893 if(contents && contents->len){
9894 segdir->offset = *running_offset;
9895 segdir->length = contents->len;
9896 *running_offset += segdir->length;
9897 }else{
9898 segdir->offset = -1;
9899 segdir->length = 0;
9900 }
9901
9902 /* TODO: do these ever change? */
9903 segdir->res08 = -1;
9904 segdir->res0c = 0xf;
9905 }
9906
9907 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9908 {
9909 DWORD written;
9910 if(segment)
9911 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9912 }
9913
9914 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9915 DWORD file_len)
9916 {
9917 DWORD i;
9918 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9919
9920 for(i = 0; i < This->TypeInfoCount; ++i){
9921 base->memoffset += file_len;
9922 ++base;
9923 }
9924
9925 return S_OK;
9926 }
9927
9928 static void WMSFT_free_file(WMSFT_TLBFile *file)
9929 {
9930 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9931 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9932 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9933 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9934 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9935 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9936 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9937 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9938 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9939 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9940 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9941 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9942 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9943 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9944 }
9945
9946 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9947 {
9948 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9949 WMSFT_TLBFile file;
9950 DWORD written, junk_size, junk_offs, running_offset;
9951 BOOL br;
9952 HANDLE outfile;
9953 HRESULT hres;
9954 DWORD *junk;
9955 UINT i;
9956
9957 TRACE("%p\n", This);
9958
9959 for(i = 0; i < This->TypeInfoCount; ++i)
9960 if(This->typeinfos[i]->needs_layout)
9961 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9962
9963 memset(&file, 0, sizeof(file));
9964
9965 file.header.magic1 = 0x5446534D;
9966 file.header.magic2 = 0x00010002;
9967 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9968 file.header.lcid2 = This->set_lcid;
9969 file.header.varflags = 0x40 | This->syskind;
9970 if (This->HelpFile)
9971 file.header.varflags |= 0x10;
9972 if (This->HelpStringDll)
9973 file.header.varflags |= HELPDLLFLAG;
9974 file.header.version = (This->ver_minor << 16) | This->ver_major;
9975 file.header.flags = This->libflags;
9976 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9977 file.header.helpcontext = This->dwHelpContext;
9978 file.header.res44 = 0x20;
9979 file.header.res48 = 0x80;
9980 file.header.dispatchpos = This->dispatch_href;
9981
9982 WMSFT_compile_namehash(This, &file);
9983 /* do name and string compilation to get offsets for other compilations */
9984 hres = WMSFT_compile_names(This, &file);
9985 if (FAILED(hres)){
9986 WMSFT_free_file(&file);
9987 return hres;
9988 }
9989
9990 hres = WMSFT_compile_strings(This, &file);
9991 if (FAILED(hres)){
9992 WMSFT_free_file(&file);
9993 return hres;
9994 }
9995
9996 WMSFT_compile_guidhash(This, &file);
9997 hres = WMSFT_compile_guids(This, &file);
9998 if (FAILED(hres)){
9999 WMSFT_free_file(&file);
10000 return hres;
10001 }
10002
10003 if(This->HelpFile)
10004 file.header.helpfile = This->HelpFile->offset;
10005 else
10006 file.header.helpfile = -1;
10007
10008 if(This->DocString)
10009 file.header.helpstring = This->DocString->offset;
10010 else
10011 file.header.helpstring = -1;
10012
10013 /* do some more segment compilation */
10014 file.header.nimpinfos = list_count(&This->ref_list);
10015 file.header.nrtypeinfos = This->TypeInfoCount;
10016
10017 if(This->Name)
10018 file.header.NameOffset = This->Name->offset;
10019 else
10020 file.header.NameOffset = -1;
10021
10022 file.header.CustomDataOffset = -1; /* TODO SetCustData not impl yet */
10023
10024 if(This->guid)
10025 file.header.posguid = This->guid->offset;
10026 else
10027 file.header.posguid = -1;
10028
10029 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10030 if(file.header.varflags & HELPDLLFLAG)
10031 junk_size += sizeof(DWORD);
10032 if(junk_size){
10033 junk = heap_alloc_zero(junk_size);
10034 if(file.header.varflags & HELPDLLFLAG){
10035 *junk = This->HelpStringDll->offset;
10036 junk_offs = 1;
10037 }else
10038 junk_offs = 0;
10039 }else{
10040 junk = NULL;
10041 junk_offs = 0;
10042 }
10043
10044 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10045 WMSFT_compile_impinfo(This, &file);
10046
10047 running_offset = 0;
10048
10049 TRACE("header at: 0x%x\n", running_offset);
10050 running_offset += sizeof(file.header);
10051
10052 TRACE("junk at: 0x%x\n", running_offset);
10053 running_offset += junk_size;
10054
10055 TRACE("segdir at: 0x%x\n", running_offset);
10056 running_offset += sizeof(file.segdir);
10057
10058 TRACE("typeinfo at: 0x%x\n", running_offset);
10059 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10060
10061 TRACE("guidhashtab at: 0x%x\n", running_offset);
10062 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10063
10064 TRACE("guidtab at: 0x%x\n", running_offset);
10065 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10066
10067 TRACE("reftab at: 0x%x\n", running_offset);
10068 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10069
10070 TRACE("impinfo at: 0x%x\n", running_offset);
10071 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10072
10073 TRACE("impfiles at: 0x%x\n", running_offset);
10074 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10075
10076 TRACE("namehashtab at: 0x%x\n", running_offset);
10077 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10078
10079 TRACE("nametab at: 0x%x\n", running_offset);
10080 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10081
10082 TRACE("stringtab at: 0x%x\n", running_offset);
10083 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10084
10085 TRACE("typdesc at: 0x%x\n", running_offset);
10086 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10087
10088 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10089 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10090
10091 TRACE("custdata at: 0x%x\n", running_offset);
10092 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10093
10094 TRACE("cdguids at: 0x%x\n", running_offset);
10095 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10096
10097 TRACE("res0e at: 0x%x\n", running_offset);
10098 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10099
10100 TRACE("res0f at: 0x%x\n", running_offset);
10101 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10102
10103 TRACE("aux_seg at: 0x%x\n", running_offset);
10104
10105 WMSFT_fixup_typeinfos(This, &file, running_offset);
10106
10107 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10108 FILE_ATTRIBUTE_NORMAL, 0);
10109 if (outfile == INVALID_HANDLE_VALUE){
10110 WMSFT_free_file(&file);
10111 heap_free(junk);
10112 return TYPE_E_IOERROR;
10113 }
10114
10115 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10116 if (!br) {
10117 WMSFT_free_file(&file);
10118 CloseHandle(outfile);
10119 heap_free(junk);
10120 return TYPE_E_IOERROR;
10121 }
10122
10123 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10124 heap_free(junk);
10125 if (!br) {
10126 WMSFT_free_file(&file);
10127 CloseHandle(outfile);
10128 return TYPE_E_IOERROR;
10129 }
10130
10131 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10132 if (!br) {
10133 WMSFT_free_file(&file);
10134 CloseHandle(outfile);
10135 return TYPE_E_IOERROR;
10136 }
10137
10138 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10139 WMSFT_write_segment(outfile, &file.guidhash_seg);
10140 WMSFT_write_segment(outfile, &file.guid_seg);
10141 WMSFT_write_segment(outfile, &file.ref_seg);
10142 WMSFT_write_segment(outfile, &file.impinfo_seg);
10143 WMSFT_write_segment(outfile, &file.impfile_seg);
10144 WMSFT_write_segment(outfile, &file.namehash_seg);
10145 WMSFT_write_segment(outfile, &file.name_seg);
10146 WMSFT_write_segment(outfile, &file.string_seg);
10147 WMSFT_write_segment(outfile, &file.typdesc_seg);
10148 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10149 WMSFT_write_segment(outfile, &file.custdata_seg);
10150 WMSFT_write_segment(outfile, &file.cdguids_seg);
10151 WMSFT_write_segment(outfile, &file.aux_seg);
10152
10153 WMSFT_free_file(&file);
10154
10155 CloseHandle(outfile);
10156
10157 return S_OK;
10158 }
10159
10160 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10161 LPOLESTR name)
10162 {
10163 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10164 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10165 return E_NOTIMPL;
10166 }
10167
10168 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10169 REFGUID guid, VARIANT *varVal)
10170 {
10171 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10172 FIXME("%p %s %p - stub\n", This, debugstr_guid(guid), varVal);
10173 return E_NOTIMPL;
10174 }
10175
10176 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10177 ULONG helpStringContext)
10178 {
10179 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10180 FIXME("%p %u - stub\n", This, helpStringContext);
10181 return E_NOTIMPL;
10182 }
10183
10184 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10185 LPOLESTR filename)
10186 {
10187 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10188 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10189
10190 if (!filename)
10191 return E_INVALIDARG;
10192
10193 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10194
10195 return S_OK;
10196 }
10197
10198 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10199 ICreateTypeLib2_fnQueryInterface,
10200 ICreateTypeLib2_fnAddRef,
10201 ICreateTypeLib2_fnRelease,
10202 ICreateTypeLib2_fnCreateTypeInfo,
10203 ICreateTypeLib2_fnSetName,
10204 ICreateTypeLib2_fnSetVersion,
10205 ICreateTypeLib2_fnSetGuid,
10206 ICreateTypeLib2_fnSetDocString,
10207 ICreateTypeLib2_fnSetHelpFileName,
10208 ICreateTypeLib2_fnSetHelpContext,
10209 ICreateTypeLib2_fnSetLcid,
10210 ICreateTypeLib2_fnSetLibFlags,
10211 ICreateTypeLib2_fnSaveAllChanges,
10212 ICreateTypeLib2_fnDeleteTypeInfo,
10213 ICreateTypeLib2_fnSetCustData,
10214 ICreateTypeLib2_fnSetHelpStringContext,
10215 ICreateTypeLib2_fnSetHelpStringDll
10216 };
10217
10218 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10219 REFIID riid, void **object)
10220 {
10221 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10222
10223 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10224 }
10225
10226 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10227 {
10228 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10229
10230 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10231 }
10232
10233 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10234 {
10235 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10236
10237 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10238 }
10239
10240 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10241 REFGUID guid)
10242 {
10243 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10244
10245 TRACE("%p %s\n", This, debugstr_guid(guid));
10246
10247 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10248
10249 return S_OK;
10250 }
10251
10252 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10253 UINT typeFlags)
10254 {
10255 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10256 WORD old_flags;
10257 HRESULT hres;
10258
10259 TRACE("%p %x\n", This, typeFlags);
10260
10261 if (typeFlags & TYPEFLAG_FDUAL) {
10262 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10263 ITypeLib *stdole;
10264 ITypeInfo *dispatch;
10265 HREFTYPE hreftype;
10266 HRESULT hres;
10267
10268 hres = LoadTypeLib(stdole2tlb, &stdole);
10269 if(FAILED(hres))
10270 return hres;
10271
10272 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10273 ITypeLib_Release(stdole);
10274 if(FAILED(hres))
10275 return hres;
10276
10277 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10278 ITypeInfo_Release(dispatch);
10279 if(FAILED(hres))
10280 return hres;
10281 }
10282
10283 old_flags = This->wTypeFlags;
10284 This->wTypeFlags = typeFlags;
10285
10286 hres = ICreateTypeInfo2_LayOut(iface);
10287 if (FAILED(hres)) {
10288 This->wTypeFlags = old_flags;
10289 return hres;
10290 }
10291
10292 return S_OK;
10293 }
10294
10295 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10296 LPOLESTR doc)
10297 {
10298 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10299
10300 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10301
10302 if (!doc)
10303 return E_INVALIDARG;
10304
10305 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10306
10307 return S_OK;
10308 }
10309
10310 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10311 DWORD helpContext)
10312 {
10313 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10314
10315 TRACE("%p %d\n", This, helpContext);
10316
10317 This->dwHelpContext = helpContext;
10318
10319 return S_OK;
10320 }
10321
10322 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10323 WORD majorVerNum, WORD minorVerNum)
10324 {
10325 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10326
10327 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10328
10329 This->wMajorVerNum = majorVerNum;
10330 This->wMinorVerNum = minorVerNum;
10331
10332 return S_OK;
10333 }
10334
10335 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10336 ITypeInfo *typeInfo, HREFTYPE *refType)
10337 {
10338 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10339 UINT index;
10340 ITypeLib *container;
10341 TLBRefType *ref_type;
10342 TLBImpLib *implib;
10343 TYPEATTR *typeattr;
10344 TLIBATTR *libattr;
10345 HRESULT hres;
10346
10347 TRACE("%p %p %p\n", This, typeInfo, refType);
10348
10349 if (!typeInfo || !refType)
10350 return E_INVALIDARG;
10351
10352 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10353 if (FAILED(hres))
10354 return hres;
10355
10356 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10357 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10358
10359 ITypeLib_Release(container);
10360
10361 *refType = target->hreftype;
10362
10363 return S_OK;
10364 }
10365
10366 hres = ITypeLib_GetLibAttr(container, &libattr);
10367 if (FAILED(hres)) {
10368 ITypeLib_Release(container);
10369 return hres;
10370 }
10371
10372 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10373 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10374 implib->lcid == libattr->lcid &&
10375 implib->wVersionMajor == libattr->wMajorVerNum &&
10376 implib->wVersionMinor == libattr->wMinorVerNum)
10377 break;
10378 }
10379
10380 if(&implib->entry == &This->pTypeLib->implib_list){
10381 implib = heap_alloc_zero(sizeof(TLBImpLib));
10382
10383 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10384 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10385 implib->name = SysAllocString(our_container->path);
10386 }else{
10387 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10388 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10389 if(FAILED(hres)){
10390 implib->name = NULL;
10391 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10392 }
10393 }
10394
10395 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10396 implib->lcid = libattr->lcid;
10397 implib->wVersionMajor = libattr->wMajorVerNum;
10398 implib->wVersionMinor = libattr->wMinorVerNum;
10399
10400 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10401 }
10402
10403 ITypeLib_ReleaseTLibAttr(container, libattr);
10404 ITypeLib_Release(container);
10405
10406 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10407 if (FAILED(hres))
10408 return hres;
10409
10410 index = 0;
10411 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10412 if(ref_type->index == TLB_REF_USE_GUID &&
10413 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10414 ref_type->tkind == typeattr->typekind)
10415 break;
10416 ++index;
10417 }
10418
10419 if(&ref_type->entry == &This->pTypeLib->ref_list){
10420 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10421
10422 ref_type->tkind = typeattr->typekind;
10423 ref_type->pImpTLInfo = implib;
10424 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10425
10426 ref_type->index = TLB_REF_USE_GUID;
10427
10428 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10429
10430 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10431 }
10432
10433 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10434
10435 *refType = ref_type->reference | 0x1;
10436
10437 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10438 This->pTypeLib->dispatch_href = *refType;
10439
10440 return S_OK;
10441 }
10442
10443 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10444 UINT index, FUNCDESC *funcDesc)
10445 {
10446 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10447 TLBFuncDesc tmp_func_desc, *func_desc;
10448 int buf_size, i;
10449 char *buffer;
10450 HRESULT hres;
10451
10452 TRACE("%p %u %p\n", This, index, funcDesc);
10453
10454 if (!funcDesc || funcDesc->oVft & 3)
10455 return E_INVALIDARG;
10456
10457 switch (This->typekind) {
10458 case TKIND_MODULE:
10459 if (funcDesc->funckind != FUNC_STATIC)
10460 return TYPE_E_BADMODULEKIND;
10461 break;
10462 case TKIND_DISPATCH:
10463 if (funcDesc->funckind != FUNC_DISPATCH)
10464 return TYPE_E_BADMODULEKIND;
10465 break;
10466 default:
10467 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10468 return TYPE_E_BADMODULEKIND;
10469 }
10470
10471 if (index > This->cFuncs)
10472 return TYPE_E_ELEMENTNOTFOUND;
10473
10474 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10475 !funcDesc->cParams)
10476 return TYPE_E_INCONSISTENTPROPFUNCS;
10477
10478 #ifdef _WIN64
10479 if(This->pTypeLib->syskind == SYS_WIN64 &&
10480 funcDesc->oVft % 8 != 0)
10481 return E_INVALIDARG;
10482 #endif
10483
10484 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10485 TLBFuncDesc_Constructor(&tmp_func_desc);
10486
10487 tmp_func_desc.funcdesc = *funcDesc;
10488
10489 if (tmp_func_desc.funcdesc.oVft != 0)
10490 tmp_func_desc.funcdesc.oVft |= 1;
10491
10492 if (funcDesc->cScodes) {
10493 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10494 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10495 } else
10496 tmp_func_desc.funcdesc.lprgscode = NULL;
10497
10498 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10499 for (i = 0; i < funcDesc->cParams; ++i) {
10500 buf_size += sizeof(ELEMDESC);
10501 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10502 }
10503 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10504 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10505
10506 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10507 if (FAILED(hres)) {
10508 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10509 heap_free(tmp_func_desc.funcdesc.lprgscode);
10510 return hres;
10511 }
10512
10513 for (i = 0; i < funcDesc->cParams; ++i) {
10514 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10515 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10516 if (FAILED(hres)) {
10517 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10518 heap_free(tmp_func_desc.funcdesc.lprgscode);
10519 return hres;
10520 }
10521 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10522 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10523 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10524 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10525 if (FAILED(hres)) {
10526 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10527 heap_free(tmp_func_desc.funcdesc.lprgscode);
10528 return hres;
10529 }
10530 }
10531 }
10532
10533 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10534
10535 if (This->funcdescs) {
10536 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10537 sizeof(TLBFuncDesc) * (This->cFuncs + 1));
10538
10539 if (index < This->cFuncs) {
10540 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10541 (This->cFuncs - index) * sizeof(TLBFuncDesc));
10542 func_desc = This->funcdescs + index;
10543 } else
10544 func_desc = This->funcdescs + This->cFuncs;
10545
10546 /* move custdata lists to the new memory location */
10547 for(i = 0; i < This->cFuncs + 1; ++i){
10548 if(index != i){
10549 TLBFuncDesc *fd = &This->funcdescs[i];
10550 if(fd->custdata_list.prev == fd->custdata_list.next)
10551 list_init(&fd->custdata_list);
10552 else{
10553 fd->custdata_list.prev->next = &fd->custdata_list;
10554 fd->custdata_list.next->prev = &fd->custdata_list;
10555 }
10556 }
10557 }
10558 } else
10559 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10560
10561 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10562 list_init(&func_desc->custdata_list);
10563
10564 ++This->cFuncs;
10565
10566 This->needs_layout = TRUE;
10567
10568 return S_OK;
10569 }
10570
10571 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10572 UINT index, HREFTYPE refType)
10573 {
10574 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10575 TLBImplType *impl_type;
10576 HRESULT hres;
10577
10578 TRACE("%p %u %d\n", This, index, refType);
10579
10580 switch(This->typekind){
10581 case TKIND_COCLASS: {
10582 if (index == -1) {
10583 FIXME("Unhandled index: -1\n");
10584 return E_NOTIMPL;
10585 }
10586
10587 if(index != This->cImplTypes)
10588 return TYPE_E_ELEMENTNOTFOUND;
10589
10590 break;
10591 }
10592 case TKIND_INTERFACE:
10593 case TKIND_DISPATCH:
10594 if (index != 0 || This->cImplTypes)
10595 return TYPE_E_ELEMENTNOTFOUND;
10596 break;
10597 default:
10598 FIXME("Unimplemented typekind: %d\n", This->typekind);
10599 return E_NOTIMPL;
10600 }
10601
10602 if (This->impltypes){
10603 UINT i;
10604
10605 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10606 sizeof(TLBImplType) * (This->cImplTypes + 1));
10607
10608 if (index < This->cImplTypes) {
10609 memmove(This->impltypes + index + 1, This->impltypes + index,
10610 (This->cImplTypes - index) * sizeof(TLBImplType));
10611 impl_type = This->impltypes + index;
10612 } else
10613 impl_type = This->impltypes + This->cImplTypes;
10614
10615 /* move custdata lists to the new memory location */
10616 for(i = 0; i < This->cImplTypes + 1; ++i){
10617 if(index != i){
10618 TLBImplType *it = &This->impltypes[i];
10619 if(it->custdata_list.prev == it->custdata_list.next)
10620 list_init(&it->custdata_list);
10621 else{
10622 it->custdata_list.prev->next = &it->custdata_list;
10623 it->custdata_list.next->prev = &it->custdata_list;
10624 }
10625 }
10626 }
10627 } else
10628 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10629
10630 memset(impl_type, 0, sizeof(TLBImplType));
10631 TLBImplType_Constructor(impl_type);
10632 impl_type->hRef = refType;
10633
10634 ++This->cImplTypes;
10635
10636 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10637 This->wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10638
10639 hres = ICreateTypeInfo2_LayOut(iface);
10640 if (FAILED(hres))
10641 return hres;
10642
10643 return S_OK;
10644 }
10645
10646 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10647 UINT index, INT implTypeFlags)
10648 {
10649 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10650 TLBImplType *impl_type = &This->impltypes[index];
10651
10652 TRACE("%p %u %x\n", This, index, implTypeFlags);
10653
10654 if (This->typekind != TKIND_COCLASS)
10655 return TYPE_E_BADMODULEKIND;
10656
10657 if (index >= This->cImplTypes)
10658 return TYPE_E_ELEMENTNOTFOUND;
10659
10660 impl_type->implflags = implTypeFlags;
10661
10662 return S_OK;
10663 }
10664
10665 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10666 WORD alignment)
10667 {
10668 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10669
10670 TRACE("%p %d\n", This, alignment);
10671
10672 This->cbAlignment = alignment;
10673
10674 return S_OK;
10675 }
10676
10677 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10678 LPOLESTR schema)
10679 {
10680 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10681
10682 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10683
10684 if (!schema)
10685 return E_INVALIDARG;
10686
10687 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10688
10689 This->lpstrSchema = This->Schema->str;
10690
10691 return S_OK;
10692 }
10693
10694 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10695 UINT index, VARDESC *varDesc)
10696 {
10697 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10698 TLBVarDesc *var_desc;
10699
10700 TRACE("%p %u %p\n", This, index, varDesc);
10701
10702 if (This->vardescs){
10703 UINT i;
10704
10705 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10706 sizeof(TLBVarDesc) * (This->cVars + 1));
10707
10708 if (index < This->cVars) {
10709 memmove(This->vardescs + index + 1, This->vardescs + index,
10710 (This->cVars - index) * sizeof(TLBVarDesc));
10711 var_desc = This->vardescs + index;
10712 } else
10713 var_desc = This->vardescs + This->cVars;
10714
10715 /* move custdata lists to the new memory location */
10716 for(i = 0; i < This->cVars + 1; ++i){
10717 if(index != i){
10718 TLBVarDesc *var = &This->vardescs[i];
10719 if(var->custdata_list.prev == var->custdata_list.next)
10720 list_init(&var->custdata_list);
10721 else{
10722 var->custdata_list.prev->next = &var->custdata_list;
10723 var->custdata_list.next->prev = &var->custdata_list;
10724 }
10725 }
10726 }
10727 } else
10728 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10729
10730 TLBVarDesc_Constructor(var_desc);
10731 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10732 var_desc->vardesc = *var_desc->vardesc_create;
10733
10734 ++This->cVars;
10735
10736 This->needs_layout = TRUE;
10737
10738 return S_OK;
10739 }
10740
10741 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10742 UINT index, LPOLESTR *names, UINT numNames)
10743 {
10744 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10745 TLBFuncDesc *func_desc = &This->funcdescs[index];
10746 int i;
10747
10748 TRACE("%p %u %p %u\n", This, index, names, numNames);
10749
10750 if (!names)
10751 return E_INVALIDARG;
10752
10753 if (index >= This->cFuncs || numNames == 0)
10754 return TYPE_E_ELEMENTNOTFOUND;
10755
10756 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10757 if(numNames > func_desc->funcdesc.cParams)
10758 return TYPE_E_ELEMENTNOTFOUND;
10759 } else
10760 if(numNames > func_desc->funcdesc.cParams + 1)
10761 return TYPE_E_ELEMENTNOTFOUND;
10762
10763 for(i = 0; i < This->cFuncs; ++i) {
10764 TLBFuncDesc *iter = &This->funcdescs[i];
10765 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10766 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10767 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10768 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10769 continue;
10770 return TYPE_E_AMBIGUOUSNAME;
10771 }
10772 }
10773
10774 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10775
10776 for (i = 1; i < numNames; ++i) {
10777 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10778 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10779 }
10780
10781 return S_OK;
10782 }
10783
10784 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10785 UINT index, LPOLESTR name)
10786 {
10787 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10788
10789 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10790
10791 if(!name)
10792 return E_INVALIDARG;
10793
10794 if(index >= This->cVars)
10795 return TYPE_E_ELEMENTNOTFOUND;
10796
10797 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10798 return S_OK;
10799 }
10800
10801 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10802 TYPEDESC *tdescAlias)
10803 {
10804 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10805 HRESULT hr;
10806
10807 TRACE("%p %p\n", This, tdescAlias);
10808
10809 if(!tdescAlias)
10810 return E_INVALIDARG;
10811
10812 if(This->typekind != TKIND_ALIAS)
10813 return TYPE_E_BADMODULEKIND;
10814
10815 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->cbSizeInstance, &This->cbAlignment);
10816 if(FAILED(hr))
10817 return hr;
10818
10819 heap_free(This->tdescAlias);
10820 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10821 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10822
10823 return S_OK;
10824 }
10825
10826 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10827 UINT index, LPOLESTR dllName, LPOLESTR procName)
10828 {
10829 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10830 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10831 return E_NOTIMPL;
10832 }
10833
10834 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10835 UINT index, LPOLESTR docString)
10836 {
10837 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10838 TLBFuncDesc *func_desc = &This->funcdescs[index];
10839
10840 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10841
10842 if(!docString)
10843 return E_INVALIDARG;
10844
10845 if(index >= This->cFuncs)
10846 return TYPE_E_ELEMENTNOTFOUND;
10847
10848 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10849
10850 return S_OK;
10851 }
10852
10853 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10854 UINT index, LPOLESTR docString)
10855 {
10856 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10857 TLBVarDesc *var_desc = &This->vardescs[index];
10858
10859 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10860
10861 if(!docString)
10862 return E_INVALIDARG;
10863
10864 if(index >= This->cVars)
10865 return TYPE_E_ELEMENTNOTFOUND;
10866
10867 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10868
10869 return S_OK;
10870 }
10871
10872 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10873 UINT index, DWORD helpContext)
10874 {
10875 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10876 TLBFuncDesc *func_desc = &This->funcdescs[index];
10877
10878 TRACE("%p %u %d\n", This, index, helpContext);
10879
10880 if(index >= This->cFuncs)
10881 return TYPE_E_ELEMENTNOTFOUND;
10882
10883 func_desc->helpcontext = helpContext;
10884
10885 return S_OK;
10886 }
10887
10888 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10889 UINT index, DWORD helpContext)
10890 {
10891 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10892 TLBVarDesc *var_desc = &This->vardescs[index];
10893
10894 TRACE("%p %u %d\n", This, index, helpContext);
10895
10896 if(index >= This->cVars)
10897 return TYPE_E_ELEMENTNOTFOUND;
10898
10899 var_desc->HelpContext = helpContext;
10900
10901 return S_OK;
10902 }
10903
10904 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10905 UINT index, BSTR bstrMops)
10906 {
10907 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10908 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10909 return E_NOTIMPL;
10910 }
10911
10912 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10913 IDLDESC *idlDesc)
10914 {
10915 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10916
10917 TRACE("%p %p\n", This, idlDesc);
10918
10919 if (!idlDesc)
10920 return E_INVALIDARG;
10921
10922 This->idldescType.dwReserved = idlDesc->dwReserved;
10923 This->idldescType.wIDLFlags = idlDesc->wIDLFlags;
10924
10925 return S_OK;
10926 }
10927
10928 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10929 {
10930 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10931 ITypeInfo *tinfo;
10932 TLBFuncDesc *func_desc;
10933 UINT user_vft = 0, i, depth = 0;
10934 HRESULT hres = S_OK;
10935
10936 TRACE("%p\n", This);
10937
10938 This->needs_layout = FALSE;
10939
10940 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10941 if (FAILED(hres))
10942 return hres;
10943
10944 if (This->typekind == TKIND_INTERFACE) {
10945 ITypeInfo *inh;
10946 TYPEATTR *attr;
10947 HREFTYPE inh_href;
10948
10949 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10950
10951 if (SUCCEEDED(hres)) {
10952 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10953
10954 if (SUCCEEDED(hres)) {
10955 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10956 if (FAILED(hres)) {
10957 ITypeInfo_Release(inh);
10958 ITypeInfo_Release(tinfo);
10959 return hres;
10960 }
10961 This->cbSizeVft = attr->cbSizeVft;
10962 ITypeInfo_ReleaseTypeAttr(inh, attr);
10963
10964 do{
10965 ++depth;
10966 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10967 if(SUCCEEDED(hres)){
10968 ITypeInfo *next;
10969 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10970 if(SUCCEEDED(hres)){
10971 ITypeInfo_Release(inh);
10972 inh = next;
10973 }
10974 }
10975 }while(SUCCEEDED(hres));
10976 hres = S_OK;
10977
10978 ITypeInfo_Release(inh);
10979 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10980 This->cbSizeVft = 0;
10981 hres = S_OK;
10982 } else {
10983 ITypeInfo_Release(tinfo);
10984 return hres;
10985 }
10986 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10987 This->cbSizeVft = 0;
10988 hres = S_OK;
10989 } else {
10990 ITypeInfo_Release(tinfo);
10991 return hres;
10992 }
10993 } else if (This->typekind == TKIND_DISPATCH)
10994 This->cbSizeVft = 7 * This->pTypeLib->ptr_size;
10995 else
10996 This->cbSizeVft = 0;
10997
10998 func_desc = This->funcdescs;
10999 i = 0;
11000 while (i < This->cFuncs) {
11001 if (!(func_desc->funcdesc.oVft & 0x1))
11002 func_desc->funcdesc.oVft = This->cbSizeVft;
11003
11004 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11005 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11006
11007 This->cbSizeVft += This->pTypeLib->ptr_size;
11008
11009 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11010 TLBFuncDesc *iter;
11011 UINT j = 0;
11012 BOOL reset = FALSE;
11013
11014 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11015
11016 iter = This->funcdescs;
11017 while (j < This->cFuncs) {
11018 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11019 if (!reset) {
11020 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->cFuncs;
11021 reset = TRUE;
11022 } else
11023 ++func_desc->funcdesc.memid;
11024 iter = This->funcdescs;
11025 j = 0;
11026 } else {
11027 ++iter;
11028 ++j;
11029 }
11030 }
11031 }
11032
11033 ++func_desc;
11034 ++i;
11035 }
11036
11037 if (user_vft > This->cbSizeVft)
11038 This->cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11039
11040 for(i = 0; i < This->cVars; ++i){
11041 TLBVarDesc *var_desc = &This->vardescs[i];
11042 if(var_desc->vardesc.memid == MEMBERID_NIL){
11043 UINT j = 0;
11044 BOOL reset = FALSE;
11045 TLBVarDesc *iter;
11046
11047 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11048
11049 iter = This->vardescs;
11050 while (j < This->cVars) {
11051 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11052 if (!reset) {
11053 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->cVars;
11054 reset = TRUE;
11055 } else
11056 ++var_desc->vardesc.memid;
11057 iter = This->vardescs;
11058 j = 0;
11059 } else {
11060 ++iter;
11061 ++j;
11062 }
11063 }
11064 }
11065 }
11066
11067 ITypeInfo_Release(tinfo);
11068 return hres;
11069 }
11070
11071 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11072 UINT index)
11073 {
11074 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11075 FIXME("%p %u - stub\n", This, index);
11076 return E_NOTIMPL;
11077 }
11078
11079 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11080 MEMBERID memid, INVOKEKIND invKind)
11081 {
11082 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11083 FIXME("%p %x %d - stub\n", This, memid, invKind);
11084 return E_NOTIMPL;
11085 }
11086
11087 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11088 UINT index)
11089 {
11090 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11091 FIXME("%p %u - stub\n", This, index);
11092 return E_NOTIMPL;
11093 }
11094
11095 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11096 MEMBERID memid)
11097 {
11098 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11099 FIXME("%p %x - stub\n", This, memid);
11100 return E_NOTIMPL;
11101 }
11102
11103 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11104 UINT index)
11105 {
11106 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11107 FIXME("%p %u - stub\n", This, index);
11108 return E_NOTIMPL;
11109 }
11110
11111 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11112 REFGUID guid, VARIANT *varVal)
11113 {
11114 TLBGuid *tlbguid;
11115
11116 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11117
11118 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11119
11120 if (!guid || !varVal)
11121 return E_INVALIDARG;
11122
11123 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11124
11125 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11126 }
11127
11128 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11129 UINT index, REFGUID guid, VARIANT *varVal)
11130 {
11131 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11132 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11133 return E_NOTIMPL;
11134 }
11135
11136 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11137 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11138 {
11139 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11140 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11141 return E_NOTIMPL;
11142 }
11143
11144 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11145 UINT index, REFGUID guid, VARIANT *varVal)
11146 {
11147 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11148 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11149 return E_NOTIMPL;
11150 }
11151
11152 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11153 UINT index, REFGUID guid, VARIANT *varVal)
11154 {
11155 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11156 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11157 return E_NOTIMPL;
11158 }
11159
11160 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11161 ULONG helpStringContext)
11162 {
11163 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11164
11165 TRACE("%p %u\n", This, helpStringContext);
11166
11167 This->dwHelpStringContext = helpStringContext;
11168
11169 return S_OK;
11170 }
11171
11172 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11173 UINT index, ULONG helpStringContext)
11174 {
11175 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11176 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11177 return E_NOTIMPL;
11178 }
11179
11180 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11181 UINT index, ULONG helpStringContext)
11182 {
11183 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11184 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11185 return E_NOTIMPL;
11186 }
11187
11188 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11189 {
11190 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11191 FIXME("%p - stub\n", This);
11192 return E_NOTIMPL;
11193 }
11194
11195 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11196 LPOLESTR name)
11197 {
11198 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11199
11200 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11201
11202 if (!name)
11203 return E_INVALIDARG;
11204
11205 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11206
11207 return S_OK;
11208 }
11209
11210 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11211 ICreateTypeInfo2_fnQueryInterface,
11212 ICreateTypeInfo2_fnAddRef,
11213 ICreateTypeInfo2_fnRelease,
11214 ICreateTypeInfo2_fnSetGuid,
11215 ICreateTypeInfo2_fnSetTypeFlags,
11216 ICreateTypeInfo2_fnSetDocString,
11217 ICreateTypeInfo2_fnSetHelpContext,
11218 ICreateTypeInfo2_fnSetVersion,
11219 ICreateTypeInfo2_fnAddRefTypeInfo,
11220 ICreateTypeInfo2_fnAddFuncDesc,
11221 ICreateTypeInfo2_fnAddImplType,
11222 ICreateTypeInfo2_fnSetImplTypeFlags,
11223 ICreateTypeInfo2_fnSetAlignment,
11224 ICreateTypeInfo2_fnSetSchema,
11225 ICreateTypeInfo2_fnAddVarDesc,
11226 ICreateTypeInfo2_fnSetFuncAndParamNames,
11227 ICreateTypeInfo2_fnSetVarName,
11228 ICreateTypeInfo2_fnSetTypeDescAlias,
11229 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11230 ICreateTypeInfo2_fnSetFuncDocString,
11231 ICreateTypeInfo2_fnSetVarDocString,
11232 ICreateTypeInfo2_fnSetFuncHelpContext,
11233 ICreateTypeInfo2_fnSetVarHelpContext,
11234 ICreateTypeInfo2_fnSetMops,
11235 ICreateTypeInfo2_fnSetTypeIdldesc,
11236 ICreateTypeInfo2_fnLayOut,
11237 ICreateTypeInfo2_fnDeleteFuncDesc,
11238 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11239 ICreateTypeInfo2_fnDeleteVarDesc,
11240 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11241 ICreateTypeInfo2_fnDeleteImplType,
11242 ICreateTypeInfo2_fnSetCustData,
11243 ICreateTypeInfo2_fnSetFuncCustData,
11244 ICreateTypeInfo2_fnSetParamCustData,
11245 ICreateTypeInfo2_fnSetVarCustData,
11246 ICreateTypeInfo2_fnSetImplTypeCustData,
11247 ICreateTypeInfo2_fnSetHelpStringContext,
11248 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11249 ICreateTypeInfo2_fnSetVarHelpStringContext,
11250 ICreateTypeInfo2_fnInvalidate,
11251 ICreateTypeInfo2_fnSetName
11252 };
11253
11254 /******************************************************************************
11255 * ClearCustData (OLEAUT32.171)
11256 *
11257 * Clear a custom data type's data.
11258 *
11259 * PARAMS
11260 * lpCust [I] The custom data type instance
11261 *
11262 * RETURNS
11263 * Nothing.
11264 */
11265 void WINAPI ClearCustData(CUSTDATA *lpCust)
11266 {
11267 if (lpCust && lpCust->cCustData)
11268 {
11269 if (lpCust->prgCustData)
11270 {
11271 DWORD i;
11272
11273 for (i = 0; i < lpCust->cCustData; i++)
11274 VariantClear(&lpCust->prgCustData[i].varValue);
11275
11276 CoTaskMemFree(lpCust->prgCustData);
11277 lpCust->prgCustData = NULL;
11278 }
11279 lpCust->cCustData = 0;
11280 }
11281 }