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