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 "config.h" 51 #include "wine/port.h" 52 53 #include <stdlib.h> 54 #include <string.h> 55 #include <stdarg.h> 56 #include <stdio.h> 57 #include <ctype.h> 58 59 #define COBJMACROS 60 #define NONAMELESSUNION 61 62 #include "winerror.h" 63 #include "windef.h" 64 #include "winbase.h" 65 #include "winnls.h" 66 #include "winreg.h" 67 #include "winuser.h" 68 #include "winternl.h" 69 #include "lzexpand.h" 70 71 #include "wine/unicode.h" 72 #include "objbase.h" 73 #include "typelib.h" 74 #include "wine/debug.h" 75 #include "variant.h" 76 #include "wine/heap.h" 77 #include "wine/list.h" 78 79 WINE_DEFAULT_DEBUG_CHANNEL(ole); 80 WINE_DECLARE_DEBUG_CHANNEL(typelib); 81 82 typedef struct 83 { 84 WORD offset; 85 WORD length; 86 WORD flags; 87 WORD id; 88 WORD handle; 89 WORD usage; 90 } NE_NAMEINFO; 91 92 typedef struct 93 { 94 WORD type_id; /* Type identifier */ 95 WORD count; /* Number of resources of this type */ 96 DWORD resloader; /* SetResourceHandler() */ 97 /* 98 * Name info array. 99 */ 100 } NE_TYPEINFO; 101 102 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt); 103 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr); 104 static void TLB_FreeVarDesc(VARDESC*); 105 106 /**************************************************************************** 107 * FromLExxx 108 * 109 * Takes p_iVal (which is in little endian) and returns it 110 * in the host machine's byte order. 111 */ 112 #ifdef WORDS_BIGENDIAN 113 static WORD FromLEWord(WORD p_iVal) 114 { 115 return (((p_iVal & 0x00FF) << 8) | 116 ((p_iVal & 0xFF00) >> 8)); 117 } 118 119 120 static DWORD FromLEDWord(DWORD p_iVal) 121 { 122 return (((p_iVal & 0x000000FF) << 24) | 123 ((p_iVal & 0x0000FF00) << 8) | 124 ((p_iVal & 0x00FF0000) >> 8) | 125 ((p_iVal & 0xFF000000) >> 24)); 126 } 127 #else 128 #define FromLEWord(X) (X) 129 #define FromLEDWord(X) (X) 130 #endif 131 132 #define DISPATCH_HREF_OFFSET 0x01000000 133 #define DISPATCH_HREF_MASK 0xff000000 134 135 /**************************************************************************** 136 * FromLExxx 137 * 138 * Fix byte order in any structure if necessary 139 */ 140 #ifdef WORDS_BIGENDIAN 141 static void FromLEWords(void *p_Val, int p_iSize) 142 { 143 WORD *Val = p_Val; 144 145 p_iSize /= sizeof(WORD); 146 147 while (p_iSize) { 148 *Val = FromLEWord(*Val); 149 Val++; 150 p_iSize--; 151 } 152 } 153 154 155 static void FromLEDWords(void *p_Val, int p_iSize) 156 { 157 DWORD *Val = p_Val; 158 159 p_iSize /= sizeof(DWORD); 160 161 while (p_iSize) { 162 *Val = FromLEDWord(*Val); 163 Val++; 164 p_iSize--; 165 } 166 } 167 #else 168 #define FromLEWords(X,Y) /*nothing*/ 169 #define FromLEDWords(X,Y) /*nothing*/ 170 #endif 171 172 /* 173 * Find a typelib key which matches a requested maj.min version. 174 */ 175 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin ) 176 { 177 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0}; 178 WCHAR buffer[60]; 179 char key_name[16]; 180 DWORD len, i; 181 INT best_maj = -1, best_min = -1; 182 HKEY hkey; 183 184 memcpy( buffer, typelibW, sizeof(typelibW) ); 185 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 186 187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS) 188 return FALSE; 189 190 len = sizeof(key_name); 191 i = 0; 192 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) 193 { 194 INT v_maj, v_min; 195 196 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2) 197 { 198 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min); 199 200 if (*wMaj == 0xffff && *wMin == 0xffff) 201 { 202 if (v_maj > best_maj) best_maj = v_maj; 203 if (v_min > best_min) best_min = v_min; 204 } 205 else if (*wMaj == v_maj) 206 { 207 best_maj = v_maj; 208 209 if (*wMin == v_min) 210 { 211 best_min = v_min; 212 break; /* exact match */ 213 } 214 if (*wMin != 0xffff && v_min > best_min) best_min = v_min; 215 } 216 } 217 len = sizeof(key_name); 218 } 219 RegCloseKey( hkey ); 220 221 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min); 222 223 if (*wMaj == 0xffff && *wMin == 0xffff) 224 { 225 if (best_maj >= 0 && best_min >= 0) 226 { 227 *wMaj = best_maj; 228 *wMin = best_min; 229 return TRUE; 230 } 231 } 232 233 if (*wMaj == best_maj && best_min >= 0) 234 { 235 *wMin = best_min; 236 return TRUE; 237 } 238 return FALSE; 239 } 240 241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */ 242 /* buffer must be at least 60 characters long */ 243 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer ) 244 { 245 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0}; 246 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0}; 247 248 memcpy( buffer, TypelibW, sizeof(TypelibW) ); 249 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 250 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin ); 251 return buffer; 252 } 253 254 /* get the path of an interface key, in the form "Interface\\<guid>" */ 255 /* buffer must be at least 50 characters long */ 256 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer ) 257 { 258 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0}; 259 260 memcpy( buffer, InterfaceW, sizeof(InterfaceW) ); 261 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 262 return buffer; 263 } 264 265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */ 266 /* buffer must be at least 16 characters long */ 267 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer ) 268 { 269 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0}; 270 static const WCHAR win16W[] = {'w','i','n','1','6',0}; 271 static const WCHAR win32W[] = {'w','i','n','3','2',0}; 272 static const WCHAR win64W[] = {'w','i','n','6','4',0}; 273 274 sprintfW( buffer, LcidFormatW, lcid ); 275 switch(syskind) 276 { 277 case SYS_WIN16: strcatW( buffer, win16W ); break; 278 case SYS_WIN32: strcatW( buffer, win32W ); break; 279 case SYS_WIN64: strcatW( buffer, win64W ); break; 280 default: 281 TRACE("Typelib is for unsupported syskind %i\n", syskind); 282 return NULL; 283 } 284 return buffer; 285 } 286 287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib); 288 289 struct tlibredirect_data 290 { 291 ULONG size; 292 DWORD res; 293 ULONG name_len; 294 ULONG name_offset; 295 LANGID langid; 296 WORD flags; 297 ULONG help_len; 298 ULONG help_offset; 299 WORD major_version; 300 WORD minor_version; 301 }; 302 303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */ 304 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin, 305 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir ) 306 { 307 HRESULT hr = TYPE_E_LIBNOTREGISTERED; 308 LCID myLCID = lcid; 309 HKEY hkey; 310 WCHAR buffer[60]; 311 WCHAR Path[MAX_PATH]; 312 LONG res; 313 314 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path); 315 316 if (redir) 317 { 318 ACTCTX_SECTION_KEYED_DATA data; 319 320 data.cbSize = sizeof(data); 321 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data )) 322 { 323 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData; 324 WCHAR *nameW; 325 DWORD len; 326 327 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin)) 328 return TYPE_E_LIBNOTREGISTERED; 329 330 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset); 331 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL ); 332 if (!len) return TYPE_E_LIBNOTREGISTERED; 333 334 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path)); 335 *path = SysAllocString( Path ); 336 return S_OK; 337 } 338 } 339 340 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED; 341 get_typelib_key( guid, wMaj, wMin, buffer ); 342 343 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ); 344 if (res == ERROR_FILE_NOT_FOUND) 345 { 346 TRACE_(typelib)("%s not found\n", debugstr_w(buffer)); 347 return TYPE_E_LIBNOTREGISTERED; 348 } 349 else if (res != ERROR_SUCCESS) 350 { 351 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer)); 352 return TYPE_E_REGISTRYACCESS; 353 } 354 355 while (hr != S_OK) 356 { 357 LONG dwPathLen = sizeof(Path); 358 359 get_lcid_subkey( myLCID, syskind, buffer ); 360 361 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen)) 362 { 363 if (!lcid) 364 break; 365 else if (myLCID == lcid) 366 { 367 /* try with sub-langid */ 368 myLCID = SUBLANGID(lcid); 369 } 370 else if ((myLCID == SUBLANGID(lcid)) && myLCID) 371 { 372 /* try with system langid */ 373 myLCID = 0; 374 } 375 else 376 { 377 break; 378 } 379 } 380 else 381 { 382 *path = SysAllocString( Path ); 383 hr = S_OK; 384 } 385 } 386 RegCloseKey( hkey ); 387 TRACE_(typelib)("-- 0x%08x\n", hr); 388 return hr; 389 } 390 391 /**************************************************************************** 392 * QueryPathOfRegTypeLib [OLEAUT32.164] 393 * 394 * Gets the path to a registered type library. 395 * 396 * PARAMS 397 * guid [I] referenced guid 398 * wMaj [I] major version 399 * wMin [I] minor version 400 * lcid [I] locale id 401 * path [O] path of typelib 402 * 403 * RETURNS 404 * Success: S_OK. 405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED 406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be 407 * opened. 408 */ 409 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path ) 410 { 411 BOOL redir = TRUE; 412 #ifdef _WIN64 413 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE ); 414 if(SUCCEEDED(hres)) 415 return hres; 416 redir = FALSE; 417 #endif 418 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir ); 419 } 420 421 /****************************************************************************** 422 * CreateTypeLib [OLEAUT32.160] creates a typelib 423 * 424 * RETURNS 425 * Success: S_OK 426 * Failure: Status 427 */ 428 HRESULT WINAPI CreateTypeLib(SYSKIND syskind, LPCOLESTR file, ICreateTypeLib **ctlib) 429 { 430 ICreateTypeLib2 *typelib2; 431 HRESULT hres; 432 433 FIXME("(%d, %s, %p): forwarding to CreateTypeLib2\n", syskind, debugstr_w(file), ctlib); 434 435 hres = CreateTypeLib2(syskind, file, &typelib2); 436 if(SUCCEEDED(hres)) 437 { 438 hres = ICreateTypeLib2_QueryInterface(typelib2, &IID_ICreateTypeLib, (void **)&ctlib); 439 ICreateTypeLib2_Release(typelib2); 440 } 441 442 return hres; 443 } 444 445 /****************************************************************************** 446 * LoadTypeLib [OLEAUT32.161] 447 * 448 * Loads a type library 449 * 450 * PARAMS 451 * szFile [I] Name of file to load from. 452 * pptLib [O] Pointer that receives ITypeLib object on success. 453 * 454 * RETURNS 455 * Success: S_OK 456 * Failure: Status 457 * 458 * SEE 459 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib. 460 */ 461 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib) 462 { 463 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib); 464 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib); 465 } 466 467 /****************************************************************************** 468 * LoadTypeLibEx [OLEAUT32.183] 469 * 470 * Loads and optionally registers a type library 471 * 472 * RETURNS 473 * Success: S_OK 474 * Failure: Status 475 */ 476 HRESULT WINAPI LoadTypeLibEx( 477 LPCOLESTR szFile, /* [in] Name of file to load from */ 478 REGKIND regkind, /* [in] Specify kind of registration */ 479 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */ 480 { 481 WCHAR szPath[MAX_PATH+1]; 482 HRESULT res; 483 484 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib); 485 486 if (!szFile || !pptLib) 487 return E_INVALIDARG; 488 489 *pptLib = NULL; 490 491 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib); 492 493 if (SUCCEEDED(res)) 494 switch(regkind) 495 { 496 case REGKIND_DEFAULT: 497 /* don't register typelibs supplied with full path. Experimentation confirms the following */ 498 if (((szFile[0] == '\\') && (szFile[1] == '\\')) || 499 (szFile[0] && (szFile[1] == ':'))) break; 500 /* else fall-through */ 501 502 case REGKIND_REGISTER: 503 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL))) 504 { 505 ITypeLib_Release(*pptLib); 506 *pptLib = 0; 507 } 508 break; 509 case REGKIND_NONE: 510 break; 511 } 512 513 TRACE(" returns %08x\n",res); 514 return res; 515 } 516 517 /****************************************************************************** 518 * LoadRegTypeLib [OLEAUT32.162] 519 * 520 * Loads a registered type library. 521 * 522 * PARAMS 523 * rguid [I] GUID of the registered type library. 524 * wVerMajor [I] major version. 525 * wVerMinor [I] minor version. 526 * lcid [I] locale ID. 527 * ppTLib [O] pointer that receives an ITypeLib object on success. 528 * 529 * RETURNS 530 * Success: S_OK. 531 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or 532 * LoadTypeLib. 533 */ 534 HRESULT WINAPI LoadRegTypeLib( 535 REFGUID rguid, 536 WORD wVerMajor, 537 WORD wVerMinor, 538 LCID lcid, 539 ITypeLib **ppTLib) 540 { 541 BSTR bstr=NULL; 542 HRESULT res; 543 544 *ppTLib = NULL; 545 546 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr); 547 548 if(SUCCEEDED(res)) 549 { 550 res= LoadTypeLib(bstr, ppTLib); 551 SysFreeString(bstr); 552 553 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib) 554 { 555 TLIBATTR *attr; 556 557 res = ITypeLib_GetLibAttr(*ppTLib, &attr); 558 if (res == S_OK) 559 { 560 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor; 561 ITypeLib_ReleaseTLibAttr(*ppTLib, attr); 562 563 if (mismatch) 564 { 565 ITypeLib_Release(*ppTLib); 566 *ppTLib = NULL; 567 res = TYPE_E_LIBNOTREGISTERED; 568 } 569 } 570 } 571 } 572 573 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib); 574 575 return res; 576 } 577 578 579 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */ 580 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0}; 581 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0}; 582 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0}; 583 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0}; 584 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0}; 585 586 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag) 587 { 588 WCHAR keyName[60]; 589 HKEY key, subKey; 590 591 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-', 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 if (name) 600 RegSetValueExW(key, NULL, 0, REG_SZ, 601 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR)); 602 603 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0, 604 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) { 605 RegSetValueExW(subKey, NULL, 0, REG_SZ, 606 (const BYTE *)PSOA, sizeof PSOA); 607 RegCloseKey(subKey); 608 } 609 610 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0, 611 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) { 612 RegSetValueExW(subKey, NULL, 0, REG_SZ, 613 (const BYTE *)PSOA, sizeof PSOA); 614 RegCloseKey(subKey); 615 } 616 617 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0, 618 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) 619 { 620 WCHAR buffer[40]; 621 static const WCHAR fmtver[] = {'%','x','.','%','x',0 }; 622 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0}; 623 624 StringFromGUID2(&libattr->guid, buffer, 40); 625 RegSetValueExW(subKey, NULL, 0, REG_SZ, 626 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR)); 627 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum); 628 RegSetValueExW(subKey, VersionW, 0, REG_SZ, 629 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR)); 630 RegCloseKey(subKey); 631 } 632 633 RegCloseKey(key); 634 } 635 } 636 637 /****************************************************************************** 638 * RegisterTypeLib [OLEAUT32.163] 639 * Adds information about a type library to the System Registry 640 * NOTES 641 * Docs: ITypeLib FAR * ptlib 642 * Docs: OLECHAR FAR* szFullPath 643 * Docs: OLECHAR FAR* szHelpDir 644 * 645 * RETURNS 646 * Success: S_OK 647 * Failure: Status 648 */ 649 HRESULT WINAPI RegisterTypeLib( 650 ITypeLib * ptlib, /* [in] Pointer to the library*/ 651 OLECHAR * szFullPath, /* [in] full Path of the library*/ 652 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library, 653 may be NULL*/ 654 { 655 HRESULT res; 656 TLIBATTR *attr; 657 WCHAR keyName[60]; 658 WCHAR tmp[16]; 659 HKEY key, subKey; 660 UINT types, tidx; 661 TYPEKIND kind; 662 DWORD disposition; 663 664 if (ptlib == NULL || szFullPath == NULL) 665 return E_INVALIDARG; 666 667 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr))) 668 return E_FAIL; 669 670 #ifndef _WIN64 671 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND; 672 #endif 673 674 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName ); 675 676 res = S_OK; 677 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, 678 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) 679 { 680 LPOLESTR doc; 681 682 /* Set the human-readable name of the typelib */ 683 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL))) 684 res = E_FAIL; 685 else if (doc) 686 { 687 if (RegSetValueExW(key, NULL, 0, REG_SZ, 688 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) 689 res = E_FAIL; 690 691 SysFreeString(doc); 692 } 693 694 /* Make up the name of the typelib path subkey */ 695 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL; 696 697 /* Create the typelib path subkey */ 698 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0, 699 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) 700 { 701 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 702 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) 703 res = E_FAIL; 704 705 RegCloseKey(subKey); 706 } 707 else 708 res = E_FAIL; 709 710 /* Create the flags subkey */ 711 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0, 712 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) 713 { 714 /* FIXME: is %u correct? */ 715 static const WCHAR formatW[] = {'%','u',0}; 716 WCHAR buf[20]; 717 sprintfW(buf, formatW, attr->wLibFlags); 718 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 719 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS) 720 res = E_FAIL; 721 722 RegCloseKey(subKey); 723 } 724 else 725 res = E_FAIL; 726 727 /* create the helpdir subkey */ 728 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0, 729 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS) 730 { 731 BOOL freeHelpDir = FALSE; 732 OLECHAR* pIndexStr; 733 734 /* if we created a new key, and helpDir was null, set the helpdir 735 to the directory which contains the typelib. However, 736 if we just opened an existing key, we leave the helpdir alone */ 737 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) { 738 szHelpDir = SysAllocString(szFullPath); 739 pIndexStr = strrchrW(szHelpDir, '\\'); 740 if (pIndexStr) { 741 *pIndexStr = 0; 742 } 743 freeHelpDir = TRUE; 744 } 745 746 /* if we have an szHelpDir, set it! */ 747 if (szHelpDir != NULL) { 748 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 749 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) { 750 res = E_FAIL; 751 } 752 } 753 754 /* tidy up */ 755 if (freeHelpDir) SysFreeString(szHelpDir); 756 RegCloseKey(subKey); 757 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 *strrchrW( 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 = sizeof(subKeyName)/sizeof(WCHAR); 983 deleteOtherStuff = TRUE; 984 i = 0; 985 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { 986 tmpLength = sizeof(subKeyName)/sizeof(WCHAR); 987 988 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */ 989 if (!strcmpW(subKeyName, FLAGSW)) continue; 990 if (!strcmpW(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 *strrchrW( 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 (strcmpW(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; /* FIXME: this is only the non inherited part */ 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) && !strncasecmp( (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) && !strncasecmp( (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 = strrchrW(pszFileName, '\\'); 3300 if(index_str && *++index_str != '\0') 3301 { 3302 LPWSTR end_ptr; 3303 LONG idx = strtolW(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(strchrW(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, (strlenW(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 (!strcmpiW(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((strlenW(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]) strcatW(buf, spaceW); 3768 MultiByteToWideChar(CP_ACP, 0, p, -1, buf + strlenW(buf), buf_size - strlenW(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 && !strcmpW(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 += (strlenW(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 = strlenW(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 __ASM_GLOBAL_FUNC( call_method, 6409 "pushl %ebp\n\t" 6410 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") 6411 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") 6412 "movl %esp,%ebp\n\t" 6413 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") 6414 "pushl %esi\n\t" 6415 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t") 6416 "pushl %edi\n\t" 6417 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t") 6418 "movl 12(%ebp),%edx\n\t" 6419 "movl %esp,%edi\n\t" 6420 "shll $2,%edx\n\t" 6421 "jz 1f\n\t" 6422 "subl %edx,%edi\n\t" 6423 "andl $~15,%edi\n\t" 6424 "movl %edi,%esp\n\t" 6425 "movl 12(%ebp),%ecx\n\t" 6426 "movl 16(%ebp),%esi\n\t" 6427 "cld\n\t" 6428 "rep; movsl\n" 6429 "1:\tcall *8(%ebp)\n\t" 6430 "subl %esp,%edi\n\t" 6431 "movl 20(%ebp),%ecx\n\t" 6432 "movl %edi,(%ecx)\n\t" 6433 "leal -8(%ebp),%esp\n\t" 6434 "popl %edi\n\t" 6435 __ASM_CFI(".cfi_same_value %edi\n\t") 6436 "popl %esi\n\t" 6437 __ASM_CFI(".cfi_same_value %esi\n\t") 6438 "popl %ebp\n\t" 6439 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") 6440 __ASM_CFI(".cfi_same_value %ebp\n\t") 6441 "ret" ) 6442 6443 /* same function but returning floating point */ 6444 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method; 6445 6446 /* ITypeInfo::Invoke 6447 * 6448 * Invokes a method, or accesses a property of an object, that implements the 6449 * interface described by the type description. 6450 */ 6451 DWORD _invoke(FARPROC func, CALLCONV callconv, int nrargs, DWORD_PTR *args) 6452 { 6453 DWORD res; 6454 int stack_offset; 6455 6456 if (TRACE_ON(ole)) { 6457 int i; 6458 TRACE("Calling %p(",func); 6459 for (i=0;i<min(nrargs,30);i++) TRACE("%08lx,",args[i]); 6460 if (nrargs > 30) TRACE("..."); 6461 TRACE(")\n"); 6462 } 6463 6464 switch (callconv) { 6465 case CC_STDCALL: 6466 case CC_CDECL: 6467 res = call_method(func, nrargs, (DWORD *)args, &stack_offset); 6468 break; 6469 default: 6470 FIXME("unsupported calling convention %d\n",callconv); 6471 res = -1; 6472 break; 6473 } 6474 TRACE("returns %08x\n",res); 6475 return res; 6476 } 6477 6478 #elif defined(__x86_64__) 6479 6480 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args ); 6481 __ASM_GLOBAL_FUNC( call_method, 6482 "pushq %rbp\n\t" 6483 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t") 6484 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") 6485 "movq %rsp,%rbp\n\t" 6486 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t") 6487 "pushq %rsi\n\t" 6488 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t") 6489 "pushq %rdi\n\t" 6490 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t") 6491 "movq %rcx,%rax\n\t" 6492 "movq $4,%rcx\n\t" 6493 "cmp %rcx,%rdx\n\t" 6494 "cmovgq %rdx,%rcx\n\t" 6495 "leaq 0(,%rcx,8),%rdx\n\t" 6496 "subq %rdx,%rsp\n\t" 6497 "andq $~15,%rsp\n\t" 6498 "movq %rsp,%rdi\n\t" 6499 "movq %r8,%rsi\n\t" 6500 "rep; movsq\n\t" 6501 "movq 0(%rsp),%rcx\n\t" 6502 "movq 8(%rsp),%rdx\n\t" 6503 "movq 16(%rsp),%r8\n\t" 6504 "movq 24(%rsp),%r9\n\t" 6505 "movq 0(%rsp),%xmm0\n\t" 6506 "movq 8(%rsp),%xmm1\n\t" 6507 "movq 16(%rsp),%xmm2\n\t" 6508 "movq 24(%rsp),%xmm3\n\t" 6509 "callq *%rax\n\t" 6510 "leaq -16(%rbp),%rsp\n\t" 6511 "popq %rdi\n\t" 6512 __ASM_CFI(".cfi_same_value %rdi\n\t") 6513 "popq %rsi\n\t" 6514 __ASM_CFI(".cfi_same_value %rsi\n\t") 6515 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t") 6516 "popq %rbp\n\t" 6517 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") 6518 __ASM_CFI(".cfi_same_value %rbp\n\t") 6519 "ret") 6520 6521 /* same function but returning floating point */ 6522 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method; 6523 6524 DWORD _invoke(FARPROC func, CALLCONV callconv, int nrargs, DWORD_PTR *args) 6525 { 6526 DWORD res; 6527 6528 if (TRACE_ON(ole)) 6529 { 6530 int i; 6531 TRACE("Calling %p(", func); 6532 for (i=0; i<min(nrargs, 30); i++) TRACE("%016lx,", args[i]); 6533 if (nrargs > 30) TRACE("..."); 6534 TRACE(")\n"); 6535 } 6536 6537 switch (callconv) { 6538 case CC_STDCALL: 6539 case CC_CDECL: 6540 res = call_method(func, nrargs, args); 6541 break; 6542 default: 6543 FIXME("unsupported calling convention %d\n", callconv); 6544 res = -1; 6545 break; 6546 } 6547 6548 TRACE("returns %08x\n", res); 6549 return res; 6550 } 6551 6552 #elif defined(__arm__) 6553 6554 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args ); 6555 __ASM_GLOBAL_FUNC( call_method, 6556 /* r0 = *func 6557 * r1 = nb_stk_args 6558 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack) 6559 * 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) 6560 */ 6561 6562 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */ 6563 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */ 6564 6565 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */ 6566 "beq 1f\n\t" /* Skip allocation if no stack args */ 6567 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */ 6568 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */ 6569 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */ 6570 "subs r1, r1, #4\n\t" /* Decrement count */ 6571 "bgt 2b\n\t" /* Loop till done */ 6572 6573 "1:\n\t" 6574 #ifndef __SOFTFP__ 6575 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */ 6576 #endif 6577 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */ 6578 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */ 6579 6580 "blx ip\n\t" /* Call the target function */ 6581 6582 "mov sp, fp\n\t" /* Clean the stack using fp */ 6583 "pop {fp, pc}\n\t" /* Restore fp and return */ 6584 ) 6585 6586 /* same function but returning single/double floating point */ 6587 static float (CDECL * const call_float_method)(void *, int, const DWORD *, const DWORD *) = (void *)call_method; 6588 static double (CDECL * const call_double_method)(void *, int, const DWORD *, const DWORD *) = (void *)call_method; 6589 6590 #endif /* __x86_64__ */ 6591 6592 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt) 6593 { 6594 HRESULT hr = S_OK; 6595 ITypeInfo *tinfo2 = NULL; 6596 TYPEATTR *tattr = NULL; 6597 6598 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2); 6599 if (hr) 6600 { 6601 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, " 6602 "hr = 0x%08x\n", 6603 tdesc->u.hreftype, hr); 6604 return hr; 6605 } 6606 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr); 6607 if (hr) 6608 { 6609 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr); 6610 ITypeInfo_Release(tinfo2); 6611 return hr; 6612 } 6613 6614 switch (tattr->typekind) 6615 { 6616 case TKIND_ENUM: 6617 *vt |= VT_I4; 6618 break; 6619 6620 case TKIND_ALIAS: 6621 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt); 6622 break; 6623 6624 case TKIND_INTERFACE: 6625 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) 6626 *vt |= VT_DISPATCH; 6627 else 6628 *vt |= VT_UNKNOWN; 6629 break; 6630 6631 case TKIND_DISPATCH: 6632 *vt |= VT_DISPATCH; 6633 break; 6634 6635 case TKIND_COCLASS: 6636 *vt |= VT_DISPATCH; 6637 break; 6638 6639 case TKIND_RECORD: 6640 FIXME("TKIND_RECORD unhandled.\n"); 6641 hr = E_NOTIMPL; 6642 break; 6643 6644 case TKIND_UNION: 6645 FIXME("TKIND_UNION unhandled.\n"); 6646 hr = E_NOTIMPL; 6647 break; 6648 6649 default: 6650 FIXME("TKIND %d unhandled.\n",tattr->typekind); 6651 hr = E_NOTIMPL; 6652 break; 6653 } 6654 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 6655 ITypeInfo_Release(tinfo2); 6656 return hr; 6657 } 6658 6659 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt) 6660 { 6661 HRESULT hr = S_OK; 6662 6663 /* enforce only one level of pointer indirection */ 6664 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR)) 6665 { 6666 tdesc = tdesc->u.lptdesc; 6667 6668 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or 6669 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into 6670 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */ 6671 if ((tdesc->vt == VT_USERDEFINED) || 6672 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED))) 6673 { 6674 VARTYPE vt_userdefined = 0; 6675 const TYPEDESC *tdesc_userdefined = tdesc; 6676 if (tdesc->vt == VT_PTR) 6677 { 6678 vt_userdefined = VT_BYREF; 6679 tdesc_userdefined = tdesc->u.lptdesc; 6680 } 6681 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined); 6682 if ((hr == S_OK) && 6683 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) || 6684 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH))) 6685 { 6686 *vt |= vt_userdefined; 6687 return S_OK; 6688 } 6689 } 6690 *vt = VT_BYREF; 6691 } 6692 6693 switch (tdesc->vt) 6694 { 6695 case VT_HRESULT: 6696 *vt |= VT_ERROR; 6697 break; 6698 case VT_USERDEFINED: 6699 hr = userdefined_to_variantvt(tinfo, tdesc, vt); 6700 break; 6701 case VT_VOID: 6702 case VT_CARRAY: 6703 case VT_PTR: 6704 case VT_LPSTR: 6705 case VT_LPWSTR: 6706 ERR("cannot convert type %d into variant VT\n", tdesc->vt); 6707 hr = DISP_E_BADVARTYPE; 6708 break; 6709 case VT_SAFEARRAY: 6710 *vt |= VT_ARRAY; 6711 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt); 6712 break; 6713 case VT_INT: 6714 *vt |= VT_I4; 6715 break; 6716 case VT_UINT: 6717 *vt |= VT_UI4; 6718 break; 6719 default: 6720 *vt |= tdesc->vt; 6721 break; 6722 } 6723 return hr; 6724 } 6725 6726 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid) 6727 { 6728 ITypeInfo *tinfo2; 6729 TYPEATTR *tattr; 6730 HRESULT hres; 6731 6732 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2); 6733 if(FAILED(hres)) 6734 return hres; 6735 6736 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr); 6737 if(FAILED(hres)) { 6738 ITypeInfo_Release(tinfo2); 6739 return hres; 6740 } 6741 6742 switch(tattr->typekind) { 6743 case TKIND_ALIAS: 6744 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid); 6745 break; 6746 6747 case TKIND_INTERFACE: 6748 case TKIND_DISPATCH: 6749 *guid = tattr->guid; 6750 break; 6751 6752 case TKIND_COCLASS: { 6753 unsigned int i; 6754 int type_flags; 6755 6756 for(i = 0; i < tattr->cImplTypes; i++) 6757 if(SUCCEEDED(ITypeInfo_GetImplTypeFlags(tinfo2, i, &type_flags)) && 6758 type_flags == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) break; 6759 6760 if(i < tattr->cImplTypes) { 6761 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href); 6762 if(SUCCEEDED(hres)) hres = get_iface_guid(tinfo2, href, guid); 6763 } else hres = E_UNEXPECTED; 6764 break; 6765 } 6766 6767 default: 6768 ERR("Unexpected typekind %d\n", tattr->typekind); 6769 hres = E_UNEXPECTED; 6770 } 6771 6772 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 6773 ITypeInfo_Release(tinfo2); 6774 return hres; 6775 } 6776 6777 /*********************************************************************** 6778 * DispCallFunc (OLEAUT32.@) 6779 * 6780 * Invokes a function of the specified calling convention, passing the 6781 * specified arguments and returns the result. 6782 * 6783 * PARAMS 6784 * pvInstance [I] Optional pointer to the instance whose function to invoke. 6785 * oVft [I] The offset in the vtable. See notes. 6786 * cc [I] Calling convention of the function to call. 6787 * vtReturn [I] The return type of the function. 6788 * cActuals [I] Number of parameters. 6789 * prgvt [I] The types of the parameters to pass. This is used for sizing only. 6790 * prgpvarg [I] The arguments to pass. 6791 * pvargResult [O] The return value of the function. Can be NULL. 6792 * 6793 * RETURNS 6794 * Success: S_OK. 6795 * Failure: HRESULT code. 6796 * 6797 * NOTES 6798 * The HRESULT return value of this function is not affected by the return 6799 * value of the user supplied function, which is returned in pvargResult. 6800 * 6801 * If pvInstance is NULL then a non-object function is to be called and oVft 6802 * is the address of the function to call. 6803 * 6804 * The cc parameter can be one of the following values: 6805 *|CC_FASTCALL 6806 *|CC_CDECL 6807 *|CC_PASCAL 6808 *|CC_STDCALL 6809 *|CC_FPFASTCALL 6810 *|CC_SYSCALL 6811 *|CC_MPWCDECL 6812 *|CC_MPWPASCAL 6813 * 6814 */ 6815 HRESULT WINAPI 6816 DispCallFunc( 6817 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals, 6818 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult) 6819 { 6820 #ifdef __i386__ 6821 int argspos, stack_offset; 6822 void *func; 6823 UINT i; 6824 DWORD *args; 6825 6826 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n", 6827 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, 6828 pvargResult, V_VT(pvargResult)); 6829 6830 if (cc != CC_STDCALL && cc != CC_CDECL) 6831 { 6832 FIXME("unsupported calling convention %d\n",cc); 6833 return E_INVALIDARG; 6834 } 6835 6836 /* maximum size for an argument is sizeof(VARIANT) */ 6837 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 ); 6838 6839 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */ 6840 argspos = 1; 6841 if (pvInstance) 6842 { 6843 const FARPROC *vtable = *(FARPROC **)pvInstance; 6844 func = vtable[oVft/sizeof(void *)]; 6845 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */ 6846 } 6847 else func = (void *)oVft; 6848 6849 for (i = 0; i < cActuals; i++) 6850 { 6851 VARIANT *arg = prgpvarg[i]; 6852 6853 switch (prgvt[i]) 6854 { 6855 case VT_EMPTY: 6856 break; 6857 case VT_I8: 6858 case VT_UI8: 6859 case VT_R8: 6860 case VT_DATE: 6861 case VT_CY: 6862 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) ); 6863 argspos += sizeof(V_I8(arg)) / sizeof(DWORD); 6864 break; 6865 case VT_DECIMAL: 6866 case VT_VARIANT: 6867 memcpy( &args[argspos], arg, sizeof(*arg) ); 6868 argspos += sizeof(*arg) / sizeof(DWORD); 6869 break; 6870 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */ 6871 args[argspos++] = V_BOOL(arg); 6872 break; 6873 default: 6874 args[argspos++] = V_UI4(arg); 6875 break; 6876 } 6877 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg)); 6878 } 6879 6880 switch (vtReturn) 6881 { 6882 case VT_EMPTY: 6883 call_method( func, argspos - 1, args + 1, &stack_offset ); 6884 break; 6885 case VT_R4: 6886 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset ); 6887 break; 6888 case VT_R8: 6889 case VT_DATE: 6890 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset ); 6891 break; 6892 case VT_DECIMAL: 6893 case VT_VARIANT: 6894 if (pvInstance) 6895 { 6896 args[0] = (DWORD)pvInstance; /* arg 0 is a pointer to the instance */ 6897 args[1] = (DWORD)pvargResult; /* arg 1 is a pointer to the result */ 6898 call_method( func, argspos, args, &stack_offset ); 6899 } 6900 else 6901 { 6902 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */ 6903 call_method( func, argspos, args, &stack_offset ); 6904 } 6905 break; 6906 case VT_I8: 6907 case VT_UI8: 6908 case VT_CY: 6909 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset ); 6910 break; 6911 case VT_HRESULT: 6912 WARN("invalid return type %u\n", vtReturn); 6913 heap_free( args ); 6914 return E_INVALIDARG; 6915 default: 6916 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset ); 6917 break; 6918 } 6919 heap_free( args ); 6920 if (stack_offset && cc == CC_STDCALL) 6921 { 6922 WARN( "stack pointer off by %d\n", stack_offset ); 6923 return DISP_E_BADCALLEE; 6924 } 6925 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn; 6926 TRACE("retval: %s\n", debugstr_variant(pvargResult)); 6927 return S_OK; 6928 6929 #elif defined(__x86_64__) 6930 int argspos; 6931 UINT i; 6932 DWORD_PTR *args; 6933 void *func; 6934 6935 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n", 6936 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, 6937 pvargResult, V_VT(pvargResult)); 6938 6939 if (cc != CC_STDCALL && cc != CC_CDECL) 6940 { 6941 FIXME("unsupported calling convention %d\n",cc); 6942 return E_INVALIDARG; 6943 } 6944 6945 /* maximum size for an argument is sizeof(DWORD_PTR) */ 6946 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) ); 6947 6948 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */ 6949 argspos = 1; 6950 if (pvInstance) 6951 { 6952 const FARPROC *vtable = *(FARPROC **)pvInstance; 6953 func = vtable[oVft/sizeof(void *)]; 6954 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */ 6955 } 6956 else func = (void *)oVft; 6957 6958 for (i = 0; i < cActuals; i++) 6959 { 6960 VARIANT *arg = prgpvarg[i]; 6961 6962 switch (prgvt[i]) 6963 { 6964 case VT_DECIMAL: 6965 case VT_VARIANT: 6966 args[argspos++] = (ULONG_PTR)arg; 6967 break; 6968 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */ 6969 args[argspos++] = V_BOOL(arg); 6970 break; 6971 default: 6972 args[argspos++] = V_UI8(arg); 6973 break; 6974 } 6975 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg)); 6976 } 6977 6978 switch (vtReturn) 6979 { 6980 case VT_R4: 6981 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 ); 6982 break; 6983 case VT_R8: 6984 case VT_DATE: 6985 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 ); 6986 break; 6987 case VT_DECIMAL: 6988 case VT_VARIANT: 6989 if (pvInstance) 6990 { 6991 args[0] = (DWORD_PTR)pvInstance; /* arg 0 is a pointer to the instance */ 6992 args[1] = (DWORD_PTR)pvargResult; /* arg 1 is a pointer to the result */ 6993 call_method( func, argspos, args ); 6994 } 6995 else 6996 { 6997 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */ 6998 call_method( func, argspos, args ); 6999 } 7000 break; 7001 case VT_HRESULT: 7002 WARN("invalid return type %u\n", vtReturn); 7003 heap_free( args ); 7004 return E_INVALIDARG; 7005 default: 7006 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 ); 7007 break; 7008 } 7009 heap_free( args ); 7010 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn; 7011 TRACE("retval: %s\n", debugstr_variant(pvargResult)); 7012 return S_OK; 7013 7014 #elif defined(__arm__) 7015 int argspos; 7016 void *func; 7017 UINT i; 7018 DWORD *args; 7019 struct { 7020 #ifndef __SOFTFP__ 7021 union { 7022 float s[16]; 7023 double d[8]; 7024 } sd; 7025 #endif 7026 DWORD r[4]; 7027 } regs; 7028 int rcount; /* 32-bit register index count */ 7029 #ifndef __SOFTFP__ 7030 int scount = 0; /* single-precision float register index count */ 7031 int dcount = 0; /* double-precision float register index count */ 7032 #endif 7033 7034 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n", 7035 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)); 7036 7037 if (cc != CC_STDCALL && cc != CC_CDECL) 7038 { 7039 FIXME("unsupported calling convention %d\n",cc); 7040 return E_INVALIDARG; 7041 } 7042 7043 argspos = 0; 7044 rcount = 0; 7045 7046 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */ 7047 /* first as it will need to be in the 'r' registers: */ 7048 switch (vtReturn) 7049 { 7050 case VT_DECIMAL: 7051 case VT_VARIANT: 7052 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */ 7053 break; 7054 case VT_HRESULT: 7055 WARN("invalid return type %u\n", vtReturn); 7056 return E_INVALIDARG; 7057 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */ 7058 break; 7059 } 7060 7061 if (pvInstance) 7062 { 7063 const FARPROC *vtable = *(FARPROC **)pvInstance; 7064 func = vtable[oVft/sizeof(void *)]; 7065 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */ 7066 } 7067 else func = (void *)oVft; 7068 7069 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */ 7070 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 ); 7071 7072 for (i = 0; i < cActuals; i++) 7073 { 7074 VARIANT *arg = prgpvarg[i]; 7075 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */ 7076 int ntemp; /* Used for counting words split between registers and stack */ 7077 7078 switch (prgvt[i]) 7079 { 7080 case VT_EMPTY: 7081 break; 7082 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */ 7083 case VT_DATE: 7084 #ifndef __SOFTFP__ 7085 dcount = max( (scount + 1) / 2, dcount ); 7086 if (dcount < 8) 7087 { 7088 regs.sd.d[dcount++] = V_R8(arg); 7089 } 7090 else 7091 { 7092 argspos += (argspos % 2); /* align argspos to 8-bytes */ 7093 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) ); 7094 argspos += sizeof(V_R8(arg)) / sizeof(DWORD); 7095 } 7096 break; 7097 #endif 7098 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */ 7099 case VT_UI8: 7100 case VT_CY: 7101 if (rcount < 3) 7102 { 7103 rcount += (rcount % 2); /* align rcount to 8-byte register pair */ 7104 memcpy( ®s.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) ); 7105 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD); 7106 } 7107 else 7108 { 7109 rcount = 4; /* Make sure we flag that all 'r' regs are full */ 7110 argspos += (argspos % 2); /* align argspos to 8-bytes */ 7111 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) ); 7112 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD); 7113 } 7114 break; 7115 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */ 7116 case VT_VARIANT: 7117 /* 8-byte align 'r' and/or stack: */ 7118 if (rcount < 3) 7119 rcount += (rcount % 2); 7120 else 7121 { 7122 rcount = 4; 7123 argspos += (argspos % 2); 7124 } 7125 ntemp = sizeof(*arg) / sizeof(DWORD); 7126 while (ntemp > 0) 7127 { 7128 if (rcount < 4) 7129 regs.r[rcount++] = *pdwarg++; 7130 else 7131 args[argspos++] = *pdwarg++; 7132 --ntemp; 7133 } 7134 break; 7135 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */ 7136 if (rcount < 4) 7137 regs.r[rcount++] = V_BOOL(arg); 7138 else 7139 args[argspos++] = V_BOOL(arg); 7140 break; 7141 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */ 7142 #ifndef __SOFTFP__ 7143 if (!(scount % 2)) scount = max( scount, dcount * 2 ); 7144 if (scount < 16) 7145 regs.sd.s[scount++] = V_R4(arg); 7146 else 7147 args[argspos++] = V_UI4(arg); 7148 break; 7149 #endif 7150 default: 7151 if (rcount < 4) 7152 regs.r[rcount++] = V_UI4(arg); 7153 else 7154 args[argspos++] = V_UI4(arg); 7155 break; 7156 } 7157 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg)); 7158 } 7159 7160 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */ 7161 7162 switch (vtReturn) 7163 { 7164 case VT_EMPTY: /* EMPTY = no return value */ 7165 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */ 7166 case VT_VARIANT: 7167 call_method( func, argspos, args, (DWORD*)®s ); 7168 break; 7169 case VT_R4: 7170 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)®s ); 7171 break; 7172 case VT_R8: 7173 case VT_DATE: 7174 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)®s ); 7175 break; 7176 case VT_I8: 7177 case VT_UI8: 7178 case VT_CY: 7179 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)®s ); 7180 break; 7181 default: 7182 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)®s ); 7183 break; 7184 } 7185 heap_free( args ); 7186 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn; 7187 TRACE("retval: %s\n", debugstr_variant(pvargResult)); 7188 return S_OK; 7189 7190 #else 7191 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n", 7192 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)); 7193 return E_NOTIMPL; 7194 #endif 7195 } 7196 7197 static inline BOOL func_restricted( const FUNCDESC *desc ) 7198 { 7199 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0); 7200 } 7201 7202 #define INVBUF_ELEMENT_SIZE \ 7203 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE)) 7204 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer) 7205 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \ 7206 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params))) 7207 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \ 7208 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params))) 7209 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \ 7210 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params))) 7211 7212 static HRESULT WINAPI ITypeInfo_fnInvoke( 7213 ITypeInfo2 *iface, 7214 VOID *pIUnk, 7215 MEMBERID memid, 7216 UINT16 wFlags, 7217 DISPPARAMS *pDispParams, 7218 VARIANT *pVarResult, 7219 EXCEPINFO *pExcepInfo, 7220 UINT *pArgErr) 7221 { 7222 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 7223 int i; 7224 unsigned int var_index; 7225 TYPEKIND type_kind; 7226 HRESULT hres; 7227 const TLBFuncDesc *pFuncInfo; 7228 UINT fdc; 7229 7230 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n", 7231 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr 7232 ); 7233 7234 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED ) 7235 return DISP_E_MEMBERNOTFOUND; 7236 7237 if (!pDispParams) 7238 { 7239 ERR("NULL pDispParams not allowed\n"); 7240 return E_INVALIDARG; 7241 } 7242 7243 dump_DispParms(pDispParams); 7244 7245 if (pDispParams->cNamedArgs > pDispParams->cArgs) 7246 { 7247 ERR("named argument array cannot be bigger than argument array (%d/%d)\n", 7248 pDispParams->cNamedArgs, pDispParams->cArgs); 7249 return E_INVALIDARG; 7250 } 7251 7252 /* we do this instead of using GetFuncDesc since it will return a fake 7253 * FUNCDESC for dispinterfaces and we want the real function description */ 7254 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){ 7255 pFuncInfo = &This->funcdescs[fdc]; 7256 if ((memid == pFuncInfo->funcdesc.memid) && 7257 (wFlags & pFuncInfo->funcdesc.invkind) && 7258 !func_restricted( &pFuncInfo->funcdesc )) 7259 break; 7260 } 7261 7262 if (fdc < This->typeattr.cFuncs) { 7263 const FUNCDESC *func_desc = &pFuncInfo->funcdesc; 7264 7265 if (TRACE_ON(ole)) 7266 { 7267 TRACE("invoking:\n"); 7268 dump_TLBFuncDescOne(pFuncInfo); 7269 } 7270 7271 switch (func_desc->funckind) { 7272 case FUNC_PUREVIRTUAL: 7273 case FUNC_VIRTUAL: { 7274 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams); 7275 VARIANT varresult; 7276 VARIANT retval; /* pointer for storing byref retvals in */ 7277 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams); 7278 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams); 7279 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams); 7280 UINT cNamedArgs = pDispParams->cNamedArgs; 7281 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs; 7282 UINT vargs_converted=0; 7283 7284 hres = S_OK; 7285 7286 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF)) 7287 { 7288 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT)) 7289 { 7290 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n"); 7291 hres = DISP_E_PARAMNOTFOUND; 7292 goto func_fail; 7293 } 7294 } 7295 7296 if (func_desc->cParamsOpt < 0 && cNamedArgs) 7297 { 7298 ERR("functions with the vararg attribute do not support named arguments\n"); 7299 hres = DISP_E_NONAMEDARGS; 7300 goto func_fail; 7301 } 7302 7303 for (i = 0; i < func_desc->cParams; i++) 7304 { 7305 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; 7306 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]); 7307 if (FAILED(hres)) 7308 goto func_fail; 7309 } 7310 7311 TRACE("changing args\n"); 7312 for (i = 0; i < func_desc->cParams; i++) 7313 { 7314 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; 7315 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; 7316 VARIANTARG *src_arg; 7317 7318 if (wParamFlags & PARAMFLAG_FLCID) 7319 { 7320 VARIANTARG *arg; 7321 arg = prgpvarg[i] = &rgvarg[i]; 7322 V_VT(arg) = VT_I4; 7323 V_I4(arg) = This->pTypeLib->lcid; 7324 continue; 7325 } 7326 7327 src_arg = NULL; 7328 7329 if (cNamedArgs) 7330 { 7331 USHORT j; 7332 for (j = 0; j < cNamedArgs; j++) 7333 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT)) 7334 { 7335 src_arg = &pDispParams->rgvarg[j]; 7336 break; 7337 } 7338 } 7339 7340 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs) 7341 { 7342 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]; 7343 vargs_converted++; 7344 } 7345 7346 if (wParamFlags & PARAMFLAG_FRETVAL) 7347 { 7348 /* under most conditions the caller is not allowed to 7349 * pass in a dispparam arg in the index of what would be 7350 * the retval parameter. however, there is an exception 7351 * where the extra parameter is used in an extra 7352 * IDispatch::Invoke below */ 7353 if ((i < pDispParams->cArgs) && 7354 ((func_desc->cParams != 1) || !pVarResult || 7355 !(func_desc->invkind & INVOKE_PROPERTYGET))) 7356 { 7357 hres = DISP_E_BADPARAMCOUNT; 7358 break; 7359 } 7360 7361 /* note: this check is placed so that if the caller passes 7362 * in a VARIANTARG for the retval we just ignore it, like 7363 * native does */ 7364 if (i == func_desc->cParams - 1) 7365 { 7366 VARIANTARG *arg; 7367 arg = prgpvarg[i] = &rgvarg[i]; 7368 memset(arg, 0, sizeof(*arg)); 7369 V_VT(arg) = rgvt[i]; 7370 memset(&retval, 0, sizeof(retval)); 7371 V_BYREF(arg) = &retval; 7372 } 7373 else 7374 { 7375 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams); 7376 hres = E_UNEXPECTED; 7377 break; 7378 } 7379 } 7380 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) && 7381 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND)) 7382 { 7383 TRACE("%s\n", debugstr_variant(src_arg)); 7384 7385 if(rgvt[i]!=V_VT(src_arg)) 7386 { 7387 if (rgvt[i] == VT_VARIANT) 7388 hres = VariantCopy(&rgvarg[i], src_arg); 7389 else if (rgvt[i] == (VT_VARIANT | VT_BYREF)) 7390 { 7391 if (rgvt[i] == V_VT(src_arg)) 7392 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg); 7393 else 7394 { 7395 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 7396 if (wParamFlags & PARAMFLAG_FIN) 7397 hres = VariantCopy(&missing_arg[i], src_arg); 7398 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i]; 7399 } 7400 V_VT(&rgvarg[i]) = rgvt[i]; 7401 } 7402 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0) 7403 { 7404 SAFEARRAY *a; 7405 SAFEARRAYBOUND bound; 7406 VARIANT *v; 7407 LONG j; 7408 bound.lLbound = 0; 7409 bound.cElements = pDispParams->cArgs-i; 7410 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound))) 7411 { 7412 ERR("SafeArrayCreate failed\n"); 7413 break; 7414 } 7415 hres = SafeArrayAccessData(a, (LPVOID)&v); 7416 if (hres != S_OK) 7417 { 7418 ERR("SafeArrayAccessData failed with %x\n", hres); 7419 SafeArrayDestroy(a); 7420 break; 7421 } 7422 for (j = 0; j < bound.cElements; j++) 7423 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]); 7424 hres = SafeArrayUnaccessData(a); 7425 if (hres != S_OK) 7426 { 7427 ERR("SafeArrayUnaccessData failed with %x\n", hres); 7428 SafeArrayDestroy(a); 7429 break; 7430 } 7431 if (rgvt[i] & VT_BYREF) 7432 V_BYREF(&rgvarg[i]) = &a; 7433 else 7434 V_ARRAY(&rgvarg[i]) = a; 7435 V_VT(&rgvarg[i]) = rgvt[i]; 7436 } 7437 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg)) 7438 { 7439 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 7440 if (wParamFlags & PARAMFLAG_FIN) 7441 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF); 7442 else 7443 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF; 7444 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]); 7445 V_VT(&rgvarg[i]) = rgvt[i]; 7446 } 7447 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg))) 7448 { 7449 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg); 7450 V_VT(&rgvarg[i]) = rgvt[i]; 7451 } 7452 else 7453 { 7454 /* FIXME: this doesn't work for VT_BYREF arguments if 7455 * they are not the same type as in the paramdesc */ 7456 V_VT(&rgvarg[i]) = V_VT(src_arg); 7457 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]); 7458 V_VT(&rgvarg[i]) = rgvt[i]; 7459 } 7460 7461 if (FAILED(hres)) 7462 { 7463 ERR("failed to convert param %d to %s from %s\n", i, 7464 debugstr_vt(rgvt[i]), debugstr_variant(src_arg)); 7465 break; 7466 } 7467 prgpvarg[i] = &rgvarg[i]; 7468 } 7469 else 7470 { 7471 prgpvarg[i] = src_arg; 7472 } 7473 7474 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED)) 7475 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN) 7476 && V_UNKNOWN(prgpvarg[i])) { 7477 IUnknown *userdefined_iface; 7478 GUID guid; 7479 7480 if (tdesc->vt == VT_PTR) 7481 tdesc = tdesc->u.lptdesc; 7482 7483 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid); 7484 if(FAILED(hres)) 7485 break; 7486 7487 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface); 7488 if(FAILED(hres)) { 7489 ERR("argument does not support %s interface\n", debugstr_guid(&guid)); 7490 break; 7491 } 7492 7493 IUnknown_Release(V_UNKNOWN(prgpvarg[i])); 7494 V_UNKNOWN(prgpvarg[i]) = userdefined_iface; 7495 } 7496 } 7497 else if (wParamFlags & PARAMFLAG_FOPT) 7498 { 7499 VARIANTARG *arg; 7500 arg = prgpvarg[i] = &rgvarg[i]; 7501 if (wParamFlags & PARAMFLAG_FHASDEFAULT) 7502 { 7503 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue); 7504 if (FAILED(hres)) 7505 break; 7506 } 7507 else 7508 { 7509 VARIANTARG *missing_arg; 7510 /* if the function wants a pointer to a variant then 7511 * set that up, otherwise just pass the VT_ERROR in 7512 * the argument by value */ 7513 if (rgvt[i] & VT_BYREF) 7514 { 7515 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i; 7516 V_VT(arg) = VT_VARIANT | VT_BYREF; 7517 V_VARIANTREF(arg) = missing_arg; 7518 } 7519 else 7520 missing_arg = arg; 7521 V_VT(missing_arg) = VT_ERROR; 7522 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND; 7523 } 7524 } 7525 else 7526 { 7527 hres = DISP_E_BADPARAMCOUNT; 7528 break; 7529 } 7530 } 7531 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ 7532 7533 /* VT_VOID is a special case for return types, so it is not 7534 * handled in the general function */ 7535 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID) 7536 V_VT(&varresult) = VT_EMPTY; 7537 else 7538 { 7539 V_VT(&varresult) = 0; 7540 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult)); 7541 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ 7542 } 7543 7544 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv, 7545 V_VT(&varresult), func_desc->cParams, rgvt, 7546 prgpvarg, &varresult); 7547 7548 vargs_converted = 0; 7549 7550 for (i = 0; i < func_desc->cParams; i++) 7551 { 7552 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; 7553 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 7554 7555 if (wParamFlags & PARAMFLAG_FLCID) 7556 continue; 7557 else if (wParamFlags & PARAMFLAG_FRETVAL) 7558 { 7559 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i])); 7560 7561 if (pVarResult) 7562 { 7563 VariantInit(pVarResult); 7564 /* deref return value */ 7565 hres = VariantCopyInd(pVarResult, prgpvarg[i]); 7566 } 7567 7568 VARIANT_ClearInd(prgpvarg[i]); 7569 } 7570 else if (vargs_converted < pDispParams->cArgs) 7571 { 7572 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]; 7573 if (wParamFlags & PARAMFLAG_FOUT) 7574 { 7575 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF)) 7576 { 7577 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg)); 7578 7579 if (FAILED(hres)) 7580 { 7581 ERR("failed to convert param %d to vt %d\n", i, 7582 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted])); 7583 break; 7584 } 7585 } 7586 } 7587 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) && 7588 func_desc->cParamsOpt < 0 && 7589 i == func_desc->cParams-1) 7590 { 7591 SAFEARRAY *a = V_ARRAY(prgpvarg[i]); 7592 LONG j, ubound; 7593 VARIANT *v; 7594 hres = SafeArrayGetUBound(a, 1, &ubound); 7595 if (hres != S_OK) 7596 { 7597 ERR("SafeArrayGetUBound failed with %x\n", hres); 7598 break; 7599 } 7600 hres = SafeArrayAccessData(a, (LPVOID)&v); 7601 if (hres != S_OK) 7602 { 7603 ERR("SafeArrayAccessData failed with %x\n", hres); 7604 break; 7605 } 7606 for (j = 0; j <= ubound; j++) 7607 VariantClear(&v[j]); 7608 hres = SafeArrayUnaccessData(a); 7609 if (hres != S_OK) 7610 { 7611 ERR("SafeArrayUnaccessData failed with %x\n", hres); 7612 break; 7613 } 7614 } 7615 VariantClear(&rgvarg[i]); 7616 vargs_converted++; 7617 } 7618 else if (wParamFlags & PARAMFLAG_FOPT) 7619 { 7620 if (wParamFlags & PARAMFLAG_FHASDEFAULT) 7621 VariantClear(&rgvarg[i]); 7622 } 7623 7624 VariantClear(&missing_arg[i]); 7625 } 7626 7627 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult))) 7628 { 7629 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult)); 7630 hres = DISP_E_EXCEPTION; 7631 if (pExcepInfo) 7632 { 7633 IErrorInfo *pErrorInfo; 7634 pExcepInfo->scode = V_ERROR(&varresult); 7635 if (GetErrorInfo(0, &pErrorInfo) == S_OK) 7636 { 7637 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription); 7638 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile); 7639 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource); 7640 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext); 7641 7642 IErrorInfo_Release(pErrorInfo); 7643 } 7644 } 7645 } 7646 if (V_VT(&varresult) != VT_ERROR) 7647 { 7648 TRACE("varresult value: %s\n", debugstr_variant(&varresult)); 7649 7650 if (pVarResult) 7651 { 7652 VariantClear(pVarResult); 7653 *pVarResult = varresult; 7654 } 7655 else 7656 VariantClear(&varresult); 7657 } 7658 7659 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) && 7660 (func_desc->invkind & INVOKE_PROPERTYGET) && 7661 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) && 7662 (pDispParams->cArgs != 0)) 7663 { 7664 if (V_VT(pVarResult) == VT_DISPATCH) 7665 { 7666 IDispatch *pDispatch = V_DISPATCH(pVarResult); 7667 /* Note: not VariantClear; we still need the dispatch 7668 * pointer to be valid */ 7669 VariantInit(pVarResult); 7670 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, 7671 GetSystemDefaultLCID(), wFlags, 7672 pDispParams, pVarResult, pExcepInfo, pArgErr); 7673 IDispatch_Release(pDispatch); 7674 } 7675 else 7676 { 7677 VariantClear(pVarResult); 7678 hres = DISP_E_NOTACOLLECTION; 7679 } 7680 } 7681 7682 func_fail: 7683 heap_free(buffer); 7684 break; 7685 } 7686 case FUNC_DISPATCH: { 7687 IDispatch *disp; 7688 7689 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp); 7690 if (SUCCEEDED(hres)) { 7691 FIXME("Calling Invoke in IDispatch iface. untested!\n"); 7692 hres = IDispatch_Invoke( 7693 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams, 7694 pVarResult,pExcepInfo,pArgErr 7695 ); 7696 if (FAILED(hres)) 7697 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres); 7698 IDispatch_Release(disp); 7699 } else 7700 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n"); 7701 break; 7702 } 7703 default: 7704 FIXME("Unknown function invocation type %d\n", func_desc->funckind); 7705 hres = E_FAIL; 7706 break; 7707 } 7708 7709 TRACE("-- 0x%08x\n", hres); 7710 return hres; 7711 7712 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) { 7713 VARDESC *var_desc; 7714 7715 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc); 7716 if(FAILED(hres)) return hres; 7717 7718 FIXME("varseek: Found memid, but variable-based invoking not supported\n"); 7719 dump_VARDESC(var_desc); 7720 ITypeInfo2_ReleaseVarDesc(iface, var_desc); 7721 return E_NOTIMPL; 7722 } 7723 7724 /* not found, look for it in inherited interfaces */ 7725 ITypeInfo2_GetTypeKind(iface, &type_kind); 7726 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) { 7727 if(This->impltypes) { 7728 /* recursive search */ 7729 ITypeInfo *pTInfo; 7730 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo); 7731 if(SUCCEEDED(hres)){ 7732 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); 7733 ITypeInfo_Release(pTInfo); 7734 return hres; 7735 } 7736 WARN("Could not search inherited interface!\n"); 7737 } 7738 } 7739 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags); 7740 return DISP_E_MEMBERNOTFOUND; 7741 } 7742 7743 /* ITypeInfo::GetDocumentation 7744 * 7745 * Retrieves the documentation string, the complete Help file name and path, 7746 * and the context ID for the Help topic for a specified type description. 7747 * 7748 * (Can be tested by the Visual Basic Editor in Word for instance.) 7749 */ 7750 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface, 7751 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString, 7752 DWORD *pdwHelpContext, BSTR *pBstrHelpFile) 7753 { 7754 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 7755 const TLBFuncDesc *pFDesc; 7756 const TLBVarDesc *pVDesc; 7757 TRACE("(%p) memid %d Name(%p) DocString(%p)" 7758 " HelpContext(%p) HelpFile(%p)\n", 7759 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile); 7760 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */ 7761 if(pBstrName) 7762 *pBstrName=SysAllocString(TLB_get_bstr(This->Name)); 7763 if(pBstrDocString) 7764 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString)); 7765 if(pdwHelpContext) 7766 *pdwHelpContext=This->dwHelpContext; 7767 if(pBstrHelpFile) 7768 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile)); 7769 return S_OK; 7770 }else {/* for a member */ 7771 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid); 7772 if(pFDesc){ 7773 if(pBstrName) 7774 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name)); 7775 if(pBstrDocString) 7776 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString)); 7777 if(pdwHelpContext) 7778 *pdwHelpContext=pFDesc->helpcontext; 7779 if(pBstrHelpFile) 7780 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile)); 7781 return S_OK; 7782 } 7783 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid); 7784 if(pVDesc){ 7785 if(pBstrName) 7786 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name)); 7787 if(pBstrDocString) 7788 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString)); 7789 if(pdwHelpContext) 7790 *pdwHelpContext=pVDesc->HelpContext; 7791 if(pBstrHelpFile) 7792 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile)); 7793 return S_OK; 7794 } 7795 } 7796 7797 if(This->impltypes && 7798 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) { 7799 /* recursive search */ 7800 ITypeInfo *pTInfo; 7801 HRESULT result; 7802 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo); 7803 if(SUCCEEDED(result)) { 7804 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName, 7805 pBstrDocString, pdwHelpContext, pBstrHelpFile); 7806 ITypeInfo_Release(pTInfo); 7807 return result; 7808 } 7809 WARN("Could not search inherited interface!\n"); 7810 } 7811 7812 WARN("member %d not found\n", memid); 7813 return TYPE_E_ELEMENTNOTFOUND; 7814 } 7815 7816 /* ITypeInfo::GetDllEntry 7817 * 7818 * Retrieves a description or specification of an entry point for a function 7819 * in a DLL. 7820 */ 7821 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid, 7822 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName, 7823 WORD *pwOrdinal) 7824 { 7825 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 7826 const TLBFuncDesc *pFDesc; 7827 7828 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal); 7829 7830 if (pBstrDllName) *pBstrDllName = NULL; 7831 if (pBstrName) *pBstrName = NULL; 7832 if (pwOrdinal) *pwOrdinal = 0; 7833 7834 if (This->typeattr.typekind != TKIND_MODULE) 7835 return TYPE_E_BADMODULEKIND; 7836 7837 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid); 7838 if(pFDesc){ 7839 dump_TypeInfo(This); 7840 if (TRACE_ON(ole)) 7841 dump_TLBFuncDescOne(pFDesc); 7842 7843 if (pBstrDllName) 7844 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName)); 7845 7846 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) { 7847 if (pBstrName) 7848 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry)); 7849 if (pwOrdinal) 7850 *pwOrdinal = -1; 7851 return S_OK; 7852 } 7853 if (pBstrName) 7854 *pBstrName = NULL; 7855 if (pwOrdinal) 7856 *pwOrdinal = LOWORD(pFDesc->Entry); 7857 return S_OK; 7858 } 7859 return TYPE_E_ELEMENTNOTFOUND; 7860 } 7861 7862 /* internal function to make the inherited interfaces' methods appear 7863 * part of the interface */ 7864 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface, 7865 HREFTYPE *hRefType, ITypeInfo **ppTInfo) 7866 { 7867 ITypeInfoImpl *This = impl_from_ITypeInfo(iface); 7868 HRESULT hr; 7869 7870 TRACE("%p, 0x%x\n", iface, *hRefType); 7871 7872 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK)) 7873 { 7874 ITypeInfo *pSubTypeInfo; 7875 7876 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo); 7877 if (FAILED(hr)) 7878 return hr; 7879 7880 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo, 7881 hRefType, ppTInfo); 7882 ITypeInfo_Release(pSubTypeInfo); 7883 if (SUCCEEDED(hr)) 7884 return hr; 7885 } 7886 *hRefType -= DISPATCH_HREF_OFFSET; 7887 7888 if (!(*hRefType & DISPATCH_HREF_MASK)) 7889 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo); 7890 else 7891 return E_FAIL; 7892 } 7893 7894 struct search_res_tlb_params 7895 { 7896 const GUID *guid; 7897 ITypeLib *pTLib; 7898 }; 7899 7900 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam) 7901 { 7902 struct search_res_tlb_params *params = (LPVOID)lParam; 7903 static const WCHAR formatW[] = {'\\','%','d',0}; 7904 WCHAR szPath[MAX_PATH+1]; 7905 ITypeLib *pTLib = NULL; 7906 HRESULT ret; 7907 DWORD len; 7908 7909 if (IS_INTRESOURCE(lpszName) == FALSE) 7910 return TRUE; 7911 7912 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH))) 7913 return TRUE; 7914 7915 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0) 7916 return TRUE; 7917 7918 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib); 7919 if (SUCCEEDED(ret)) 7920 { 7921 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib); 7922 if (IsEqualGUID(params->guid, impl->guid)) 7923 { 7924 params->pTLib = pTLib; 7925 return FALSE; /* stop enumeration */ 7926 } 7927 ITypeLib_Release(pTLib); 7928 } 7929 7930 return TRUE; 7931 } 7932 7933 /* ITypeInfo::GetRefTypeInfo 7934 * 7935 * If a type description references other type descriptions, it retrieves 7936 * the referenced type descriptions. 7937 */ 7938 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( 7939 ITypeInfo2 *iface, 7940 HREFTYPE hRefType, 7941 ITypeInfo **ppTInfo) 7942 { 7943 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 7944 HRESULT result = E_FAIL; 7945 7946 if(!ppTInfo) 7947 return E_INVALIDARG; 7948 7949 if ((INT)hRefType < 0) { 7950 ITypeInfoImpl *pTypeInfoImpl; 7951 7952 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) || 7953 !(This->typeattr.typekind == TKIND_INTERFACE || 7954 This->typeattr.typekind == TKIND_DISPATCH)) 7955 return TYPE_E_ELEMENTNOTFOUND; 7956 7957 /* when we meet a DUAL typeinfo, we must create the alternate 7958 * version of it. 7959 */ 7960 pTypeInfoImpl = ITypeInfoImpl_Constructor(); 7961 7962 *pTypeInfoImpl = *This; 7963 pTypeInfoImpl->ref = 0; 7964 list_init(&pTypeInfoImpl->custdata_list); 7965 7966 if (This->typeattr.typekind == TKIND_INTERFACE) 7967 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH; 7968 else 7969 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE; 7970 7971 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface; 7972 /* the AddRef implicitly adds a reference to the parent typelib, which 7973 * stops the copied data from being destroyed until the new typeinfo's 7974 * refcount goes to zero, but we need to signal to the new instance to 7975 * not free its data structures when it is destroyed */ 7976 pTypeInfoImpl->not_attached_to_typelib = TRUE; 7977 7978 ITypeInfo_AddRef(*ppTInfo); 7979 7980 result = S_OK; 7981 } else if ((hRefType & DISPATCH_HREF_MASK) && 7982 (This->typeattr.typekind == TKIND_DISPATCH)) 7983 { 7984 HREFTYPE href_dispatch = hRefType; 7985 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo); 7986 } else { 7987 TLBRefType *ref_type; 7988 ITypeLib *pTLib = NULL; 7989 UINT i; 7990 7991 if(!(hRefType & 0x1)){ 7992 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i) 7993 { 7994 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3))) 7995 { 7996 result = S_OK; 7997 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface; 7998 ITypeInfo_AddRef(*ppTInfo); 7999 goto end; 8000 } 8001 } 8002 } 8003 8004 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry) 8005 { 8006 if(ref_type->reference == (hRefType & (~0x3))) 8007 break; 8008 } 8009 if(&ref_type->entry == &This->pTypeLib->ref_list) 8010 { 8011 FIXME("Can't find pRefType for ref %x\n", hRefType); 8012 goto end; 8013 } 8014 8015 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) { 8016 UINT Index; 8017 TRACE("internal reference\n"); 8018 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index); 8019 } else { 8020 if(ref_type->pImpTLInfo->pImpTypeLib) { 8021 TRACE("typeinfo in imported typelib that is already loaded\n"); 8022 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface; 8023 ITypeLib_AddRef(pTLib); 8024 result = S_OK; 8025 } else { 8026 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0}; 8027 struct search_res_tlb_params params; 8028 BSTR libnam; 8029 8030 TRACE("typeinfo in imported typelib that isn't already loaded\n"); 8031 8032 /* Search in resource table */ 8033 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid); 8034 params.pTLib = NULL; 8035 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)¶ms); 8036 pTLib = params.pTLib; 8037 result = S_OK; 8038 8039 if (!pTLib) 8040 { 8041 /* Search on disk */ 8042 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid), 8043 ref_type->pImpTLInfo->wVersionMajor, 8044 ref_type->pImpTLInfo->wVersionMinor, 8045 This->pTypeLib->syskind, 8046 ref_type->pImpTLInfo->lcid, &libnam, TRUE); 8047 if (FAILED(result)) 8048 libnam = SysAllocString(ref_type->pImpTLInfo->name); 8049 8050 result = LoadTypeLib(libnam, &pTLib); 8051 SysFreeString(libnam); 8052 } 8053 8054 if(SUCCEEDED(result)) { 8055 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib); 8056 ITypeLib_AddRef(pTLib); 8057 } 8058 } 8059 } 8060 if(SUCCEEDED(result)) { 8061 if(ref_type->index == TLB_REF_USE_GUID) 8062 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo); 8063 else 8064 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo); 8065 } 8066 if (pTLib != NULL) 8067 ITypeLib_Release(pTLib); 8068 } 8069 8070 end: 8071 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType, 8072 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo); 8073 return result; 8074 } 8075 8076 /* ITypeInfo::AddressOfMember 8077 * 8078 * Retrieves the addresses of static functions or variables, such as those 8079 * defined in a DLL. 8080 */ 8081 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface, 8082 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) 8083 { 8084 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8085 HRESULT hr; 8086 BSTR dll, entry; 8087 WORD ordinal; 8088 HMODULE module; 8089 8090 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv); 8091 8092 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal); 8093 if (FAILED(hr)) 8094 return hr; 8095 8096 module = LoadLibraryW(dll); 8097 if (!module) 8098 { 8099 ERR("couldn't load %s\n", debugstr_w(dll)); 8100 SysFreeString(dll); 8101 SysFreeString(entry); 8102 return STG_E_FILENOTFOUND; 8103 } 8104 /* FIXME: store library somewhere where we can free it */ 8105 8106 if (entry) 8107 { 8108 LPSTR entryA; 8109 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL); 8110 entryA = heap_alloc(len); 8111 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL); 8112 8113 *ppv = GetProcAddress(module, entryA); 8114 if (!*ppv) 8115 ERR("function not found %s\n", debugstr_a(entryA)); 8116 8117 heap_free(entryA); 8118 } 8119 else 8120 { 8121 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal)); 8122 if (!*ppv) 8123 ERR("function not found %d\n", ordinal); 8124 } 8125 8126 SysFreeString(dll); 8127 SysFreeString(entry); 8128 8129 if (!*ppv) 8130 return TYPE_E_DLLFUNCTIONNOTFOUND; 8131 8132 return S_OK; 8133 } 8134 8135 /* ITypeInfo::CreateInstance 8136 * 8137 * Creates a new instance of a type that describes a component object class 8138 * (coclass). 8139 */ 8140 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface, 8141 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj) 8142 { 8143 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8144 HRESULT hr; 8145 TYPEATTR *pTA; 8146 8147 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj); 8148 8149 *ppvObj = NULL; 8150 8151 if(pOuterUnk) 8152 { 8153 WARN("Not able to aggregate\n"); 8154 return CLASS_E_NOAGGREGATION; 8155 } 8156 8157 hr = ITypeInfo2_GetTypeAttr(iface, &pTA); 8158 if(FAILED(hr)) return hr; 8159 8160 if(pTA->typekind != TKIND_COCLASS) 8161 { 8162 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind); 8163 hr = E_INVALIDARG; 8164 goto end; 8165 } 8166 8167 hr = S_FALSE; 8168 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT) 8169 { 8170 IUnknown *pUnk; 8171 hr = GetActiveObject(&pTA->guid, NULL, &pUnk); 8172 TRACE("GetActiveObject rets %08x\n", hr); 8173 if(hr == S_OK) 8174 { 8175 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj); 8176 IUnknown_Release(pUnk); 8177 } 8178 } 8179 8180 if(hr != S_OK) 8181 hr = CoCreateInstance(&pTA->guid, NULL, 8182 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 8183 riid, ppvObj); 8184 8185 end: 8186 ITypeInfo2_ReleaseTypeAttr(iface, pTA); 8187 return hr; 8188 } 8189 8190 /* ITypeInfo::GetMops 8191 * 8192 * Retrieves marshalling information. 8193 */ 8194 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, 8195 BSTR *pBstrMops) 8196 { 8197 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8198 FIXME("(%p %d) stub!\n", This, memid); 8199 *pBstrMops = NULL; 8200 return S_OK; 8201 } 8202 8203 /* ITypeInfo::GetContainingTypeLib 8204 * 8205 * Retrieves the containing type library and the index of the type description 8206 * within that type library. 8207 */ 8208 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface, 8209 ITypeLib * *ppTLib, UINT *pIndex) 8210 { 8211 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8212 8213 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */ 8214 if (pIndex) { 8215 *pIndex=This->index; 8216 TRACE("returning pIndex=%d\n", *pIndex); 8217 } 8218 8219 if (ppTLib) { 8220 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface; 8221 ITypeLib_AddRef(*ppTLib); 8222 TRACE("returning ppTLib=%p\n", *ppTLib); 8223 } 8224 8225 return S_OK; 8226 } 8227 8228 /* ITypeInfo::ReleaseTypeAttr 8229 * 8230 * Releases a TYPEATTR previously returned by Get 8231 * 8232 */ 8233 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface, 8234 TYPEATTR* pTypeAttr) 8235 { 8236 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8237 TRACE("(%p)->(%p)\n", This, pTypeAttr); 8238 heap_free(pTypeAttr); 8239 } 8240 8241 /* ITypeInfo::ReleaseFuncDesc 8242 * 8243 * Releases a FUNCDESC previously returned by GetFuncDesc. * 8244 */ 8245 static void WINAPI ITypeInfo_fnReleaseFuncDesc( 8246 ITypeInfo2 *iface, 8247 FUNCDESC *pFuncDesc) 8248 { 8249 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8250 SHORT i; 8251 8252 TRACE("(%p)->(%p)\n", This, pFuncDesc); 8253 8254 for (i = 0; i < pFuncDesc->cParams; i++) 8255 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]); 8256 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc); 8257 8258 SysFreeString((BSTR)pFuncDesc); 8259 } 8260 8261 /* ITypeInfo::ReleaseVarDesc 8262 * 8263 * Releases a VARDESC previously returned by GetVarDesc. 8264 */ 8265 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface, 8266 VARDESC *pVarDesc) 8267 { 8268 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8269 TRACE("(%p)->(%p)\n", This, pVarDesc); 8270 8271 TLB_FreeVarDesc(pVarDesc); 8272 } 8273 8274 /* ITypeInfo2::GetTypeKind 8275 * 8276 * Returns the TYPEKIND enumeration quickly, without doing any allocations. 8277 * 8278 */ 8279 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface, 8280 TYPEKIND *pTypeKind) 8281 { 8282 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8283 *pTypeKind = This->typeattr.typekind; 8284 TRACE("(%p) type 0x%0x\n", This,*pTypeKind); 8285 return S_OK; 8286 } 8287 8288 /* ITypeInfo2::GetTypeFlags 8289 * 8290 * Returns the type flags without any allocations. This returns a DWORD type 8291 * flag, which expands the type flags without growing the TYPEATTR (type 8292 * attribute). 8293 * 8294 */ 8295 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags) 8296 { 8297 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8298 *pTypeFlags=This->typeattr.wTypeFlags; 8299 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags); 8300 return S_OK; 8301 } 8302 8303 /* ITypeInfo2::GetFuncIndexOfMemId 8304 * Binds to a specific member based on a known DISPID, where the member name 8305 * is not known (for example, when binding to a default member). 8306 * 8307 */ 8308 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface, 8309 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex) 8310 { 8311 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8312 UINT fdc; 8313 HRESULT result; 8314 8315 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){ 8316 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc]; 8317 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind)) 8318 break; 8319 } 8320 if(fdc < This->typeattr.cFuncs) { 8321 *pFuncIndex = fdc; 8322 result = S_OK; 8323 } else 8324 result = TYPE_E_ELEMENTNOTFOUND; 8325 8326 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This, 8327 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED"); 8328 return result; 8329 } 8330 8331 /* TypeInfo2::GetVarIndexOfMemId 8332 * 8333 * Binds to a specific member based on a known DISPID, where the member name 8334 * is not known (for example, when binding to a default member). 8335 * 8336 */ 8337 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface, 8338 MEMBERID memid, UINT *pVarIndex) 8339 { 8340 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8341 TLBVarDesc *pVarInfo; 8342 8343 TRACE("%p %d %p\n", iface, memid, pVarIndex); 8344 8345 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid); 8346 if(!pVarInfo) 8347 return TYPE_E_ELEMENTNOTFOUND; 8348 8349 *pVarIndex = (pVarInfo - This->vardescs); 8350 8351 return S_OK; 8352 } 8353 8354 /* ITypeInfo2::GetCustData 8355 * 8356 * Gets the custom data 8357 */ 8358 static HRESULT WINAPI ITypeInfo2_fnGetCustData( 8359 ITypeInfo2 * iface, 8360 REFGUID guid, 8361 VARIANT *pVarVal) 8362 { 8363 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8364 TLBCustData *pCData; 8365 8366 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal); 8367 8368 if(!guid || !pVarVal) 8369 return E_INVALIDARG; 8370 8371 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid); 8372 8373 VariantInit( pVarVal); 8374 if (pCData) 8375 VariantCopy( pVarVal, &pCData->data); 8376 else 8377 VariantClear( pVarVal ); 8378 return S_OK; 8379 } 8380 8381 /* ITypeInfo2::GetFuncCustData 8382 * 8383 * Gets the custom data 8384 */ 8385 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( 8386 ITypeInfo2 * iface, 8387 UINT index, 8388 REFGUID guid, 8389 VARIANT *pVarVal) 8390 { 8391 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8392 TLBCustData *pCData; 8393 TLBFuncDesc *pFDesc = &This->funcdescs[index]; 8394 8395 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal); 8396 8397 if(index >= This->typeattr.cFuncs) 8398 return TYPE_E_ELEMENTNOTFOUND; 8399 8400 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid); 8401 if(!pCData) 8402 return TYPE_E_ELEMENTNOTFOUND; 8403 8404 VariantInit(pVarVal); 8405 VariantCopy(pVarVal, &pCData->data); 8406 8407 return S_OK; 8408 } 8409 8410 /* ITypeInfo2::GetParamCustData 8411 * 8412 * Gets the custom data 8413 */ 8414 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( 8415 ITypeInfo2 * iface, 8416 UINT indexFunc, 8417 UINT indexParam, 8418 REFGUID guid, 8419 VARIANT *pVarVal) 8420 { 8421 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8422 TLBCustData *pCData; 8423 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc]; 8424 8425 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam, 8426 debugstr_guid(guid), pVarVal); 8427 8428 if(indexFunc >= This->typeattr.cFuncs) 8429 return TYPE_E_ELEMENTNOTFOUND; 8430 8431 if(indexParam >= pFDesc->funcdesc.cParams) 8432 return TYPE_E_ELEMENTNOTFOUND; 8433 8434 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid); 8435 if(!pCData) 8436 return TYPE_E_ELEMENTNOTFOUND; 8437 8438 VariantInit(pVarVal); 8439 VariantCopy(pVarVal, &pCData->data); 8440 8441 return S_OK; 8442 } 8443 8444 /* ITypeInfo2::GetVarCustData 8445 * 8446 * Gets the custom data 8447 */ 8448 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( 8449 ITypeInfo2 * iface, 8450 UINT index, 8451 REFGUID guid, 8452 VARIANT *pVarVal) 8453 { 8454 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8455 TLBCustData *pCData; 8456 TLBVarDesc *pVDesc = &This->vardescs[index]; 8457 8458 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal); 8459 8460 if(index >= This->typeattr.cVars) 8461 return TYPE_E_ELEMENTNOTFOUND; 8462 8463 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid); 8464 if(!pCData) 8465 return TYPE_E_ELEMENTNOTFOUND; 8466 8467 VariantInit(pVarVal); 8468 VariantCopy(pVarVal, &pCData->data); 8469 8470 return S_OK; 8471 } 8472 8473 /* ITypeInfo2::GetImplCustData 8474 * 8475 * Gets the custom data 8476 */ 8477 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( 8478 ITypeInfo2 * iface, 8479 UINT index, 8480 REFGUID guid, 8481 VARIANT *pVarVal) 8482 { 8483 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8484 TLBCustData *pCData; 8485 TLBImplType *pRDesc = &This->impltypes[index]; 8486 8487 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal); 8488 8489 if(index >= This->typeattr.cImplTypes) 8490 return TYPE_E_ELEMENTNOTFOUND; 8491 8492 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid); 8493 if(!pCData) 8494 return TYPE_E_ELEMENTNOTFOUND; 8495 8496 VariantInit(pVarVal); 8497 VariantCopy(pVarVal, &pCData->data); 8498 8499 return S_OK; 8500 } 8501 8502 /* ITypeInfo2::GetDocumentation2 8503 * 8504 * Retrieves the documentation string, the complete Help file name and path, 8505 * the localization context to use, and the context ID for the library Help 8506 * topic in the Help file. 8507 * 8508 */ 8509 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( 8510 ITypeInfo2 * iface, 8511 MEMBERID memid, 8512 LCID lcid, 8513 BSTR *pbstrHelpString, 8514 DWORD *pdwHelpStringContext, 8515 BSTR *pbstrHelpStringDll) 8516 { 8517 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8518 const TLBFuncDesc *pFDesc; 8519 const TLBVarDesc *pVDesc; 8520 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) " 8521 "HelpStringContext(%p) HelpStringDll(%p)\n", 8522 This, memid, lcid, pbstrHelpString, pdwHelpStringContext, 8523 pbstrHelpStringDll ); 8524 /* the help string should be obtained from the helpstringdll, 8525 * using the _DLLGetDocumentation function, based on the supplied 8526 * lcid. Nice to do sometime... 8527 */ 8528 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */ 8529 if(pbstrHelpString) 8530 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name)); 8531 if(pdwHelpStringContext) 8532 *pdwHelpStringContext=This->dwHelpStringContext; 8533 if(pbstrHelpStringDll) 8534 *pbstrHelpStringDll= 8535 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */ 8536 return S_OK; 8537 }else {/* for a member */ 8538 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid); 8539 if(pFDesc){ 8540 if(pbstrHelpString) 8541 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString)); 8542 if(pdwHelpStringContext) 8543 *pdwHelpStringContext=pFDesc->HelpStringContext; 8544 if(pbstrHelpStringDll) 8545 *pbstrHelpStringDll= 8546 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */ 8547 return S_OK; 8548 } 8549 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid); 8550 if(pVDesc){ 8551 if(pbstrHelpString) 8552 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString)); 8553 if(pdwHelpStringContext) 8554 *pdwHelpStringContext=pVDesc->HelpStringContext; 8555 if(pbstrHelpStringDll) 8556 *pbstrHelpStringDll= 8557 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */ 8558 return S_OK; 8559 } 8560 } 8561 return TYPE_E_ELEMENTNOTFOUND; 8562 } 8563 8564 /* ITypeInfo2::GetAllCustData 8565 * 8566 * Gets all custom data items for the Type info. 8567 * 8568 */ 8569 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( 8570 ITypeInfo2 * iface, 8571 CUSTDATA *pCustData) 8572 { 8573 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8574 8575 TRACE("%p %p\n", This, pCustData); 8576 8577 return TLB_copy_all_custdata(This->pcustdata_list, pCustData); 8578 } 8579 8580 /* ITypeInfo2::GetAllFuncCustData 8581 * 8582 * Gets all custom data items for the specified Function 8583 * 8584 */ 8585 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( 8586 ITypeInfo2 * iface, 8587 UINT index, 8588 CUSTDATA *pCustData) 8589 { 8590 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8591 TLBFuncDesc *pFDesc = &This->funcdescs[index]; 8592 8593 TRACE("%p %u %p\n", This, index, pCustData); 8594 8595 if(index >= This->typeattr.cFuncs) 8596 return TYPE_E_ELEMENTNOTFOUND; 8597 8598 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData); 8599 } 8600 8601 /* ITypeInfo2::GetAllParamCustData 8602 * 8603 * Gets all custom data items for the Functions 8604 * 8605 */ 8606 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface, 8607 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData) 8608 { 8609 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8610 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc]; 8611 8612 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData); 8613 8614 if(indexFunc >= This->typeattr.cFuncs) 8615 return TYPE_E_ELEMENTNOTFOUND; 8616 8617 if(indexParam >= pFDesc->funcdesc.cParams) 8618 return TYPE_E_ELEMENTNOTFOUND; 8619 8620 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData); 8621 } 8622 8623 /* ITypeInfo2::GetAllVarCustData 8624 * 8625 * Gets all custom data items for the specified Variable 8626 * 8627 */ 8628 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface, 8629 UINT index, CUSTDATA *pCustData) 8630 { 8631 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8632 TLBVarDesc * pVDesc = &This->vardescs[index]; 8633 8634 TRACE("%p %u %p\n", This, index, pCustData); 8635 8636 if(index >= This->typeattr.cVars) 8637 return TYPE_E_ELEMENTNOTFOUND; 8638 8639 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData); 8640 } 8641 8642 /* ITypeInfo2::GetAllImplCustData 8643 * 8644 * Gets all custom data items for the specified implementation type 8645 * 8646 */ 8647 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( 8648 ITypeInfo2 * iface, 8649 UINT index, 8650 CUSTDATA *pCustData) 8651 { 8652 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface); 8653 TLBImplType *pRDesc = &This->impltypes[index]; 8654 8655 TRACE("%p %u %p\n", This, index, pCustData); 8656 8657 if(index >= This->typeattr.cImplTypes) 8658 return TYPE_E_ELEMENTNOTFOUND; 8659 8660 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData); 8661 } 8662 8663 static const ITypeInfo2Vtbl tinfvt = 8664 { 8665 8666 ITypeInfo_fnQueryInterface, 8667 ITypeInfo_fnAddRef, 8668 ITypeInfo_fnRelease, 8669 8670 ITypeInfo_fnGetTypeAttr, 8671 ITypeInfo_fnGetTypeComp, 8672 ITypeInfo_fnGetFuncDesc, 8673 ITypeInfo_fnGetVarDesc, 8674 ITypeInfo_fnGetNames, 8675 ITypeInfo_fnGetRefTypeOfImplType, 8676 ITypeInfo_fnGetImplTypeFlags, 8677 ITypeInfo_fnGetIDsOfNames, 8678 ITypeInfo_fnInvoke, 8679 ITypeInfo_fnGetDocumentation, 8680 ITypeInfo_fnGetDllEntry, 8681 ITypeInfo_fnGetRefTypeInfo, 8682 ITypeInfo_fnAddressOfMember, 8683 ITypeInfo_fnCreateInstance, 8684 ITypeInfo_fnGetMops, 8685 ITypeInfo_fnGetContainingTypeLib, 8686 ITypeInfo_fnReleaseTypeAttr, 8687 ITypeInfo_fnReleaseFuncDesc, 8688 ITypeInfo_fnReleaseVarDesc, 8689 8690 ITypeInfo2_fnGetTypeKind, 8691 ITypeInfo2_fnGetTypeFlags, 8692 ITypeInfo2_fnGetFuncIndexOfMemId, 8693 ITypeInfo2_fnGetVarIndexOfMemId, 8694 ITypeInfo2_fnGetCustData, 8695 ITypeInfo2_fnGetFuncCustData, 8696 ITypeInfo2_fnGetParamCustData, 8697 ITypeInfo2_fnGetVarCustData, 8698 ITypeInfo2_fnGetImplTypeCustData, 8699 ITypeInfo2_fnGetDocumentation2, 8700 ITypeInfo2_fnGetAllCustData, 8701 ITypeInfo2_fnGetAllFuncCustData, 8702 ITypeInfo2_fnGetAllParamCustData, 8703 ITypeInfo2_fnGetAllVarCustData, 8704 ITypeInfo2_fnGetAllImplTypeCustData, 8705 }; 8706 8707 /****************************************************************************** 8708 * CreateDispTypeInfo [OLEAUT32.31] 8709 * 8710 * Build type information for an object so it can be called through an 8711 * IDispatch interface. 8712 * 8713 * RETURNS 8714 * Success: S_OK. pptinfo contains the created ITypeInfo object. 8715 * Failure: E_INVALIDARG, if one or more arguments is invalid. 8716 * 8717 * NOTES 8718 * This call allows an objects methods to be accessed through IDispatch, by 8719 * building an ITypeInfo object that IDispatch can use to call through. 8720 */ 8721 HRESULT WINAPI CreateDispTypeInfo( 8722 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */ 8723 LCID lcid, /* [I] Locale Id */ 8724 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */ 8725 { 8726 ITypeInfoImpl *pTIClass, *pTIIface; 8727 ITypeLibImpl *pTypeLibImpl; 8728 unsigned int param, func; 8729 TLBFuncDesc *pFuncDesc; 8730 TLBRefType *ref; 8731 8732 TRACE("\n"); 8733 pTypeLibImpl = TypeLibImpl_Constructor(); 8734 if (!pTypeLibImpl) return E_FAIL; 8735 8736 pTypeLibImpl->TypeInfoCount = 2; 8737 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*)); 8738 8739 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor(); 8740 pTIIface->pTypeLib = pTypeLibImpl; 8741 pTIIface->index = 0; 8742 pTIIface->Name = NULL; 8743 pTIIface->dwHelpContext = -1; 8744 pTIIface->guid = NULL; 8745 pTIIface->typeattr.lcid = lcid; 8746 pTIIface->typeattr.typekind = TKIND_INTERFACE; 8747 pTIIface->typeattr.wMajorVerNum = 0; 8748 pTIIface->typeattr.wMinorVerNum = 0; 8749 pTIIface->typeattr.cbAlignment = 2; 8750 pTIIface->typeattr.cbSizeInstance = -1; 8751 pTIIface->typeattr.cbSizeVft = -1; 8752 pTIIface->typeattr.cFuncs = 0; 8753 pTIIface->typeattr.cImplTypes = 0; 8754 pTIIface->typeattr.cVars = 0; 8755 pTIIface->typeattr.wTypeFlags = 0; 8756 pTIIface->hreftype = 0; 8757 8758 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers); 8759 pFuncDesc = pTIIface->funcdescs; 8760 for(func = 0; func < pidata->cMembers; func++) { 8761 METHODDATA *md = pidata->pmethdata + func; 8762 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName); 8763 pFuncDesc->funcdesc.memid = md->dispid; 8764 pFuncDesc->funcdesc.lprgscode = NULL; 8765 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL; 8766 pFuncDesc->funcdesc.invkind = md->wFlags; 8767 pFuncDesc->funcdesc.callconv = md->cc; 8768 pFuncDesc->funcdesc.cParams = md->cArgs; 8769 pFuncDesc->funcdesc.cParamsOpt = 0; 8770 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *); 8771 pFuncDesc->funcdesc.cScodes = 0; 8772 pFuncDesc->funcdesc.wFuncFlags = 0; 8773 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn; 8774 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE; 8775 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL; 8776 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 8777 md->cArgs * sizeof(ELEMDESC)); 8778 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs); 8779 for(param = 0; param < md->cArgs; param++) { 8780 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt; 8781 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName); 8782 } 8783 pFuncDesc->helpcontext = 0; 8784 pFuncDesc->HelpStringContext = 0; 8785 pFuncDesc->HelpString = NULL; 8786 pFuncDesc->Entry = NULL; 8787 list_init(&pFuncDesc->custdata_list); 8788 pTIIface->typeattr.cFuncs++; 8789 ++pFuncDesc; 8790 } 8791 8792 dump_TypeInfo(pTIIface); 8793 8794 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor(); 8795 pTIClass->pTypeLib = pTypeLibImpl; 8796 pTIClass->index = 1; 8797 pTIClass->Name = NULL; 8798 pTIClass->dwHelpContext = -1; 8799 pTIClass->guid = NULL; 8800 pTIClass->typeattr.lcid = lcid; 8801 pTIClass->typeattr.typekind = TKIND_COCLASS; 8802 pTIClass->typeattr.wMajorVerNum = 0; 8803 pTIClass->typeattr.wMinorVerNum = 0; 8804 pTIClass->typeattr.cbAlignment = 2; 8805 pTIClass->typeattr.cbSizeInstance = -1; 8806 pTIClass->typeattr.cbSizeVft = -1; 8807 pTIClass->typeattr.cFuncs = 0; 8808 pTIClass->typeattr.cImplTypes = 1; 8809 pTIClass->typeattr.cVars = 0; 8810 pTIClass->typeattr.wTypeFlags = 0; 8811 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase); 8812 8813 pTIClass->impltypes = TLBImplType_Alloc(1); 8814 8815 ref = heap_alloc_zero(sizeof(*ref)); 8816 ref->pImpTLInfo = TLB_REF_INTERNAL; 8817 list_add_head(&pTypeLibImpl->ref_list, &ref->entry); 8818 8819 dump_TypeInfo(pTIClass); 8820 8821 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface; 8822 8823 ITypeInfo_AddRef(*pptinfo); 8824 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface); 8825 8826 return S_OK; 8827 8828 } 8829 8830 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv) 8831 { 8832 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 8833 8834 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv); 8835 } 8836 8837 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface) 8838 { 8839 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 8840 8841 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface); 8842 } 8843 8844 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface) 8845 { 8846 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 8847 8848 return ITypeInfo2_Release(&This->ITypeInfo2_iface); 8849 } 8850 8851 static HRESULT WINAPI ITypeComp_fnBind( 8852 ITypeComp * iface, 8853 OLECHAR * szName, 8854 ULONG lHash, 8855 WORD wFlags, 8856 ITypeInfo ** ppTInfo, 8857 DESCKIND * pDescKind, 8858 BINDPTR * pBindPtr) 8859 { 8860 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 8861 const TLBFuncDesc *pFDesc; 8862 const TLBVarDesc *pVDesc; 8863 HRESULT hr = DISP_E_MEMBERNOTFOUND; 8864 UINT fdc; 8865 8866 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 8867 8868 *pDescKind = DESCKIND_NONE; 8869 pBindPtr->lpfuncdesc = NULL; 8870 *ppTInfo = NULL; 8871 8872 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){ 8873 pFDesc = &This->funcdescs[fdc]; 8874 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) { 8875 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags)) 8876 break; 8877 else 8878 /* name found, but wrong flags */ 8879 hr = TYPE_E_TYPEMISMATCH; 8880 } 8881 } 8882 8883 if (fdc < This->typeattr.cFuncs) 8884 { 8885 HRESULT hr = TLB_AllocAndInitFuncDesc( 8886 &pFDesc->funcdesc, 8887 &pBindPtr->lpfuncdesc, 8888 This->typeattr.typekind == TKIND_DISPATCH); 8889 if (FAILED(hr)) 8890 return hr; 8891 *pDescKind = DESCKIND_FUNCDESC; 8892 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface; 8893 ITypeInfo_AddRef(*ppTInfo); 8894 return S_OK; 8895 } else { 8896 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName); 8897 if(pVDesc){ 8898 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc); 8899 if (FAILED(hr)) 8900 return hr; 8901 *pDescKind = DESCKIND_VARDESC; 8902 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface; 8903 ITypeInfo_AddRef(*ppTInfo); 8904 return S_OK; 8905 } 8906 } 8907 8908 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) { 8909 /* recursive search */ 8910 ITypeInfo *pTInfo; 8911 ITypeComp *pTComp; 8912 HRESULT hr; 8913 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo); 8914 if (SUCCEEDED(hr)) 8915 { 8916 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp); 8917 ITypeInfo_Release(pTInfo); 8918 } 8919 if (SUCCEEDED(hr)) 8920 { 8921 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 8922 ITypeComp_Release(pTComp); 8923 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC && 8924 This->typeattr.typekind == TKIND_DISPATCH) 8925 { 8926 FUNCDESC *tmp = pBindPtr->lpfuncdesc; 8927 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE); 8928 SysFreeString((BSTR)tmp); 8929 } 8930 return hr; 8931 } 8932 WARN("Could not search inherited interface!\n"); 8933 } 8934 if (hr == DISP_E_MEMBERNOTFOUND) 8935 hr = S_OK; 8936 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags); 8937 return hr; 8938 } 8939 8940 static HRESULT WINAPI ITypeComp_fnBindType( 8941 ITypeComp * iface, 8942 OLECHAR * szName, 8943 ULONG lHash, 8944 ITypeInfo ** ppTInfo, 8945 ITypeComp ** ppTComp) 8946 { 8947 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp); 8948 8949 /* strange behaviour (does nothing) but like the 8950 * original */ 8951 8952 if (!ppTInfo || !ppTComp) 8953 return E_POINTER; 8954 8955 *ppTInfo = NULL; 8956 *ppTComp = NULL; 8957 8958 return S_OK; 8959 } 8960 8961 static const ITypeCompVtbl tcompvt = 8962 { 8963 8964 ITypeComp_fnQueryInterface, 8965 ITypeComp_fnAddRef, 8966 ITypeComp_fnRelease, 8967 8968 ITypeComp_fnBind, 8969 ITypeComp_fnBindType 8970 }; 8971 8972 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile, 8973 ICreateTypeLib2** ppctlib) 8974 { 8975 ITypeLibImpl *This; 8976 HRESULT hres; 8977 8978 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib); 8979 8980 if (!szFile) return E_INVALIDARG; 8981 8982 This = TypeLibImpl_Constructor(); 8983 if (!This) 8984 return E_OUTOFMEMORY; 8985 8986 This->lcid = GetSystemDefaultLCID(); 8987 This->syskind = syskind; 8988 This->ptr_size = get_ptr_size(syskind); 8989 8990 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR)); 8991 if (!This->path) { 8992 ITypeLib2_Release(&This->ITypeLib2_iface); 8993 return E_OUTOFMEMORY; 8994 } 8995 lstrcpyW(This->path, szFile); 8996 8997 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib); 8998 ITypeLib2_Release(&This->ITypeLib2_iface); 8999 return hres; 9000 } 9001 9002 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface, 9003 REFIID riid, void **object) 9004 { 9005 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9006 9007 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object); 9008 } 9009 9010 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface) 9011 { 9012 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9013 9014 return ITypeLib2_AddRef(&This->ITypeLib2_iface); 9015 } 9016 9017 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface) 9018 { 9019 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9020 9021 return ITypeLib2_Release(&This->ITypeLib2_iface); 9022 } 9023 9024 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface, 9025 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo) 9026 { 9027 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9028 ITypeInfoImpl *info; 9029 HRESULT hres; 9030 9031 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo); 9032 9033 if (!ctinfo || !name) 9034 return E_INVALIDARG; 9035 9036 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name); 9037 if (info) 9038 return TYPE_E_NAMECONFLICT; 9039 9040 if (This->typeinfos) 9041 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos, 9042 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1)); 9043 else 9044 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*)); 9045 9046 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor(); 9047 9048 info->pTypeLib = This; 9049 info->Name = TLB_append_str(&This->name_list, name); 9050 info->index = This->TypeInfoCount; 9051 info->typeattr.typekind = kind; 9052 info->typeattr.cbAlignment = 4; 9053 9054 switch (info->typeattr.typekind) { 9055 case TKIND_ENUM: 9056 case TKIND_INTERFACE: 9057 case TKIND_DISPATCH: 9058 case TKIND_COCLASS: 9059 info->typeattr.cbSizeInstance = This->ptr_size; 9060 break; 9061 case TKIND_RECORD: 9062 case TKIND_UNION: 9063 info->typeattr.cbSizeInstance = 0; 9064 break; 9065 case TKIND_MODULE: 9066 info->typeattr.cbSizeInstance = 2; 9067 break; 9068 case TKIND_ALIAS: 9069 info->typeattr.cbSizeInstance = -0x75; 9070 break; 9071 default: 9072 FIXME("unrecognized typekind %d\n", info->typeattr.typekind); 9073 info->typeattr.cbSizeInstance = 0xdeadbeef; 9074 break; 9075 } 9076 9077 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface, 9078 &IID_ICreateTypeInfo, (void **)ctinfo); 9079 if (FAILED(hres)) { 9080 ITypeInfo2_Release(&info->ITypeInfo2_iface); 9081 return hres; 9082 } 9083 9084 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase); 9085 9086 ++This->TypeInfoCount; 9087 9088 return S_OK; 9089 } 9090 9091 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface, 9092 LPOLESTR name) 9093 { 9094 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9095 9096 TRACE("%p %s\n", This, wine_dbgstr_w(name)); 9097 9098 if (!name) 9099 return E_INVALIDARG; 9100 9101 This->Name = TLB_append_str(&This->name_list, name); 9102 9103 return S_OK; 9104 } 9105 9106 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface, 9107 WORD majorVerNum, WORD minorVerNum) 9108 { 9109 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9110 9111 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum); 9112 9113 This->ver_major = majorVerNum; 9114 This->ver_minor = minorVerNum; 9115 9116 return S_OK; 9117 } 9118 9119 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface, 9120 REFGUID guid) 9121 { 9122 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9123 9124 TRACE("%p %s\n", This, debugstr_guid(guid)); 9125 9126 This->guid = TLB_append_guid(&This->guid_list, guid, -2); 9127 9128 return S_OK; 9129 } 9130 9131 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface, 9132 LPOLESTR doc) 9133 { 9134 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9135 9136 TRACE("%p %s\n", This, wine_dbgstr_w(doc)); 9137 9138 if (!doc) 9139 return E_INVALIDARG; 9140 9141 This->DocString = TLB_append_str(&This->string_list, doc); 9142 9143 return S_OK; 9144 } 9145 9146 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface, 9147 LPOLESTR helpFileName) 9148 { 9149 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9150 9151 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName)); 9152 9153 if (!helpFileName) 9154 return E_INVALIDARG; 9155 9156 This->HelpFile = TLB_append_str(&This->string_list, helpFileName); 9157 9158 return S_OK; 9159 } 9160 9161 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface, 9162 DWORD helpContext) 9163 { 9164 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9165 9166 TRACE("%p %d\n", This, helpContext); 9167 9168 This->dwHelpContext = helpContext; 9169 9170 return S_OK; 9171 } 9172 9173 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface, 9174 LCID lcid) 9175 { 9176 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9177 9178 TRACE("%p %x\n", This, lcid); 9179 9180 This->set_lcid = lcid; 9181 9182 return S_OK; 9183 } 9184 9185 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface, 9186 UINT libFlags) 9187 { 9188 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 9189 9190 TRACE("%p %x\n", This, libFlags); 9191 9192 This->libflags = libFlags; 9193 9194 return S_OK; 9195 } 9196 9197 typedef struct tagWMSFT_SegContents { 9198 DWORD len; 9199 void *data; 9200 } WMSFT_SegContents; 9201 9202 typedef struct tagWMSFT_TLBFile { 9203 MSFT_Header header; 9204 WMSFT_SegContents typeinfo_seg; 9205 WMSFT_SegContents impfile_seg; 9206 WMSFT_SegContents impinfo_seg; 9207 WMSFT_SegContents ref_seg; 9208 WMSFT_SegContents guidhash_seg; 9209 WMSFT_SegContents guid_seg; 9210 WMSFT_SegContents namehash_seg; 9211 WMSFT_SegContents name_seg; 9212 WMSFT_SegContents string_seg; 9213 WMSFT_SegContents typdesc_seg; 9214 WMSFT_SegContents arraydesc_seg; 9215 WMSFT_SegContents custdata_seg; 9216 WMSFT_SegContents cdguids_seg; 9217 MSFT_SegDir segdir; 9218 WMSFT_SegContents aux_seg; 9219 } WMSFT_TLBFile; 9220 9221 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This, 9222 WMSFT_TLBFile *file) 9223 { 9224 TLBString *str; 9225 UINT last_offs; 9226 char *data; 9227 9228 file->string_seg.len = 0; 9229 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) { 9230 int size; 9231 9232 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL); 9233 if (size == 0) 9234 return E_UNEXPECTED; 9235 9236 size += sizeof(INT16); 9237 if (size % 4) 9238 size = (size + 4) & ~0x3; 9239 if (size < 8) 9240 size = 8; 9241 9242 file->string_seg.len += size; 9243 9244 /* temporarily use str->offset to store the length of the aligned, 9245 * converted string */ 9246 str->offset = size; 9247 } 9248 9249 file->string_seg.data = data = heap_alloc(file->string_seg.len); 9250 9251 last_offs = 0; 9252 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) { 9253 int size; 9254 9255 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), 9256 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL); 9257 if (size == 0) { 9258 heap_free(file->string_seg.data); 9259 return E_UNEXPECTED; 9260 } 9261 9262 *((INT16*)data) = size; 9263 9264 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16)); 9265 9266 size = str->offset; 9267 data += size; 9268 str->offset = last_offs; 9269 last_offs += size; 9270 } 9271 9272 return S_OK; 9273 } 9274 9275 static HRESULT WMSFT_compile_names(ITypeLibImpl *This, 9276 WMSFT_TLBFile *file) 9277 { 9278 TLBString *str; 9279 UINT last_offs; 9280 char *data; 9281 MSFT_NameIntro *last_intro = NULL; 9282 9283 file->header.nametablecount = 0; 9284 file->header.nametablechars = 0; 9285 9286 file->name_seg.len = 0; 9287 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) { 9288 int size; 9289 9290 size = strlenW(str->str); 9291 file->header.nametablechars += size; 9292 file->header.nametablecount++; 9293 9294 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL); 9295 if (size == 0) 9296 return E_UNEXPECTED; 9297 9298 size += sizeof(MSFT_NameIntro); 9299 if (size % 4) 9300 size = (size + 4) & ~0x3; 9301 if (size < 8) 9302 size = 8; 9303 9304 file->name_seg.len += size; 9305 9306 /* temporarily use str->offset to store the length of the aligned, 9307 * converted string */ 9308 str->offset = size; 9309 } 9310 9311 /* Allocate bigger buffer so we can temporarily NULL terminate the name */ 9312 file->name_seg.data = data = heap_alloc(file->name_seg.len+1); 9313 9314 last_offs = 0; 9315 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) { 9316 int size, hash; 9317 MSFT_NameIntro *intro = (MSFT_NameIntro*)data; 9318 9319 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), 9320 data + sizeof(MSFT_NameIntro), 9321 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL); 9322 if (size == 0) { 9323 heap_free(file->name_seg.data); 9324 return E_UNEXPECTED; 9325 } 9326 data[sizeof(MSFT_NameIntro) + size] = '\0'; 9327 9328 intro->hreftype = -1; /* TODO? */ 9329 intro->namelen = size & 0xFF; 9330 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */ 9331 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro)); 9332 intro->namelen |= hash << 16; 9333 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f]; 9334 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs; 9335 9336 memset(data + sizeof(MSFT_NameIntro) + size, 0x57, 9337 str->offset - size - sizeof(MSFT_NameIntro)); 9338 9339 /* update str->offset to actual value to use in other 9340 * compilation functions that require positions within 9341 * the string table */ 9342 last_intro = intro; 9343 size = str->offset; 9344 data += size; 9345 str->offset = last_offs; 9346 last_offs += size; 9347 } 9348 9349 if(last_intro) 9350 last_intro->hreftype = 0; /* last one is 0? */ 9351 9352 return S_OK; 9353 } 9354 9355 static inline int hash_guid(GUID *guid) 9356 { 9357 int i, hash = 0; 9358 9359 for (i = 0; i < 8; i ++) 9360 hash ^= ((const short *)guid)[i]; 9361 9362 return hash & 0x1f; 9363 } 9364 9365 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file) 9366 { 9367 TLBGuid *guid; 9368 MSFT_GuidEntry *entry; 9369 DWORD offs; 9370 int hash_key, *guidhashtab; 9371 9372 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list); 9373 file->guid_seg.data = heap_alloc(file->guid_seg.len); 9374 9375 entry = file->guid_seg.data; 9376 offs = 0; 9377 guidhashtab = file->guidhash_seg.data; 9378 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){ 9379 memcpy(&entry->guid, &guid->guid, sizeof(GUID)); 9380 entry->hreftype = guid->hreftype; 9381 9382 hash_key = hash_guid(&guid->guid); 9383 entry->next_hash = guidhashtab[hash_key]; 9384 guidhashtab[hash_key] = offs; 9385 9386 guid->offset = offs; 9387 offs += sizeof(MSFT_GuidEntry); 9388 ++entry; 9389 } 9390 9391 return S_OK; 9392 } 9393 9394 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file) 9395 { 9396 VARIANT v = *value; 9397 VARTYPE arg_type = V_VT(value); 9398 int mask = 0; 9399 HRESULT hres; 9400 DWORD ret = file->custdata_seg.len; 9401 9402 if(arg_type == VT_INT) 9403 arg_type = VT_I4; 9404 if(arg_type == VT_UINT) 9405 arg_type = VT_UI4; 9406 9407 v = *value; 9408 if(V_VT(value) != arg_type) { 9409 hres = VariantChangeType(&v, value, 0, arg_type); 9410 if(FAILED(hres)){ 9411 ERR("VariantChangeType failed: %08x\n", hres); 9412 return -1; 9413 } 9414 } 9415 9416 /* Check if default value can be stored in-place */ 9417 switch(arg_type){ 9418 case VT_I4: 9419 case VT_UI4: 9420 mask = 0x3ffffff; 9421 if(V_UI4(&v) > 0x3ffffff) 9422 break; 9423 /* fall through */ 9424 case VT_I1: 9425 case VT_UI1: 9426 case VT_BOOL: 9427 if(!mask) 9428 mask = 0xff; 9429 /* fall through */ 9430 case VT_I2: 9431 case VT_UI2: 9432 if(!mask) 9433 mask = 0xffff; 9434 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask); 9435 } 9436 9437 /* have to allocate space in custdata_seg */ 9438 switch(arg_type) { 9439 case VT_I4: 9440 case VT_R4: 9441 case VT_UI4: 9442 case VT_INT: 9443 case VT_UINT: 9444 case VT_HRESULT: 9445 case VT_PTR: { 9446 /* Construct the data to be allocated */ 9447 int *data; 9448 9449 if(file->custdata_seg.data){ 9450 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2); 9451 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len); 9452 file->custdata_seg.len += sizeof(int) * 2; 9453 }else{ 9454 file->custdata_seg.len = sizeof(int) * 2; 9455 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len); 9456 } 9457 9458 data[0] = V_VT(value) + (V_UI4(&v) << 16); 9459 data[1] = (V_UI4(&v) >> 16) + 0x57570000; 9460 9461 /* TODO: Check if the encoded data is already present in custdata_seg */ 9462 9463 return ret; 9464 } 9465 9466 case VT_BSTR: { 9467 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3; 9468 char *data; 9469 9470 if(file->custdata_seg.data){ 9471 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len); 9472 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len; 9473 file->custdata_seg.len += len; 9474 }else{ 9475 file->custdata_seg.len = len; 9476 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len); 9477 } 9478 9479 *((unsigned short *)data) = V_VT(value); 9480 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v)); 9481 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) { 9482 if(V_BSTR(&v)[i] <= 0x7f) 9483 data[i+6] = V_BSTR(&v)[i]; 9484 else 9485 data[i+6] = '?'; 9486 } 9487 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL); 9488 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++) 9489 data[i] = 0x57; 9490 9491 /* TODO: Check if the encoded data is already present in custdata_seg */ 9492 9493 return ret; 9494 } 9495 default: 9496 FIXME("Argument type not yet handled\n"); 9497 return -1; 9498 } 9499 } 9500 9501 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size); 9502 9503 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file) 9504 { 9505 DWORD offs = file->arraydesc_seg.len; 9506 DWORD *encoded; 9507 USHORT i; 9508 9509 /* TODO: we should check for duplicates, but that's harder because each 9510 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC 9511 * at the library-level) */ 9512 9513 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD); 9514 if(!file->arraydesc_seg.data) 9515 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len); 9516 else 9517 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len); 9518 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs); 9519 9520 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL); 9521 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16); 9522 for(i = 0; i < desc->cDims; ++i){ 9523 encoded[2 + i * 2] = desc->rgbounds[i].cElements; 9524 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound; 9525 } 9526 9527 return offs; 9528 } 9529 9530 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size) 9531 { 9532 DWORD junk; 9533 INT16 junk2; 9534 DWORD offs = 0; 9535 DWORD encoded[2]; 9536 VARTYPE vt, subtype; 9537 char *data; 9538 9539 if(!desc) 9540 return -1; 9541 9542 if(!out_mix) 9543 out_mix = &junk; 9544 if(!out_size) 9545 out_size = &junk2; 9546 9547 vt = desc->vt & VT_TYPEMASK; 9548 9549 if(vt == VT_PTR || vt == VT_SAFEARRAY){ 9550 DWORD mix; 9551 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size); 9552 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16); 9553 *out_mix = 0x7FFF; 9554 *out_size += 2 * sizeof(DWORD); 9555 }else if(vt == VT_CARRAY){ 9556 encoded[0] = desc->vt | (0x7FFE << 16); 9557 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file); 9558 *out_mix = 0x7FFE; 9559 }else if(vt == VT_USERDEFINED){ 9560 encoded[0] = desc->vt | (0x7FFF << 16); 9561 encoded[1] = desc->u.hreftype; 9562 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */ 9563 }else{ 9564 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt); 9565 9566 switch(vt){ 9567 case VT_INT: 9568 subtype = VT_I4; 9569 break; 9570 case VT_UINT: 9571 subtype = VT_UI4; 9572 break; 9573 case VT_VOID: 9574 subtype = VT_EMPTY; 9575 break; 9576 default: 9577 subtype = vt; 9578 break; 9579 } 9580 9581 *out_mix = subtype; 9582 return 0x80000000 | (subtype << 16) | desc->vt; 9583 } 9584 9585 data = file->typdesc_seg.data; 9586 while(offs < file->typdesc_seg.len){ 9587 if(!memcmp(&data[offs], encoded, sizeof(encoded))) 9588 return offs; 9589 offs += sizeof(encoded); 9590 } 9591 9592 file->typdesc_seg.len += sizeof(encoded); 9593 if(!file->typdesc_seg.data) 9594 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len); 9595 else 9596 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len); 9597 9598 memcpy(&data[offs], encoded, sizeof(encoded)); 9599 9600 return offs; 9601 } 9602 9603 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file) 9604 { 9605 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg; 9606 DWORD ret = cdguids_seg->len, offs; 9607 MSFT_CDGuid *cdguid; 9608 TLBCustData *cd; 9609 9610 if(list_empty(custdata_list)) 9611 return -1; 9612 9613 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list); 9614 if(!cdguids_seg->data){ 9615 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len); 9616 }else { 9617 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len); 9618 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret); 9619 } 9620 9621 offs = ret + sizeof(MSFT_CDGuid); 9622 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){ 9623 cdguid->GuidOffset = cd->guid->offset; 9624 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file); 9625 cdguid->next = offs; 9626 offs += sizeof(MSFT_CDGuid); 9627 ++cdguid; 9628 } 9629 9630 --cdguid; 9631 cdguid->next = -1; 9632 9633 return ret; 9634 } 9635 9636 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info, 9637 WMSFT_TLBFile *file) 9638 { 9639 WMSFT_SegContents *aux_seg = &file->aux_seg; 9640 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0; 9641 MSFT_VarRecord *varrecord; 9642 MSFT_FuncRecord *funcrecord; 9643 MEMBERID *memid; 9644 DWORD *name, *offsets, offs; 9645 9646 for(i = 0; i < info->typeattr.cFuncs; ++i){ 9647 TLBFuncDesc *desc = &info->funcdescs[i]; 9648 9649 recorded_size += 6 * sizeof(INT); /* mandatory fields */ 9650 9651 /* optional fields */ 9652 /* TODO: oArgCustData - FuncSetCustData not impl yet */ 9653 if(!list_empty(&desc->custdata_list)) 9654 recorded_size += 7 * sizeof(INT); 9655 else if(desc->HelpStringContext != 0) 9656 recorded_size += 6 * sizeof(INT); 9657 /* res9? resA? */ 9658 else if(desc->Entry) 9659 recorded_size += 3 * sizeof(INT); 9660 else if(desc->HelpString) 9661 recorded_size += 2 * sizeof(INT); 9662 else if(desc->helpcontext) 9663 recorded_size += sizeof(INT); 9664 9665 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo); 9666 9667 for(j = 0; j < desc->funcdesc.cParams; ++j){ 9668 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){ 9669 recorded_size += desc->funcdesc.cParams * sizeof(INT); 9670 break; 9671 } 9672 } 9673 9674 extra_size += 2 * sizeof(INT); /* memberid, name offs */ 9675 } 9676 9677 for(i = 0; i < info->typeattr.cVars; ++i){ 9678 TLBVarDesc *desc = &info->vardescs[i]; 9679 9680 recorded_size += 5 * sizeof(INT); /* mandatory fields */ 9681 9682 /* optional fields */ 9683 if(desc->HelpStringContext != 0) 9684 recorded_size += 5 * sizeof(INT); 9685 else if(!list_empty(&desc->custdata_list)) 9686 recorded_size += 4 * sizeof(INT); 9687 /* res9? */ 9688 else if(desc->HelpString) 9689 recorded_size += 2 * sizeof(INT); 9690 else if(desc->HelpContext != 0) 9691 recorded_size += sizeof(INT); 9692 9693 extra_size += 2 * sizeof(INT); /* memberid, name offs */ 9694 } 9695 9696 if(!recorded_size && !extra_size) 9697 return ret; 9698 9699 extra_size += sizeof(INT); /* total aux size for this typeinfo */ 9700 9701 aux_seg->len += recorded_size + extra_size; 9702 9703 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */ 9704 9705 if(aux_seg->data) 9706 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len); 9707 else 9708 aux_seg->data = heap_alloc(aux_seg->len); 9709 9710 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size; 9711 9712 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size); 9713 offs = 0; 9714 9715 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT)); 9716 for(i = 0; i < info->typeattr.cFuncs; ++i){ 9717 TLBFuncDesc *desc = &info->funcdescs[i]; 9718 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault; 9719 9720 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC); 9721 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize); 9722 funcrecord->Flags = desc->funcdesc.wFuncFlags; 9723 funcrecord->VtableOffset = desc->funcdesc.oVft; 9724 9725 /* FKCCIC: 9726 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX 9727 * ^^^funckind 9728 * ^^^ ^invkind 9729 * ^has_cust_data 9730 * ^^^^callconv 9731 * ^has_param_defaults 9732 * ^oEntry_is_intresource 9733 */ 9734 funcrecord->FKCCIC = 9735 desc->funcdesc.funckind | 9736 (desc->funcdesc.invkind << 3) | 9737 (list_empty(&desc->custdata_list) ? 0 : 0x80) | 9738 (desc->funcdesc.callconv << 8); 9739 9740 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry)) 9741 funcrecord->FKCCIC |= 0x2000; 9742 9743 for(j = 0; j < desc->funcdesc.cParams; ++j){ 9744 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){ 9745 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams; 9746 funcrecord->funcdescsize += sizeof(PARAMDESCEX); 9747 } 9748 } 9749 if(paramdefault_size > 0) 9750 funcrecord->FKCCIC |= 0x1000; 9751 9752 funcrecord->nrargs = desc->funcdesc.cParams; 9753 funcrecord->nroargs = desc->funcdesc.cParamsOpt; 9754 9755 /* optional fields */ 9756 /* res9? resA? */ 9757 if(!list_empty(&desc->custdata_list)){ 9758 size += 7 * sizeof(INT); 9759 funcrecord->HelpContext = desc->helpcontext; 9760 if(desc->HelpString) 9761 funcrecord->oHelpString = desc->HelpString->offset; 9762 else 9763 funcrecord->oHelpString = -1; 9764 if(!desc->Entry) 9765 funcrecord->oEntry = -1; 9766 else if(IS_INTRESOURCE(desc->Entry)) 9767 funcrecord->oEntry = LOWORD(desc->Entry); 9768 else 9769 funcrecord->oEntry = desc->Entry->offset; 9770 funcrecord->res9 = -1; 9771 funcrecord->resA = -1; 9772 funcrecord->HelpStringContext = desc->HelpStringContext; 9773 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file); 9774 }else if(desc->HelpStringContext != 0){ 9775 size += 6 * sizeof(INT); 9776 funcrecord->HelpContext = desc->helpcontext; 9777 if(desc->HelpString) 9778 funcrecord->oHelpString = desc->HelpString->offset; 9779 else 9780 funcrecord->oHelpString = -1; 9781 if(!desc->Entry) 9782 funcrecord->oEntry = -1; 9783 else if(IS_INTRESOURCE(desc->Entry)) 9784 funcrecord->oEntry = LOWORD(desc->Entry); 9785 else 9786 funcrecord->oEntry = desc->Entry->offset; 9787 funcrecord->res9 = -1; 9788 funcrecord->resA = -1; 9789 funcrecord->HelpStringContext = desc->HelpStringContext; 9790 }else if(desc->Entry){ 9791 size += 3 * sizeof(INT); 9792 funcrecord->HelpContext = desc->helpcontext; 9793 if(desc->HelpString) 9794 funcrecord->oHelpString = desc->HelpString->offset; 9795 else 9796 funcrecord->oHelpString = -1; 9797 if(!desc->Entry) 9798 funcrecord->oEntry = -1; 9799 else if(IS_INTRESOURCE(desc->Entry)) 9800 funcrecord->oEntry = LOWORD(desc->Entry); 9801 else 9802 funcrecord->oEntry = desc->Entry->offset; 9803 }else if(desc->HelpString){ 9804 size += 2 * sizeof(INT); 9805 funcrecord->HelpContext = desc->helpcontext; 9806 funcrecord->oHelpString = desc->HelpString->offset; 9807 }else if(desc->helpcontext){ 9808 size += sizeof(INT); 9809 funcrecord->HelpContext = desc->helpcontext; 9810 } 9811 9812 paramdefault = (DWORD*)((char *)funcrecord + size); 9813 size += paramdefault_size; 9814 9815 for(j = 0; j < desc->funcdesc.cParams; ++j){ 9816 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size); 9817 9818 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize); 9819 if(desc->pParamDesc[j].Name) 9820 info->oName = desc->pParamDesc[j].Name->offset; 9821 else 9822 info->oName = -1; 9823 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags; 9824 9825 if(paramdefault_size){ 9826 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 9827 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file); 9828 else if(paramdefault_size) 9829 *paramdefault = -1; 9830 ++paramdefault; 9831 } 9832 9833 size += sizeof(MSFT_ParameterInfo); 9834 } 9835 9836 funcrecord->Info = size | (i << 16); /* is it just the index? */ 9837 9838 *offsets = offs; 9839 offs += size; 9840 ++offsets; 9841 9842 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size); 9843 } 9844 9845 varrecord = (MSFT_VarRecord*)funcrecord; 9846 for(i = 0; i < info->typeattr.cVars; ++i){ 9847 TLBVarDesc *desc = &info->vardescs[i]; 9848 DWORD size = 5 * sizeof(INT); 9849 9850 varrecord->vardescsize = sizeof(desc->vardesc); 9851 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize); 9852 varrecord->Flags = desc->vardesc.wVarFlags; 9853 varrecord->VarKind = desc->vardesc.varkind; 9854 9855 if(desc->vardesc.varkind == VAR_CONST){ 9856 varrecord->vardescsize += sizeof(VARIANT); 9857 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file); 9858 }else 9859 varrecord->OffsValue = desc->vardesc.u.oInst; 9860 9861 /* res9? */ 9862 if(desc->HelpStringContext != 0){ 9863 size += 5 * sizeof(INT); 9864 varrecord->HelpContext = desc->HelpContext; 9865 if(desc->HelpString) 9866 varrecord->HelpString = desc->HelpString->offset; 9867 else 9868 varrecord->HelpString = -1; 9869 varrecord->res9 = -1; 9870 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file); 9871 varrecord->HelpStringContext = desc->HelpStringContext; 9872 }else if(!list_empty(&desc->custdata_list)){ 9873 size += 4 * sizeof(INT); 9874 varrecord->HelpContext = desc->HelpContext; 9875 if(desc->HelpString) 9876 varrecord->HelpString = desc->HelpString->offset; 9877 else 9878 varrecord->HelpString = -1; 9879 varrecord->res9 = -1; 9880 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file); 9881 }else if(desc->HelpString){ 9882 size += 2 * sizeof(INT); 9883 varrecord->HelpContext = desc->HelpContext; 9884 if(desc->HelpString) 9885 varrecord->HelpString = desc->HelpString->offset; 9886 else 9887 varrecord->HelpString = -1; 9888 }else if(desc->HelpContext != 0){ 9889 size += sizeof(INT); 9890 varrecord->HelpContext = desc->HelpContext; 9891 } 9892 9893 varrecord->Info = size | (i << 16); 9894 9895 *offsets = offs; 9896 offs += size; 9897 ++offsets; 9898 9899 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size); 9900 } 9901 9902 memid = (MEMBERID*)varrecord; 9903 for(i = 0; i < info->typeattr.cFuncs; ++i){ 9904 TLBFuncDesc *desc = &info->funcdescs[i]; 9905 *memid = desc->funcdesc.memid; 9906 ++memid; 9907 } 9908 for(i = 0; i < info->typeattr.cVars; ++i){ 9909 TLBVarDesc *desc = &info->vardescs[i]; 9910 *memid = desc->vardesc.memid; 9911 ++memid; 9912 } 9913 9914 name = (UINT*)memid; 9915 for(i = 0; i < info->typeattr.cFuncs; ++i){ 9916 TLBFuncDesc *desc = &info->funcdescs[i]; 9917 if(desc->Name) 9918 *name = desc->Name->offset; 9919 else 9920 *name = -1; 9921 ++name; 9922 } 9923 for(i = 0; i < info->typeattr.cVars; ++i){ 9924 TLBVarDesc *desc = &info->vardescs[i]; 9925 if(desc->Name) 9926 *name = desc->Name->offset; 9927 else 9928 *name = -1; 9929 ++name; 9930 } 9931 9932 return ret; 9933 } 9934 9935 typedef struct tagWMSFT_RefChunk { 9936 DWORD href; 9937 DWORD res04; 9938 DWORD res08; 9939 DWORD next; 9940 } WMSFT_RefChunk; 9941 9942 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file) 9943 { 9944 DWORD offs = file->ref_seg.len, i; 9945 WMSFT_RefChunk *chunk; 9946 9947 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk); 9948 if(!file->ref_seg.data) 9949 file->ref_seg.data = heap_alloc(file->ref_seg.len); 9950 else 9951 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len); 9952 9953 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs); 9954 9955 for(i = 0; i < info->typeattr.cImplTypes; ++i){ 9956 chunk->href = info->impltypes[i].hRef; 9957 chunk->res04 = info->impltypes[i].implflags; 9958 chunk->res08 = -1; 9959 if(i < info->typeattr.cImplTypes - 1) 9960 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1); 9961 else 9962 chunk->next = -1; 9963 ++chunk; 9964 } 9965 9966 return offs; 9967 } 9968 9969 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data) 9970 { 9971 DWORD size; 9972 9973 size = sizeof(MSFT_TypeInfoBase); 9974 9975 if(data){ 9976 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data; 9977 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL) 9978 base->typekind = TKIND_DISPATCH; 9979 else 9980 base->typekind = info->typeattr.typekind; 9981 base->typekind |= index << 16; /* TODO: There are some other flags here */ 9982 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6); 9983 base->memoffset = WMSFT_compile_typeinfo_aux(info, file); 9984 base->res2 = 0; 9985 base->res3 = 0; 9986 base->res4 = 3; 9987 base->res5 = 0; 9988 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs; 9989 base->res7 = 0; 9990 base->res8 = 0; 9991 base->res9 = 0; 9992 base->resA = 0; 9993 if(info->guid) 9994 base->posguid = info->guid->offset; 9995 else 9996 base->posguid = -1; 9997 base->flags = info->typeattr.wTypeFlags; 9998 if(info->Name) { 9999 base->NameOffset = info->Name->offset; 10000 10001 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38; 10002 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype; 10003 }else { 10004 base->NameOffset = -1; 10005 } 10006 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum; 10007 if(info->DocString) 10008 base->docstringoffs = info->DocString->offset; 10009 else 10010 base->docstringoffs = -1; 10011 base->helpstringcontext = info->dwHelpStringContext; 10012 base->helpcontext = info->dwHelpContext; 10013 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file); 10014 base->cImplTypes = info->typeattr.cImplTypes; 10015 base->cbSizeVft = info->typeattr.cbSizeVft; 10016 base->size = info->typeattr.cbSizeInstance; 10017 if(info->typeattr.typekind == TKIND_COCLASS){ 10018 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file); 10019 }else if(info->typeattr.typekind == TKIND_ALIAS){ 10020 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL); 10021 }else if(info->typeattr.typekind == TKIND_MODULE){ 10022 if(info->DllName) 10023 base->datatype1 = info->DllName->offset; 10024 else 10025 base->datatype1 = -1; 10026 }else{ 10027 if(info->typeattr.cImplTypes > 0) 10028 base->datatype1 = info->impltypes[0].hRef; 10029 else 10030 base->datatype1 = -1; 10031 } 10032 base->datatype2 = index; /* FIXME: i think there's more here */ 10033 base->res18 = 0; 10034 base->res19 = -1; 10035 } 10036 10037 return size; 10038 } 10039 10040 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk) 10041 { 10042 UINT i; 10043 10044 file->typeinfo_seg.len = 0; 10045 for(i = 0; i < This->TypeInfoCount; ++i){ 10046 ITypeInfoImpl *info = This->typeinfos[i]; 10047 *junk = file->typeinfo_seg.len; 10048 ++junk; 10049 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL); 10050 } 10051 10052 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len); 10053 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len); 10054 10055 file->aux_seg.len = 0; 10056 file->aux_seg.data = NULL; 10057 10058 file->typeinfo_seg.len = 0; 10059 for(i = 0; i < This->TypeInfoCount; ++i){ 10060 ITypeInfoImpl *info = This->typeinfos[i]; 10061 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file, 10062 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len); 10063 } 10064 } 10065 10066 typedef struct tagWMSFT_ImpFile { 10067 INT guid_offs; 10068 LCID lcid; 10069 DWORD version; 10070 } WMSFT_ImpFile; 10071 10072 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file) 10073 { 10074 TLBImpLib *implib; 10075 WMSFT_ImpFile *impfile; 10076 char *data; 10077 DWORD last_offs = 0; 10078 10079 file->impfile_seg.len = 0; 10080 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){ 10081 int size = 0; 10082 10083 if(implib->name){ 10084 WCHAR *path = strrchrW(implib->name, '\\'); 10085 if(path) 10086 ++path; 10087 else 10088 path = implib->name; 10089 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL); 10090 if (size == 0) 10091 ERR("failed to convert wide string: %s\n", debugstr_w(path)); 10092 } 10093 10094 size += sizeof(INT16); 10095 if (size % 4) 10096 size = (size + 4) & ~0x3; 10097 if (size < 8) 10098 size = 8; 10099 10100 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size; 10101 } 10102 10103 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len); 10104 10105 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){ 10106 int strlen = 0, size; 10107 10108 impfile = (WMSFT_ImpFile*)data; 10109 impfile->guid_offs = implib->guid->offset; 10110 impfile->lcid = implib->lcid; 10111 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor; 10112 10113 data += sizeof(WMSFT_ImpFile); 10114 10115 if(implib->name){ 10116 WCHAR *path= strrchrW(implib->name, '\\'); 10117 if(path) 10118 ++path; 10119 else 10120 path = implib->name; 10121 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), 10122 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL); 10123 if (strlen == 0) 10124 ERR("failed to convert wide string: %s\n", debugstr_w(path)); 10125 } 10126 10127 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */ 10128 10129 size = strlen + sizeof(INT16); 10130 if (size % 4) 10131 size = (size + 4) & ~0x3; 10132 if (size < 8) 10133 size = 8; 10134 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16)); 10135 10136 data += size; 10137 implib->offset = last_offs; 10138 last_offs += size + sizeof(WMSFT_ImpFile); 10139 } 10140 } 10141 10142 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file) 10143 { 10144 MSFT_ImpInfo *info; 10145 TLBRefType *ref_type; 10146 UINT i = 0; 10147 10148 WMSFT_compile_impfile(This, file); 10149 10150 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list); 10151 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len); 10152 10153 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){ 10154 info->flags = i | ((ref_type->tkind & 0xFF) << 24); 10155 if(ref_type->index == TLB_REF_USE_GUID){ 10156 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID; 10157 info->oGuid = ref_type->guid->offset; 10158 }else 10159 info->oGuid = ref_type->index; 10160 info->oImpFile = ref_type->pImpTLInfo->offset; 10161 ++i; 10162 ++info; 10163 } 10164 } 10165 10166 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file) 10167 { 10168 file->guidhash_seg.len = 0x80; 10169 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len); 10170 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len); 10171 } 10172 10173 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file) 10174 { 10175 file->namehash_seg.len = 0x200; 10176 file->namehash_seg.data = heap_alloc(file->namehash_seg.len); 10177 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len); 10178 } 10179 10180 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset) 10181 { 10182 if(contents && contents->len){ 10183 segdir->offset = *running_offset; 10184 segdir->length = contents->len; 10185 *running_offset += segdir->length; 10186 }else{ 10187 segdir->offset = -1; 10188 segdir->length = 0; 10189 } 10190 10191 /* TODO: do these ever change? */ 10192 segdir->res08 = -1; 10193 segdir->res0c = 0xf; 10194 } 10195 10196 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment) 10197 { 10198 DWORD written; 10199 if(segment) 10200 WriteFile(outfile, segment->data, segment->len, &written, NULL); 10201 } 10202 10203 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file, 10204 DWORD file_len) 10205 { 10206 DWORD i; 10207 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data; 10208 10209 for(i = 0; i < This->TypeInfoCount; ++i){ 10210 base->memoffset += file_len; 10211 ++base; 10212 } 10213 10214 return S_OK; 10215 } 10216 10217 static void WMSFT_free_file(WMSFT_TLBFile *file) 10218 { 10219 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data); 10220 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data); 10221 HeapFree(GetProcessHeap(), 0, file->guid_seg.data); 10222 HeapFree(GetProcessHeap(), 0, file->ref_seg.data); 10223 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data); 10224 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data); 10225 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data); 10226 HeapFree(GetProcessHeap(), 0, file->name_seg.data); 10227 HeapFree(GetProcessHeap(), 0, file->string_seg.data); 10228 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data); 10229 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data); 10230 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data); 10231 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data); 10232 HeapFree(GetProcessHeap(), 0, file->aux_seg.data); 10233 } 10234 10235 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface) 10236 { 10237 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 10238 WMSFT_TLBFile file; 10239 DWORD written, junk_size, junk_offs, running_offset; 10240 BOOL br; 10241 HANDLE outfile; 10242 HRESULT hres; 10243 DWORD *junk; 10244 UINT i; 10245 10246 TRACE("%p\n", This); 10247 10248 for(i = 0; i < This->TypeInfoCount; ++i) 10249 if(This->typeinfos[i]->needs_layout) 10250 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface); 10251 10252 memset(&file, 0, sizeof(file)); 10253 10254 file.header.magic1 = 0x5446534D; 10255 file.header.magic2 = 0x00010002; 10256 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); 10257 file.header.lcid2 = This->set_lcid; 10258 file.header.varflags = 0x40 | This->syskind; 10259 if (This->HelpFile) 10260 file.header.varflags |= 0x10; 10261 if (This->HelpStringDll) 10262 file.header.varflags |= HELPDLLFLAG; 10263 file.header.version = (This->ver_minor << 16) | This->ver_major; 10264 file.header.flags = This->libflags; 10265 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */ 10266 file.header.helpcontext = This->dwHelpContext; 10267 file.header.res44 = 0x20; 10268 file.header.res48 = 0x80; 10269 file.header.dispatchpos = This->dispatch_href; 10270 10271 WMSFT_compile_namehash(This, &file); 10272 /* do name and string compilation to get offsets for other compilations */ 10273 hres = WMSFT_compile_names(This, &file); 10274 if (FAILED(hres)){ 10275 WMSFT_free_file(&file); 10276 return hres; 10277 } 10278 10279 hres = WMSFT_compile_strings(This, &file); 10280 if (FAILED(hres)){ 10281 WMSFT_free_file(&file); 10282 return hres; 10283 } 10284 10285 WMSFT_compile_guidhash(This, &file); 10286 hres = WMSFT_compile_guids(This, &file); 10287 if (FAILED(hres)){ 10288 WMSFT_free_file(&file); 10289 return hres; 10290 } 10291 10292 if(This->HelpFile) 10293 file.header.helpfile = This->HelpFile->offset; 10294 else 10295 file.header.helpfile = -1; 10296 10297 if(This->DocString) 10298 file.header.helpstring = This->DocString->offset; 10299 else 10300 file.header.helpstring = -1; 10301 10302 /* do some more segment compilation */ 10303 file.header.nimpinfos = list_count(&This->ref_list); 10304 file.header.nrtypeinfos = This->TypeInfoCount; 10305 10306 if(This->Name) 10307 file.header.NameOffset = This->Name->offset; 10308 else 10309 file.header.NameOffset = -1; 10310 10311 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file); 10312 10313 if(This->guid) 10314 file.header.posguid = This->guid->offset; 10315 else 10316 file.header.posguid = -1; 10317 10318 junk_size = file.header.nrtypeinfos * sizeof(DWORD); 10319 if(file.header.varflags & HELPDLLFLAG) 10320 junk_size += sizeof(DWORD); 10321 if(junk_size){ 10322 junk = heap_alloc_zero(junk_size); 10323 if(file.header.varflags & HELPDLLFLAG){ 10324 *junk = This->HelpStringDll->offset; 10325 junk_offs = 1; 10326 }else 10327 junk_offs = 0; 10328 }else{ 10329 junk = NULL; 10330 junk_offs = 0; 10331 } 10332 10333 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs); 10334 WMSFT_compile_impinfo(This, &file); 10335 10336 running_offset = 0; 10337 10338 TRACE("header at: 0x%x\n", running_offset); 10339 running_offset += sizeof(file.header); 10340 10341 TRACE("junk at: 0x%x\n", running_offset); 10342 running_offset += junk_size; 10343 10344 TRACE("segdir at: 0x%x\n", running_offset); 10345 running_offset += sizeof(file.segdir); 10346 10347 TRACE("typeinfo at: 0x%x\n", running_offset); 10348 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset); 10349 10350 TRACE("guidhashtab at: 0x%x\n", running_offset); 10351 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset); 10352 10353 TRACE("guidtab at: 0x%x\n", running_offset); 10354 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset); 10355 10356 TRACE("reftab at: 0x%x\n", running_offset); 10357 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset); 10358 10359 TRACE("impinfo at: 0x%x\n", running_offset); 10360 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset); 10361 10362 TRACE("impfiles at: 0x%x\n", running_offset); 10363 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset); 10364 10365 TRACE("namehashtab at: 0x%x\n", running_offset); 10366 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset); 10367 10368 TRACE("nametab at: 0x%x\n", running_offset); 10369 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset); 10370 10371 TRACE("stringtab at: 0x%x\n", running_offset); 10372 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset); 10373 10374 TRACE("typdesc at: 0x%x\n", running_offset); 10375 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset); 10376 10377 TRACE("arraydescriptions at: 0x%x\n", running_offset); 10378 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset); 10379 10380 TRACE("custdata at: 0x%x\n", running_offset); 10381 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset); 10382 10383 TRACE("cdguids at: 0x%x\n", running_offset); 10384 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset); 10385 10386 TRACE("res0e at: 0x%x\n", running_offset); 10387 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset); 10388 10389 TRACE("res0f at: 0x%x\n", running_offset); 10390 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset); 10391 10392 TRACE("aux_seg at: 0x%x\n", running_offset); 10393 10394 WMSFT_fixup_typeinfos(This, &file, running_offset); 10395 10396 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 10397 FILE_ATTRIBUTE_NORMAL, 0); 10398 if (outfile == INVALID_HANDLE_VALUE){ 10399 WMSFT_free_file(&file); 10400 heap_free(junk); 10401 return TYPE_E_IOERROR; 10402 } 10403 10404 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL); 10405 if (!br) { 10406 WMSFT_free_file(&file); 10407 CloseHandle(outfile); 10408 heap_free(junk); 10409 return TYPE_E_IOERROR; 10410 } 10411 10412 br = WriteFile(outfile, junk, junk_size, &written, NULL); 10413 heap_free(junk); 10414 if (!br) { 10415 WMSFT_free_file(&file); 10416 CloseHandle(outfile); 10417 return TYPE_E_IOERROR; 10418 } 10419 10420 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL); 10421 if (!br) { 10422 WMSFT_free_file(&file); 10423 CloseHandle(outfile); 10424 return TYPE_E_IOERROR; 10425 } 10426 10427 WMSFT_write_segment(outfile, &file.typeinfo_seg); 10428 WMSFT_write_segment(outfile, &file.guidhash_seg); 10429 WMSFT_write_segment(outfile, &file.guid_seg); 10430 WMSFT_write_segment(outfile, &file.ref_seg); 10431 WMSFT_write_segment(outfile, &file.impinfo_seg); 10432 WMSFT_write_segment(outfile, &file.impfile_seg); 10433 WMSFT_write_segment(outfile, &file.namehash_seg); 10434 WMSFT_write_segment(outfile, &file.name_seg); 10435 WMSFT_write_segment(outfile, &file.string_seg); 10436 WMSFT_write_segment(outfile, &file.typdesc_seg); 10437 WMSFT_write_segment(outfile, &file.arraydesc_seg); 10438 WMSFT_write_segment(outfile, &file.custdata_seg); 10439 WMSFT_write_segment(outfile, &file.cdguids_seg); 10440 WMSFT_write_segment(outfile, &file.aux_seg); 10441 10442 WMSFT_free_file(&file); 10443 10444 CloseHandle(outfile); 10445 10446 return S_OK; 10447 } 10448 10449 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface, 10450 LPOLESTR name) 10451 { 10452 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 10453 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name)); 10454 return E_NOTIMPL; 10455 } 10456 10457 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface, 10458 REFGUID guid, VARIANT *varVal) 10459 { 10460 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 10461 TLBGuid *tlbguid; 10462 10463 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal); 10464 10465 if (!guid || !varVal) 10466 return E_INVALIDARG; 10467 10468 tlbguid = TLB_append_guid(&This->guid_list, guid, -1); 10469 10470 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal); 10471 } 10472 10473 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface, 10474 ULONG helpStringContext) 10475 { 10476 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 10477 FIXME("%p %u - stub\n", This, helpStringContext); 10478 return E_NOTIMPL; 10479 } 10480 10481 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface, 10482 LPOLESTR filename) 10483 { 10484 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface); 10485 TRACE("%p %s\n", This, wine_dbgstr_w(filename)); 10486 10487 if (!filename) 10488 return E_INVALIDARG; 10489 10490 This->HelpStringDll = TLB_append_str(&This->string_list, filename); 10491 10492 return S_OK; 10493 } 10494 10495 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = { 10496 ICreateTypeLib2_fnQueryInterface, 10497 ICreateTypeLib2_fnAddRef, 10498 ICreateTypeLib2_fnRelease, 10499 ICreateTypeLib2_fnCreateTypeInfo, 10500 ICreateTypeLib2_fnSetName, 10501 ICreateTypeLib2_fnSetVersion, 10502 ICreateTypeLib2_fnSetGuid, 10503 ICreateTypeLib2_fnSetDocString, 10504 ICreateTypeLib2_fnSetHelpFileName, 10505 ICreateTypeLib2_fnSetHelpContext, 10506 ICreateTypeLib2_fnSetLcid, 10507 ICreateTypeLib2_fnSetLibFlags, 10508 ICreateTypeLib2_fnSaveAllChanges, 10509 ICreateTypeLib2_fnDeleteTypeInfo, 10510 ICreateTypeLib2_fnSetCustData, 10511 ICreateTypeLib2_fnSetHelpStringContext, 10512 ICreateTypeLib2_fnSetHelpStringDll 10513 }; 10514 10515 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface, 10516 REFIID riid, void **object) 10517 { 10518 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10519 10520 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object); 10521 } 10522 10523 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface) 10524 { 10525 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10526 10527 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface); 10528 } 10529 10530 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface) 10531 { 10532 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10533 10534 return ITypeInfo2_Release(&This->ITypeInfo2_iface); 10535 } 10536 10537 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface, 10538 REFGUID guid) 10539 { 10540 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10541 10542 TRACE("%p %s\n", This, debugstr_guid(guid)); 10543 10544 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype); 10545 10546 return S_OK; 10547 } 10548 10549 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface, 10550 UINT typeFlags) 10551 { 10552 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10553 WORD old_flags; 10554 HRESULT hres; 10555 10556 TRACE("%p %x\n", This, typeFlags); 10557 10558 if (typeFlags & TYPEFLAG_FDUAL) { 10559 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 }; 10560 ITypeLib *stdole; 10561 ITypeInfo *dispatch; 10562 HREFTYPE hreftype; 10563 HRESULT hres; 10564 10565 hres = LoadTypeLib(stdole2tlb, &stdole); 10566 if(FAILED(hres)) 10567 return hres; 10568 10569 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch); 10570 ITypeLib_Release(stdole); 10571 if(FAILED(hres)) 10572 return hres; 10573 10574 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype); 10575 ITypeInfo_Release(dispatch); 10576 if(FAILED(hres)) 10577 return hres; 10578 } 10579 10580 old_flags = This->typeattr.wTypeFlags; 10581 This->typeattr.wTypeFlags = typeFlags; 10582 10583 hres = ICreateTypeInfo2_LayOut(iface); 10584 if (FAILED(hres)) { 10585 This->typeattr.wTypeFlags = old_flags; 10586 return hres; 10587 } 10588 10589 return S_OK; 10590 } 10591 10592 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface, 10593 LPOLESTR doc) 10594 { 10595 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10596 10597 TRACE("%p %s\n", This, wine_dbgstr_w(doc)); 10598 10599 if (!doc) 10600 return E_INVALIDARG; 10601 10602 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc); 10603 10604 return S_OK; 10605 } 10606 10607 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface, 10608 DWORD helpContext) 10609 { 10610 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10611 10612 TRACE("%p %d\n", This, helpContext); 10613 10614 This->dwHelpContext = helpContext; 10615 10616 return S_OK; 10617 } 10618 10619 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface, 10620 WORD majorVerNum, WORD minorVerNum) 10621 { 10622 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10623 10624 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum); 10625 10626 This->typeattr.wMajorVerNum = majorVerNum; 10627 This->typeattr.wMinorVerNum = minorVerNum; 10628 10629 return S_OK; 10630 } 10631 10632 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface, 10633 ITypeInfo *typeInfo, HREFTYPE *refType) 10634 { 10635 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10636 UINT index; 10637 ITypeLib *container; 10638 TLBRefType *ref_type; 10639 TLBImpLib *implib; 10640 TYPEATTR *typeattr; 10641 TLIBATTR *libattr; 10642 HRESULT hres; 10643 10644 TRACE("%p %p %p\n", This, typeInfo, refType); 10645 10646 if (!typeInfo || !refType) 10647 return E_INVALIDARG; 10648 10649 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index); 10650 if (FAILED(hres)) 10651 return hres; 10652 10653 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) { 10654 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo); 10655 10656 ITypeLib_Release(container); 10657 10658 *refType = target->hreftype; 10659 10660 return S_OK; 10661 } 10662 10663 hres = ITypeLib_GetLibAttr(container, &libattr); 10664 if (FAILED(hres)) { 10665 ITypeLib_Release(container); 10666 return hres; 10667 } 10668 10669 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){ 10670 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) && 10671 implib->lcid == libattr->lcid && 10672 implib->wVersionMajor == libattr->wMajorVerNum && 10673 implib->wVersionMinor == libattr->wMinorVerNum) 10674 break; 10675 } 10676 10677 if(&implib->entry == &This->pTypeLib->implib_list){ 10678 implib = heap_alloc_zero(sizeof(TLBImpLib)); 10679 10680 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){ 10681 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container); 10682 implib->name = SysAllocString(our_container->path); 10683 }else{ 10684 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum, 10685 libattr->wMinorVerNum, libattr->lcid, &implib->name); 10686 if(FAILED(hres)){ 10687 implib->name = NULL; 10688 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres); 10689 } 10690 } 10691 10692 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2); 10693 implib->lcid = libattr->lcid; 10694 implib->wVersionMajor = libattr->wMajorVerNum; 10695 implib->wVersionMinor = libattr->wMinorVerNum; 10696 10697 list_add_tail(&This->pTypeLib->implib_list, &implib->entry); 10698 } 10699 10700 ITypeLib_ReleaseTLibAttr(container, libattr); 10701 ITypeLib_Release(container); 10702 10703 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr); 10704 if (FAILED(hres)) 10705 return hres; 10706 10707 index = 0; 10708 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){ 10709 if(ref_type->index == TLB_REF_USE_GUID && 10710 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) && 10711 ref_type->tkind == typeattr->typekind) 10712 break; 10713 ++index; 10714 } 10715 10716 if(&ref_type->entry == &This->pTypeLib->ref_list){ 10717 ref_type = heap_alloc_zero(sizeof(TLBRefType)); 10718 10719 ref_type->tkind = typeattr->typekind; 10720 ref_type->pImpTLInfo = implib; 10721 ref_type->reference = index * sizeof(MSFT_ImpInfo); 10722 10723 ref_type->index = TLB_REF_USE_GUID; 10724 10725 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1); 10726 10727 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry); 10728 } 10729 10730 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr); 10731 10732 *refType = ref_type->reference | 0x1; 10733 10734 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch)) 10735 This->pTypeLib->dispatch_href = *refType; 10736 10737 return S_OK; 10738 } 10739 10740 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface, 10741 UINT index, FUNCDESC *funcDesc) 10742 { 10743 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10744 TLBFuncDesc tmp_func_desc, *func_desc; 10745 int buf_size, i; 10746 char *buffer; 10747 HRESULT hres; 10748 10749 TRACE("%p %u %p\n", This, index, funcDesc); 10750 10751 if (!funcDesc || funcDesc->oVft & 3) 10752 return E_INVALIDARG; 10753 10754 switch (This->typeattr.typekind) { 10755 case TKIND_MODULE: 10756 if (funcDesc->funckind != FUNC_STATIC) 10757 return TYPE_E_BADMODULEKIND; 10758 break; 10759 case TKIND_DISPATCH: 10760 if (funcDesc->funckind != FUNC_DISPATCH) 10761 return TYPE_E_BADMODULEKIND; 10762 break; 10763 default: 10764 if (funcDesc->funckind != FUNC_PUREVIRTUAL) 10765 return TYPE_E_BADMODULEKIND; 10766 } 10767 10768 if (index > This->typeattr.cFuncs) 10769 return TYPE_E_ELEMENTNOTFOUND; 10770 10771 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) && 10772 !funcDesc->cParams) 10773 return TYPE_E_INCONSISTENTPROPFUNCS; 10774 10775 #ifdef _WIN64 10776 if(This->pTypeLib->syskind == SYS_WIN64 && 10777 funcDesc->oVft % 8 != 0) 10778 return E_INVALIDARG; 10779 #endif 10780 10781 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc)); 10782 TLBFuncDesc_Constructor(&tmp_func_desc); 10783 10784 tmp_func_desc.funcdesc = *funcDesc; 10785 10786 if (tmp_func_desc.funcdesc.oVft != 0) 10787 tmp_func_desc.funcdesc.oVft |= 1; 10788 10789 if (funcDesc->cScodes && funcDesc->lprgscode) { 10790 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes); 10791 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes); 10792 } else { 10793 tmp_func_desc.funcdesc.lprgscode = NULL; 10794 tmp_func_desc.funcdesc.cScodes = 0; 10795 } 10796 10797 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc); 10798 for (i = 0; i < funcDesc->cParams; ++i) { 10799 buf_size += sizeof(ELEMDESC); 10800 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i); 10801 } 10802 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size); 10803 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams); 10804 10805 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer); 10806 if (FAILED(hres)) { 10807 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam); 10808 heap_free(tmp_func_desc.funcdesc.lprgscode); 10809 return hres; 10810 } 10811 10812 for (i = 0; i < funcDesc->cParams; ++i) { 10813 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i, 10814 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer); 10815 if (FAILED(hres)) { 10816 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam); 10817 heap_free(tmp_func_desc.funcdesc.lprgscode); 10818 return hres; 10819 } 10820 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT && 10821 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT && 10822 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){ 10823 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue); 10824 if (FAILED(hres)) { 10825 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam); 10826 heap_free(tmp_func_desc.funcdesc.lprgscode); 10827 return hres; 10828 } 10829 } 10830 } 10831 10832 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams); 10833 10834 if (This->funcdescs) { 10835 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs, 10836 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1)); 10837 10838 if (index < This->typeattr.cFuncs) { 10839 memmove(This->funcdescs + index + 1, This->funcdescs + index, 10840 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc)); 10841 func_desc = This->funcdescs + index; 10842 } else 10843 func_desc = This->funcdescs + This->typeattr.cFuncs; 10844 10845 /* move custdata lists to the new memory location */ 10846 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){ 10847 if(index != i){ 10848 TLBFuncDesc *fd = &This->funcdescs[i]; 10849 if(fd->custdata_list.prev == fd->custdata_list.next) 10850 list_init(&fd->custdata_list); 10851 else{ 10852 fd->custdata_list.prev->next = &fd->custdata_list; 10853 fd->custdata_list.next->prev = &fd->custdata_list; 10854 } 10855 } 10856 } 10857 } else 10858 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc)); 10859 10860 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc)); 10861 list_init(&func_desc->custdata_list); 10862 10863 ++This->typeattr.cFuncs; 10864 10865 This->needs_layout = TRUE; 10866 10867 return S_OK; 10868 } 10869 10870 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface, 10871 UINT index, HREFTYPE refType) 10872 { 10873 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10874 TLBImplType *impl_type; 10875 HRESULT hres; 10876 10877 TRACE("%p %u %d\n", This, index, refType); 10878 10879 switch(This->typeattr.typekind){ 10880 case TKIND_COCLASS: { 10881 if (index == -1) { 10882 FIXME("Unhandled index: -1\n"); 10883 return E_NOTIMPL; 10884 } 10885 10886 if(index != This->typeattr.cImplTypes) 10887 return TYPE_E_ELEMENTNOTFOUND; 10888 10889 break; 10890 } 10891 case TKIND_INTERFACE: 10892 case TKIND_DISPATCH: 10893 if (index != 0 || This->typeattr.cImplTypes) 10894 return TYPE_E_ELEMENTNOTFOUND; 10895 break; 10896 default: 10897 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind); 10898 return E_NOTIMPL; 10899 } 10900 10901 if (This->impltypes){ 10902 UINT i; 10903 10904 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes, 10905 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1)); 10906 10907 if (index < This->typeattr.cImplTypes) { 10908 memmove(This->impltypes + index + 1, This->impltypes + index, 10909 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType)); 10910 impl_type = This->impltypes + index; 10911 } else 10912 impl_type = This->impltypes + This->typeattr.cImplTypes; 10913 10914 /* move custdata lists to the new memory location */ 10915 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){ 10916 if(index != i){ 10917 TLBImplType *it = &This->impltypes[i]; 10918 if(it->custdata_list.prev == it->custdata_list.next) 10919 list_init(&it->custdata_list); 10920 else{ 10921 it->custdata_list.prev->next = &it->custdata_list; 10922 it->custdata_list.next->prev = &it->custdata_list; 10923 } 10924 } 10925 } 10926 } else 10927 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType)); 10928 10929 memset(impl_type, 0, sizeof(TLBImplType)); 10930 TLBImplType_Constructor(impl_type); 10931 impl_type->hRef = refType; 10932 10933 ++This->typeattr.cImplTypes; 10934 10935 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3))) 10936 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE; 10937 10938 hres = ICreateTypeInfo2_LayOut(iface); 10939 if (FAILED(hres)) 10940 return hres; 10941 10942 return S_OK; 10943 } 10944 10945 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface, 10946 UINT index, INT implTypeFlags) 10947 { 10948 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10949 TLBImplType *impl_type = &This->impltypes[index]; 10950 10951 TRACE("%p %u %x\n", This, index, implTypeFlags); 10952 10953 if (This->typeattr.typekind != TKIND_COCLASS) 10954 return TYPE_E_BADMODULEKIND; 10955 10956 if (index >= This->typeattr.cImplTypes) 10957 return TYPE_E_ELEMENTNOTFOUND; 10958 10959 impl_type->implflags = implTypeFlags; 10960 10961 return S_OK; 10962 } 10963 10964 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface, 10965 WORD alignment) 10966 { 10967 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10968 10969 TRACE("%p %d\n", This, alignment); 10970 10971 This->typeattr.cbAlignment = alignment; 10972 10973 return S_OK; 10974 } 10975 10976 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface, 10977 LPOLESTR schema) 10978 { 10979 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10980 10981 TRACE("%p %s\n", This, wine_dbgstr_w(schema)); 10982 10983 if (!schema) 10984 return E_INVALIDARG; 10985 10986 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema); 10987 10988 This->typeattr.lpstrSchema = This->Schema->str; 10989 10990 return S_OK; 10991 } 10992 10993 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface, 10994 UINT index, VARDESC *varDesc) 10995 { 10996 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 10997 TLBVarDesc *var_desc; 10998 10999 TRACE("%p %u %p\n", This, index, varDesc); 11000 11001 if (This->vardescs){ 11002 UINT i; 11003 11004 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs, 11005 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1)); 11006 11007 if (index < This->typeattr.cVars) { 11008 memmove(This->vardescs + index + 1, This->vardescs + index, 11009 (This->typeattr.cVars - index) * sizeof(TLBVarDesc)); 11010 var_desc = This->vardescs + index; 11011 } else 11012 var_desc = This->vardescs + This->typeattr.cVars; 11013 11014 /* move custdata lists to the new memory location */ 11015 for(i = 0; i < This->typeattr.cVars + 1; ++i){ 11016 if(index != i){ 11017 TLBVarDesc *var = &This->vardescs[i]; 11018 if(var->custdata_list.prev == var->custdata_list.next) 11019 list_init(&var->custdata_list); 11020 else{ 11021 var->custdata_list.prev->next = &var->custdata_list; 11022 var->custdata_list.next->prev = &var->custdata_list; 11023 } 11024 } 11025 } 11026 } else 11027 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc)); 11028 11029 TLBVarDesc_Constructor(var_desc); 11030 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create); 11031 var_desc->vardesc = *var_desc->vardesc_create; 11032 11033 ++This->typeattr.cVars; 11034 11035 This->needs_layout = TRUE; 11036 11037 return S_OK; 11038 } 11039 11040 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface, 11041 UINT index, LPOLESTR *names, UINT numNames) 11042 { 11043 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11044 TLBFuncDesc *func_desc = &This->funcdescs[index]; 11045 int i; 11046 11047 TRACE("%p %u %p %u\n", This, index, names, numNames); 11048 11049 if (!names) 11050 return E_INVALIDARG; 11051 11052 if (index >= This->typeattr.cFuncs || numNames == 0) 11053 return TYPE_E_ELEMENTNOTFOUND; 11054 11055 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){ 11056 if(numNames > func_desc->funcdesc.cParams) 11057 return TYPE_E_ELEMENTNOTFOUND; 11058 } else 11059 if(numNames > func_desc->funcdesc.cParams + 1) 11060 return TYPE_E_ELEMENTNOTFOUND; 11061 11062 for(i = 0; i < This->typeattr.cFuncs; ++i) { 11063 TLBFuncDesc *iter = &This->funcdescs[i]; 11064 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) { 11065 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) && 11066 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) && 11067 func_desc->funcdesc.invkind != iter->funcdesc.invkind) 11068 continue; 11069 return TYPE_E_AMBIGUOUSNAME; 11070 } 11071 } 11072 11073 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names); 11074 11075 for (i = 1; i < numNames; ++i) { 11076 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1; 11077 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i)); 11078 } 11079 11080 return S_OK; 11081 } 11082 11083 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface, 11084 UINT index, LPOLESTR name) 11085 { 11086 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11087 11088 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name)); 11089 11090 if(!name) 11091 return E_INVALIDARG; 11092 11093 if(index >= This->typeattr.cVars) 11094 return TYPE_E_ELEMENTNOTFOUND; 11095 11096 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name); 11097 return S_OK; 11098 } 11099 11100 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface, 11101 TYPEDESC *tdescAlias) 11102 { 11103 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11104 HRESULT hr; 11105 11106 TRACE("%p %p\n", This, tdescAlias); 11107 11108 if(!tdescAlias) 11109 return E_INVALIDARG; 11110 11111 if(This->typeattr.typekind != TKIND_ALIAS) 11112 return TYPE_E_BADMODULEKIND; 11113 11114 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment); 11115 if(FAILED(hr)) 11116 return hr; 11117 11118 heap_free(This->tdescAlias); 11119 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE)); 11120 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias); 11121 11122 return S_OK; 11123 } 11124 11125 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface, 11126 UINT index, LPOLESTR dllName, LPOLESTR procName) 11127 { 11128 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11129 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName)); 11130 return E_NOTIMPL; 11131 } 11132 11133 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface, 11134 UINT index, LPOLESTR docString) 11135 { 11136 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11137 TLBFuncDesc *func_desc = &This->funcdescs[index]; 11138 11139 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString)); 11140 11141 if(!docString) 11142 return E_INVALIDARG; 11143 11144 if(index >= This->typeattr.cFuncs) 11145 return TYPE_E_ELEMENTNOTFOUND; 11146 11147 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString); 11148 11149 return S_OK; 11150 } 11151 11152 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface, 11153 UINT index, LPOLESTR docString) 11154 { 11155 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11156 TLBVarDesc *var_desc = &This->vardescs[index]; 11157 11158 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString)); 11159 11160 if(!docString) 11161 return E_INVALIDARG; 11162 11163 if(index >= This->typeattr.cVars) 11164 return TYPE_E_ELEMENTNOTFOUND; 11165 11166 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString); 11167 11168 return S_OK; 11169 } 11170 11171 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface, 11172 UINT index, DWORD helpContext) 11173 { 11174 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11175 TLBFuncDesc *func_desc = &This->funcdescs[index]; 11176 11177 TRACE("%p %u %d\n", This, index, helpContext); 11178 11179 if(index >= This->typeattr.cFuncs) 11180 return TYPE_E_ELEMENTNOTFOUND; 11181 11182 func_desc->helpcontext = helpContext; 11183 11184 return S_OK; 11185 } 11186 11187 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface, 11188 UINT index, DWORD helpContext) 11189 { 11190 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11191 TLBVarDesc *var_desc = &This->vardescs[index]; 11192 11193 TRACE("%p %u %d\n", This, index, helpContext); 11194 11195 if(index >= This->typeattr.cVars) 11196 return TYPE_E_ELEMENTNOTFOUND; 11197 11198 var_desc->HelpContext = helpContext; 11199 11200 return S_OK; 11201 } 11202 11203 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface, 11204 UINT index, BSTR bstrMops) 11205 { 11206 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11207 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops)); 11208 return E_NOTIMPL; 11209 } 11210 11211 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface, 11212 IDLDESC *idlDesc) 11213 { 11214 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11215 11216 TRACE("%p %p\n", This, idlDesc); 11217 11218 if (!idlDesc) 11219 return E_INVALIDARG; 11220 11221 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved; 11222 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags; 11223 11224 return S_OK; 11225 } 11226 11227 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface) 11228 { 11229 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11230 ITypeInfo *tinfo; 11231 TLBFuncDesc *func_desc; 11232 UINT user_vft = 0, i, depth = 0; 11233 HRESULT hres = S_OK; 11234 11235 TRACE("%p\n", This); 11236 11237 This->needs_layout = FALSE; 11238 11239 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo); 11240 if (FAILED(hres)) 11241 return hres; 11242 11243 if (This->typeattr.typekind == TKIND_INTERFACE) { 11244 ITypeInfo *inh; 11245 TYPEATTR *attr; 11246 HREFTYPE inh_href; 11247 11248 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href); 11249 11250 if (SUCCEEDED(hres)) { 11251 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh); 11252 11253 if (SUCCEEDED(hres)) { 11254 hres = ITypeInfo_GetTypeAttr(inh, &attr); 11255 if (FAILED(hres)) { 11256 ITypeInfo_Release(inh); 11257 ITypeInfo_Release(tinfo); 11258 return hres; 11259 } 11260 This->typeattr.cbSizeVft = attr->cbSizeVft; 11261 ITypeInfo_ReleaseTypeAttr(inh, attr); 11262 11263 do{ 11264 ++depth; 11265 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href); 11266 if(SUCCEEDED(hres)){ 11267 ITypeInfo *next; 11268 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next); 11269 if(SUCCEEDED(hres)){ 11270 ITypeInfo_Release(inh); 11271 inh = next; 11272 } 11273 } 11274 }while(SUCCEEDED(hres)); 11275 hres = S_OK; 11276 11277 ITypeInfo_Release(inh); 11278 } else if (hres == TYPE_E_ELEMENTNOTFOUND) { 11279 This->typeattr.cbSizeVft = 0; 11280 hres = S_OK; 11281 } else { 11282 ITypeInfo_Release(tinfo); 11283 return hres; 11284 } 11285 } else if (hres == TYPE_E_ELEMENTNOTFOUND) { 11286 This->typeattr.cbSizeVft = 0; 11287 hres = S_OK; 11288 } else { 11289 ITypeInfo_Release(tinfo); 11290 return hres; 11291 } 11292 } else if (This->typeattr.typekind == TKIND_DISPATCH) 11293 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size; 11294 else 11295 This->typeattr.cbSizeVft = 0; 11296 11297 func_desc = This->funcdescs; 11298 i = 0; 11299 while (i < This->typeattr.cFuncs) { 11300 if (!(func_desc->funcdesc.oVft & 0x1)) 11301 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft; 11302 11303 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft) 11304 user_vft = func_desc->funcdesc.oVft & 0xFFFC; 11305 11306 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size; 11307 11308 if (func_desc->funcdesc.memid == MEMBERID_NIL) { 11309 TLBFuncDesc *iter; 11310 UINT j = 0; 11311 BOOL reset = FALSE; 11312 11313 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i; 11314 11315 iter = This->funcdescs; 11316 while (j < This->typeattr.cFuncs) { 11317 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) { 11318 if (!reset) { 11319 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs; 11320 reset = TRUE; 11321 } else 11322 ++func_desc->funcdesc.memid; 11323 iter = This->funcdescs; 11324 j = 0; 11325 } else { 11326 ++iter; 11327 ++j; 11328 } 11329 } 11330 } 11331 11332 ++func_desc; 11333 ++i; 11334 } 11335 11336 if (user_vft > This->typeattr.cbSizeVft) 11337 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size; 11338 11339 for(i = 0; i < This->typeattr.cVars; ++i){ 11340 TLBVarDesc *var_desc = &This->vardescs[i]; 11341 if(var_desc->vardesc.memid == MEMBERID_NIL){ 11342 UINT j = 0; 11343 BOOL reset = FALSE; 11344 TLBVarDesc *iter; 11345 11346 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i; 11347 11348 iter = This->vardescs; 11349 while (j < This->typeattr.cVars) { 11350 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) { 11351 if (!reset) { 11352 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars; 11353 reset = TRUE; 11354 } else 11355 ++var_desc->vardesc.memid; 11356 iter = This->vardescs; 11357 j = 0; 11358 } else { 11359 ++iter; 11360 ++j; 11361 } 11362 } 11363 } 11364 } 11365 11366 ITypeInfo_Release(tinfo); 11367 return hres; 11368 } 11369 11370 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface, 11371 UINT index) 11372 { 11373 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11374 FIXME("%p %u - stub\n", This, index); 11375 return E_NOTIMPL; 11376 } 11377 11378 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface, 11379 MEMBERID memid, INVOKEKIND invKind) 11380 { 11381 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11382 FIXME("%p %x %d - stub\n", This, memid, invKind); 11383 return E_NOTIMPL; 11384 } 11385 11386 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface, 11387 UINT index) 11388 { 11389 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11390 FIXME("%p %u - stub\n", This, index); 11391 return E_NOTIMPL; 11392 } 11393 11394 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface, 11395 MEMBERID memid) 11396 { 11397 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11398 FIXME("%p %x - stub\n", This, memid); 11399 return E_NOTIMPL; 11400 } 11401 11402 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface, 11403 UINT index) 11404 { 11405 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11406 FIXME("%p %u - stub\n", This, index); 11407 return E_NOTIMPL; 11408 } 11409 11410 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface, 11411 REFGUID guid, VARIANT *varVal) 11412 { 11413 TLBGuid *tlbguid; 11414 11415 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11416 11417 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal); 11418 11419 if (!guid || !varVal) 11420 return E_INVALIDARG; 11421 11422 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1); 11423 11424 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal); 11425 } 11426 11427 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface, 11428 UINT index, REFGUID guid, VARIANT *varVal) 11429 { 11430 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11431 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal); 11432 return E_NOTIMPL; 11433 } 11434 11435 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface, 11436 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal) 11437 { 11438 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11439 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal); 11440 return E_NOTIMPL; 11441 } 11442 11443 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface, 11444 UINT index, REFGUID guid, VARIANT *varVal) 11445 { 11446 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11447 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal); 11448 return E_NOTIMPL; 11449 } 11450 11451 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface, 11452 UINT index, REFGUID guid, VARIANT *varVal) 11453 { 11454 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11455 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal); 11456 return E_NOTIMPL; 11457 } 11458 11459 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface, 11460 ULONG helpStringContext) 11461 { 11462 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11463 11464 TRACE("%p %u\n", This, helpStringContext); 11465 11466 This->dwHelpStringContext = helpStringContext; 11467 11468 return S_OK; 11469 } 11470 11471 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface, 11472 UINT index, ULONG helpStringContext) 11473 { 11474 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11475 FIXME("%p %u %u - stub\n", This, index, helpStringContext); 11476 return E_NOTIMPL; 11477 } 11478 11479 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface, 11480 UINT index, ULONG helpStringContext) 11481 { 11482 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11483 FIXME("%p %u %u - stub\n", This, index, helpStringContext); 11484 return E_NOTIMPL; 11485 } 11486 11487 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface) 11488 { 11489 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11490 FIXME("%p - stub\n", This); 11491 return E_NOTIMPL; 11492 } 11493 11494 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface, 11495 LPOLESTR name) 11496 { 11497 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface); 11498 11499 TRACE("%p %s\n", This, wine_dbgstr_w(name)); 11500 11501 if (!name) 11502 return E_INVALIDARG; 11503 11504 This->Name = TLB_append_str(&This->pTypeLib->name_list, name); 11505 11506 return S_OK; 11507 } 11508 11509 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = { 11510 ICreateTypeInfo2_fnQueryInterface, 11511 ICreateTypeInfo2_fnAddRef, 11512 ICreateTypeInfo2_fnRelease, 11513 ICreateTypeInfo2_fnSetGuid, 11514 ICreateTypeInfo2_fnSetTypeFlags, 11515 ICreateTypeInfo2_fnSetDocString, 11516 ICreateTypeInfo2_fnSetHelpContext, 11517 ICreateTypeInfo2_fnSetVersion, 11518 ICreateTypeInfo2_fnAddRefTypeInfo, 11519 ICreateTypeInfo2_fnAddFuncDesc, 11520 ICreateTypeInfo2_fnAddImplType, 11521 ICreateTypeInfo2_fnSetImplTypeFlags, 11522 ICreateTypeInfo2_fnSetAlignment, 11523 ICreateTypeInfo2_fnSetSchema, 11524 ICreateTypeInfo2_fnAddVarDesc, 11525 ICreateTypeInfo2_fnSetFuncAndParamNames, 11526 ICreateTypeInfo2_fnSetVarName, 11527 ICreateTypeInfo2_fnSetTypeDescAlias, 11528 ICreateTypeInfo2_fnDefineFuncAsDllEntry, 11529 ICreateTypeInfo2_fnSetFuncDocString, 11530 ICreateTypeInfo2_fnSetVarDocString, 11531 ICreateTypeInfo2_fnSetFuncHelpContext, 11532 ICreateTypeInfo2_fnSetVarHelpContext, 11533 ICreateTypeInfo2_fnSetMops, 11534 ICreateTypeInfo2_fnSetTypeIdldesc, 11535 ICreateTypeInfo2_fnLayOut, 11536 ICreateTypeInfo2_fnDeleteFuncDesc, 11537 ICreateTypeInfo2_fnDeleteFuncDescByMemId, 11538 ICreateTypeInfo2_fnDeleteVarDesc, 11539 ICreateTypeInfo2_fnDeleteVarDescByMemId, 11540 ICreateTypeInfo2_fnDeleteImplType, 11541 ICreateTypeInfo2_fnSetCustData, 11542 ICreateTypeInfo2_fnSetFuncCustData, 11543 ICreateTypeInfo2_fnSetParamCustData, 11544 ICreateTypeInfo2_fnSetVarCustData, 11545 ICreateTypeInfo2_fnSetImplTypeCustData, 11546 ICreateTypeInfo2_fnSetHelpStringContext, 11547 ICreateTypeInfo2_fnSetFuncHelpStringContext, 11548 ICreateTypeInfo2_fnSetVarHelpStringContext, 11549 ICreateTypeInfo2_fnInvalidate, 11550 ICreateTypeInfo2_fnSetName 11551 }; 11552 11553 /****************************************************************************** 11554 * ClearCustData (OLEAUT32.171) 11555 * 11556 * Clear a custom data type's data. 11557 * 11558 * PARAMS 11559 * lpCust [I] The custom data type instance 11560 * 11561 * RETURNS 11562 * Nothing. 11563 */ 11564 void WINAPI ClearCustData(CUSTDATA *lpCust) 11565 { 11566 if (lpCust && lpCust->cCustData) 11567 { 11568 if (lpCust->prgCustData) 11569 { 11570 DWORD i; 11571 11572 for (i = 0; i < lpCust->cCustData; i++) 11573 VariantClear(&lpCust->prgCustData[i].varValue); 11574 11575 CoTaskMemFree(lpCust->prgCustData); 11576 lpCust->prgCustData = NULL; 11577 } 11578 lpCust->cCustData = 0; 11579 } 11580 } 11581