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 * 2005 Robert Shearman, for CodeWeavers 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 * 24 * -------------------------------------------------------------------------------------- 25 * Known problems (2000, Francois Jacques) 26 * 27 * - Tested using OLEVIEW (Platform SDK tool) only. 28 * 29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are 30 * creating by doing a straight copy of the dispinterface instance and just changing 31 * its typekind. Pointed structures aren't copied - only the address of the pointers. 32 * 33 * - locale stuff is partially implemented but hasn't been tested. 34 * 35 * - typelib file is still read in its entirety, but it is released now. 36 * 37 * -------------------------------------------------------------------------------------- 38 * Known problems left from previous implementation (1999, Rein Klazes) : 39 * 40 * -. Data structures are straightforward, but slow for look-ups. 41 * -. (related) nothing is hashed 42 * -. Most error return values are just guessed not checked with windows 43 * behaviour. 44 * -. lousy fatal error handling 45 * 46 */ 47 48 #include "config.h" 49 #include "wine/port.h" 50 51 #include <stdlib.h> 52 #include <string.h> 53 #include <stdarg.h> 54 #include <stdio.h> 55 #include <ctype.h> 56 57 #define COBJMACROS 58 #define NONAMELESSUNION 59 #define NONAMELESSSTRUCT 60 61 #include "winerror.h" 62 #include "windef.h" 63 #include "winbase.h" 64 #include "winnls.h" 65 #include "winreg.h" 66 #include "winuser.h" 67 #include "lzexpand.h" 68 69 #include "wine/unicode.h" 70 #include "objbase.h" 71 #include "typelib.h" 72 #include "wine/debug.h" 73 #include "variant.h" 74 #include "wine/list.h" 75 76 WINE_DEFAULT_DEBUG_CHANNEL(ole); 77 WINE_DECLARE_DEBUG_CHANNEL(typelib); 78 79 typedef struct 80 { 81 WORD offset; 82 WORD length; 83 WORD flags; 84 WORD id; 85 WORD handle; 86 WORD usage; 87 } NE_NAMEINFO; 88 89 typedef struct 90 { 91 WORD type_id; /* Type identifier */ 92 WORD count; /* Number of resources of this type */ 93 DWORD resloader; /* SetResourceHandler() */ 94 /* 95 * Name info array. 96 */ 97 } NE_TYPEINFO; 98 99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt); 100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr); 101 102 /**************************************************************************** 103 * FromLExxx 104 * 105 * Takes p_iVal (which is in little endian) and returns it 106 * in the host machine's byte order. 107 */ 108 #ifdef WORDS_BIGENDIAN 109 static WORD FromLEWord(WORD p_iVal) 110 { 111 return (((p_iVal & 0x00FF) << 8) | 112 ((p_iVal & 0xFF00) >> 8)); 113 } 114 115 116 static DWORD FromLEDWord(DWORD p_iVal) 117 { 118 return (((p_iVal & 0x000000FF) << 24) | 119 ((p_iVal & 0x0000FF00) << 8) | 120 ((p_iVal & 0x00FF0000) >> 8) | 121 ((p_iVal & 0xFF000000) >> 24)); 122 } 123 #else 124 #define FromLEWord(X) (X) 125 #define FromLEDWord(X) (X) 126 #endif 127 128 #define DISPATCH_HREF_OFFSET 0x01000000 129 #define DISPATCH_HREF_MASK 0xff000000 130 131 /**************************************************************************** 132 * FromLExxx 133 * 134 * Fix byte order in any structure if necessary 135 */ 136 #ifdef WORDS_BIGENDIAN 137 static void FromLEWords(void *p_Val, int p_iSize) 138 { 139 WORD *Val = p_Val; 140 141 p_iSize /= sizeof(WORD); 142 143 while (p_iSize) { 144 *Val = FromLEWord(*Val); 145 Val++; 146 p_iSize--; 147 } 148 } 149 150 151 static void FromLEDWords(void *p_Val, int p_iSize) 152 { 153 DWORD *Val = p_Val; 154 155 p_iSize /= sizeof(DWORD); 156 157 while (p_iSize) { 158 *Val = FromLEDWord(*Val); 159 Val++; 160 p_iSize--; 161 } 162 } 163 #else 164 #define FromLEWords(X,Y) /*nothing*/ 165 #define FromLEDWords(X,Y) /*nothing*/ 166 #endif 167 168 /* 169 * Find a typelib key which matches a requested maj.min version. 170 */ 171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin ) 172 { 173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0}; 174 WCHAR buffer[60]; 175 char key_name[16]; 176 DWORD len, i; 177 INT best_maj = -1, best_min = -1; 178 HKEY hkey; 179 180 memcpy( buffer, typelibW, sizeof(typelibW) ); 181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 182 183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS) 184 return FALSE; 185 186 len = sizeof(key_name); 187 i = 0; 188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) 189 { 190 INT v_maj, v_min; 191 192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2) 193 { 194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min); 195 196 if (*wMaj == 0xffff && *wMin == 0xffff) 197 { 198 if (v_maj > best_maj) best_maj = v_maj; 199 if (v_min > best_min) best_min = v_min; 200 } 201 else if (*wMaj == v_maj) 202 { 203 best_maj = v_maj; 204 205 if (*wMin == v_min) 206 { 207 best_min = v_min; 208 break; /* exact match */ 209 } 210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min; 211 } 212 } 213 len = sizeof(key_name); 214 } 215 RegCloseKey( hkey ); 216 217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min); 218 219 if (*wMaj == 0xffff && *wMin == 0xffff) 220 { 221 if (best_maj >= 0 && best_min >= 0) 222 { 223 *wMaj = best_maj; 224 *wMin = best_min; 225 return TRUE; 226 } 227 } 228 229 if (*wMaj == best_maj && best_min >= 0) 230 { 231 *wMin = best_min; 232 return TRUE; 233 } 234 return FALSE; 235 } 236 237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */ 238 /* buffer must be at least 60 characters long */ 239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer ) 240 { 241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0}; 242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0}; 243 244 memcpy( buffer, TypelibW, sizeof(TypelibW) ); 245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin ); 247 return buffer; 248 } 249 250 /* get the path of an interface key, in the form "Interface\\<guid>" */ 251 /* buffer must be at least 50 characters long */ 252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer ) 253 { 254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0}; 255 256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) ); 257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 258 return buffer; 259 } 260 261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */ 262 /* buffer must be at least 16 characters long */ 263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer ) 264 { 265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0}; 266 static const WCHAR win16W[] = {'w','i','n','1','6',0}; 267 static const WCHAR win32W[] = {'w','i','n','3','2',0}; 268 static const WCHAR win64W[] = {'w','i','n','6','4',0}; 269 270 sprintfW( buffer, LcidFormatW, lcid ); 271 switch(syskind) 272 { 273 case SYS_WIN16: strcatW( buffer, win16W ); break; 274 case SYS_WIN32: strcatW( buffer, win32W ); break; 275 case SYS_WIN64: strcatW( buffer, win64W ); break; 276 default: 277 TRACE("Typelib is for unsupported syskind %i\n", syskind); 278 return NULL; 279 } 280 return buffer; 281 } 282 283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib); 284 285 286 /**************************************************************************** 287 * QueryPathOfRegTypeLib [OLEAUT32.164] 288 * 289 * Gets the path to a registered type library. 290 * 291 * PARAMS 292 * guid [I] referenced guid 293 * wMaj [I] major version 294 * wMin [I] minor version 295 * lcid [I] locale id 296 * path [O] path of typelib 297 * 298 * RETURNS 299 * Success: S_OK. 300 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED 301 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be 302 * opened. 303 */ 304 HRESULT WINAPI QueryPathOfRegTypeLib( 305 REFGUID guid, 306 WORD wMaj, 307 WORD wMin, 308 LCID lcid, 309 LPBSTR path ) 310 { 311 HRESULT hr = TYPE_E_LIBNOTREGISTERED; 312 LCID myLCID = lcid; 313 HKEY hkey; 314 WCHAR buffer[60]; 315 WCHAR Path[MAX_PATH]; 316 LONG res; 317 318 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path); 319 320 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED; 321 get_typelib_key( guid, wMaj, wMin, buffer ); 322 323 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ); 324 if (res == ERROR_FILE_NOT_FOUND) 325 { 326 TRACE_(typelib)("%s not found\n", debugstr_w(buffer)); 327 return TYPE_E_LIBNOTREGISTERED; 328 } 329 else if (res != ERROR_SUCCESS) 330 { 331 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer)); 332 return TYPE_E_REGISTRYACCESS; 333 } 334 335 while (hr != S_OK) 336 { 337 LONG dwPathLen = sizeof(Path); 338 339 get_lcid_subkey( myLCID, SYS_WIN32, buffer ); 340 341 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen)) 342 { 343 if (!lcid) 344 break; 345 else if (myLCID == lcid) 346 { 347 /* try with sub-langid */ 348 myLCID = SUBLANGID(lcid); 349 } 350 else if ((myLCID == SUBLANGID(lcid)) && myLCID) 351 { 352 /* try with system langid */ 353 myLCID = 0; 354 } 355 else 356 { 357 break; 358 } 359 } 360 else 361 { 362 *path = SysAllocString( Path ); 363 hr = S_OK; 364 } 365 } 366 RegCloseKey( hkey ); 367 TRACE_(typelib)("-- 0x%08x\n", hr); 368 return hr; 369 } 370 371 /****************************************************************************** 372 * CreateTypeLib [OLEAUT32.160] creates a typelib 373 * 374 * RETURNS 375 * Success: S_OK 376 * Failure: Status 377 */ 378 HRESULT WINAPI CreateTypeLib( 379 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib 380 ) { 381 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib); 382 return E_FAIL; 383 } 384 385 /****************************************************************************** 386 * LoadTypeLib [OLEAUT32.161] 387 * 388 * Loads a type library 389 * 390 * PARAMS 391 * szFile [I] Name of file to load from. 392 * pptLib [O] Pointer that receives ITypeLib object on success. 393 * 394 * RETURNS 395 * Success: S_OK 396 * Failure: Status 397 * 398 * SEE 399 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib. 400 */ 401 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib) 402 { 403 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib); 404 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib); 405 } 406 407 /****************************************************************************** 408 * LoadTypeLibEx [OLEAUT32.183] 409 * 410 * Loads and optionally registers a type library 411 * 412 * RETURNS 413 * Success: S_OK 414 * Failure: Status 415 */ 416 HRESULT WINAPI LoadTypeLibEx( 417 LPCOLESTR szFile, /* [in] Name of file to load from */ 418 REGKIND regkind, /* [in] Specify kind of registration */ 419 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */ 420 { 421 WCHAR szPath[MAX_PATH+1]; 422 HRESULT res; 423 424 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib); 425 426 *pptLib = NULL; 427 428 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib); 429 430 if (SUCCEEDED(res)) 431 switch(regkind) 432 { 433 case REGKIND_DEFAULT: 434 /* don't register typelibs supplied with full path. Experimentation confirms the following */ 435 if (((szFile[0] == '\\') && (szFile[1] == '\\')) || 436 (szFile[0] && (szFile[1] == ':'))) break; 437 /* else fall-through */ 438 439 case REGKIND_REGISTER: 440 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL))) 441 { 442 IUnknown_Release(*pptLib); 443 *pptLib = 0; 444 } 445 break; 446 case REGKIND_NONE: 447 break; 448 } 449 450 TRACE(" returns %08x\n",res); 451 return res; 452 } 453 454 /****************************************************************************** 455 * LoadRegTypeLib [OLEAUT32.162] 456 * 457 * Loads a registered type library. 458 * 459 * PARAMS 460 * rguid [I] GUID of the registered type library. 461 * wVerMajor [I] major version. 462 * wVerMinor [I] minor version. 463 * lcid [I] locale ID. 464 * ppTLib [O] pointer that receives an ITypeLib object on success. 465 * 466 * RETURNS 467 * Success: S_OK. 468 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or 469 * LoadTypeLib. 470 */ 471 HRESULT WINAPI LoadRegTypeLib( 472 REFGUID rguid, 473 WORD wVerMajor, 474 WORD wVerMinor, 475 LCID lcid, 476 ITypeLib **ppTLib) 477 { 478 BSTR bstr=NULL; 479 HRESULT res; 480 481 *ppTLib = NULL; 482 483 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr); 484 485 if(SUCCEEDED(res)) 486 { 487 res= LoadTypeLib(bstr, ppTLib); 488 SysFreeString(bstr); 489 } 490 491 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib); 492 493 return res; 494 } 495 496 497 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */ 498 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0}; 499 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0}; 500 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0}; 501 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0}; 502 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0}; 503 504 /****************************************************************************** 505 * RegisterTypeLib [OLEAUT32.163] 506 * Adds information about a type library to the System Registry 507 * NOTES 508 * Docs: ITypeLib FAR * ptlib 509 * Docs: OLECHAR FAR* szFullPath 510 * Docs: OLECHAR FAR* szHelpDir 511 * 512 * RETURNS 513 * Success: S_OK 514 * Failure: Status 515 */ 516 HRESULT WINAPI RegisterTypeLib( 517 ITypeLib * ptlib, /* [in] Pointer to the library*/ 518 OLECHAR * szFullPath, /* [in] full Path of the library*/ 519 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library, 520 may be NULL*/ 521 { 522 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-', 523 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-', 524 '0','0','0','0','0','0','0','0','0','0','4','6','}',0}; 525 HRESULT res; 526 TLIBATTR *attr; 527 WCHAR keyName[60]; 528 WCHAR tmp[16]; 529 HKEY key, subKey; 530 UINT types, tidx; 531 TYPEKIND kind; 532 DWORD disposition; 533 534 if (ptlib == NULL || szFullPath == NULL) 535 return E_INVALIDARG; 536 537 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr))) 538 return E_FAIL; 539 540 #ifdef _WIN64 541 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND; 542 #else 543 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND; 544 #endif 545 546 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName ); 547 548 res = S_OK; 549 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, 550 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) 551 { 552 LPOLESTR doc; 553 554 /* Set the human-readable name of the typelib */ 555 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL))) 556 { 557 if (RegSetValueExW(key, NULL, 0, REG_SZ, 558 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) 559 res = E_FAIL; 560 561 SysFreeString(doc); 562 } 563 else 564 res = E_FAIL; 565 566 /* Make up the name of the typelib path subkey */ 567 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL; 568 569 /* Create the typelib path subkey */ 570 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0, 571 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) 572 { 573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 574 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) 575 res = E_FAIL; 576 577 RegCloseKey(subKey); 578 } 579 else 580 res = E_FAIL; 581 582 /* Create the flags subkey */ 583 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0, 584 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) 585 { 586 /* FIXME: is %u correct? */ 587 static const WCHAR formatW[] = {'%','u',0}; 588 WCHAR buf[20]; 589 sprintfW(buf, formatW, attr->wLibFlags); 590 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 591 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS) 592 res = E_FAIL; 593 594 RegCloseKey(subKey); 595 } 596 else 597 res = E_FAIL; 598 599 /* create the helpdir subkey */ 600 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0, 601 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS) 602 { 603 BOOL freeHelpDir = FALSE; 604 OLECHAR* pIndexStr; 605 606 /* if we created a new key, and helpDir was null, set the helpdir 607 to the directory which contains the typelib. However, 608 if we just opened an existing key, we leave the helpdir alone */ 609 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) { 610 szHelpDir = SysAllocString(szFullPath); 611 pIndexStr = strrchrW(szHelpDir, '\\'); 612 if (pIndexStr) { 613 *pIndexStr = 0; 614 } 615 freeHelpDir = TRUE; 616 } 617 618 /* if we have an szHelpDir, set it! */ 619 if (szHelpDir != NULL) { 620 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 621 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) { 622 res = E_FAIL; 623 } 624 } 625 626 /* tidy up */ 627 if (freeHelpDir) SysFreeString(szHelpDir); 628 RegCloseKey(subKey); 629 630 } else { 631 res = E_FAIL; 632 } 633 634 RegCloseKey(key); 635 } 636 else 637 res = E_FAIL; 638 639 /* register OLE Automation-compatible interfaces for this typelib */ 640 types = ITypeLib_GetTypeInfoCount(ptlib); 641 for (tidx=0; tidx<types; tidx++) { 642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) { 643 LPOLESTR name = NULL; 644 ITypeInfo *tinfo = NULL; 645 646 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL); 647 648 switch (kind) { 649 case TKIND_INTERFACE: 650 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name)); 651 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); 652 break; 653 654 case TKIND_DISPATCH: 655 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name)); 656 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); 657 break; 658 659 default: 660 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name)); 661 break; 662 } 663 664 if (tinfo) { 665 TYPEATTR *tattr = NULL; 666 ITypeInfo_GetTypeAttr(tinfo, &tattr); 667 668 if (tattr) { 669 TRACE_(typelib)("guid=%s, flags=%04x (", 670 debugstr_guid(&tattr->guid), 671 tattr->wTypeFlags); 672 673 if (TRACE_ON(typelib)) { 674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|"); 675 XX(FAPPOBJECT); 676 XX(FCANCREATE); 677 XX(FLICENSED); 678 XX(FPREDECLID); 679 XX(FHIDDEN); 680 XX(FCONTROL); 681 XX(FDUAL); 682 XX(FNONEXTENSIBLE); 683 XX(FOLEAUTOMATION); 684 XX(FRESTRICTED); 685 XX(FAGGREGATABLE); 686 XX(FREPLACEABLE); 687 XX(FDISPATCHABLE); 688 XX(FREVERSEBIND); 689 XX(FPROXY); 690 #undef XX 691 MESSAGE("\n"); 692 } 693 694 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE)) 695 { 696 /* register interface<->typelib coupling */ 697 get_interface_key( &tattr->guid, keyName ); 698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, 699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) 700 { 701 if (name) 702 RegSetValueExW(key, NULL, 0, REG_SZ, 703 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR)); 704 705 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0, 706 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { 707 RegSetValueExW(subKey, NULL, 0, REG_SZ, 708 (const BYTE *)PSOA, sizeof PSOA); 709 RegCloseKey(subKey); 710 } 711 712 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0, 713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { 714 RegSetValueExW(subKey, NULL, 0, REG_SZ, 715 (const BYTE *)PSOA, sizeof PSOA); 716 RegCloseKey(subKey); 717 } 718 719 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0, 720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) 721 { 722 WCHAR buffer[40]; 723 static const WCHAR fmtver[] = {'%','x','.','%','x',0 }; 724 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0}; 725 726 StringFromGUID2(&attr->guid, buffer, 40); 727 RegSetValueExW(subKey, NULL, 0, REG_SZ, 728 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR)); 729 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum); 730 RegSetValueExW(subKey, VersionW, 0, REG_SZ, 731 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR)); 732 RegCloseKey(subKey); 733 } 734 735 RegCloseKey(key); 736 } 737 } 738 739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr); 740 } 741 742 ITypeInfo_Release(tinfo); 743 } 744 745 SysFreeString(name); 746 } 747 } 748 749 ITypeLib_ReleaseTLibAttr(ptlib, attr); 750 751 return res; 752 } 753 754 755 /****************************************************************************** 756 * UnRegisterTypeLib [OLEAUT32.186] 757 * Removes information about a type library from the System Registry 758 * NOTES 759 * 760 * RETURNS 761 * Success: S_OK 762 * Failure: Status 763 */ 764 HRESULT WINAPI UnRegisterTypeLib( 765 REFGUID libid, /* [in] Guid of the library */ 766 WORD wVerMajor, /* [in] major version */ 767 WORD wVerMinor, /* [in] minor version */ 768 LCID lcid, /* [in] locale id */ 769 SYSKIND syskind) 770 { 771 BSTR tlibPath = NULL; 772 DWORD tmpLength; 773 WCHAR keyName[60]; 774 WCHAR subKeyName[50]; 775 int result = S_OK; 776 DWORD i = 0; 777 BOOL deleteOtherStuff; 778 HKEY key = NULL; 779 HKEY subKey = NULL; 780 TYPEATTR* typeAttr = NULL; 781 TYPEKIND kind; 782 ITypeInfo* typeInfo = NULL; 783 ITypeLib* typeLib = NULL; 784 int numTypes; 785 786 TRACE("(IID: %s)\n",debugstr_guid(libid)); 787 788 /* Create the path to the key */ 789 get_typelib_key( libid, wVerMajor, wVerMinor, keyName ); 790 791 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64) 792 { 793 TRACE("Unsupported syskind %i\n", syskind); 794 result = E_INVALIDARG; 795 goto end; 796 } 797 798 /* get the path to the typelib on disk */ 799 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) { 800 result = E_INVALIDARG; 801 goto end; 802 } 803 804 /* Try and open the key to the type library. */ 805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) { 806 result = E_INVALIDARG; 807 goto end; 808 } 809 810 /* Try and load the type library */ 811 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) { 812 result = TYPE_E_INVALIDSTATE; 813 goto end; 814 } 815 816 /* remove any types registered with this typelib */ 817 numTypes = ITypeLib_GetTypeInfoCount(typeLib); 818 for (i=0; i<numTypes; i++) { 819 /* get the kind of type */ 820 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) { 821 goto enddeleteloop; 822 } 823 824 /* skip non-interfaces, and get type info for the type */ 825 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) { 826 goto enddeleteloop; 827 } 828 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) { 829 goto enddeleteloop; 830 } 831 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) { 832 goto enddeleteloop; 833 } 834 835 /* the path to the type */ 836 get_interface_key( &typeAttr->guid, subKeyName ); 837 838 /* Delete its bits */ 839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) { 840 goto enddeleteloop; 841 } 842 RegDeleteKeyW(subKey, ProxyStubClsidW); 843 RegDeleteKeyW(subKey, ProxyStubClsid32W); 844 RegDeleteKeyW(subKey, TypeLibW); 845 RegCloseKey(subKey); 846 subKey = NULL; 847 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName); 848 849 enddeleteloop: 850 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr); 851 typeAttr = NULL; 852 if (typeInfo) ITypeInfo_Release(typeInfo); 853 typeInfo = NULL; 854 } 855 856 /* Now, delete the type library path subkey */ 857 get_lcid_subkey( lcid, syskind, subKeyName ); 858 RegDeleteKeyW(key, subKeyName); 859 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */ 860 RegDeleteKeyW(key, subKeyName); 861 862 /* check if there is anything besides the FLAGS/HELPDIR keys. 863 If there is, we don't delete them */ 864 tmpLength = sizeof(subKeyName)/sizeof(WCHAR); 865 deleteOtherStuff = TRUE; 866 i = 0; 867 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { 868 tmpLength = sizeof(subKeyName)/sizeof(WCHAR); 869 870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */ 871 if (!strcmpW(subKeyName, FLAGSW)) continue; 872 if (!strcmpW(subKeyName, HELPDIRW)) continue; 873 deleteOtherStuff = FALSE; 874 break; 875 } 876 877 /* only delete the other parts of the key if we're absolutely sure */ 878 if (deleteOtherStuff) { 879 RegDeleteKeyW(key, FLAGSW); 880 RegDeleteKeyW(key, HELPDIRW); 881 RegCloseKey(key); 882 key = NULL; 883 884 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName); 885 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */ 886 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName); 887 } 888 889 end: 890 SysFreeString(tlibPath); 891 if (typeLib) ITypeLib_Release(typeLib); 892 if (subKey) RegCloseKey(subKey); 893 if (key) RegCloseKey(key); 894 return result; 895 } 896 897 /*======================= ITypeLib implementation =======================*/ 898 899 typedef struct tagTLBCustData 900 { 901 GUID guid; 902 VARIANT data; 903 struct tagTLBCustData* next; 904 } TLBCustData; 905 906 /* data structure for import typelibs */ 907 typedef struct tagTLBImpLib 908 { 909 int offset; /* offset in the file (MSFT) 910 offset in nametable (SLTG) 911 just used to identify library while reading 912 data from file */ 913 GUID guid; /* libid */ 914 BSTR name; /* name */ 915 916 LCID lcid; /* lcid of imported typelib */ 917 918 WORD wVersionMajor; /* major version number */ 919 WORD wVersionMinor; /* minor version number */ 920 921 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or 922 NULL if not yet loaded */ 923 struct tagTLBImpLib * next; 924 } TLBImpLib; 925 926 /* internal ITypeLib data */ 927 typedef struct tagITypeLibImpl 928 { 929 const ITypeLib2Vtbl *lpVtbl; 930 const ITypeCompVtbl *lpVtblTypeComp; 931 LONG ref; 932 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */ 933 LCID lcid; 934 935 /* strings can be stored in tlb as multibyte strings BUT they are *always* 936 * exported to the application as a UNICODE string. 937 */ 938 BSTR Name; 939 BSTR DocString; 940 BSTR HelpFile; 941 BSTR HelpStringDll; 942 DWORD dwHelpContext; 943 int TypeInfoCount; /* nr of typeinfo's in librarry */ 944 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */ 945 int ctCustData; /* number of items in cust data list */ 946 TLBCustData * pCustData; /* linked list to cust data */ 947 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */ 948 int ctTypeDesc; /* number of items in type desc array */ 949 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the 950 library. Only used while reading MSFT 951 typelibs */ 952 struct list ref_list; /* list of ref types in this typelib */ 953 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */ 954 955 956 /* typelibs are cached, keyed by path and index, so store the linked list info within them */ 957 struct tagITypeLibImpl *next, *prev; 958 WCHAR *path; 959 INT index; 960 } ITypeLibImpl; 961 962 static const ITypeLib2Vtbl tlbvt; 963 static const ITypeCompVtbl tlbtcvt; 964 965 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface ) 966 { 967 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp)); 968 } 969 970 /* ITypeLib methods */ 971 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength); 972 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength); 973 974 /*======================= ITypeInfo implementation =======================*/ 975 976 /* data for referenced types */ 977 typedef struct tagTLBRefType 978 { 979 INT index; /* Type index for internal ref or for external ref 980 it the format is SLTG. -2 indicates to 981 use guid */ 982 983 GUID guid; /* guid of the referenced type */ 984 /* if index == TLB_REF_USE_GUID */ 985 986 HREFTYPE reference; /* The href of this ref */ 987 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data 988 TLB_REF_INTERNAL for internal refs 989 TLB_REF_NOT_FOUND for broken refs */ 990 991 struct list entry; 992 } TLBRefType; 993 994 #define TLB_REF_USE_GUID -2 995 996 #define TLB_REF_INTERNAL (void*)-2 997 #define TLB_REF_NOT_FOUND (void*)-1 998 999 /* internal Parameter data */ 1000 typedef struct tagTLBParDesc 1001 { 1002 BSTR Name; 1003 int ctCustData; 1004 TLBCustData * pCustData; /* linked list to cust data */ 1005 } TLBParDesc; 1006 1007 /* internal Function data */ 1008 typedef struct tagTLBFuncDesc 1009 { 1010 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */ 1011 BSTR Name; /* the name of this function */ 1012 TLBParDesc *pParamDesc; /* array with param names and custom data */ 1013 int helpcontext; 1014 int HelpStringContext; 1015 BSTR HelpString; 1016 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/ 1017 int ctCustData; 1018 TLBCustData * pCustData; /* linked list to cust data; */ 1019 struct tagTLBFuncDesc * next; 1020 } TLBFuncDesc; 1021 1022 /* internal Variable data */ 1023 typedef struct tagTLBVarDesc 1024 { 1025 VARDESC vardesc; /* lots of info on the variable and its attributes. */ 1026 BSTR Name; /* the name of this variable */ 1027 int HelpContext; 1028 int HelpStringContext; /* FIXME: where? */ 1029 BSTR HelpString; 1030 int ctCustData; 1031 TLBCustData * pCustData;/* linked list to cust data; */ 1032 struct tagTLBVarDesc * next; 1033 } TLBVarDesc; 1034 1035 /* internal implemented interface data */ 1036 typedef struct tagTLBImplType 1037 { 1038 HREFTYPE hRef; /* hRef of interface */ 1039 int implflags; /* IMPLFLAG_*s */ 1040 int ctCustData; 1041 TLBCustData * pCustData;/* linked list to custom data; */ 1042 struct tagTLBImplType *next; 1043 } TLBImplType; 1044 1045 /* internal TypeInfo data */ 1046 typedef struct tagITypeInfoImpl 1047 { 1048 const ITypeInfo2Vtbl *lpVtbl; 1049 const ITypeCompVtbl *lpVtblTypeComp; 1050 LONG ref; 1051 BOOL no_free_data; /* don't free data structures */ 1052 TYPEATTR TypeAttr ; /* _lots_ of type information. */ 1053 ITypeLibImpl * pTypeLib; /* back pointer to typelib */ 1054 int index; /* index in this typelib; */ 1055 HREFTYPE hreftype; /* hreftype for app object binding */ 1056 /* type libs seem to store the doc strings in ascii 1057 * so why should we do it in unicode? 1058 */ 1059 BSTR Name; 1060 BSTR DocString; 1061 BSTR DllName; 1062 DWORD dwHelpContext; 1063 DWORD dwHelpStringContext; 1064 1065 /* functions */ 1066 TLBFuncDesc * funclist; /* linked list with function descriptions */ 1067 1068 /* variables */ 1069 TLBVarDesc * varlist; /* linked list with variable descriptions */ 1070 1071 /* Implemented Interfaces */ 1072 TLBImplType * impltypelist; 1073 1074 int ctCustData; 1075 TLBCustData * pCustData; /* linked list to cust data; */ 1076 struct tagITypeInfoImpl * next; 1077 } ITypeInfoImpl; 1078 1079 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface ) 1080 { 1081 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp)); 1082 } 1083 1084 static const ITypeInfo2Vtbl tinfvt; 1085 static const ITypeCompVtbl tcompvt; 1086 1087 static ITypeInfo2 * ITypeInfo_Constructor(void); 1088 1089 typedef struct tagTLBContext 1090 { 1091 unsigned int oStart; /* start of TLB in file */ 1092 unsigned int pos; /* current pos */ 1093 unsigned int length; /* total length */ 1094 void *mapping; /* memory mapping */ 1095 MSFT_SegDir * pTblDir; 1096 ITypeLibImpl* pLibInfo; 1097 } TLBContext; 1098 1099 1100 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset); 1101 1102 /* 1103 debug 1104 */ 1105 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) { 1106 if (pTD->vt & VT_RESERVED) 1107 szVarType += strlen(strcpy(szVarType, "reserved | ")); 1108 if (pTD->vt & VT_BYREF) 1109 szVarType += strlen(strcpy(szVarType, "ref to ")); 1110 if (pTD->vt & VT_ARRAY) 1111 szVarType += strlen(strcpy(szVarType, "array of ")); 1112 if (pTD->vt & VT_VECTOR) 1113 szVarType += strlen(strcpy(szVarType, "vector of ")); 1114 switch(pTD->vt & VT_TYPEMASK) { 1115 case VT_UI1: sprintf(szVarType, "VT_UI1"); break; 1116 case VT_I2: sprintf(szVarType, "VT_I2"); break; 1117 case VT_I4: sprintf(szVarType, "VT_I4"); break; 1118 case VT_R4: sprintf(szVarType, "VT_R4"); break; 1119 case VT_R8: sprintf(szVarType, "VT_R8"); break; 1120 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break; 1121 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break; 1122 case VT_CY: sprintf(szVarType, "VT_CY"); break; 1123 case VT_DATE: sprintf(szVarType, "VT_DATE"); break; 1124 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break; 1125 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break; 1126 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break; 1127 case VT_I1: sprintf(szVarType, "VT_I1"); break; 1128 case VT_UI2: sprintf(szVarType, "VT_UI2"); break; 1129 case VT_UI4: sprintf(szVarType, "VT_UI4"); break; 1130 case VT_INT: sprintf(szVarType, "VT_INT"); break; 1131 case VT_UINT: sprintf(szVarType, "VT_UINT"); break; 1132 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break; 1133 case VT_VOID: sprintf(szVarType, "VT_VOID"); break; 1134 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break; 1135 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x", 1136 pTD->u.hreftype); break; 1137 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break; 1138 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break; 1139 case VT_PTR: sprintf(szVarType, "ptr to "); 1140 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7); 1141 break; 1142 case VT_SAFEARRAY: sprintf(szVarType, "safearray of "); 1143 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13); 1144 break; 1145 case VT_CARRAY: sprintf(szVarType, "%d dim array of ", 1146 pTD->u.lpadesc->cDims); /* FIXME print out sizes */ 1147 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType)); 1148 break; 1149 1150 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break; 1151 } 1152 } 1153 1154 static void dump_ELEMDESC(const ELEMDESC *edesc) { 1155 char buf[200]; 1156 USHORT flags = edesc->u.paramdesc.wParamFlags; 1157 dump_TypeDesc(&edesc->tdesc,buf); 1158 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf); 1159 MESSAGE("\t\tu.paramdesc.wParamFlags"); 1160 if (!flags) MESSAGE(" PARAMFLAGS_NONE"); 1161 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN"); 1162 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT"); 1163 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID"); 1164 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL"); 1165 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT"); 1166 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT"); 1167 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA"); 1168 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex); 1169 } 1170 static void dump_FUNCDESC(const FUNCDESC *funcdesc) { 1171 int i; 1172 MESSAGE("memid is %08x\n",funcdesc->memid); 1173 for (i=0;i<funcdesc->cParams;i++) { 1174 MESSAGE("Param %d:\n",i); 1175 dump_ELEMDESC(funcdesc->lprgelemdescParam+i); 1176 } 1177 MESSAGE("\tfunckind: %d (",funcdesc->funckind); 1178 switch (funcdesc->funckind) { 1179 case FUNC_VIRTUAL: MESSAGE("virtual");break; 1180 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break; 1181 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break; 1182 case FUNC_STATIC: MESSAGE("static");break; 1183 case FUNC_DISPATCH: MESSAGE("dispatch");break; 1184 default: MESSAGE("unknown");break; 1185 } 1186 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind); 1187 switch (funcdesc->invkind) { 1188 case INVOKE_FUNC: MESSAGE("func");break; 1189 case INVOKE_PROPERTYGET: MESSAGE("property get");break; 1190 case INVOKE_PROPERTYPUT: MESSAGE("property put");break; 1191 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break; 1192 } 1193 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv); 1194 switch (funcdesc->callconv) { 1195 case CC_CDECL: MESSAGE("cdecl");break; 1196 case CC_PASCAL: MESSAGE("pascal");break; 1197 case CC_STDCALL: MESSAGE("stdcall");break; 1198 case CC_SYSCALL: MESSAGE("syscall");break; 1199 default:break; 1200 } 1201 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft); 1202 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt); 1203 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags); 1204 1205 MESSAGE("\telemdescFunc (return value type):\n"); 1206 dump_ELEMDESC(&funcdesc->elemdescFunc); 1207 } 1208 1209 static const char * const typekind_desc[] = 1210 { 1211 "TKIND_ENUM", 1212 "TKIND_RECORD", 1213 "TKIND_MODULE", 1214 "TKIND_INTERFACE", 1215 "TKIND_DISPATCH", 1216 "TKIND_COCLASS", 1217 "TKIND_ALIAS", 1218 "TKIND_UNION", 1219 "TKIND_MAX" 1220 }; 1221 1222 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd) 1223 { 1224 int i; 1225 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams); 1226 for (i=0;i<pfd->funcdesc.cParams;i++) 1227 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name)); 1228 1229 1230 dump_FUNCDESC(&(pfd->funcdesc)); 1231 1232 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString)); 1233 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry)); 1234 } 1235 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd) 1236 { 1237 while (pfd) 1238 { 1239 dump_TLBFuncDescOne(pfd); 1240 pfd = pfd->next; 1241 }; 1242 } 1243 static void dump_TLBVarDesc(const TLBVarDesc * pvd) 1244 { 1245 while (pvd) 1246 { 1247 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name)); 1248 pvd = pvd->next; 1249 }; 1250 } 1251 1252 static void dump_TLBImpLib(const TLBImpLib *import) 1253 { 1254 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)), 1255 debugstr_w(import->name)); 1256 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor, 1257 import->wVersionMinor, import->lcid, import->offset); 1258 } 1259 1260 static void dump_TLBRefType(const ITypeLibImpl *pTL) 1261 { 1262 TLBRefType *ref; 1263 1264 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry) 1265 { 1266 TRACE_(typelib)("href:0x%08x\n", ref->reference); 1267 if(ref->index == -1) 1268 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid))); 1269 else 1270 TRACE_(typelib)("type no: %d\n", ref->index); 1271 1272 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND) 1273 { 1274 TRACE_(typelib)("in lib\n"); 1275 dump_TLBImpLib(ref->pImpTLInfo); 1276 } 1277 } 1278 } 1279 1280 static void dump_TLBImplType(const TLBImplType * impl) 1281 { 1282 while (impl) { 1283 TRACE_(typelib)( 1284 "implementing/inheriting interface hRef = %x implflags %x\n", 1285 impl->hRef, impl->implflags); 1286 impl = impl->next; 1287 } 1288 } 1289 1290 static void dump_Variant(const VARIANT * pvar) 1291 { 1292 SYSTEMTIME st; 1293 1294 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar)); 1295 1296 if (pvar) 1297 { 1298 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN || 1299 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD) 1300 { 1301 TRACE(",%p", V_BYREF(pvar)); 1302 } 1303 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar)) 1304 { 1305 TRACE(",%p", V_ARRAY(pvar)); 1306 } 1307 else switch (V_TYPE(pvar)) 1308 { 1309 case VT_I1: TRACE(",%d", V_I1(pvar)); break; 1310 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break; 1311 case VT_I2: TRACE(",%d", V_I2(pvar)); break; 1312 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break; 1313 case VT_INT: 1314 case VT_I4: TRACE(",%d", V_I4(pvar)); break; 1315 case VT_UINT: 1316 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break; 1317 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32), 1318 (ULONG)(V_I8(pvar) & 0xffffffff)); break; 1319 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32), 1320 (ULONG)(V_UI8(pvar) & 0xffffffff)); break; 1321 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break; 1322 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break; 1323 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break; 1324 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break; 1325 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi, 1326 V_CY(pvar).s.Lo); break; 1327 case VT_DATE: 1328 if(!VariantTimeToSystemTime(V_DATE(pvar), &st)) 1329 TRACE(",<invalid>"); 1330 else 1331 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, 1332 st.wHour, st.wMinute, st.wSecond); 1333 break; 1334 case VT_ERROR: 1335 case VT_VOID: 1336 case VT_USERDEFINED: 1337 case VT_EMPTY: 1338 case VT_NULL: break; 1339 default: TRACE(",?"); break; 1340 } 1341 } 1342 TRACE("}\n"); 1343 } 1344 1345 static void dump_DispParms(const DISPPARAMS * pdp) 1346 { 1347 unsigned int index; 1348 1349 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs); 1350 1351 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs) 1352 { 1353 TRACE("named args:\n"); 1354 for (index = 0; index < pdp->cNamedArgs; index++) 1355 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] ); 1356 } 1357 1358 if (pdp->cArgs && pdp->rgvarg) 1359 { 1360 TRACE("args:\n"); 1361 for (index = 0; index < pdp->cArgs; index++) 1362 dump_Variant( &pdp->rgvarg[index] ); 1363 } 1364 } 1365 1366 static void dump_TypeInfo(const ITypeInfoImpl * pty) 1367 { 1368 TRACE("%p ref=%u\n", pty, pty->ref); 1369 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString)); 1370 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid))); 1371 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]); 1372 TRACE("fct:%u var:%u impl:%u\n", 1373 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes); 1374 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags); 1375 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index); 1376 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName)); 1377 if (TRACE_ON(ole)) 1378 dump_TLBFuncDesc(pty->funclist); 1379 dump_TLBVarDesc(pty->varlist); 1380 dump_TLBImplType(pty->impltypelist); 1381 } 1382 1383 static void dump_VARDESC(const VARDESC *v) 1384 { 1385 MESSAGE("memid %d\n",v->memid); 1386 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema)); 1387 MESSAGE("oInst %d\n",v->u.oInst); 1388 dump_ELEMDESC(&(v->elemdescVar)); 1389 MESSAGE("wVarFlags %x\n",v->wVarFlags); 1390 MESSAGE("varkind %d\n",v->varkind); 1391 } 1392 1393 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]= 1394 { 1395 /* VT_LPWSTR is largest type that */ 1396 /* may appear in type description*/ 1397 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4}, 1398 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9}, 1399 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14}, 1400 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19}, 1401 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24}, 1402 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29}, 1403 {{0},30},{{0},31} 1404 }; 1405 1406 static void TLB_abort(void) 1407 { 1408 DebugBreak(); 1409 } 1410 1411 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1); 1412 static void * TLB_Alloc(unsigned size) 1413 { 1414 void * ret; 1415 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){ 1416 /* FIXME */ 1417 ERR("cannot allocate memory\n"); 1418 } 1419 return ret; 1420 } 1421 1422 static void TLB_Free(void * ptr) 1423 { 1424 HeapFree(GetProcessHeap(), 0, ptr); 1425 } 1426 1427 /* returns the size required for a deep copy of a typedesc into a 1428 * flat buffer */ 1429 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space ) 1430 { 1431 SIZE_T size = 0; 1432 1433 if (alloc_initial_space) 1434 size += sizeof(TYPEDESC); 1435 1436 switch (tdesc->vt) 1437 { 1438 case VT_PTR: 1439 case VT_SAFEARRAY: 1440 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE); 1441 break; 1442 case VT_CARRAY: 1443 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]); 1444 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE); 1445 break; 1446 } 1447 return size; 1448 } 1449 1450 /* deep copy a typedesc into a flat buffer */ 1451 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer ) 1452 { 1453 if (!dest) 1454 { 1455 dest = buffer; 1456 buffer = (char *)buffer + sizeof(TYPEDESC); 1457 } 1458 1459 *dest = *src; 1460 1461 switch (src->vt) 1462 { 1463 case VT_PTR: 1464 case VT_SAFEARRAY: 1465 dest->u.lptdesc = buffer; 1466 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer); 1467 break; 1468 case VT_CARRAY: 1469 dest->u.lpadesc = buffer; 1470 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims])); 1471 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]); 1472 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer); 1473 break; 1474 } 1475 return buffer; 1476 } 1477 1478 /* free custom data allocated by MSFT_CustData */ 1479 static inline void TLB_FreeCustData(TLBCustData *pCustData) 1480 { 1481 TLBCustData *pCustDataNext; 1482 for (; pCustData; pCustData = pCustDataNext) 1483 { 1484 VariantClear(&pCustData->data); 1485 1486 pCustDataNext = pCustData->next; 1487 TLB_Free(pCustData); 1488 } 1489 } 1490 1491 static BSTR TLB_MultiByteToBSTR(const char *ptr) 1492 { 1493 DWORD len; 1494 BSTR ret; 1495 1496 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0); 1497 ret = SysAllocStringLen(NULL, len - 1); 1498 if (!ret) return ret; 1499 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len); 1500 return ret; 1501 } 1502 1503 /********************************************************************** 1504 * 1505 * Functions for reading MSFT typelibs (those created by CreateTypeLib2) 1506 */ 1507 static inline unsigned int MSFT_Tell(const TLBContext *pcx) 1508 { 1509 return pcx->pos; 1510 } 1511 1512 static inline void MSFT_Seek(TLBContext *pcx, long where) 1513 { 1514 if (where != DO_NOT_SEEK) 1515 { 1516 where += pcx->oStart; 1517 if (where > pcx->length) 1518 { 1519 /* FIXME */ 1520 ERR("seek beyond end (%ld/%d)\n", where, pcx->length ); 1521 TLB_abort(); 1522 } 1523 pcx->pos = where; 1524 } 1525 } 1526 1527 /* read function */ 1528 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where ) 1529 { 1530 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n", 1531 pcx->pos, count, pcx->oStart, pcx->length, where); 1532 1533 MSFT_Seek(pcx, where); 1534 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos; 1535 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count ); 1536 pcx->pos += count; 1537 return count; 1538 } 1539 1540 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx, 1541 long where ) 1542 { 1543 DWORD ret; 1544 1545 ret = MSFT_Read(buffer, count, pcx, where); 1546 FromLEDWords(buffer, ret); 1547 1548 return ret; 1549 } 1550 1551 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx, 1552 long where ) 1553 { 1554 DWORD ret; 1555 1556 ret = MSFT_Read(buffer, count, pcx, where); 1557 FromLEWords(buffer, ret); 1558 1559 return ret; 1560 } 1561 1562 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx) 1563 { 1564 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){ 1565 memset(pGuid,0, sizeof(GUID)); 1566 return; 1567 } 1568 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset ); 1569 pGuid->Data1 = FromLEDWord(pGuid->Data1); 1570 pGuid->Data2 = FromLEWord(pGuid->Data2); 1571 pGuid->Data3 = FromLEWord(pGuid->Data3); 1572 TRACE_(typelib)("%s\n", debugstr_guid(pGuid)); 1573 } 1574 1575 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset ) 1576 { 1577 MSFT_NameIntro niName; 1578 1579 if (offset < 0) 1580 { 1581 ERR_(typelib)("bad offset %d\n", offset); 1582 return -1; 1583 } 1584 1585 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx, 1586 pcx->pTblDir->pNametab.offset+offset); 1587 1588 return niName.hreftype; 1589 } 1590 1591 static BSTR MSFT_ReadName( TLBContext *pcx, int offset) 1592 { 1593 char * name; 1594 MSFT_NameIntro niName; 1595 int lengthInChars; 1596 BSTR bstrName = NULL; 1597 1598 if (offset < 0) 1599 { 1600 ERR_(typelib)("bad offset %d\n", offset); 1601 return NULL; 1602 } 1603 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx, 1604 pcx->pTblDir->pNametab.offset+offset); 1605 niName.namelen &= 0xFF; /* FIXME: correct ? */ 1606 name=TLB_Alloc((niName.namelen & 0xff) +1); 1607 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK); 1608 name[niName.namelen & 0xff]='\0'; 1609 1610 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, 1611 name, -1, NULL, 0); 1612 1613 /* no invalid characters in string */ 1614 if (lengthInChars) 1615 { 1616 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR)); 1617 1618 /* don't check for invalid character since this has been done previously */ 1619 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars); 1620 } 1621 TLB_Free(name); 1622 1623 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars); 1624 return bstrName; 1625 } 1626 1627 static BSTR MSFT_ReadString( TLBContext *pcx, int offset) 1628 { 1629 char * string; 1630 INT16 length; 1631 int lengthInChars; 1632 BSTR bstr = NULL; 1633 1634 if(offset<0) return NULL; 1635 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset); 1636 if(length <= 0) return 0; 1637 string=TLB_Alloc(length +1); 1638 MSFT_Read(string, length, pcx, DO_NOT_SEEK); 1639 string[length]='\0'; 1640 1641 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, 1642 string, -1, NULL, 0); 1643 1644 /* no invalid characters in string */ 1645 if (lengthInChars) 1646 { 1647 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR)); 1648 1649 /* don't check for invalid character since this has been done previously */ 1650 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars); 1651 } 1652 TLB_Free(string); 1653 1654 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars); 1655 return bstr; 1656 } 1657 /* 1658 * read a value and fill a VARIANT structure 1659 */ 1660 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) 1661 { 1662 int size; 1663 1664 TRACE_(typelib)("\n"); 1665 1666 if(offset <0) { /* data are packed in here */ 1667 V_VT(pVar) = (offset & 0x7c000000 )>> 26; 1668 V_I4(pVar) = offset & 0x3ffffff; 1669 return; 1670 } 1671 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx, 1672 pcx->pTblDir->pCustData.offset + offset ); 1673 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar)); 1674 switch (V_VT(pVar)){ 1675 case VT_EMPTY: /* FIXME: is this right? */ 1676 case VT_NULL: /* FIXME: is this right? */ 1677 case VT_I2 : /* this should not happen */ 1678 case VT_I4 : 1679 case VT_R4 : 1680 case VT_ERROR : 1681 case VT_BOOL : 1682 case VT_I1 : 1683 case VT_UI1 : 1684 case VT_UI2 : 1685 case VT_UI4 : 1686 case VT_INT : 1687 case VT_UINT : 1688 case VT_VOID : /* FIXME: is this right? */ 1689 case VT_HRESULT : 1690 size=4; break; 1691 case VT_R8 : 1692 case VT_CY : 1693 case VT_DATE : 1694 case VT_I8 : 1695 case VT_UI8 : 1696 case VT_DECIMAL : /* FIXME: is this right? */ 1697 case VT_FILETIME : 1698 size=8;break; 1699 /* pointer types with known behaviour */ 1700 case VT_BSTR :{ 1701 char * ptr; 1702 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK ); 1703 if(size < 0) { 1704 char next; 1705 DWORD origPos = MSFT_Tell(pcx), nullPos; 1706 1707 do { 1708 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK); 1709 } while (next); 1710 nullPos = MSFT_Tell(pcx); 1711 size = nullPos - origPos; 1712 MSFT_Seek(pcx, origPos); 1713 } 1714 ptr=TLB_Alloc(size);/* allocate temp buffer */ 1715 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */ 1716 V_BSTR(pVar)=SysAllocStringLen(NULL,size); 1717 /* FIXME: do we need a AtoW conversion here? */ 1718 V_UNION(pVar, bstrVal[size])='\0'; 1719 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size]; 1720 TLB_Free(ptr); 1721 } 1722 size=-4; break; 1723 /* FIXME: this will not work AT ALL when the variant contains a pointer */ 1724 case VT_DISPATCH : 1725 case VT_VARIANT : 1726 case VT_UNKNOWN : 1727 case VT_PTR : 1728 case VT_SAFEARRAY : 1729 case VT_CARRAY : 1730 case VT_USERDEFINED : 1731 case VT_LPSTR : 1732 case VT_LPWSTR : 1733 case VT_BLOB : 1734 case VT_STREAM : 1735 case VT_STORAGE : 1736 case VT_STREAMED_OBJECT : 1737 case VT_STORED_OBJECT : 1738 case VT_BLOB_OBJECT : 1739 case VT_CF : 1740 case VT_CLSID : 1741 default: 1742 size=0; 1743 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n", 1744 V_VT(pVar)); 1745 } 1746 1747 if(size>0) /* (big|small) endian correct? */ 1748 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK ); 1749 return; 1750 } 1751 /* 1752 * create a linked list with custom data 1753 */ 1754 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData ) 1755 { 1756 MSFT_CDGuid entry; 1757 TLBCustData* pNew; 1758 int count=0; 1759 1760 TRACE_(typelib)("\n"); 1761 1762 while(offset >=0){ 1763 count++; 1764 pNew=TLB_Alloc(sizeof(TLBCustData)); 1765 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset); 1766 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx); 1767 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx); 1768 /* add new custom data at head of the list */ 1769 pNew->next=*ppCustData; 1770 *ppCustData=pNew; 1771 offset = entry.next; 1772 } 1773 return count; 1774 } 1775 1776 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd, 1777 ITypeInfoImpl *pTI) 1778 { 1779 if(type <0) 1780 pTd->vt=type & VT_TYPEMASK; 1781 else 1782 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))]; 1783 1784 if(pTd->vt == VT_USERDEFINED) 1785 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype); 1786 1787 TRACE_(typelib)("vt type = %X\n", pTd->vt); 1788 } 1789 1790 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc) 1791 { 1792 /* resolve referenced type if any */ 1793 while (lpTypeDesc) 1794 { 1795 switch (lpTypeDesc->vt) 1796 { 1797 case VT_PTR: 1798 lpTypeDesc = lpTypeDesc->u.lptdesc; 1799 break; 1800 1801 case VT_CARRAY: 1802 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem); 1803 break; 1804 1805 case VT_USERDEFINED: 1806 MSFT_DoRefType(pcx, pTI->pTypeLib, 1807 lpTypeDesc->u.hreftype); 1808 1809 lpTypeDesc = NULL; 1810 break; 1811 1812 default: 1813 lpTypeDesc = NULL; 1814 } 1815 } 1816 } 1817 1818 static void 1819 MSFT_DoFuncs(TLBContext* pcx, 1820 ITypeInfoImpl* pTI, 1821 int cFuncs, 1822 int cVars, 1823 int offset, 1824 TLBFuncDesc** pptfd) 1825 { 1826 /* 1827 * member information is stored in a data structure at offset 1828 * indicated by the memoffset field of the typeinfo structure 1829 * There are several distinctive parts. 1830 * The first part starts with a field that holds the total length 1831 * of this (first) part excluding this field. Then follow the records, 1832 * for each member there is one record. 1833 * 1834 * The first entry is always the length of the record (including this 1835 * length word). 1836 * The rest of the record depends on the type of the member. If there is 1837 * a field indicating the member type (function, variable, interface, etc) 1838 * I have not found it yet. At this time we depend on the information 1839 * in the type info and the usual order how things are stored. 1840 * 1841 * Second follows an array sized nrMEM*sizeof(INT) with a member id 1842 * for each member; 1843 * 1844 * Third is an equal sized array with file offsets to the name entry 1845 * of each member. 1846 * 1847 * The fourth and last (?) part is an array with offsets to the records 1848 * in the first part of this file segment. 1849 */ 1850 1851 int infolen, nameoffset, reclength, nrattributes, i; 1852 int recoffset = offset + sizeof(INT); 1853 1854 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff); 1855 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf; 1856 TLBFuncDesc *ptfd_prev = NULL; 1857 1858 TRACE_(typelib)("\n"); 1859 1860 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset); 1861 1862 for ( i = 0; i < cFuncs ; i++ ) 1863 { 1864 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc)); 1865 1866 /* name, eventually add to a hash table */ 1867 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx, 1868 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT)); 1869 1870 /* nameoffset is sometimes -1 on the second half of a propget/propput 1871 * pair of functions */ 1872 if ((nameoffset == -1) && (i > 0)) 1873 (*pptfd)->Name = SysAllocString(ptfd_prev->Name); 1874 else 1875 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset); 1876 1877 /* read the function information record */ 1878 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset); 1879 1880 reclength &= 0xffff; 1881 1882 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK); 1883 1884 /* do the attributes */ 1885 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18) 1886 / sizeof(int); 1887 1888 if ( nrattributes > 0 ) 1889 { 1890 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ; 1891 1892 if ( nrattributes > 1 ) 1893 { 1894 (*pptfd)->HelpString = MSFT_ReadString(pcx, 1895 pFuncRec->OptAttr[1]) ; 1896 1897 if ( nrattributes > 2 ) 1898 { 1899 if ( pFuncRec->FKCCIC & 0x2000 ) 1900 { 1901 if (HIWORD(pFuncRec->OptAttr[2]) != 0) 1902 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]); 1903 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2]; 1904 } 1905 else 1906 { 1907 (*pptfd)->Entry = MSFT_ReadString(pcx, 1908 pFuncRec->OptAttr[2]); 1909 } 1910 if( nrattributes > 5 ) 1911 { 1912 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ; 1913 1914 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 ) 1915 { 1916 MSFT_CustData(pcx, 1917 pFuncRec->OptAttr[6], 1918 &(*pptfd)->pCustData); 1919 } 1920 } 1921 } 1922 else 1923 { 1924 (*pptfd)->Entry = (BSTR)-1; 1925 } 1926 } 1927 } 1928 1929 /* fill the FuncDesc Structure */ 1930 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx, 1931 offset + infolen + ( i + 1) * sizeof(INT)); 1932 1933 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7; 1934 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF; 1935 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF; 1936 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ; 1937 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ; 1938 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset; 1939 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ; 1940 1941 MSFT_GetTdesc(pcx, 1942 pFuncRec->DataType, 1943 &(*pptfd)->funcdesc.elemdescFunc.tdesc, 1944 pTI); 1945 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc); 1946 1947 /* do the parameters/arguments */ 1948 if(pFuncRec->nrargs) 1949 { 1950 int j = 0; 1951 MSFT_ParameterInfo paraminfo; 1952 1953 (*pptfd)->funcdesc.lprgelemdescParam = 1954 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC)); 1955 1956 (*pptfd)->pParamDesc = 1957 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc)); 1958 1959 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx, 1960 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo)); 1961 1962 for ( j = 0 ; j < pFuncRec->nrargs ; j++ ) 1963 { 1964 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j]; 1965 1966 MSFT_GetTdesc(pcx, 1967 paraminfo.DataType, 1968 &elemdesc->tdesc, 1969 pTI); 1970 1971 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags; 1972 1973 /* name */ 1974 if (paraminfo.oName == -1) 1975 /* this occurs for [propput] or [propget] methods, so 1976 * we should just set the name of the parameter to the 1977 * name of the method. */ 1978 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name); 1979 else 1980 (*pptfd)->pParamDesc[j].Name = 1981 MSFT_ReadName( pcx, paraminfo.oName ); 1982 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name)); 1983 1984 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc); 1985 1986 /* default value */ 1987 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) && 1988 (pFuncRec->FKCCIC & 0x1000) ) 1989 { 1990 INT* pInt = (INT *)((char *)pFuncRec + 1991 reclength - 1992 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) ); 1993 1994 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc; 1995 1996 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX)); 1997 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX); 1998 1999 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue), 2000 pInt[j], pcx); 2001 } 2002 else 2003 elemdesc->u.paramdesc.pparamdescex = NULL; 2004 /* custom info */ 2005 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 ) 2006 { 2007 MSFT_CustData(pcx, 2008 pFuncRec->OptAttr[7+j], 2009 &(*pptfd)->pParamDesc[j].pCustData); 2010 } 2011 2012 /* SEEK value = jump to offset, 2013 * from there jump to the end of record, 2014 * go back by (j-1) arguments 2015 */ 2016 MSFT_ReadLEDWords( ¶minfo , 2017 sizeof(MSFT_ParameterInfo), pcx, 2018 recoffset + reclength - ((pFuncRec->nrargs - j - 1) 2019 * sizeof(MSFT_ParameterInfo))); 2020 } 2021 } 2022 2023 /* scode is not used: archaic win16 stuff FIXME: right? */ 2024 (*pptfd)->funcdesc.cScodes = 0 ; 2025 (*pptfd)->funcdesc.lprgscode = NULL ; 2026 2027 ptfd_prev = *pptfd; 2028 pptfd = & ((*pptfd)->next); 2029 recoffset += reclength; 2030 } 2031 HeapFree(GetProcessHeap(), 0, recbuf); 2032 } 2033 2034 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs, 2035 int cVars, int offset, TLBVarDesc ** pptvd) 2036 { 2037 int infolen, nameoffset, reclength; 2038 char recbuf[256]; 2039 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf; 2040 int i; 2041 int recoffset; 2042 2043 TRACE_(typelib)("\n"); 2044 2045 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset); 2046 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen + 2047 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT)); 2048 recoffset += offset+sizeof(INT); 2049 for(i=0;i<cVars;i++){ 2050 *pptvd=TLB_Alloc(sizeof(TLBVarDesc)); 2051 /* name, eventually add to a hash table */ 2052 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx, 2053 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT)); 2054 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset); 2055 /* read the variable information record */ 2056 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset); 2057 reclength &=0xff; 2058 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK); 2059 /* Optional data */ 2060 if(reclength >(6*sizeof(INT)) ) 2061 (*pptvd)->HelpContext=pVarRec->HelpContext; 2062 if(reclength >(7*sizeof(INT)) ) 2063 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ; 2064 if(reclength >(8*sizeof(INT)) ) 2065 if(reclength >(9*sizeof(INT)) ) 2066 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext; 2067 /* fill the VarDesc Structure */ 2068 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx, 2069 offset + infolen + (cFuncs + i + 1) * sizeof(INT)); 2070 (*pptvd)->vardesc.varkind = pVarRec->VarKind; 2071 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags; 2072 MSFT_GetTdesc(pcx, pVarRec->DataType, 2073 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI); 2074 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */ 2075 if(pVarRec->VarKind == VAR_CONST ){ 2076 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT)); 2077 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue, 2078 pVarRec->OffsValue, pcx); 2079 } else 2080 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue; 2081 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc); 2082 pptvd=&((*pptvd)->next); 2083 recoffset += reclength; 2084 } 2085 } 2086 /* fill in data for a hreftype (offset). When the referenced type is contained 2087 * in the typelib, it's just an (file) offset in the type info base dir. 2088 * If comes from import, it's an offset+1 in the ImpInfo table 2089 * */ 2090 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, 2091 int offset) 2092 { 2093 TLBRefType *ref; 2094 2095 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset); 2096 2097 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry) 2098 { 2099 if(ref->reference == offset) return; 2100 } 2101 2102 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref)); 2103 list_add_tail(&pTL->ref_list, &ref->entry); 2104 2105 if(!MSFT_HREFTYPE_INTHISFILE( offset)) { 2106 /* external typelib */ 2107 MSFT_ImpInfo impinfo; 2108 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs); 2109 2110 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc)); 2111 2112 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, 2113 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc)); 2114 while (pImpLib){ /* search the known offsets of all import libraries */ 2115 if(pImpLib->offset==impinfo.oImpFile) break; 2116 pImpLib=pImpLib->next; 2117 } 2118 if(pImpLib){ 2119 ref->reference = offset; 2120 ref->pImpTLInfo = pImpLib; 2121 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) { 2122 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx); 2123 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid)); 2124 ref->index = TLB_REF_USE_GUID; 2125 } else 2126 ref->index = impinfo.oGuid; 2127 }else{ 2128 ERR("Cannot find a reference\n"); 2129 ref->reference = -1; 2130 ref->pImpTLInfo = TLB_REF_NOT_FOUND; 2131 } 2132 }else{ 2133 /* in this typelib */ 2134 ref->index = MSFT_HREFTYPE_INDEX(offset); 2135 ref->reference = offset; 2136 ref->pImpTLInfo = TLB_REF_INTERNAL; 2137 } 2138 } 2139 2140 /* process Implemented Interfaces of a com class */ 2141 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count, 2142 int offset) 2143 { 2144 int i; 2145 MSFT_RefRecord refrec; 2146 TLBImplType **ppImpl = &pTI->impltypelist; 2147 2148 TRACE_(typelib)("\n"); 2149 2150 for(i=0;i<count;i++){ 2151 if(offset<0) break; /* paranoia */ 2152 *ppImpl=TLB_Alloc(sizeof(**ppImpl)); 2153 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset); 2154 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype); 2155 (*ppImpl)->hRef = refrec.reftype; 2156 (*ppImpl)->implflags=refrec.flags; 2157 (*ppImpl)->ctCustData= 2158 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData); 2159 offset=refrec.onext; 2160 ppImpl=&((*ppImpl)->next); 2161 } 2162 } 2163 /* 2164 * process a typeinfo record 2165 */ 2166 static ITypeInfoImpl * MSFT_DoTypeInfo( 2167 TLBContext *pcx, 2168 int count, 2169 ITypeLibImpl * pLibInfo) 2170 { 2171 MSFT_TypeInfoBase tiBase; 2172 ITypeInfoImpl *ptiRet; 2173 2174 TRACE_(typelib)("count=%u\n", count); 2175 2176 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor(); 2177 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx , 2178 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase)); 2179 2180 /* this is where we are coming from */ 2181 ptiRet->pTypeLib = pLibInfo; 2182 ptiRet->index=count; 2183 /* fill in the typeattr fields */ 2184 2185 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx); 2186 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */ 2187 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */ 2188 ptiRet->TypeAttr.cbSizeInstance=tiBase.size; 2189 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF; 2190 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement); 2191 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement); 2192 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */ 2193 ptiRet->TypeAttr.wTypeFlags=tiBase.flags; 2194 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version); 2195 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version); 2196 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes; 2197 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */ 2198 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS) 2199 MSFT_GetTdesc(pcx, tiBase.datatype1, 2200 &ptiRet->TypeAttr.tdescAlias, ptiRet); 2201 2202 /* FIXME: */ 2203 /* IDLDESC idldescType; *//* never saw this one != zero */ 2204 2205 /* name, eventually add to a hash table */ 2206 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset); 2207 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset); 2208 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name)); 2209 /* help info */ 2210 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs); 2211 ptiRet->dwHelpStringContext=tiBase.helpstringcontext; 2212 ptiRet->dwHelpContext=tiBase.helpcontext; 2213 2214 if (ptiRet->TypeAttr.typekind == TKIND_MODULE) 2215 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1); 2216 2217 /* note: InfoType's Help file and HelpStringDll come from the containing 2218 * library. Further HelpString and Docstring appear to be the same thing :( 2219 */ 2220 /* functions */ 2221 if(ptiRet->TypeAttr.cFuncs >0 ) 2222 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs, 2223 ptiRet->TypeAttr.cVars, 2224 tiBase.memoffset, & ptiRet->funclist); 2225 /* variables */ 2226 if(ptiRet->TypeAttr.cVars >0 ) 2227 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs, 2228 ptiRet->TypeAttr.cVars, 2229 tiBase.memoffset, & ptiRet->varlist); 2230 if(ptiRet->TypeAttr.cImplTypes >0 ) { 2231 switch(ptiRet->TypeAttr.typekind) 2232 { 2233 case TKIND_COCLASS: 2234 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes , 2235 tiBase.datatype1); 2236 break; 2237 case TKIND_DISPATCH: 2238 /* This is not -1 when the interface is a non-base dual interface or 2239 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'. 2240 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and 2241 not this interface. 2242 */ 2243 2244 if (tiBase.datatype1 != -1) 2245 { 2246 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType)); 2247 ptiRet->impltypelist->hRef = tiBase.datatype1; 2248 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1); 2249 } 2250 break; 2251 default: 2252 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType)); 2253 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1); 2254 ptiRet->impltypelist->hRef = tiBase.datatype1; 2255 break; 2256 } 2257 } 2258 ptiRet->ctCustData= 2259 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData); 2260 2261 TRACE_(typelib)("%s guid: %s kind:%s\n", 2262 debugstr_w(ptiRet->Name), 2263 debugstr_guid(&ptiRet->TypeAttr.guid), 2264 typekind_desc[ptiRet->TypeAttr.typekind]); 2265 if (TRACE_ON(typelib)) 2266 dump_TypeInfo(ptiRet); 2267 2268 return ptiRet; 2269 } 2270 2271 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same 2272 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in 2273 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable 2274 * tradeoff here. 2275 */ 2276 static ITypeLibImpl *tlb_cache_first; 2277 static CRITICAL_SECTION cache_section; 2278 static CRITICAL_SECTION_DEBUG cache_section_debug = 2279 { 2280 0, 0, &cache_section, 2281 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList }, 2282 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") } 2283 }; 2284 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 }; 2285 2286 2287 typedef struct TLB_PEFile 2288 { 2289 const IUnknownVtbl *lpvtbl; 2290 LONG refs; 2291 HMODULE dll; 2292 HRSRC typelib_resource; 2293 HGLOBAL typelib_global; 2294 LPVOID typelib_base; 2295 } TLB_PEFile; 2296 2297 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 2298 { 2299 if (IsEqualIID(riid, &IID_IUnknown)) 2300 { 2301 *ppv = iface; 2302 IUnknown_AddRef(iface); 2303 return S_OK; 2304 } 2305 *ppv = NULL; 2306 return E_NOINTERFACE; 2307 } 2308 2309 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface) 2310 { 2311 TLB_PEFile *This = (TLB_PEFile *)iface; 2312 return InterlockedIncrement(&This->refs); 2313 } 2314 2315 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface) 2316 { 2317 TLB_PEFile *This = (TLB_PEFile *)iface; 2318 ULONG refs = InterlockedDecrement(&This->refs); 2319 if (!refs) 2320 { 2321 if (This->typelib_global) 2322 FreeResource(This->typelib_global); 2323 if (This->dll) 2324 FreeLibrary(This->dll); 2325 HeapFree(GetProcessHeap(), 0, This); 2326 } 2327 return refs; 2328 } 2329 2330 static const IUnknownVtbl TLB_PEFile_Vtable = 2331 { 2332 TLB_PEFile_QueryInterface, 2333 TLB_PEFile_AddRef, 2334 TLB_PEFile_Release 2335 }; 2336 2337 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile) 2338 { 2339 TLB_PEFile *This; 2340 2341 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 2342 if (!This) 2343 return E_OUTOFMEMORY; 2344 2345 This->lpvtbl = &TLB_PEFile_Vtable; 2346 This->refs = 1; 2347 This->dll = NULL; 2348 This->typelib_resource = NULL; 2349 This->typelib_global = NULL; 2350 This->typelib_base = NULL; 2351 2352 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES | 2353 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH); 2354 2355 if (This->dll) 2356 { 2357 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0}; 2358 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW); 2359 if (This->typelib_resource) 2360 { 2361 This->typelib_global = LoadResource(This->dll, This->typelib_resource); 2362 if (This->typelib_global) 2363 { 2364 This->typelib_base = LockResource(This->typelib_global); 2365 2366 if (This->typelib_base) 2367 { 2368 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource); 2369 *ppBase = This->typelib_base; 2370 *ppFile = (IUnknown *)&This->lpvtbl; 2371 return S_OK; 2372 } 2373 } 2374 } 2375 } 2376 2377 TLB_PEFile_Release((IUnknown *)&This->lpvtbl); 2378 return TYPE_E_CANTLOADLIBRARY; 2379 } 2380 2381 typedef struct TLB_NEFile 2382 { 2383 const IUnknownVtbl *lpvtbl; 2384 LONG refs; 2385 LPVOID typelib_base; 2386 } TLB_NEFile; 2387 2388 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 2389 { 2390 if (IsEqualIID(riid, &IID_IUnknown)) 2391 { 2392 *ppv = iface; 2393 IUnknown_AddRef(iface); 2394 return S_OK; 2395 } 2396 *ppv = NULL; 2397 return E_NOINTERFACE; 2398 } 2399 2400 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface) 2401 { 2402 TLB_NEFile *This = (TLB_NEFile *)iface; 2403 return InterlockedIncrement(&This->refs); 2404 } 2405 2406 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface) 2407 { 2408 TLB_NEFile *This = (TLB_NEFile *)iface; 2409 ULONG refs = InterlockedDecrement(&This->refs); 2410 if (!refs) 2411 { 2412 HeapFree(GetProcessHeap(), 0, This->typelib_base); 2413 HeapFree(GetProcessHeap(), 0, This); 2414 } 2415 return refs; 2416 } 2417 2418 static const IUnknownVtbl TLB_NEFile_Vtable = 2419 { 2420 TLB_NEFile_QueryInterface, 2421 TLB_NEFile_AddRef, 2422 TLB_NEFile_Release 2423 }; 2424 2425 /*********************************************************************** 2426 * read_xx_header [internal] 2427 */ 2428 static int read_xx_header( HFILE lzfd ) 2429 { 2430 IMAGE_DOS_HEADER mzh; 2431 char magic[3]; 2432 2433 LZSeek( lzfd, 0, SEEK_SET ); 2434 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) ) 2435 return 0; 2436 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE ) 2437 return 0; 2438 2439 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET ); 2440 if ( 2 != LZRead( lzfd, magic, 2 ) ) 2441 return 0; 2442 2443 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET ); 2444 2445 if ( magic[0] == 'N' && magic[1] == 'E' ) 2446 return IMAGE_OS2_SIGNATURE; 2447 if ( magic[0] == 'P' && magic[1] == 'E' ) 2448 return IMAGE_NT_SIGNATURE; 2449 2450 magic[2] = '\0'; 2451 WARN("Can't handle %s files.\n", magic ); 2452 return 0; 2453 } 2454 2455 2456 /*********************************************************************** 2457 * find_ne_resource [internal] 2458 */ 2459 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid, 2460 DWORD *resLen, DWORD *resOff ) 2461 { 2462 IMAGE_OS2_HEADER nehd; 2463 NE_TYPEINFO *typeInfo; 2464 NE_NAMEINFO *nameInfo; 2465 DWORD nehdoffset; 2466 LPBYTE resTab; 2467 DWORD resTabSize; 2468 int count; 2469 2470 /* Read in NE header */ 2471 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR ); 2472 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0; 2473 2474 resTabSize = nehd.ne_restab - nehd.ne_rsrctab; 2475 if ( !resTabSize ) 2476 { 2477 TRACE("No resources in NE dll\n" ); 2478 return FALSE; 2479 } 2480 2481 /* Read in resource table */ 2482 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize ); 2483 if ( !resTab ) return FALSE; 2484 2485 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET ); 2486 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) ) 2487 { 2488 HeapFree( GetProcessHeap(), 0, resTab ); 2489 return FALSE; 2490 } 2491 2492 /* Find resource */ 2493 typeInfo = (NE_TYPEINFO *)(resTab + 2); 2494 2495 if (HIWORD(typeid) != 0) /* named type */ 2496 { 2497 BYTE len = strlen( typeid ); 2498 while (typeInfo->type_id) 2499 { 2500 if (!(typeInfo->type_id & 0x8000)) 2501 { 2502 BYTE *p = resTab + typeInfo->type_id; 2503 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type; 2504 } 2505 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) + 2506 typeInfo->count * sizeof(NE_NAMEINFO)); 2507 } 2508 } 2509 else /* numeric type id */ 2510 { 2511 WORD id = LOWORD(typeid) | 0x8000; 2512 while (typeInfo->type_id) 2513 { 2514 if (typeInfo->type_id == id) goto found_type; 2515 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) + 2516 typeInfo->count * sizeof(NE_NAMEINFO)); 2517 } 2518 } 2519 TRACE("No typeid entry found for %p\n", typeid ); 2520 HeapFree( GetProcessHeap(), 0, resTab ); 2521 return FALSE; 2522 2523 found_type: 2524 nameInfo = (NE_NAMEINFO *)(typeInfo + 1); 2525 2526 if (HIWORD(resid) != 0) /* named resource */ 2527 { 2528 BYTE len = strlen( resid ); 2529 for (count = typeInfo->count; count > 0; count--, nameInfo++) 2530 { 2531 BYTE *p = resTab + nameInfo->id; 2532 if (nameInfo->id & 0x8000) continue; 2533 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name; 2534 } 2535 } 2536 else /* numeric resource id */ 2537 { 2538 WORD id = LOWORD(resid) | 0x8000; 2539 for (count = typeInfo->count; count > 0; count--, nameInfo++) 2540 if (nameInfo->id == id) goto found_name; 2541 } 2542 TRACE("No resid entry found for %p\n", typeid ); 2543 HeapFree( GetProcessHeap(), 0, resTab ); 2544 return FALSE; 2545 2546 found_name: 2547 /* Return resource data */ 2548 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab; 2549 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab; 2550 2551 HeapFree( GetProcessHeap(), 0, resTab ); 2552 return TRUE; 2553 } 2554 2555 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){ 2556 2557 HFILE lzfd = -1; 2558 OFSTRUCT ofs; 2559 HRESULT hr = TYPE_E_CANTLOADLIBRARY; 2560 TLB_NEFile *This = NULL; 2561 2562 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 2563 if (!This) return E_OUTOFMEMORY; 2564 2565 This->lpvtbl = &TLB_NEFile_Vtable; 2566 This->refs = 1; 2567 This->typelib_base = NULL; 2568 2569 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ ); 2570 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE ) 2571 { 2572 DWORD reslen, offset; 2573 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) ) 2574 { 2575 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen); 2576 if( !This->typelib_base ) 2577 hr = E_OUTOFMEMORY; 2578 else 2579 { 2580 LZSeek( lzfd, offset, SEEK_SET ); 2581 reslen = LZRead( lzfd, This->typelib_base, reslen ); 2582 LZClose( lzfd ); 2583 *ppBase = This->typelib_base; 2584 *pdwTLBLength = reslen; 2585 *ppFile = (IUnknown *)&This->lpvtbl; 2586 return S_OK; 2587 } 2588 } 2589 } 2590 2591 if( lzfd >= 0) LZClose( lzfd ); 2592 TLB_NEFile_Release((IUnknown *)&This->lpvtbl); 2593 return hr; 2594 } 2595 2596 typedef struct TLB_Mapping 2597 { 2598 const IUnknownVtbl *lpvtbl; 2599 LONG refs; 2600 HANDLE file; 2601 HANDLE mapping; 2602 LPVOID typelib_base; 2603 } TLB_Mapping; 2604 2605 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 2606 { 2607 if (IsEqualIID(riid, &IID_IUnknown)) 2608 { 2609 *ppv = iface; 2610 IUnknown_AddRef(iface); 2611 return S_OK; 2612 } 2613 *ppv = NULL; 2614 return E_NOINTERFACE; 2615 } 2616 2617 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface) 2618 { 2619 TLB_Mapping *This = (TLB_Mapping *)iface; 2620 return InterlockedIncrement(&This->refs); 2621 } 2622 2623 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface) 2624 { 2625 TLB_Mapping *This = (TLB_Mapping *)iface; 2626 ULONG refs = InterlockedDecrement(&This->refs); 2627 if (!refs) 2628 { 2629 if (This->typelib_base) 2630 UnmapViewOfFile(This->typelib_base); 2631 if (This->mapping) 2632 CloseHandle(This->mapping); 2633 if (This->file != INVALID_HANDLE_VALUE) 2634 CloseHandle(This->file); 2635 HeapFree(GetProcessHeap(), 0, This); 2636 } 2637 return refs; 2638 } 2639 2640 static const IUnknownVtbl TLB_Mapping_Vtable = 2641 { 2642 TLB_Mapping_QueryInterface, 2643 TLB_Mapping_AddRef, 2644 TLB_Mapping_Release 2645 }; 2646 2647 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile) 2648 { 2649 TLB_Mapping *This; 2650 2651 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 2652 if (!This) 2653 return E_OUTOFMEMORY; 2654 2655 This->lpvtbl = &TLB_Mapping_Vtable; 2656 This->refs = 1; 2657 This->file = INVALID_HANDLE_VALUE; 2658 This->mapping = NULL; 2659 This->typelib_base = NULL; 2660 2661 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 2662 if (INVALID_HANDLE_VALUE != This->file) 2663 { 2664 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 2665 if (This->mapping) 2666 { 2667 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0); 2668 if(This->typelib_base) 2669 { 2670 /* retrieve file size */ 2671 *pdwTLBLength = GetFileSize(This->file, NULL); 2672 *ppBase = This->typelib_base; 2673 *ppFile = (IUnknown *)&This->lpvtbl; 2674 return S_OK; 2675 } 2676 } 2677 } 2678 2679 IUnknown_Release((IUnknown *)&This->lpvtbl); 2680 return TYPE_E_CANTLOADLIBRARY; 2681 } 2682 2683 /**************************************************************************** 2684 * TLB_ReadTypeLib 2685 * 2686 * find the type of the typelib file and map the typelib resource into 2687 * the memory 2688 */ 2689 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */ 2690 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */ 2691 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib) 2692 { 2693 ITypeLibImpl *entry; 2694 HRESULT ret; 2695 INT index = 1; 2696 LPWSTR index_str, file = (LPWSTR)pszFileName; 2697 LPVOID pBase = NULL; 2698 DWORD dwTLBLength = 0; 2699 IUnknown *pFile = NULL; 2700 2701 *ppTypeLib = NULL; 2702 2703 index_str = strrchrW(pszFileName, '\\'); 2704 if(index_str && *++index_str != '\0') 2705 { 2706 LPWSTR end_ptr; 2707 long idx = strtolW(index_str, &end_ptr, 10); 2708 if(*end_ptr == '\0') 2709 { 2710 int str_len = index_str - pszFileName - 1; 2711 index = idx; 2712 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR)); 2713 memcpy(file, pszFileName, str_len * sizeof(WCHAR)); 2714 file[str_len] = 0; 2715 } 2716 } 2717 2718 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL)) 2719 { 2720 if(strchrW(file, '\\')) 2721 { 2722 lstrcpyW(pszPath, file); 2723 } 2724 else 2725 { 2726 int len = GetSystemDirectoryW(pszPath, cchPath); 2727 pszPath[len] = '\\'; 2728 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR)); 2729 } 2730 } 2731 2732 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file); 2733 2734 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index); 2735 2736 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */ 2737 EnterCriticalSection(&cache_section); 2738 for (entry = tlb_cache_first; entry != NULL; entry = entry->next) 2739 { 2740 if (!strcmpiW(entry->path, pszPath) && entry->index == index) 2741 { 2742 TRACE("cache hit\n"); 2743 *ppTypeLib = (ITypeLib2*)entry; 2744 ITypeLib_AddRef(*ppTypeLib); 2745 LeaveCriticalSection(&cache_section); 2746 return S_OK; 2747 } 2748 } 2749 LeaveCriticalSection(&cache_section); 2750 2751 /* now actually load and parse the typelib */ 2752 2753 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile); 2754 if (ret == TYPE_E_CANTLOADLIBRARY) 2755 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile); 2756 if (ret == TYPE_E_CANTLOADLIBRARY) 2757 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile); 2758 if (SUCCEEDED(ret)) 2759 { 2760 if (dwTLBLength >= 4) 2761 { 2762 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase)); 2763 if (dwSignature == MSFT_SIGNATURE) 2764 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); 2765 else if (dwSignature == SLTG_SIGNATURE) 2766 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); 2767 else 2768 { 2769 FIXME("Header type magic 0x%08x not supported.\n",dwSignature); 2770 ret = TYPE_E_CANTLOADLIBRARY; 2771 } 2772 } 2773 else 2774 ret = TYPE_E_CANTLOADLIBRARY; 2775 IUnknown_Release(pFile); 2776 } 2777 2778 if(*ppTypeLib) { 2779 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib; 2780 2781 TRACE("adding to cache\n"); 2782 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR)); 2783 lstrcpyW(impl->path, pszPath); 2784 /* We should really canonicalise the path here. */ 2785 impl->index = index; 2786 2787 /* FIXME: check if it has added already in the meantime */ 2788 EnterCriticalSection(&cache_section); 2789 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl; 2790 impl->prev = NULL; 2791 tlb_cache_first = impl; 2792 LeaveCriticalSection(&cache_section); 2793 ret = S_OK; 2794 } else 2795 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError()); 2796 2797 return ret; 2798 } 2799 2800 /*================== ITypeLib(2) Methods ===================================*/ 2801 2802 static ITypeLibImpl* TypeLibImpl_Constructor(void) 2803 { 2804 ITypeLibImpl* pTypeLibImpl; 2805 2806 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl)); 2807 if (!pTypeLibImpl) return NULL; 2808 2809 pTypeLibImpl->lpVtbl = &tlbvt; 2810 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt; 2811 pTypeLibImpl->ref = 1; 2812 2813 list_init(&pTypeLibImpl->ref_list); 2814 pTypeLibImpl->dispatch_href = -1; 2815 2816 return pTypeLibImpl; 2817 } 2818 2819 /**************************************************************************** 2820 * ITypeLib2_Constructor_MSFT 2821 * 2822 * loading an MSFT typelib from an in-memory image 2823 */ 2824 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength) 2825 { 2826 TLBContext cx; 2827 long lPSegDir; 2828 MSFT_Header tlbHeader; 2829 MSFT_SegDir tlbSegDir; 2830 ITypeLibImpl * pTypeLibImpl; 2831 2832 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength); 2833 2834 pTypeLibImpl = TypeLibImpl_Constructor(); 2835 if (!pTypeLibImpl) return NULL; 2836 2837 /* get pointer to beginning of typelib data */ 2838 cx.pos = 0; 2839 cx.oStart=0; 2840 cx.mapping = pLib; 2841 cx.pLibInfo = pTypeLibImpl; 2842 cx.length = dwTLBLength; 2843 2844 /* read header */ 2845 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0); 2846 TRACE_(typelib)("header:\n"); 2847 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 ); 2848 if (tlbHeader.magic1 != MSFT_SIGNATURE) { 2849 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1); 2850 return NULL; 2851 } 2852 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos); 2853 2854 /* there is a small amount of information here until the next important 2855 * part: 2856 * the segment directory . Try to calculate the amount of data */ 2857 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0); 2858 2859 /* now read the segment directory */ 2860 TRACE("read segment directory (at %ld)\n",lPSegDir); 2861 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir); 2862 cx.pTblDir = &tlbSegDir; 2863 2864 /* just check two entries */ 2865 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F) 2866 { 2867 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir); 2868 HeapFree(GetProcessHeap(),0,pTypeLibImpl); 2869 return NULL; 2870 } 2871 2872 /* now fill our internal data */ 2873 /* TLIBATTR fields */ 2874 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx); 2875 2876 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2; 2877 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */ 2878 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version); 2879 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version); 2880 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */ 2881 2882 pTypeLibImpl->lcid = tlbHeader.lcid; 2883 2884 /* name, eventually add to a hash table */ 2885 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset); 2886 2887 /* help info */ 2888 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring); 2889 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile); 2890 2891 if( tlbHeader.varflags & HELPDLLFLAG) 2892 { 2893 int offset; 2894 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader)); 2895 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset); 2896 } 2897 2898 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext; 2899 2900 /* custom data */ 2901 if(tlbHeader.CustomDataOffset >= 0) 2902 { 2903 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData); 2904 } 2905 2906 /* fill in type descriptions */ 2907 if(tlbSegDir.pTypdescTab.length > 0) 2908 { 2909 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT)); 2910 INT16 td[4]; 2911 pTypeLibImpl->ctTypeDesc = cTD; 2912 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC)); 2913 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset); 2914 for(i=0; i<cTD; ) 2915 { 2916 /* FIXME: add several sanity checks here */ 2917 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK; 2918 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY) 2919 { 2920 /* FIXME: check safearray */ 2921 if(td[3] < 0) 2922 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]]; 2923 else 2924 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8]; 2925 } 2926 else if(td[0] == VT_CARRAY) 2927 { 2928 /* array descr table here */ 2929 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/ 2930 } 2931 else if(td[0] == VT_USERDEFINED) 2932 { 2933 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]); 2934 } 2935 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK); 2936 } 2937 2938 /* second time around to fill the array subscript info */ 2939 for(i=0;i<cTD;i++) 2940 { 2941 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue; 2942 if(tlbSegDir.pArrayDescriptions.offset>0) 2943 { 2944 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc); 2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1)); 2946 2947 if(td[1]<0) 2948 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK; 2949 else 2950 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8]; 2951 2952 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2]; 2953 2954 for(j = 0; j<td[2]; j++) 2955 { 2956 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements, 2957 sizeof(INT), &cx, DO_NOT_SEEK); 2958 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound, 2959 sizeof(INT), &cx, DO_NOT_SEEK); 2960 } 2961 } 2962 else 2963 { 2964 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL; 2965 ERR("didn't find array description data\n"); 2966 } 2967 } 2968 } 2969 2970 /* imported type libs */ 2971 if(tlbSegDir.pImpFiles.offset>0) 2972 { 2973 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs); 2974 int oGuid, offset = tlbSegDir.pImpFiles.offset; 2975 UINT16 size; 2976 2977 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length) 2978 { 2979 char *name; 2980 2981 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib)); 2982 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset; 2983 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset); 2984 2985 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK); 2986 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK); 2987 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK); 2988 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK); 2989 2990 size >>= 2; 2991 name = TLB_Alloc(size+1); 2992 MSFT_Read(name, size, &cx, DO_NOT_SEEK); 2993 (*ppImpLib)->name = TLB_MultiByteToBSTR(name); 2994 2995 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx); 2996 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3; 2997 2998 ppImpLib = &(*ppImpLib)->next; 2999 } 3000 } 3001 3002 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos; 3003 if(pTypeLibImpl->dispatch_href != -1) 3004 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href); 3005 3006 /* type info's */ 3007 if(tlbHeader.nrtypeinfos >= 0 ) 3008 { 3009 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */ 3010 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo); 3011 int i; 3012 3013 for(i = 0; i < tlbHeader.nrtypeinfos; i++) 3014 { 3015 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl); 3016 3017 ppTI = &((*ppTI)->next); 3018 (pTypeLibImpl->TypeInfoCount)++; 3019 } 3020 } 3021 3022 TRACE("(%p)\n", pTypeLibImpl); 3023 return (ITypeLib2*) pTypeLibImpl; 3024 } 3025 3026 3027 static BOOL TLB_GUIDFromString(const char *str, GUID *guid) 3028 { 3029 char b[3]; 3030 int i; 3031 short s; 3032 3033 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) { 3034 FIXME("Can't parse guid %s\n", debugstr_guid(guid)); 3035 return FALSE; 3036 } 3037 3038 guid->Data4[0] = s >> 8; 3039 guid->Data4[1] = s & 0xff; 3040 3041 b[2] = '\0'; 3042 for(i = 0; i < 6; i++) { 3043 memcpy(b, str + 24 + 2 * i, 2); 3044 guid->Data4[i + 2] = strtol(b, NULL, 16); 3045 } 3046 return TRUE; 3047 } 3048 3049 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr) 3050 { 3051 WORD bytelen; 3052 DWORD len; 3053 3054 *pBstr = NULL; 3055 bytelen = *(const WORD*)ptr; 3056 if(bytelen == 0xffff) return 2; 3057 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0); 3058 *pBstr = SysAllocStringLen(NULL, len); 3059 if (*pBstr) 3060 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len); 3061 return bytelen + 2; 3062 } 3063 3064 static WORD SLTG_ReadStringA(const char *ptr, char **str) 3065 { 3066 WORD bytelen; 3067 3068 *str = NULL; 3069 bytelen = *(const WORD*)ptr; 3070 if(bytelen == 0xffff) return 2; 3071 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1); 3072 memcpy(*str, ptr + 2, bytelen); 3073 (*str)[bytelen] = '\0'; 3074 return bytelen + 2; 3075 } 3076 3077 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl) 3078 { 3079 char *ptr = pLibBlk; 3080 WORD w; 3081 3082 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) { 3083 FIXME("libblk magic = %04x\n", w); 3084 return 0; 3085 } 3086 3087 ptr += 6; 3088 if((w = *(WORD*)ptr) != 0xffff) { 3089 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w); 3090 ptr += w; 3091 } 3092 ptr += 2; 3093 3094 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString); 3095 3096 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile); 3097 3098 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr; 3099 ptr += 4; 3100 3101 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr; 3102 ptr += 2; 3103 3104 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL) 3105 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0); 3106 else 3107 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0; 3108 ptr += 2; 3109 3110 ptr += 4; /* skip res12 */ 3111 3112 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr; 3113 ptr += 2; 3114 3115 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr; 3116 ptr += 2; 3117 3118 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr; 3119 ptr += 2; 3120 3121 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID)); 3122 ptr += sizeof(GUID); 3123 3124 return ptr - (char*)pLibBlk; 3125 } 3126 3127 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */ 3128 typedef struct 3129 { 3130 unsigned int num; 3131 HREFTYPE refs[1]; 3132 } sltg_ref_lookup_t; 3133 3134 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref, 3135 HREFTYPE *typelib_ref) 3136 { 3137 if(table && typeinfo_ref < table->num) 3138 { 3139 *typelib_ref = table->refs[typeinfo_ref]; 3140 return S_OK; 3141 } 3142 3143 ERR_(typelib)("Unable to find reference\n"); 3144 *typelib_ref = -1; 3145 return E_FAIL; 3146 } 3147 3148 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup) 3149 { 3150 BOOL done = FALSE; 3151 3152 while(!done) { 3153 if((*pType & 0xe00) == 0xe00) { 3154 pTD->vt = VT_PTR; 3155 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3156 sizeof(TYPEDESC)); 3157 pTD = pTD->u.lptdesc; 3158 } 3159 switch(*pType & 0x3f) { 3160 case VT_PTR: 3161 pTD->vt = VT_PTR; 3162 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3163 sizeof(TYPEDESC)); 3164 pTD = pTD->u.lptdesc; 3165 break; 3166 3167 case VT_USERDEFINED: 3168 pTD->vt = VT_USERDEFINED; 3169 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype); 3170 done = TRUE; 3171 break; 3172 3173 case VT_CARRAY: 3174 { 3175 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of 3176 array */ 3177 3178 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType)); 3179 3180 pTD->vt = VT_CARRAY; 3181 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3182 sizeof(ARRAYDESC) + 3183 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND)); 3184 pTD->u.lpadesc->cDims = pSA->cDims; 3185 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound, 3186 pSA->cDims * sizeof(SAFEARRAYBOUND)); 3187 3188 pTD = &pTD->u.lpadesc->tdescElem; 3189 break; 3190 } 3191 3192 case VT_SAFEARRAY: 3193 { 3194 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this 3195 useful? */ 3196 3197 pType++; 3198 pTD->vt = VT_SAFEARRAY; 3199 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3200 sizeof(TYPEDESC)); 3201 pTD = pTD->u.lptdesc; 3202 break; 3203 } 3204 default: 3205 pTD->vt = *pType & 0x3f; 3206 done = TRUE; 3207 break; 3208 } 3209 pType++; 3210 } 3211 return pType; 3212 } 3213 3214 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, 3215 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup) 3216 { 3217 /* Handle [in/out] first */ 3218 if((*pType & 0xc000) == 0xc000) 3219 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE; 3220 else if(*pType & 0x8000) 3221 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT; 3222 else if(*pType & 0x4000) 3223 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT; 3224 else 3225 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN; 3226 3227 if(*pType & 0x2000) 3228 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID; 3229 3230 if(*pType & 0x80) 3231 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL; 3232 3233 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup); 3234 } 3235 3236 3237 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL, 3238 char *pNameTable) 3239 { 3240 unsigned int ref; 3241 char *name; 3242 TLBRefType *ref_type; 3243 sltg_ref_lookup_t *table; 3244 HREFTYPE typelib_ref; 3245 3246 if(pRef->magic != SLTG_REF_MAGIC) { 3247 FIXME("Ref magic = %x\n", pRef->magic); 3248 return NULL; 3249 } 3250 name = ( (char*)pRef->names + pRef->number); 3251 3252 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0])); 3253 table->num = pRef->number >> 3; 3254 3255 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */ 3256 3257 /* We don't want the first href to be 0 */ 3258 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2; 3259 3260 for(ref = 0; ref < pRef->number >> 3; ref++) { 3261 char *refname; 3262 unsigned int lib_offs, type_num; 3263 3264 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type)); 3265 3266 name += SLTG_ReadStringA(name, &refname); 3267 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2) 3268 FIXME_(typelib)("Can't sscanf ref\n"); 3269 if(lib_offs != 0xffff) { 3270 TLBImpLib **import = &pTL->pImpLibs; 3271 3272 while(*import) { 3273 if((*import)->offset == lib_offs) 3274 break; 3275 import = &(*import)->next; 3276 } 3277 if(!*import) { 3278 char fname[MAX_PATH+1]; 3279 int len; 3280 3281 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3282 sizeof(**import)); 3283 (*import)->offset = lib_offs; 3284 TLB_GUIDFromString( pNameTable + lib_offs + 4, 3285 &(*import)->guid); 3286 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s", 3287 &(*import)->wVersionMajor, 3288 &(*import)->wVersionMinor, 3289 &(*import)->lcid, fname) != 4) { 3290 FIXME_(typelib)("can't sscanf ref %s\n", 3291 pNameTable + lib_offs + 40); 3292 } 3293 len = strlen(fname); 3294 if(fname[len-1] != '#') 3295 FIXME("fname = %s\n", fname); 3296 fname[len-1] = '\0'; 3297 (*import)->name = TLB_MultiByteToBSTR(fname); 3298 } 3299 ref_type->pImpTLInfo = *import; 3300 3301 /* Store a reference to IDispatch */ 3302 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4) 3303 pTL->dispatch_href = typelib_ref; 3304 3305 } else { /* internal ref */ 3306 ref_type->pImpTLInfo = TLB_REF_INTERNAL; 3307 } 3308 ref_type->reference = typelib_ref; 3309 ref_type->index = type_num; 3310 3311 HeapFree(GetProcessHeap(), 0, refname); 3312 list_add_tail(&pTL->ref_list, &ref_type->entry); 3313 3314 table->refs[ref] = typelib_ref; 3315 typelib_ref += 4; 3316 } 3317 if((BYTE)*name != SLTG_REF_MAGIC) 3318 FIXME_(typelib)("End of ref block magic = %x\n", *name); 3319 dump_TLBRefType(pTL); 3320 return table; 3321 } 3322 3323 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI, 3324 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup) 3325 { 3326 SLTG_ImplInfo *info; 3327 TLBImplType **ppImplType = &pTI->impltypelist; 3328 /* I don't really get this structure, usually it's 0x16 bytes 3329 long, but iuser.tlb contains some that are 0x18 bytes long. 3330 That's ok because we can use the next ptr to jump to the next 3331 one. But how do we know the length of the last one? The WORD 3332 at offs 0x8 might be the clue. For now I'm just assuming that 3333 the last one is the regular 0x16 bytes. */ 3334 3335 info = (SLTG_ImplInfo*)pBlk; 3336 while(1) { 3337 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3338 sizeof(**ppImplType)); 3339 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef); 3340 (*ppImplType)->implflags = info->impltypeflags; 3341 pTI->TypeAttr.cImplTypes++; 3342 ppImplType = &(*ppImplType)->next; 3343 3344 if(info->next == 0xffff) 3345 break; 3346 if(OneOnly) 3347 FIXME_(typelib)("Interface inheriting more than one interface\n"); 3348 info = (SLTG_ImplInfo*)(pBlk + info->next); 3349 } 3350 info++; /* see comment at top of function */ 3351 return (char*)info; 3352 } 3353 3354 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, 3355 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup) 3356 { 3357 TLBVarDesc **ppVarDesc = &pTI->varlist; 3358 BSTR bstrPrevName = NULL; 3359 SLTG_Variable *pItem; 3360 unsigned short i; 3361 WORD *pType; 3362 3363 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars; 3364 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) { 3365 3366 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3367 sizeof(**ppVarDesc)); 3368 (*ppVarDesc)->vardesc.memid = pItem->memid; 3369 3370 if (pItem->magic != SLTG_VAR_MAGIC && 3371 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) { 3372 FIXME_(typelib)("var magic = %02x\n", pItem->magic); 3373 return; 3374 } 3375 3376 if (pItem->name == 0xfffe) 3377 (*ppVarDesc)->Name = SysAllocString(bstrPrevName); 3378 else 3379 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable); 3380 3381 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name)); 3382 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs); 3383 TRACE_(typelib)("memid = 0x%x\n", pItem->memid); 3384 3385 if(pItem->flags & 0x02) 3386 pType = &pItem->type; 3387 else 3388 pType = (WORD*)(pBlk + pItem->type); 3389 3390 if (pItem->flags & ~0xda) 3391 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda); 3392 3393 SLTG_DoElem(pType, pBlk, 3394 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup); 3395 3396 if (TRACE_ON(typelib)) { 3397 char buf[300]; 3398 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf); 3399 TRACE_(typelib)("elemdescVar: %s\n", buf); 3400 } 3401 3402 if (pItem->flags & 0x40) { 3403 TRACE_(typelib)("VAR_DISPATCH\n"); 3404 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH; 3405 } 3406 else if (pItem->flags & 0x10) { 3407 TRACE_(typelib)("VAR_CONST\n"); 3408 (*ppVarDesc)->vardesc.varkind = VAR_CONST; 3409 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0, 3410 sizeof(VARIANT)); 3411 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT; 3412 if (pItem->flags & 0x08) 3413 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs; 3414 else { 3415 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt) 3416 { 3417 case VT_LPSTR: 3418 case VT_LPWSTR: 3419 case VT_BSTR: 3420 { 3421 WORD len = *(WORD *)(pBlk + pItem->byte_offs); 3422 BSTR str; 3423 TRACE_(typelib)("len = %u\n", len); 3424 if (len == 0xffff) { 3425 str = NULL; 3426 } else { 3427 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0); 3428 str = SysAllocStringLen(NULL, alloc_len); 3429 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len); 3430 } 3431 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR; 3432 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str; 3433 break; 3434 } 3435 case VT_I2: 3436 case VT_UI2: 3437 case VT_I4: 3438 case VT_UI4: 3439 case VT_INT: 3440 case VT_UINT: 3441 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = 3442 *(INT*)(pBlk + pItem->byte_offs); 3443 break; 3444 default: 3445 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt); 3446 } 3447 } 3448 } 3449 else { 3450 TRACE_(typelib)("VAR_PERINSTANCE\n"); 3451 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs; 3452 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE; 3453 } 3454 3455 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC) 3456 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags; 3457 3458 if (pItem->flags & 0x80) 3459 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY; 3460 3461 bstrPrevName = (*ppVarDesc)->Name; 3462 ppVarDesc = &((*ppVarDesc)->next); 3463 } 3464 pTI->TypeAttr.cVars = cVars; 3465 } 3466 3467 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, 3468 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup) 3469 { 3470 SLTG_Function *pFunc; 3471 unsigned short i; 3472 TLBFuncDesc **ppFuncDesc = &pTI->funclist; 3473 3474 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs; 3475 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) { 3476 3477 int param; 3478 WORD *pType, *pArg; 3479 3480 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3481 sizeof(**ppFuncDesc)); 3482 3483 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) { 3484 case SLTG_FUNCTION_MAGIC: 3485 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL; 3486 break; 3487 case SLTG_DISPATCH_FUNCTION_MAGIC: 3488 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH; 3489 break; 3490 case SLTG_STATIC_FUNCTION_MAGIC: 3491 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC; 3492 break; 3493 default: 3494 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT); 3495 HeapFree(GetProcessHeap(), 0, *ppFuncDesc); 3496 *ppFuncDesc = NULL; 3497 return; 3498 } 3499 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable); 3500 3501 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid; 3502 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4; 3503 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7; 3504 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3; 3505 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1; 3506 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos; 3507 3508 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT) 3509 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags; 3510 3511 if(pFunc->retnextopt & 0x80) 3512 pType = &pFunc->rettype; 3513 else 3514 pType = (WORD*)(pBlk + pFunc->rettype); 3515 3516 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup); 3517 3518 (*ppFuncDesc)->funcdesc.lprgelemdescParam = 3519 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3520 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC)); 3521 (*ppFuncDesc)->pParamDesc = 3522 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3523 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc)); 3524 3525 pArg = (WORD*)(pBlk + pFunc->arg_off); 3526 3527 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) { 3528 char *paramName = pNameTable + *pArg; 3529 BOOL HaveOffs; 3530 /* If arg type follows then paramName points to the 2nd 3531 letter of the name, else the next WORD is an offset to 3532 the arg type and paramName points to the first letter. 3533 So let's take one char off paramName and see if we're 3534 pointing at an alpha-numeric char. However if *pArg is 3535 0xffff or 0xfffe then the param has no name, the former 3536 meaning that the next WORD is the type, the latter 3537 meaning that the next WORD is an offset to the type. */ 3538 3539 HaveOffs = FALSE; 3540 if(*pArg == 0xffff) 3541 paramName = NULL; 3542 else if(*pArg == 0xfffe) { 3543 paramName = NULL; 3544 HaveOffs = TRUE; 3545 } 3546 else if(paramName[-1] && !isalnum(paramName[-1])) 3547 HaveOffs = TRUE; 3548 3549 pArg++; 3550 3551 if(HaveOffs) { /* the next word is an offset to type */ 3552 pType = (WORD*)(pBlk + *pArg); 3553 SLTG_DoElem(pType, pBlk, 3554 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup); 3555 pArg++; 3556 } else { 3557 if(paramName) 3558 paramName--; 3559 pArg = SLTG_DoElem(pArg, pBlk, 3560 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup); 3561 } 3562 3563 /* Are we an optional param ? */ 3564 if((*ppFuncDesc)->funcdesc.cParams - param <= 3565 (*ppFuncDesc)->funcdesc.cParamsOpt) 3566 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT; 3567 3568 if(paramName) { 3569 (*ppFuncDesc)->pParamDesc[param].Name = 3570 TLB_MultiByteToBSTR(paramName); 3571 } else { 3572 (*ppFuncDesc)->pParamDesc[param].Name = 3573 SysAllocString((*ppFuncDesc)->Name); 3574 } 3575 } 3576 3577 ppFuncDesc = &((*ppFuncDesc)->next); 3578 if(pFunc->next == 0xffff) break; 3579 } 3580 pTI->TypeAttr.cFuncs = cFuncs; 3581 } 3582 3583 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI, 3584 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 3585 SLTG_TypeInfoTail *pTITail) 3586 { 3587 char *pFirstItem; 3588 sltg_ref_lookup_t *ref_lookup = NULL; 3589 3590 if(pTIHeader->href_table != 0xffffffff) { 3591 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 3592 pNameTable); 3593 } 3594 3595 pFirstItem = pBlk; 3596 3597 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) { 3598 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup); 3599 } 3600 HeapFree(GetProcessHeap(), 0, ref_lookup); 3601 } 3602 3603 3604 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI, 3605 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 3606 const SLTG_TypeInfoTail *pTITail) 3607 { 3608 char *pFirstItem; 3609 sltg_ref_lookup_t *ref_lookup = NULL; 3610 3611 if(pTIHeader->href_table != 0xffffffff) { 3612 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 3613 pNameTable); 3614 } 3615 3616 pFirstItem = pBlk; 3617 3618 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) { 3619 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup); 3620 } 3621 3622 if (pTITail->funcs_off != 0xffff) 3623 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); 3624 3625 HeapFree(GetProcessHeap(), 0, ref_lookup); 3626 3627 if (TRACE_ON(typelib)) 3628 dump_TLBFuncDesc(pTI->funclist); 3629 } 3630 3631 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI, 3632 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 3633 const SLTG_TypeInfoTail *pTITail) 3634 { 3635 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL); 3636 } 3637 3638 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI, 3639 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 3640 const SLTG_TypeInfoTail *pTITail) 3641 { 3642 WORD *pType; 3643 sltg_ref_lookup_t *ref_lookup = NULL; 3644 3645 if (pTITail->simple_alias) { 3646 /* if simple alias, no more processing required */ 3647 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt; 3648 return; 3649 } 3650 3651 if(pTIHeader->href_table != 0xffffffff) { 3652 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 3653 pNameTable); 3654 } 3655 3656 /* otherwise it is an offset to a type */ 3657 pType = (WORD *)(pBlk + pTITail->tdescalias_vt); 3658 3659 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup); 3660 3661 HeapFree(GetProcessHeap(), 0, ref_lookup); 3662 } 3663 3664 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI, 3665 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 3666 const SLTG_TypeInfoTail *pTITail) 3667 { 3668 sltg_ref_lookup_t *ref_lookup = NULL; 3669 if (pTIHeader->href_table != 0xffffffff) 3670 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 3671 pNameTable); 3672 3673 if (pTITail->vars_off != 0xffff) 3674 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup); 3675 3676 if (pTITail->funcs_off != 0xffff) 3677 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); 3678 3679 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number 3680 * of dispinterface functions including the IDispatch ones, so 3681 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */ 3682 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *); 3683 3684 HeapFree(GetProcessHeap(), 0, ref_lookup); 3685 if (TRACE_ON(typelib)) 3686 dump_TLBFuncDesc(pTI->funclist); 3687 } 3688 3689 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI, 3690 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 3691 const SLTG_TypeInfoTail *pTITail) 3692 { 3693 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL); 3694 } 3695 3696 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI, 3697 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 3698 const SLTG_TypeInfoTail *pTITail) 3699 { 3700 sltg_ref_lookup_t *ref_lookup = NULL; 3701 if (pTIHeader->href_table != 0xffffffff) 3702 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 3703 pNameTable); 3704 3705 if (pTITail->vars_off != 0xffff) 3706 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup); 3707 3708 if (pTITail->funcs_off != 0xffff) 3709 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); 3710 HeapFree(GetProcessHeap(), 0, ref_lookup); 3711 if (TRACE_ON(typelib)) 3712 dump_TypeInfo(pTI); 3713 } 3714 3715 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more 3716 managable copy of it into this */ 3717 typedef struct { 3718 WORD small_no; 3719 char *index_name; 3720 char *other_name; 3721 WORD res1a; 3722 WORD name_offs; 3723 WORD more_bytes; 3724 char *extra; 3725 WORD res20; 3726 DWORD helpcontext; 3727 WORD res26; 3728 GUID uuid; 3729 } SLTG_InternalOtherTypeInfo; 3730 3731 /**************************************************************************** 3732 * ITypeLib2_Constructor_SLTG 3733 * 3734 * loading a SLTG typelib from an in-memory image 3735 */ 3736 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) 3737 { 3738 ITypeLibImpl *pTypeLibImpl; 3739 SLTG_Header *pHeader; 3740 SLTG_BlkEntry *pBlkEntry; 3741 SLTG_Magic *pMagic; 3742 SLTG_Index *pIndex; 3743 SLTG_Pad9 *pPad9; 3744 LPVOID pBlk, pFirstBlk; 3745 SLTG_LibBlk *pLibBlk; 3746 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks; 3747 char *pAfterOTIBlks = NULL; 3748 char *pNameTable, *ptr; 3749 int i; 3750 DWORD len, order; 3751 ITypeInfoImpl **ppTypeInfoImpl; 3752 3753 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength); 3754 3755 3756 pTypeLibImpl = TypeLibImpl_Constructor(); 3757 if (!pTypeLibImpl) return NULL; 3758 3759 pHeader = pLib; 3760 3761 TRACE_(typelib)("header:\n"); 3762 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic, 3763 pHeader->nrOfFileBlks ); 3764 if (pHeader->SLTG_magic != SLTG_SIGNATURE) { 3765 FIXME_(typelib)("Header type magic 0x%08x not supported.\n", 3766 pHeader->SLTG_magic); 3767 return NULL; 3768 } 3769 3770 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */ 3771 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2; 3772 3773 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */ 3774 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1); 3775 3776 /* Next we have a magic block */ 3777 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1); 3778 3779 /* Let's see if we're still in sync */ 3780 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC, 3781 sizeof(SLTG_COMPOBJ_MAGIC))) { 3782 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic); 3783 return NULL; 3784 } 3785 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC, 3786 sizeof(SLTG_DIR_MAGIC))) { 3787 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic); 3788 return NULL; 3789 } 3790 3791 pIndex = (SLTG_Index*)(pMagic+1); 3792 3793 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount); 3794 3795 pFirstBlk = pPad9 + 1; 3796 3797 /* We'll set up a ptr to the main library block, which is the last one. */ 3798 3799 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0; 3800 pBlkEntry[order].next != 0; 3801 order = pBlkEntry[order].next - 1, i++) { 3802 pBlk = (char*)pBlk + pBlkEntry[order].len; 3803 } 3804 pLibBlk = pBlk; 3805 3806 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl); 3807 3808 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount 3809 interspersed */ 3810 3811 len += 0x40; 3812 3813 /* And now TypeInfoCount of SLTG_OtherTypeInfo */ 3814 3815 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 3816 sizeof(*pOtherTypeInfoBlks) * 3817 pTypeLibImpl->TypeInfoCount); 3818 3819 3820 ptr = (char*)pLibBlk + len; 3821 3822 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) { 3823 WORD w, extra; 3824 len = 0; 3825 3826 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr; 3827 3828 w = *(WORD*)(ptr + 2); 3829 if(w != 0xffff) { 3830 len += w; 3831 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0, 3832 w+1); 3833 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w); 3834 pOtherTypeInfoBlks[i].index_name[w] = '\0'; 3835 } 3836 w = *(WORD*)(ptr + 4 + len); 3837 if(w != 0xffff) { 3838 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w)); 3839 len += w; 3840 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0, 3841 w+1); 3842 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w); 3843 pOtherTypeInfoBlks[i].other_name[w] = '\0'; 3844 } 3845 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6); 3846 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8); 3847 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len); 3848 if(extra) { 3849 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0, 3850 extra); 3851 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra); 3852 len += extra; 3853 } 3854 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len); 3855 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len); 3856 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len); 3857 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID)); 3858 len += sizeof(SLTG_OtherTypeInfo); 3859 ptr += len; 3860 } 3861 3862 pAfterOTIBlks = ptr; 3863 3864 /* Skip this WORD and get the next DWORD */ 3865 len = *(DWORD*)(pAfterOTIBlks + 2); 3866 3867 /* Now add this to pLibBLk look at what we're pointing at and 3868 possibly add 0x20, then add 0x216, sprinkle a bit a magic 3869 dust and we should be pointing at the beginning of the name 3870 table */ 3871 3872 pNameTable = (char*)pLibBlk + len; 3873 3874 switch(*(WORD*)pNameTable) { 3875 case 0xffff: 3876 break; 3877 case 0x0200: 3878 pNameTable += 0x20; 3879 break; 3880 default: 3881 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable); 3882 break; 3883 } 3884 3885 pNameTable += 0x216; 3886 3887 pNameTable += 2; 3888 3889 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name); 3890 3891 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name); 3892 3893 3894 /* Hopefully we now have enough ptrs set up to actually read in 3895 some TypeInfos. It's not clear which order to do them in, so 3896 I'll just follow the links along the BlkEntry chain and read 3897 them in the order in which they are in the file */ 3898 3899 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo); 3900 3901 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0; 3902 pBlkEntry[order].next != 0; 3903 order = pBlkEntry[order].next - 1, i++) { 3904 3905 SLTG_TypeInfoHeader *pTIHeader; 3906 SLTG_TypeInfoTail *pTITail; 3907 SLTG_MemberHeader *pMemHeader; 3908 3909 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, 3910 pOtherTypeInfoBlks[i].index_name)) { 3911 FIXME_(typelib)("Index strings don't match\n"); 3912 return NULL; 3913 } 3914 3915 pTIHeader = pBlk; 3916 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) { 3917 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic); 3918 return NULL; 3919 } 3920 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, " 3921 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n", 3922 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e); 3923 3924 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor(); 3925 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl; 3926 (*ppTypeInfoImpl)->index = i; 3927 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR( 3928 pOtherTypeInfoBlks[i].name_offs + 3929 pNameTable); 3930 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext; 3931 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid; 3932 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind; 3933 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version; 3934 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version; 3935 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags = 3936 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5); 3937 3938 if((pTIHeader->typeflags1 & 7) != 2) 3939 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1); 3940 if(pTIHeader->typeflags3 != 2) 3941 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3); 3942 3943 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n", 3944 debugstr_w((*ppTypeInfoImpl)->Name), 3945 typekind_desc[pTIHeader->typekind], 3946 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid), 3947 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags); 3948 3949 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table); 3950 3951 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra); 3952 3953 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment; 3954 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance; 3955 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft; 3956 3957 switch(pTIHeader->typekind) { 3958 case TKIND_ENUM: 3959 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 3960 pTIHeader, pTITail); 3961 break; 3962 3963 case TKIND_RECORD: 3964 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 3965 pTIHeader, pTITail); 3966 break; 3967 3968 case TKIND_INTERFACE: 3969 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 3970 pTIHeader, pTITail); 3971 break; 3972 3973 case TKIND_COCLASS: 3974 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 3975 pTIHeader, pTITail); 3976 break; 3977 3978 case TKIND_ALIAS: 3979 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 3980 pTIHeader, pTITail); 3981 break; 3982 3983 case TKIND_DISPATCH: 3984 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 3985 pTIHeader, pTITail); 3986 break; 3987 3988 case TKIND_MODULE: 3989 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 3990 pTIHeader, pTITail); 3991 break; 3992 3993 default: 3994 FIXME("Not processing typekind %d\n", pTIHeader->typekind); 3995 break; 3996 3997 } 3998 3999 /* could get cFuncs, cVars and cImplTypes from here 4000 but we've already set those */ 4001 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x); 4002 X(06); 4003 X(16); 4004 X(18); 4005 X(1a); 4006 X(1e); 4007 X(24); 4008 X(26); 4009 X(2a); 4010 X(2c); 4011 X(2e); 4012 X(30); 4013 X(32); 4014 X(34); 4015 #undef X 4016 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next); 4017 pBlk = (char*)pBlk + pBlkEntry[order].len; 4018 } 4019 4020 if(i != pTypeLibImpl->TypeInfoCount) { 4021 FIXME("Somehow processed %d TypeInfos\n", i); 4022 return NULL; 4023 } 4024 4025 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks); 4026 return (ITypeLib2*)pTypeLibImpl; 4027 } 4028 4029 /* ITypeLib::QueryInterface 4030 */ 4031 static HRESULT WINAPI ITypeLib2_fnQueryInterface( 4032 ITypeLib2 * iface, 4033 REFIID riid, 4034 VOID **ppvObject) 4035 { 4036 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4037 4038 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid)); 4039 4040 *ppvObject=NULL; 4041 if(IsEqualIID(riid, &IID_IUnknown) || 4042 IsEqualIID(riid,&IID_ITypeLib)|| 4043 IsEqualIID(riid,&IID_ITypeLib2)) 4044 { 4045 *ppvObject = This; 4046 } 4047 4048 if(*ppvObject) 4049 { 4050 ITypeLib2_AddRef(iface); 4051 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject); 4052 return S_OK; 4053 } 4054 TRACE("-- Interface: E_NOINTERFACE\n"); 4055 return E_NOINTERFACE; 4056 } 4057 4058 /* ITypeLib::AddRef 4059 */ 4060 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface) 4061 { 4062 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4063 ULONG ref = InterlockedIncrement(&This->ref); 4064 4065 TRACE("(%p)->ref was %u\n",This, ref - 1); 4066 4067 return ref; 4068 } 4069 4070 /* ITypeLib::Release 4071 */ 4072 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) 4073 { 4074 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4075 ULONG ref = InterlockedDecrement(&This->ref); 4076 4077 TRACE("(%p)->(%u)\n",This, ref); 4078 4079 if (!ref) 4080 { 4081 TLBImpLib *pImpLib, *pImpLibNext; 4082 TLBCustData *pCustData, *pCustDataNext; 4083 TLBRefType *ref_type; 4084 void *cursor2; 4085 int i; 4086 4087 /* remove cache entry */ 4088 if(This->path) 4089 { 4090 TRACE("removing from cache list\n"); 4091 EnterCriticalSection(&cache_section); 4092 if (This->next) This->next->prev = This->prev; 4093 if (This->prev) This->prev->next = This->next; 4094 else tlb_cache_first = This->next; 4095 LeaveCriticalSection(&cache_section); 4096 HeapFree(GetProcessHeap(), 0, This->path); 4097 } 4098 TRACE(" destroying ITypeLib(%p)\n",This); 4099 4100 SysFreeString(This->Name); 4101 This->Name = NULL; 4102 4103 SysFreeString(This->DocString); 4104 This->DocString = NULL; 4105 4106 SysFreeString(This->HelpFile); 4107 This->HelpFile = NULL; 4108 4109 SysFreeString(This->HelpStringDll); 4110 This->HelpStringDll = NULL; 4111 4112 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext) 4113 { 4114 VariantClear(&pCustData->data); 4115 4116 pCustDataNext = pCustData->next; 4117 TLB_Free(pCustData); 4118 } 4119 4120 for (i = 0; i < This->ctTypeDesc; i++) 4121 if (This->pTypeDesc[i].vt == VT_CARRAY) 4122 TLB_Free(This->pTypeDesc[i].u.lpadesc); 4123 4124 TLB_Free(This->pTypeDesc); 4125 4126 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext) 4127 { 4128 if (pImpLib->pImpTypeLib) 4129 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib); 4130 SysFreeString(pImpLib->name); 4131 4132 pImpLibNext = pImpLib->next; 4133 TLB_Free(pImpLib); 4134 } 4135 4136 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry) 4137 { 4138 list_remove(&ref_type->entry); 4139 TLB_Free(ref_type); 4140 } 4141 4142 if (This->pTypeInfo) /* can be NULL */ 4143 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo); 4144 HeapFree(GetProcessHeap(),0,This); 4145 return 0; 4146 } 4147 4148 return ref; 4149 } 4150 4151 /* ITypeLib::GetTypeInfoCount 4152 * 4153 * Returns the number of type descriptions in the type library 4154 */ 4155 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface) 4156 { 4157 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4158 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount); 4159 return This->TypeInfoCount; 4160 } 4161 4162 /* ITypeLib::GetTypeInfo 4163 * 4164 * retrieves the specified type description in the library. 4165 */ 4166 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo( 4167 ITypeLib2 *iface, 4168 UINT index, 4169 ITypeInfo **ppTInfo) 4170 { 4171 UINT i; 4172 4173 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4174 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; 4175 4176 TRACE("(%p)->(index=%d)\n", This, index); 4177 4178 if (!ppTInfo) return E_INVALIDARG; 4179 4180 /* search element n in list */ 4181 for(i=0; i < index; i++) 4182 { 4183 pTypeInfo = pTypeInfo->next; 4184 if (!pTypeInfo) 4185 { 4186 TRACE("-- element not found\n"); 4187 return TYPE_E_ELEMENTNOTFOUND; 4188 } 4189 } 4190 4191 *ppTInfo = (ITypeInfo *) pTypeInfo; 4192 4193 ITypeInfo_AddRef(*ppTInfo); 4194 TRACE("-- found (%p)\n",*ppTInfo); 4195 return S_OK; 4196 } 4197 4198 4199 /* ITypeLibs::GetTypeInfoType 4200 * 4201 * Retrieves the type of a type description. 4202 */ 4203 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType( 4204 ITypeLib2 *iface, 4205 UINT index, 4206 TYPEKIND *pTKind) 4207 { 4208 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4209 UINT i; 4210 ITypeInfoImpl *pTInfo = This->pTypeInfo; 4211 4212 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) 4213 return TYPE_E_ELEMENTNOTFOUND; 4214 4215 TRACE("(%p) index %d\n", This, index); 4216 4217 if(!pTKind) return E_INVALIDARG; 4218 4219 /* search element n in list */ 4220 for(i=0; i < index; i++) 4221 { 4222 if(!pTInfo) 4223 { 4224 TRACE("-- element not found\n"); 4225 return TYPE_E_ELEMENTNOTFOUND; 4226 } 4227 pTInfo = pTInfo->next; 4228 } 4229 4230 *pTKind = pTInfo->TypeAttr.typekind; 4231 TRACE("-- found Type (%d)\n", *pTKind); 4232 return S_OK; 4233 } 4234 4235 /* ITypeLib::GetTypeInfoOfGuid 4236 * 4237 * Retrieves the type description that corresponds to the specified GUID. 4238 * 4239 */ 4240 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid( 4241 ITypeLib2 *iface, 4242 REFGUID guid, 4243 ITypeInfo **ppTInfo) 4244 { 4245 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4246 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */ 4247 4248 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid)); 4249 4250 if (!pTypeInfo) 4251 { 4252 WARN("-- element not found\n"); 4253 return TYPE_E_ELEMENTNOTFOUND; 4254 } 4255 4256 /* search linked list for guid */ 4257 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) ) 4258 { 4259 pTypeInfo = pTypeInfo->next; 4260 4261 if (!pTypeInfo) 4262 { 4263 /* end of list reached */ 4264 WARN("-- element not found\n"); 4265 return TYPE_E_ELEMENTNOTFOUND; 4266 } 4267 } 4268 4269 TRACE("-- found (%p, %s)\n", 4270 pTypeInfo, 4271 debugstr_w(pTypeInfo->Name)); 4272 4273 *ppTInfo = (ITypeInfo*)pTypeInfo; 4274 ITypeInfo_AddRef(*ppTInfo); 4275 return S_OK; 4276 } 4277 4278 /* ITypeLib::GetLibAttr 4279 * 4280 * Retrieves the structure that contains the library's attributes. 4281 * 4282 */ 4283 static HRESULT WINAPI ITypeLib2_fnGetLibAttr( 4284 ITypeLib2 *iface, 4285 LPTLIBATTR *ppTLibAttr) 4286 { 4287 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4288 TRACE("(%p)\n",This); 4289 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr)); 4290 **ppTLibAttr = This->LibAttr; 4291 return S_OK; 4292 } 4293 4294 /* ITypeLib::GetTypeComp 4295 * 4296 * Enables a client compiler to bind to a library's types, variables, 4297 * constants, and global functions. 4298 * 4299 */ 4300 static HRESULT WINAPI ITypeLib2_fnGetTypeComp( 4301 ITypeLib2 *iface, 4302 ITypeComp **ppTComp) 4303 { 4304 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4305 4306 TRACE("(%p)->(%p)\n",This,ppTComp); 4307 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp; 4308 ITypeComp_AddRef(*ppTComp); 4309 4310 return S_OK; 4311 } 4312 4313 /* ITypeLib::GetDocumentation 4314 * 4315 * Retrieves the library's documentation string, the complete Help file name 4316 * and path, and the context identifier for the library Help topic in the Help 4317 * file. 4318 * 4319 * On a successful return all non-null BSTR pointers will have been set, 4320 * possibly to NULL. 4321 */ 4322 static HRESULT WINAPI ITypeLib2_fnGetDocumentation( 4323 ITypeLib2 *iface, 4324 INT index, 4325 BSTR *pBstrName, 4326 BSTR *pBstrDocString, 4327 DWORD *pdwHelpContext, 4328 BSTR *pBstrHelpFile) 4329 { 4330 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4331 4332 HRESULT result = E_INVALIDARG; 4333 4334 ITypeInfo *pTInfo; 4335 4336 4337 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n", 4338 This, index, 4339 pBstrName, pBstrDocString, 4340 pdwHelpContext, pBstrHelpFile); 4341 4342 if(index<0) 4343 { 4344 /* documentation for the typelib */ 4345 if(pBstrName) 4346 { 4347 if (This->Name) 4348 { 4349 if(!(*pBstrName = SysAllocString(This->Name))) 4350 goto memerr1; 4351 } 4352 else 4353 *pBstrName = NULL; 4354 } 4355 if(pBstrDocString) 4356 { 4357 if (This->DocString) 4358 { 4359 if(!(*pBstrDocString = SysAllocString(This->DocString))) 4360 goto memerr2; 4361 } 4362 else if (This->Name) 4363 { 4364 if(!(*pBstrDocString = SysAllocString(This->Name))) 4365 goto memerr2; 4366 } 4367 else 4368 *pBstrDocString = NULL; 4369 } 4370 if(pdwHelpContext) 4371 { 4372 *pdwHelpContext = This->dwHelpContext; 4373 } 4374 if(pBstrHelpFile) 4375 { 4376 if (This->HelpFile) 4377 { 4378 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) 4379 goto memerr3; 4380 } 4381 else 4382 *pBstrHelpFile = NULL; 4383 } 4384 4385 result = S_OK; 4386 } 4387 else 4388 { 4389 /* for a typeinfo */ 4390 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo); 4391 4392 if(SUCCEEDED(result)) 4393 { 4394 result = ITypeInfo_GetDocumentation(pTInfo, 4395 MEMBERID_NIL, 4396 pBstrName, 4397 pBstrDocString, 4398 pdwHelpContext, pBstrHelpFile); 4399 4400 ITypeInfo_Release(pTInfo); 4401 } 4402 } 4403 return result; 4404 memerr3: 4405 if (pBstrDocString) SysFreeString (*pBstrDocString); 4406 memerr2: 4407 if (pBstrName) SysFreeString (*pBstrName); 4408 memerr1: 4409 return STG_E_INSUFFICIENTMEMORY; 4410 } 4411 4412 /* ITypeLib::IsName 4413 * 4414 * Indicates whether a passed-in string contains the name of a type or member 4415 * described in the library. 4416 * 4417 */ 4418 static HRESULT WINAPI ITypeLib2_fnIsName( 4419 ITypeLib2 *iface, 4420 LPOLESTR szNameBuf, 4421 ULONG lHashVal, 4422 BOOL *pfName) 4423 { 4424 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4425 ITypeInfoImpl *pTInfo; 4426 TLBFuncDesc *pFInfo; 4427 TLBVarDesc *pVInfo; 4428 int i; 4429 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR); 4430 4431 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal, 4432 pfName); 4433 4434 *pfName=TRUE; 4435 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){ 4436 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit; 4437 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) { 4438 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit; 4439 for(i=0;i<pFInfo->funcdesc.cParams;i++) 4440 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen)) 4441 goto ITypeLib2_fnIsName_exit; 4442 } 4443 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) 4444 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit; 4445 4446 } 4447 *pfName=FALSE; 4448 4449 ITypeLib2_fnIsName_exit: 4450 TRACE("(%p)slow! search for %s: %s found!\n", This, 4451 debugstr_w(szNameBuf), *pfName?"NOT":""); 4452 4453 return S_OK; 4454 } 4455 4456 /* ITypeLib::FindName 4457 * 4458 * Finds occurrences of a type description in a type library. This may be used 4459 * to quickly verify that a name exists in a type library. 4460 * 4461 */ 4462 static HRESULT WINAPI ITypeLib2_fnFindName( 4463 ITypeLib2 *iface, 4464 LPOLESTR szNameBuf, 4465 ULONG lHashVal, 4466 ITypeInfo **ppTInfo, 4467 MEMBERID *rgMemId, 4468 UINT16 *pcFound) 4469 { 4470 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4471 ITypeInfoImpl *pTInfo; 4472 TLBFuncDesc *pFInfo; 4473 TLBVarDesc *pVInfo; 4474 int i,j = 0; 4475 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR); 4476 4477 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){ 4478 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit; 4479 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) { 4480 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit; 4481 for(i=0;i<pFInfo->funcdesc.cParams;i++) { 4482 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen)) 4483 goto ITypeLib2_fnFindName_exit; 4484 } 4485 } 4486 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) 4487 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit; 4488 continue; 4489 ITypeLib2_fnFindName_exit: 4490 ITypeInfo_AddRef((ITypeInfo*)pTInfo); 4491 ppTInfo[j]=(LPTYPEINFO)pTInfo; 4492 j++; 4493 } 4494 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n", 4495 This, *pcFound, debugstr_w(szNameBuf), j); 4496 4497 *pcFound=j; 4498 4499 return S_OK; 4500 } 4501 4502 /* ITypeLib::ReleaseTLibAttr 4503 * 4504 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr. 4505 * 4506 */ 4507 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr( 4508 ITypeLib2 *iface, 4509 TLIBATTR *pTLibAttr) 4510 { 4511 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4512 TRACE("freeing (%p)\n",This); 4513 HeapFree(GetProcessHeap(),0,pTLibAttr); 4514 4515 } 4516 4517 /* ITypeLib2::GetCustData 4518 * 4519 * gets the custom data 4520 */ 4521 static HRESULT WINAPI ITypeLib2_fnGetCustData( 4522 ITypeLib2 * iface, 4523 REFGUID guid, 4524 VARIANT *pVarVal) 4525 { 4526 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4527 TLBCustData *pCData; 4528 4529 for(pCData=This->pCustData; pCData; pCData = pCData->next) 4530 { 4531 if( IsEqualIID(guid, &pCData->guid)) break; 4532 } 4533 4534 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 4535 4536 if(pCData) 4537 { 4538 VariantInit( pVarVal); 4539 VariantCopy( pVarVal, &pCData->data); 4540 return S_OK; 4541 } 4542 return E_INVALIDARG; /* FIXME: correct? */ 4543 } 4544 4545 /* ITypeLib2::GetLibStatistics 4546 * 4547 * Returns statistics about a type library that are required for efficient 4548 * sizing of hash tables. 4549 * 4550 */ 4551 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics( 4552 ITypeLib2 * iface, 4553 ULONG *pcUniqueNames, 4554 ULONG *pcchUniqueNames) 4555 { 4556 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4557 4558 FIXME("(%p): stub!\n", This); 4559 4560 if(pcUniqueNames) *pcUniqueNames=1; 4561 if(pcchUniqueNames) *pcchUniqueNames=1; 4562 return S_OK; 4563 } 4564 4565 /* ITypeLib2::GetDocumentation2 4566 * 4567 * Retrieves the library's documentation string, the complete Help file name 4568 * and path, the localization context to use, and the context ID for the 4569 * library Help topic in the Help file. 4570 * 4571 */ 4572 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2( 4573 ITypeLib2 * iface, 4574 INT index, 4575 LCID lcid, 4576 BSTR *pbstrHelpString, 4577 DWORD *pdwHelpStringContext, 4578 BSTR *pbstrHelpStringDll) 4579 { 4580 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4581 HRESULT result; 4582 ITypeInfo *pTInfo; 4583 4584 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid); 4585 4586 /* the help string should be obtained from the helpstringdll, 4587 * using the _DLLGetDocumentation function, based on the supplied 4588 * lcid. Nice to do sometime... 4589 */ 4590 if(index<0) 4591 { 4592 /* documentation for the typelib */ 4593 if(pbstrHelpString) 4594 *pbstrHelpString=SysAllocString(This->DocString); 4595 if(pdwHelpStringContext) 4596 *pdwHelpStringContext=This->dwHelpContext; 4597 if(pbstrHelpStringDll) 4598 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll); 4599 4600 result = S_OK; 4601 } 4602 else 4603 { 4604 /* for a typeinfo */ 4605 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo); 4606 4607 if(SUCCEEDED(result)) 4608 { 4609 ITypeInfo2 * pTInfo2; 4610 result = ITypeInfo_QueryInterface(pTInfo, 4611 &IID_ITypeInfo2, 4612 (LPVOID*) &pTInfo2); 4613 4614 if(SUCCEEDED(result)) 4615 { 4616 result = ITypeInfo2_GetDocumentation2(pTInfo2, 4617 MEMBERID_NIL, 4618 lcid, 4619 pbstrHelpString, 4620 pdwHelpStringContext, 4621 pbstrHelpStringDll); 4622 4623 ITypeInfo2_Release(pTInfo2); 4624 } 4625 4626 ITypeInfo_Release(pTInfo); 4627 } 4628 } 4629 return result; 4630 } 4631 4632 /* ITypeLib2::GetAllCustData 4633 * 4634 * Gets all custom data items for the library. 4635 * 4636 */ 4637 static HRESULT WINAPI ITypeLib2_fnGetAllCustData( 4638 ITypeLib2 * iface, 4639 CUSTDATA *pCustData) 4640 { 4641 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4642 TLBCustData *pCData; 4643 int i; 4644 TRACE("(%p) returning %d items\n", This, This->ctCustData); 4645 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM)); 4646 if(pCustData->prgCustData ){ 4647 pCustData->cCustData=This->ctCustData; 4648 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){ 4649 pCustData->prgCustData[i].guid=pCData->guid; 4650 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data); 4651 } 4652 }else{ 4653 ERR(" OUT OF MEMORY!\n"); 4654 return E_OUTOFMEMORY; 4655 } 4656 return S_OK; 4657 } 4658 4659 static const ITypeLib2Vtbl tlbvt = { 4660 ITypeLib2_fnQueryInterface, 4661 ITypeLib2_fnAddRef, 4662 ITypeLib2_fnRelease, 4663 ITypeLib2_fnGetTypeInfoCount, 4664 ITypeLib2_fnGetTypeInfo, 4665 ITypeLib2_fnGetTypeInfoType, 4666 ITypeLib2_fnGetTypeInfoOfGuid, 4667 ITypeLib2_fnGetLibAttr, 4668 ITypeLib2_fnGetTypeComp, 4669 ITypeLib2_fnGetDocumentation, 4670 ITypeLib2_fnIsName, 4671 ITypeLib2_fnFindName, 4672 ITypeLib2_fnReleaseTLibAttr, 4673 4674 ITypeLib2_fnGetCustData, 4675 ITypeLib2_fnGetLibStatistics, 4676 ITypeLib2_fnGetDocumentation2, 4677 ITypeLib2_fnGetAllCustData 4678 }; 4679 4680 4681 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv) 4682 { 4683 ITypeLibImpl *This = impl_from_ITypeComp(iface); 4684 4685 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv); 4686 } 4687 4688 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface) 4689 { 4690 ITypeLibImpl *This = impl_from_ITypeComp(iface); 4691 4692 return ITypeLib2_AddRef((ITypeLib2 *)This); 4693 } 4694 4695 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface) 4696 { 4697 ITypeLibImpl *This = impl_from_ITypeComp(iface); 4698 4699 return ITypeLib2_Release((ITypeLib2 *)This); 4700 } 4701 4702 static HRESULT WINAPI ITypeLibComp_fnBind( 4703 ITypeComp * iface, 4704 OLECHAR * szName, 4705 ULONG lHash, 4706 WORD wFlags, 4707 ITypeInfo ** ppTInfo, 4708 DESCKIND * pDescKind, 4709 BINDPTR * pBindPtr) 4710 { 4711 ITypeLibImpl *This = impl_from_ITypeComp(iface); 4712 ITypeInfoImpl *pTypeInfo; 4713 4714 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 4715 4716 *pDescKind = DESCKIND_NONE; 4717 pBindPtr->lptcomp = NULL; 4718 *ppTInfo = NULL; 4719 4720 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next) 4721 { 4722 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name)); 4723 4724 /* FIXME: check wFlags here? */ 4725 /* FIXME: we should use a hash table to look this info up using lHash 4726 * instead of an O(n) search */ 4727 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) || 4728 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE)) 4729 { 4730 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName)) 4731 { 4732 *pDescKind = DESCKIND_TYPECOMP; 4733 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; 4734 ITypeComp_AddRef(pBindPtr->lptcomp); 4735 TRACE("module or enum: %s\n", debugstr_w(szName)); 4736 return S_OK; 4737 } 4738 } 4739 4740 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) || 4741 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM)) 4742 { 4743 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; 4744 HRESULT hr; 4745 4746 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 4747 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE)) 4748 { 4749 TRACE("found in module or in enum: %s\n", debugstr_w(szName)); 4750 return S_OK; 4751 } 4752 } 4753 4754 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) && 4755 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT)) 4756 { 4757 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; 4758 HRESULT hr; 4759 ITypeInfo *subtypeinfo; 4760 BINDPTR subbindptr; 4761 DESCKIND subdesckind; 4762 4763 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, 4764 &subtypeinfo, &subdesckind, &subbindptr); 4765 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE)) 4766 { 4767 TYPEDESC tdesc_appobject = 4768 { 4769 { 4770 (TYPEDESC *)pTypeInfo->hreftype 4771 }, 4772 VT_USERDEFINED 4773 }; 4774 const VARDESC vardesc_appobject = 4775 { 4776 -2, /* memid */ 4777 NULL, /* lpstrSchema */ 4778 { 4779 0 /* oInst */ 4780 }, 4781 { 4782 /* ELEMDESC */ 4783 { 4784 /* TYPEDESC */ 4785 { 4786 &tdesc_appobject 4787 }, 4788 VT_PTR 4789 }, 4790 }, 4791 0, /* wVarFlags */ 4792 VAR_STATIC /* varkind */ 4793 }; 4794 4795 TRACE("found in implicit app object: %s\n", debugstr_w(szName)); 4796 4797 /* cleanup things filled in by Bind call so we can put our 4798 * application object data in there instead */ 4799 switch (subdesckind) 4800 { 4801 case DESCKIND_FUNCDESC: 4802 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc); 4803 break; 4804 case DESCKIND_VARDESC: 4805 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc); 4806 break; 4807 default: 4808 break; 4809 } 4810 if (subtypeinfo) ITypeInfo_Release(subtypeinfo); 4811 4812 if (pTypeInfo->hreftype == -1) 4813 FIXME("no hreftype for interface %p\n", pTypeInfo); 4814 4815 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc); 4816 if (FAILED(hr)) 4817 return hr; 4818 4819 *pDescKind = DESCKIND_IMPLICITAPPOBJ; 4820 *ppTInfo = (ITypeInfo *)pTypeInfo; 4821 ITypeInfo_AddRef(*ppTInfo); 4822 return S_OK; 4823 } 4824 } 4825 } 4826 4827 TRACE("name not found %s\n", debugstr_w(szName)); 4828 return S_OK; 4829 } 4830 4831 static HRESULT WINAPI ITypeLibComp_fnBindType( 4832 ITypeComp * iface, 4833 OLECHAR * szName, 4834 ULONG lHash, 4835 ITypeInfo ** ppTInfo, 4836 ITypeComp ** ppTComp) 4837 { 4838 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp); 4839 return E_NOTIMPL; 4840 } 4841 4842 static const ITypeCompVtbl tlbtcvt = 4843 { 4844 4845 ITypeLibComp_fnQueryInterface, 4846 ITypeLibComp_fnAddRef, 4847 ITypeLibComp_fnRelease, 4848 4849 ITypeLibComp_fnBind, 4850 ITypeLibComp_fnBindType 4851 }; 4852 4853 /*================== ITypeInfo(2) Methods ===================================*/ 4854 static ITypeInfo2 * ITypeInfo_Constructor(void) 4855 { 4856 ITypeInfoImpl * pTypeInfoImpl; 4857 4858 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl)); 4859 if (pTypeInfoImpl) 4860 { 4861 pTypeInfoImpl->lpVtbl = &tinfvt; 4862 pTypeInfoImpl->lpVtblTypeComp = &tcompvt; 4863 pTypeInfoImpl->ref=1; 4864 pTypeInfoImpl->hreftype = -1; 4865 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL; 4866 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL; 4867 } 4868 TRACE("(%p)\n", pTypeInfoImpl); 4869 return (ITypeInfo2*) pTypeInfoImpl; 4870 } 4871 4872 /* ITypeInfo::QueryInterface 4873 */ 4874 static HRESULT WINAPI ITypeInfo_fnQueryInterface( 4875 ITypeInfo2 *iface, 4876 REFIID riid, 4877 VOID **ppvObject) 4878 { 4879 ITypeLibImpl *This = (ITypeLibImpl *)iface; 4880 4881 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid)); 4882 4883 *ppvObject=NULL; 4884 if(IsEqualIID(riid, &IID_IUnknown) || 4885 IsEqualIID(riid,&IID_ITypeInfo)|| 4886 IsEqualIID(riid,&IID_ITypeInfo2)) 4887 *ppvObject = This; 4888 4889 if(*ppvObject){ 4890 ITypeInfo_AddRef(iface); 4891 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject); 4892 return S_OK; 4893 } 4894 TRACE("-- Interface: E_NOINTERFACE\n"); 4895 return E_NOINTERFACE; 4896 } 4897 4898 /* ITypeInfo::AddRef 4899 */ 4900 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface) 4901 { 4902 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 4903 ULONG ref = InterlockedIncrement(&This->ref); 4904 4905 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib); 4906 4907 TRACE("(%p)->ref is %u\n",This, ref); 4908 return ref; 4909 } 4910 4911 /* ITypeInfo::Release 4912 */ 4913 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface) 4914 { 4915 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 4916 ULONG ref = InterlockedDecrement(&This->ref); 4917 4918 TRACE("(%p)->(%u)\n",This, ref); 4919 4920 if (ref) { 4921 /* We don't release ITypeLib when ref=0 because 4922 it means that function is called by ITypeLib2_Release */ 4923 ITypeLib2_Release((ITypeLib2*)This->pTypeLib); 4924 } else { 4925 TLBFuncDesc *pFInfo, *pFInfoNext; 4926 TLBVarDesc *pVInfo, *pVInfoNext; 4927 TLBImplType *pImpl, *pImplNext; 4928 4929 TRACE("destroying ITypeInfo(%p)\n",This); 4930 4931 if (This->no_free_data) 4932 goto finish_free; 4933 4934 SysFreeString(This->Name); 4935 This->Name = NULL; 4936 4937 SysFreeString(This->DocString); 4938 This->DocString = NULL; 4939 4940 SysFreeString(This->DllName); 4941 This->DllName = NULL; 4942 4943 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext) 4944 { 4945 INT i; 4946 for(i = 0;i < pFInfo->funcdesc.cParams; i++) 4947 { 4948 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i]; 4949 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 4950 { 4951 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue); 4952 TLB_Free(elemdesc->u.paramdesc.pparamdescex); 4953 } 4954 SysFreeString(pFInfo->pParamDesc[i].Name); 4955 } 4956 TLB_Free(pFInfo->funcdesc.lprgelemdescParam); 4957 TLB_Free(pFInfo->pParamDesc); 4958 TLB_FreeCustData(pFInfo->pCustData); 4959 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1) 4960 SysFreeString(pFInfo->Entry); 4961 SysFreeString(pFInfo->HelpString); 4962 SysFreeString(pFInfo->Name); 4963 4964 pFInfoNext = pFInfo->next; 4965 TLB_Free(pFInfo); 4966 } 4967 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext) 4968 { 4969 if (pVInfo->vardesc.varkind == VAR_CONST) 4970 { 4971 VariantClear(pVInfo->vardesc.u.lpvarValue); 4972 TLB_Free(pVInfo->vardesc.u.lpvarValue); 4973 } 4974 TLB_FreeCustData(pVInfo->pCustData); 4975 SysFreeString(pVInfo->Name); 4976 pVInfoNext = pVInfo->next; 4977 TLB_Free(pVInfo); 4978 } 4979 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext) 4980 { 4981 TLB_FreeCustData(pImpl->pCustData); 4982 pImplNext = pImpl->next; 4983 TLB_Free(pImpl); 4984 } 4985 TLB_FreeCustData(This->pCustData); 4986 4987 finish_free: 4988 if (This->next) 4989 { 4990 ITypeInfo_Release((ITypeInfo*)This->next); 4991 } 4992 4993 HeapFree(GetProcessHeap(),0,This); 4994 return 0; 4995 } 4996 return ref; 4997 } 4998 4999 /* ITypeInfo::GetTypeAttr 5000 * 5001 * Retrieves a TYPEATTR structure that contains the attributes of the type 5002 * description. 5003 * 5004 */ 5005 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface, 5006 LPTYPEATTR *ppTypeAttr) 5007 { 5008 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5009 SIZE_T size; 5010 5011 TRACE("(%p)\n",This); 5012 5013 size = sizeof(**ppTypeAttr); 5014 if (This->TypeAttr.typekind == TKIND_ALIAS) 5015 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE); 5016 5017 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size); 5018 if (!*ppTypeAttr) 5019 return E_OUTOFMEMORY; 5020 5021 **ppTypeAttr = This->TypeAttr; 5022 5023 if (This->TypeAttr.typekind == TKIND_ALIAS) 5024 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, 5025 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1); 5026 5027 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) { 5028 /* This should include all the inherited funcs */ 5029 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *); 5030 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */ 5031 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION; 5032 } 5033 return S_OK; 5034 } 5035 5036 /* ITypeInfo::GetTypeComp 5037 * 5038 * Retrieves the ITypeComp interface for the type description, which enables a 5039 * client compiler to bind to the type description's members. 5040 * 5041 */ 5042 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface, 5043 ITypeComp * *ppTComp) 5044 { 5045 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5046 5047 TRACE("(%p)->(%p)\n", This, ppTComp); 5048 5049 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp; 5050 ITypeComp_AddRef(*ppTComp); 5051 return S_OK; 5052 } 5053 5054 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc ) 5055 { 5056 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE); 5057 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 5058 size += sizeof(*elemdesc->u.paramdesc.pparamdescex); 5059 return size; 5060 } 5061 5062 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer ) 5063 { 5064 *dest = *src; 5065 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer); 5066 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 5067 { 5068 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex; 5069 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer; 5070 *buffer += sizeof(PARAMDESCEX); 5071 *pparamdescex_dest = *pparamdescex_src; 5072 VariantInit(&pparamdescex_dest->varDefaultValue); 5073 return VariantCopy(&pparamdescex_dest->varDefaultValue, 5074 (VARIANTARG *)&pparamdescex_src->varDefaultValue); 5075 } 5076 else 5077 dest->u.paramdesc.pparamdescex = NULL; 5078 return S_OK; 5079 } 5080 5081 static void TLB_FreeElemDesc( ELEMDESC *elemdesc ) 5082 { 5083 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 5084 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue); 5085 } 5086 5087 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface ) 5088 { 5089 FUNCDESC *dest; 5090 char *buffer; 5091 SIZE_T size = sizeof(*src); 5092 SHORT i; 5093 HRESULT hr; 5094 5095 size += sizeof(*src->lprgscode) * src->cScodes; 5096 size += TLB_SizeElemDesc(&src->elemdescFunc); 5097 for (i = 0; i < src->cParams; i++) 5098 { 5099 size += sizeof(ELEMDESC); 5100 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]); 5101 } 5102 5103 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size); 5104 if (!dest) return E_OUTOFMEMORY; 5105 5106 *dest = *src; 5107 if (dispinterface) /* overwrite funckind */ 5108 dest->funckind = FUNC_DISPATCH; 5109 buffer = (char *)(dest + 1); 5110 5111 dest->lprgscode = (SCODE *)buffer; 5112 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes); 5113 buffer += sizeof(*src->lprgscode) * src->cScodes; 5114 5115 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer); 5116 if (FAILED(hr)) 5117 { 5118 SysFreeString((BSTR)dest); 5119 return hr; 5120 } 5121 5122 dest->lprgelemdescParam = (ELEMDESC *)buffer; 5123 buffer += sizeof(ELEMDESC) * src->cParams; 5124 for (i = 0; i < src->cParams; i++) 5125 { 5126 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer); 5127 if (FAILED(hr)) 5128 break; 5129 } 5130 if (FAILED(hr)) 5131 { 5132 /* undo the above actions */ 5133 for (i = i - 1; i >= 0; i--) 5134 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]); 5135 TLB_FreeElemDesc(&dest->elemdescFunc); 5136 SysFreeString((BSTR)dest); 5137 return hr; 5138 } 5139 5140 /* special treatment for dispinterfaces: this makes functions appear 5141 * to return their [retval] value when it is really returning an 5142 * HRESULT */ 5143 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT) 5144 { 5145 if (dest->cParams && 5146 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL)) 5147 { 5148 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1]; 5149 if (elemdesc->tdesc.vt != VT_PTR) 5150 { 5151 ERR("elemdesc should have started with VT_PTR instead of:\n"); 5152 if (ERR_ON(ole)) 5153 dump_ELEMDESC(elemdesc); 5154 return E_UNEXPECTED; 5155 } 5156 5157 /* copy last parameter to the return value. we are using a flat 5158 * buffer so there is no danger of leaking memory in 5159 * elemdescFunc */ 5160 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc; 5161 5162 /* remove the last parameter */ 5163 dest->cParams--; 5164 } 5165 else 5166 /* otherwise this function is made to appear to have no return 5167 * value */ 5168 dest->elemdescFunc.tdesc.vt = VT_VOID; 5169 5170 } 5171 5172 *dest_ptr = dest; 5173 return S_OK; 5174 } 5175 5176 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc ) 5177 { 5178 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5179 const TLBFuncDesc *pFDesc; 5180 UINT i; 5181 5182 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next) 5183 ; 5184 5185 if (pFDesc) 5186 { 5187 *ppFuncDesc = &pFDesc->funcdesc; 5188 return S_OK; 5189 } 5190 5191 return TYPE_E_ELEMENTNOTFOUND; 5192 } 5193 5194 /* internal function to make the inherited interfaces' methods appear 5195 * part of the interface */ 5196 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface, 5197 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset) 5198 { 5199 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5200 HRESULT hr; 5201 UINT implemented_funcs = 0; 5202 5203 if (funcs) 5204 *funcs = 0; 5205 else 5206 *hrefoffset = DISPATCH_HREF_OFFSET; 5207 5208 if(This->impltypelist) 5209 { 5210 ITypeInfo *pSubTypeInfo; 5211 UINT sub_funcs; 5212 5213 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo); 5214 if (FAILED(hr)) 5215 return hr; 5216 5217 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo, 5218 index, 5219 ppFuncDesc, 5220 &sub_funcs, hrefoffset); 5221 implemented_funcs += sub_funcs; 5222 ITypeInfo_Release(pSubTypeInfo); 5223 if (SUCCEEDED(hr)) 5224 return hr; 5225 *hrefoffset += DISPATCH_HREF_OFFSET; 5226 } 5227 5228 if (funcs) 5229 *funcs = implemented_funcs + This->TypeAttr.cFuncs; 5230 else 5231 *hrefoffset = 0; 5232 5233 if (index < implemented_funcs) 5234 return E_INVALIDARG; 5235 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs, 5236 ppFuncDesc); 5237 } 5238 5239 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset) 5240 { 5241 TYPEDESC *pTypeDesc = &pElemDesc->tdesc; 5242 while (TRUE) 5243 { 5244 switch (pTypeDesc->vt) 5245 { 5246 case VT_USERDEFINED: 5247 pTypeDesc->u.hreftype += hrefoffset; 5248 return; 5249 case VT_PTR: 5250 case VT_SAFEARRAY: 5251 pTypeDesc = pTypeDesc->u.lptdesc; 5252 break; 5253 case VT_CARRAY: 5254 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem; 5255 break; 5256 default: 5257 return; 5258 } 5259 } 5260 } 5261 5262 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset) 5263 { 5264 SHORT i; 5265 for (i = 0; i < pFuncDesc->cParams; i++) 5266 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset); 5267 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset); 5268 } 5269 5270 /* ITypeInfo::GetFuncDesc 5271 * 5272 * Retrieves the FUNCDESC structure that contains information about a 5273 * specified function. 5274 * 5275 */ 5276 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index, 5277 LPFUNCDESC *ppFuncDesc) 5278 { 5279 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5280 const FUNCDESC *internal_funcdesc; 5281 HRESULT hr; 5282 UINT hrefoffset = 0; 5283 5284 TRACE("(%p) index %d\n", This, index); 5285 5286 if (This->TypeAttr.typekind == TKIND_DISPATCH) 5287 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index, 5288 &internal_funcdesc, NULL, 5289 &hrefoffset); 5290 else 5291 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, 5292 &internal_funcdesc); 5293 if (FAILED(hr)) 5294 { 5295 WARN("description for function %d not found\n", index); 5296 return hr; 5297 } 5298 5299 hr = TLB_AllocAndInitFuncDesc( 5300 internal_funcdesc, 5301 ppFuncDesc, 5302 This->TypeAttr.typekind == TKIND_DISPATCH); 5303 5304 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset) 5305 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset); 5306 5307 TRACE("-- 0x%08x\n", hr); 5308 return hr; 5309 } 5310 5311 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr ) 5312 { 5313 VARDESC *dest; 5314 char *buffer; 5315 SIZE_T size = sizeof(*src); 5316 HRESULT hr; 5317 5318 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR); 5319 if (src->varkind == VAR_CONST) 5320 size += sizeof(VARIANT); 5321 size += TLB_SizeElemDesc(&src->elemdescVar); 5322 5323 dest = (VARDESC *)SysAllocStringByteLen(NULL, size); 5324 if (!dest) return E_OUTOFMEMORY; 5325 5326 *dest = *src; 5327 buffer = (char *)(dest + 1); 5328 if (src->lpstrSchema) 5329 { 5330 int len; 5331 dest->lpstrSchema = (LPOLESTR)buffer; 5332 len = strlenW(src->lpstrSchema); 5333 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR)); 5334 buffer += (len + 1) * sizeof(WCHAR); 5335 } 5336 5337 if (src->varkind == VAR_CONST) 5338 { 5339 HRESULT hr; 5340 5341 dest->u.lpvarValue = (VARIANT *)buffer; 5342 *dest->u.lpvarValue = *src->u.lpvarValue; 5343 buffer += sizeof(VARIANT); 5344 VariantInit(dest->u.lpvarValue); 5345 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue); 5346 if (FAILED(hr)) 5347 { 5348 SysFreeString((BSTR)dest_ptr); 5349 return hr; 5350 } 5351 } 5352 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer); 5353 if (FAILED(hr)) 5354 { 5355 if (src->varkind == VAR_CONST) 5356 VariantClear(dest->u.lpvarValue); 5357 SysFreeString((BSTR)dest); 5358 return hr; 5359 } 5360 *dest_ptr = dest; 5361 return S_OK; 5362 } 5363 5364 /* ITypeInfo::GetVarDesc 5365 * 5366 * Retrieves a VARDESC structure that describes the specified variable. 5367 * 5368 */ 5369 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index, 5370 LPVARDESC *ppVarDesc) 5371 { 5372 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5373 UINT i; 5374 const TLBVarDesc *pVDesc; 5375 5376 TRACE("(%p) index %d\n", This, index); 5377 5378 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next) 5379 ; 5380 5381 if (pVDesc) 5382 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc); 5383 5384 return E_INVALIDARG; 5385 } 5386 5387 /* ITypeInfo_GetNames 5388 * 5389 * Retrieves the variable with the specified member ID (or the name of the 5390 * property or method and its parameters) that correspond to the specified 5391 * function ID. 5392 */ 5393 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid, 5394 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames) 5395 { 5396 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5397 const TLBFuncDesc *pFDesc; 5398 const TLBVarDesc *pVDesc; 5399 int i; 5400 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames); 5401 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next); 5402 if(pFDesc) 5403 { 5404 /* function found, now return function and parameter names */ 5405 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++) 5406 { 5407 if(!i) 5408 *rgBstrNames=SysAllocString(pFDesc->Name); 5409 else 5410 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name); 5411 } 5412 *pcNames=i; 5413 } 5414 else 5415 { 5416 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next); 5417 if(pVDesc) 5418 { 5419 *rgBstrNames=SysAllocString(pVDesc->Name); 5420 *pcNames=1; 5421 } 5422 else 5423 { 5424 if(This->impltypelist && 5425 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) { 5426 /* recursive search */ 5427 ITypeInfo *pTInfo; 5428 HRESULT result; 5429 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, 5430 &pTInfo); 5431 if(SUCCEEDED(result)) 5432 { 5433 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames); 5434 ITypeInfo_Release(pTInfo); 5435 return result; 5436 } 5437 WARN("Could not search inherited interface!\n"); 5438 } 5439 else 5440 { 5441 WARN("no names found\n"); 5442 } 5443 *pcNames=0; 5444 return TYPE_E_ELEMENTNOTFOUND; 5445 } 5446 } 5447 return S_OK; 5448 } 5449 5450 5451 /* ITypeInfo::GetRefTypeOfImplType 5452 * 5453 * If a type description describes a COM class, it retrieves the type 5454 * description of the implemented interface types. For an interface, 5455 * GetRefTypeOfImplType returns the type information for inherited interfaces, 5456 * if any exist. 5457 * 5458 */ 5459 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( 5460 ITypeInfo2 *iface, 5461 UINT index, 5462 HREFTYPE *pRefType) 5463 { 5464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5465 UINT i; 5466 HRESULT hr = S_OK; 5467 const TLBImplType *pImpl = This->impltypelist; 5468 5469 TRACE("(%p) index %d\n", This, index); 5470 if (TRACE_ON(ole)) dump_TypeInfo(This); 5471 5472 if(index==(UINT)-1) 5473 { 5474 /* only valid on dual interfaces; 5475 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH 5476 */ 5477 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG; 5478 5479 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE && 5480 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL ) 5481 { 5482 *pRefType = -1; 5483 } 5484 else 5485 { 5486 hr = TYPE_E_ELEMENTNOTFOUND; 5487 } 5488 } 5489 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH) 5490 { 5491 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */ 5492 *pRefType = This->pTypeLib->dispatch_href; 5493 } 5494 else 5495 { 5496 /* get element n from linked list */ 5497 for(i=0; pImpl && i<index; i++) 5498 { 5499 pImpl = pImpl->next; 5500 } 5501 5502 if (pImpl) 5503 *pRefType = pImpl->hRef; 5504 else 5505 hr = TYPE_E_ELEMENTNOTFOUND; 5506 } 5507 5508 if(TRACE_ON(ole)) 5509 { 5510 if(SUCCEEDED(hr)) 5511 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType ); 5512 else 5513 TRACE("FAILURE -- hresult = 0x%08x\n", hr); 5514 } 5515 5516 return hr; 5517 } 5518 5519 /* ITypeInfo::GetImplTypeFlags 5520 * 5521 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface 5522 * or base interface in a type description. 5523 */ 5524 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface, 5525 UINT index, INT *pImplTypeFlags) 5526 { 5527 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5528 UINT i; 5529 TLBImplType *pImpl; 5530 5531 TRACE("(%p) index %d\n", This, index); 5532 for(i=0, pImpl=This->impltypelist; i<index && pImpl; 5533 i++, pImpl=pImpl->next) 5534 ; 5535 if(i==index && pImpl){ 5536 *pImplTypeFlags=pImpl->implflags; 5537 return S_OK; 5538 } 5539 *pImplTypeFlags=0; 5540 return TYPE_E_ELEMENTNOTFOUND; 5541 } 5542 5543 /* GetIDsOfNames 5544 * Maps between member names and member IDs, and parameter names and 5545 * parameter IDs. 5546 */ 5547 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface, 5548 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId) 5549 { 5550 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 5551 const TLBFuncDesc *pFDesc; 5552 const TLBVarDesc *pVDesc; 5553 HRESULT ret=S_OK; 5554 UINT i; 5555 5556 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames), 5557 cNames); 5558 5559 /* init out parameters in case of failure */ 5560 for (i = 0; i < cNames; i++) 5561 pMemId[i] = MEMBERID_NIL; 5562 5563 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) { 5564 int j; 5565 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) { 5566 if(cNames) *pMemId=pFDesc->funcdesc.memid; 5567 for(i=1; i < cNames; i++){ 5568 for(j=0; j<pFDesc->funcdesc.cParams; j++) 5569 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name)) 5570 break; 5571 if( j<pFDesc->funcdesc.cParams) 5572 pMemId[i]=j; 5573 else 5574 ret=DISP_E_UNKNOWNNAME; 5575 }; 5576 TRACE("-- 0x%08x\n", ret); 5577 return ret; 5578 } 5579 } 5580 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) { 5581 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) { 5582 if(cNames) *pMemId=pVDesc->vardesc.memid; 5583 return ret; 5584 } 5585 } 5586 /* not found, see if it can be found in an inherited interface */ 5587 if(This->impltypelist) { 5588 /* recursive search */ 5589 ITypeInfo *pTInfo; 5590 ret=ITypeInfo_GetRefTypeInfo(iface, 5591 This->impltypelist->hRef, &pTInfo); 5592 if(SUCCEEDED(ret)){ 5593 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId ); 5594 ITypeInfo_Release(pTInfo); 5595 return ret; 5596 } 5597 WARN("Could not search inherited interface!\n"); 5598 } else 5599 WARN("no names found\n"); 5600 return DISP_E_UNKNOWNNAME; 5601 } 5602 5603 /* ITypeInfo::Invoke 5604 * 5605 * Invokes a method, or accesses a property of an object, that implements the 5606 * interface described by the type description. 5607 */ 5608 DWORD 5609 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) { 5610 DWORD res; 5611 5612 if (TRACE_ON(ole)) { 5613 int i; 5614 TRACE("Calling %p(",func); 5615 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]); 5616 TRACE(")\n"); 5617 } 5618 5619 switch (callconv) { 5620 case CC_STDCALL: 5621 5622 switch (nrargs) { 5623 case 0: 5624 res = func(); 5625 break; 5626 case 1: 5627 res = func(args[0]); 5628 break; 5629 case 2: 5630 res = func(args[0],args[1]); 5631 break; 5632 case 3: 5633 res = func(args[0],args[1],args[2]); 5634 break; 5635 case 4: 5636 res = func(args[0],args[1],args[2],args[3]); 5637 break; 5638 case 5: 5639 res = func(args[0],args[1],args[2],args[3],args[4]); 5640 break; 5641 case 6: 5642 res = func(args[0],args[1],args[2],args[3],args[4],args[5]); 5643 break; 5644 case 7: 5645 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]); 5646 break; 5647 case 8: 5648 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); 5649 break; 5650 case 9: 5651 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); 5652 break; 5653 case 10: 5654 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]); 5655 break; 5656 case 11: 5657 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]); 5658 break; 5659 case 12: 5660 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]); 5661 break; 5662 case 13: 5663 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]); 5664 break; 5665 case 14: 5666 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]); 5667 break; 5668 case 15: 5669 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]); 5670 break; 5671 case 16: 5672 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]); 5673 break; 5674 case 17: 5675 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]); 5676 break; 5677 case 18: 5678 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]); 5679 break; 5680 case 19: 5681 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]); 5682 break; 5683 case 20: 5684 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]); 5685 break; 5686 case 21: 5687 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]); 5688 break; 5689 case 22: 5690 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]); 5691 break; 5692 case 23: 5693 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]); 5694 break; 5695 case 24: 5696 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]); 5697 break; 5698 case 25: 5699 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]); 5700 break; 5701 case 26: 5702 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]); 5703 break; 5704 case 27: 5705 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]); 5706 break; 5707 case 28: 5708 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]); 5709 break; 5710 case 29: 5711 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]); 5712 break; 5713 case 30: 5714 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]); 5715 break; 5716 default: 5717 FIXME("unsupported number of arguments %d in stdcall\n",nrargs); 5718 res = -1; 5719 break; 5720 } 5721 break; 5722 default: 5723 FIXME("unsupported calling convention %d\n",callconv); 5724 res = -1; 5725 break; 5726 } 5727 TRACE("returns %08x\n",res); 5728 return res; 5729 } 5730 5731 /* The size of the argument on the stack in DWORD units (in all x86 call 5732 * convetions the arguments on the stack are DWORD-aligned) 5733 */ 5734 static int _dispargsize(VARTYPE vt) 5735 { 5736 switch (vt) { 5737 case VT_I8: 5738 case VT_UI8: 5739 return 8/sizeof(DWORD); 5740 case VT_R8: 5741 return sizeof(double)/sizeof(DWORD); 5742 case VT_DECIMAL: 5743 return (sizeof(DECIMAL)+3)/sizeof(DWORD); 5744 case VT_CY: 5745 return sizeof(CY)/sizeof(DWORD); 5746 case VT_DATE: 5747 return sizeof(DATE)/sizeof(DWORD); 5748 case VT_VARIANT: 5749 return (sizeof(VARIANT)+3)/sizeof(DWORD); 5750 case VT_RECORD: 5751 FIXME("VT_RECORD not implemented\n"); 5752 return 1; 5753 default: 5754 return 1; 5755 } 5756 } 5757 5758 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt) 5759 { 5760 HRESULT hr = S_OK; 5761 ITypeInfo *tinfo2 = NULL; 5762 TYPEATTR *tattr = NULL; 5763 5764 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2); 5765 if (hr) 5766 { 5767 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, " 5768 "hr = 0x%08x\n", 5769 tdesc->u.hreftype, hr); 5770 return hr; 5771 } 5772 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr); 5773 if (hr) 5774 { 5775 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr); 5776 ITypeInfo_Release(tinfo2); 5777 return hr; 5778 } 5779 5780 switch (tattr->typekind) 5781 { 5782 case TKIND_ENUM: 5783 *vt |= VT_I4; 5784 break; 5785 5786 case TKIND_ALIAS: 5787 tdesc = &tattr->tdescAlias; 5788 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt); 5789 break; 5790 5791 case TKIND_INTERFACE: 5792 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) 5793 *vt |= VT_DISPATCH; 5794 else 5795 *vt |= VT_UNKNOWN; 5796 break; 5797 5798 case TKIND_DISPATCH: 5799 *vt |= VT_DISPATCH; 5800 break; 5801 5802 case TKIND_COCLASS: 5803 *vt |= VT_DISPATCH; 5804 break; 5805 5806 case TKIND_RECORD: 5807 FIXME("TKIND_RECORD unhandled.\n"); 5808 hr = E_NOTIMPL; 5809 break; 5810 5811 case TKIND_UNION: 5812 FIXME("TKIND_UNION unhandled.\n"); 5813 hr = E_NOTIMPL; 5814 break; 5815 5816 default: 5817 FIXME("TKIND %d unhandled.\n",tattr->typekind); 5818 hr = E_NOTIMPL; 5819 break; 5820 } 5821 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 5822 ITypeInfo_Release(tinfo2); 5823 return hr; 5824 } 5825 5826 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt) 5827 { 5828 HRESULT hr = S_OK; 5829 5830 /* enforce only one level of pointer indirection */ 5831 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR)) 5832 { 5833 tdesc = tdesc->u.lptdesc; 5834 5835 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or 5836 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into 5837 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */ 5838 if ((tdesc->vt == VT_USERDEFINED) || 5839 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED))) 5840 { 5841 VARTYPE vt_userdefined = 0; 5842 const TYPEDESC *tdesc_userdefined = tdesc; 5843 if (tdesc->vt == VT_PTR) 5844 { 5845 vt_userdefined = VT_BYREF; 5846 tdesc_userdefined = tdesc->u.lptdesc; 5847 } 5848 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined); 5849 if ((hr == S_OK) && 5850 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) || 5851 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH))) 5852 { 5853 *vt |= vt_userdefined; 5854 return S_OK; 5855 } 5856 } 5857 *vt = VT_BYREF; 5858 } 5859 5860 switch (tdesc->vt) 5861 { 5862 case VT_HRESULT: 5863 *vt |= VT_ERROR; 5864 break; 5865 case VT_USERDEFINED: 5866 hr = userdefined_to_variantvt(tinfo, tdesc, vt); 5867 break; 5868 case VT_VOID: 5869 case VT_CARRAY: 5870 case VT_PTR: 5871 case VT_LPSTR: 5872 case VT_LPWSTR: 5873 ERR("cannot convert type %d into variant VT\n", tdesc->vt); 5874 hr = DISP_E_BADVARTYPE; 5875 break; 5876 case VT_SAFEARRAY: 5877 *vt |= VT_ARRAY; 5878 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt); 5879 break; 5880 case VT_INT: 5881 *vt |= VT_I4; 5882 break; 5883 case VT_UINT: 5884 *vt |= VT_UI4; 5885 break; 5886 default: 5887 *vt |= tdesc->vt; 5888 break; 5889 } 5890 return hr; 5891 } 5892 5893 /*********************************************************************** 5894 * DispCallFunc (OLEAUT32.@) 5895 * 5896 * Invokes a function of the specified calling convention, passing the 5897 * specified arguments and returns the result. 5898 * 5899 * PARAMS 5900 * pvInstance [I] Optional pointer to the instance whose function to invoke. 5901 * oVft [I] The offset in the vtable. See notes. 5902 * cc [I] Calling convention of the function to call. 5903 * vtReturn [I] The return type of the function. 5904 * cActuals [I] Number of parameters. 5905 * prgvt [I] The types of the parameters to pass. This is used for sizing only. 5906 * prgpvarg [I] The arguments to pass. 5907 * pvargResult [O] The return value of the function. Can be NULL. 5908 * 5909 * RETURNS 5910 * Success: S_OK. 5911 * Failure: HRESULT code. 5912 * 5913 * NOTES 5914 * The HRESULT return value of this function is not affected by the return 5915 * value of the user supplied function, which is returned in pvargResult. 5916 * 5917 * If pvInstance is NULL then a non-object function is to be called and oVft 5918 * is the address of the function to call. 5919 * 5920 * The cc parameter can be one of the following values: 5921 *|CC_FASTCALL 5922 *|CC_CDECL 5923 *|CC_PASCAL 5924 *|CC_STDCALL 5925 *|CC_FPFASTCALL 5926 *|CC_SYSCALL 5927 *|CC_MPWCDECL 5928 *|CC_MPWPASCAL 5929 * 5930 */ 5931 HRESULT WINAPI 5932 DispCallFunc( 5933 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals, 5934 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult) 5935 { 5936 int argsize, argspos; 5937 UINT i; 5938 DWORD *args; 5939 HRESULT hres; 5940 5941 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n", 5942 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, 5943 pvargResult, V_VT(pvargResult)); 5944 5945 argsize = 0; 5946 if (pvInstance) 5947 argsize++; /* for This pointer */ 5948 5949 for (i=0;i<cActuals;i++) 5950 { 5951 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i])); 5952 dump_Variant(prgpvarg[i]); 5953 argsize += _dispargsize(prgvt[i]); 5954 } 5955 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize); 5956 5957 argspos = 0; 5958 if (pvInstance) 5959 { 5960 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */ 5961 argspos++; 5962 } 5963 5964 for (i=0;i<cActuals;i++) 5965 { 5966 VARIANT *arg = prgpvarg[i]; 5967 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]); 5968 if (prgvt[i] == VT_VARIANT) 5969 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD)); 5970 else 5971 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD)); 5972 argspos += _dispargsize(prgvt[i]); 5973 } 5974 5975 if (pvInstance) 5976 { 5977 FARPROC *vtable = *(FARPROC**)pvInstance; 5978 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args); 5979 } 5980 else 5981 /* if we aren't invoking an object then the function pointer is stored 5982 * in oVft */ 5983 hres = _invoke((FARPROC)oVft, cc, argsize, args); 5984 5985 if (pvargResult && (vtReturn != VT_EMPTY)) 5986 { 5987 TRACE("Method returned 0x%08x\n",hres); 5988 V_VT(pvargResult) = vtReturn; 5989 V_UI4(pvargResult) = hres; 5990 } 5991 5992 HeapFree(GetProcessHeap(),0,args); 5993 return S_OK; 5994 } 5995 5996 #define INVBUF_ELEMENT_SIZE \ 5997 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE)) 5998 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer) 5999 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \ 6000 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params))) 6001 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \ 6002 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params))) 6003 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \ 6004 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params))) 6005 6006 static HRESULT WINAPI ITypeInfo_fnInvoke( 6007 ITypeInfo2 *iface, 6008 VOID *pIUnk, 6009 MEMBERID memid, 6010 UINT16 wFlags, 6011 DISPPARAMS *pDispParams, 6012 VARIANT *pVarResult, 6013 EXCEPINFO *pExcepInfo, 6014 UINT *pArgErr) 6015 { 6016 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6017 int i; 6018 unsigned int var_index; 6019 TYPEKIND type_kind; 6020 HRESULT hres; 6021 const TLBFuncDesc *pFuncInfo; 6022 6023 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n", 6024 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr 6025 ); 6026 6027 if (!pDispParams) 6028 { 6029 ERR("NULL pDispParams not allowed\n"); 6030 return E_INVALIDARG; 6031 } 6032 6033 dump_DispParms(pDispParams); 6034 6035 if (pDispParams->cNamedArgs > pDispParams->cArgs) 6036 { 6037 ERR("named argument array cannot be bigger than argument array (%d/%d)\n", 6038 pDispParams->cNamedArgs, pDispParams->cArgs); 6039 return E_INVALIDARG; 6040 } 6041 6042 /* we do this instead of using GetFuncDesc since it will return a fake 6043 * FUNCDESC for dispinterfaces and we want the real function description */ 6044 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next) 6045 if ((memid == pFuncInfo->funcdesc.memid) && 6046 (wFlags & pFuncInfo->funcdesc.invkind)) 6047 break; 6048 6049 if (pFuncInfo) { 6050 const FUNCDESC *func_desc = &pFuncInfo->funcdesc; 6051 6052 if (TRACE_ON(ole)) 6053 { 6054 TRACE("invoking:\n"); 6055 dump_TLBFuncDescOne(pFuncInfo); 6056 } 6057 6058 switch (func_desc->funckind) { 6059 case FUNC_PUREVIRTUAL: 6060 case FUNC_VIRTUAL: { 6061 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams); 6062 VARIANT varresult; 6063 VARIANT retval; /* pointer for storing byref retvals in */ 6064 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams); 6065 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams); 6066 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams); 6067 UINT cNamedArgs = pDispParams->cNamedArgs; 6068 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs; 6069 UINT vargs_converted=0; 6070 6071 hres = S_OK; 6072 6073 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF)) 6074 { 6075 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT)) 6076 { 6077 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n"); 6078 hres = DISP_E_PARAMNOTFOUND; 6079 goto func_fail; 6080 } 6081 /* ignore the DISPID_PROPERTYPUT named argument from now on */ 6082 cNamedArgs--; 6083 rgdispidNamedArgs++; 6084 } 6085 6086 if (func_desc->cParamsOpt < 0 && cNamedArgs) 6087 { 6088 ERR("functions with the vararg attribute do not support named arguments\n"); 6089 hres = DISP_E_NONAMEDARGS; 6090 goto func_fail; 6091 } 6092 6093 for (i = 0; i < func_desc->cParams; i++) 6094 { 6095 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; 6096 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]); 6097 if (FAILED(hres)) 6098 goto func_fail; 6099 } 6100 6101 TRACE("changing args\n"); 6102 for (i = 0; i < func_desc->cParams; i++) 6103 { 6104 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; 6105 VARIANTARG *src_arg; 6106 6107 if (wParamFlags & PARAMFLAG_FLCID) 6108 { 6109 VARIANTARG *arg; 6110 arg = prgpvarg[i] = &rgvarg[i]; 6111 V_VT(arg) = VT_I4; 6112 V_I4(arg) = This->pTypeLib->lcid; 6113 continue; 6114 } 6115 6116 if (cNamedArgs) 6117 { 6118 USHORT j; 6119 src_arg = NULL; 6120 for (j = 0; j < cNamedArgs; j++) 6121 if (rgdispidNamedArgs[j] == i) 6122 { 6123 src_arg = &pDispParams->rgvarg[j]; 6124 break; 6125 } 6126 } 6127 else 6128 { 6129 src_arg = vargs_converted < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted] : NULL; 6130 vargs_converted++; 6131 } 6132 6133 if (wParamFlags & PARAMFLAG_FRETVAL) 6134 { 6135 /* under most conditions the caller is not allowed to 6136 * pass in a dispparam arg in the index of what would be 6137 * the retval parameter. however, there is an exception 6138 * where the extra parameter is used in an extra 6139 * IDispatch::Invoke below */ 6140 if ((i < pDispParams->cArgs) && 6141 ((func_desc->cParams != 1) || !pVarResult || 6142 !(func_desc->invkind & INVOKE_PROPERTYGET))) 6143 { 6144 hres = DISP_E_BADPARAMCOUNT; 6145 break; 6146 } 6147 6148 /* note: this check is placed so that if the caller passes 6149 * in a VARIANTARG for the retval we just ignore it, like 6150 * native does */ 6151 if (i == func_desc->cParams - 1) 6152 { 6153 VARIANTARG *arg; 6154 arg = prgpvarg[i] = &rgvarg[i]; 6155 memset(arg, 0, sizeof(*arg)); 6156 V_VT(arg) = rgvt[i]; 6157 memset(&retval, 0, sizeof(retval)); 6158 V_BYREF(arg) = &retval; 6159 } 6160 else 6161 { 6162 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams); 6163 hres = E_UNEXPECTED; 6164 break; 6165 } 6166 } 6167 else if (src_arg) 6168 { 6169 dump_Variant(src_arg); 6170 6171 if (rgvt[i] == VT_VARIANT) 6172 hres = VariantCopy(&rgvarg[i], src_arg); 6173 else if (rgvt[i] == (VT_VARIANT | VT_BYREF)) 6174 { 6175 if (rgvt[i] == V_VT(src_arg)) 6176 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg); 6177 else 6178 { 6179 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 6180 hres = VariantCopy(&missing_arg[i], src_arg); 6181 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i]; 6182 } 6183 V_VT(&rgvarg[i]) = rgvt[i]; 6184 } 6185 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1) 6186 { 6187 SAFEARRAY *a; 6188 SAFEARRAYBOUND bound; 6189 VARIANT *v; 6190 LONG j; 6191 bound.lLbound = 0; 6192 bound.cElements = pDispParams->cArgs-i; 6193 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound))) 6194 { 6195 ERR("SafeArrayCreate failed\n"); 6196 break; 6197 } 6198 hres = SafeArrayAccessData(a, (LPVOID)&v); 6199 if (hres != S_OK) 6200 { 6201 ERR("SafeArrayAccessData failed with %x\n", hres); 6202 break; 6203 } 6204 for (j = 0; j < bound.cElements; j++) 6205 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]); 6206 hres = SafeArrayUnaccessData(a); 6207 if (hres != S_OK) 6208 { 6209 ERR("SafeArrayUnaccessData failed with %x\n", hres); 6210 break; 6211 } 6212 V_ARRAY(&rgvarg[i]) = a; 6213 V_VT(&rgvarg[i]) = rgvt[i]; 6214 } 6215 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg)) 6216 { 6217 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 6218 V_VT(&missing_arg[i]) = V_VT(src_arg); 6219 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF); 6220 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]); 6221 V_VT(&rgvarg[i]) = rgvt[i]; 6222 } 6223 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg))) 6224 { 6225 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg); 6226 V_VT(&rgvarg[i]) = rgvt[i]; 6227 } 6228 else 6229 { 6230 /* FIXME: this doesn't work for VT_BYREF arguments if 6231 * they are not the same type as in the paramdesc */ 6232 V_VT(&rgvarg[i]) = V_VT(src_arg); 6233 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]); 6234 V_VT(&rgvarg[i]) = rgvt[i]; 6235 } 6236 6237 if (FAILED(hres)) 6238 { 6239 ERR("failed to convert param %d to %s%s from %s%s\n", i, 6240 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]), 6241 debugstr_VT(src_arg), debugstr_VF(src_arg)); 6242 break; 6243 } 6244 prgpvarg[i] = &rgvarg[i]; 6245 } 6246 else if (wParamFlags & PARAMFLAG_FOPT) 6247 { 6248 VARIANTARG *arg; 6249 arg = prgpvarg[i] = &rgvarg[i]; 6250 if (wParamFlags & PARAMFLAG_FHASDEFAULT) 6251 { 6252 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue); 6253 if (FAILED(hres)) 6254 break; 6255 } 6256 else 6257 { 6258 VARIANTARG *missing_arg; 6259 /* if the function wants a pointer to a variant then 6260 * set that up, otherwise just pass the VT_ERROR in 6261 * the argument by value */ 6262 if (rgvt[i] & VT_BYREF) 6263 { 6264 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i; 6265 V_VT(arg) = VT_VARIANT | VT_BYREF; 6266 V_VARIANTREF(arg) = missing_arg; 6267 } 6268 else 6269 missing_arg = arg; 6270 V_VT(missing_arg) = VT_ERROR; 6271 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND; 6272 } 6273 } 6274 else 6275 { 6276 hres = DISP_E_BADPARAMCOUNT; 6277 break; 6278 } 6279 } 6280 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ 6281 6282 /* VT_VOID is a special case for return types, so it is not 6283 * handled in the general function */ 6284 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID) 6285 V_VT(&varresult) = VT_EMPTY; 6286 else 6287 { 6288 V_VT(&varresult) = 0; 6289 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult)); 6290 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ 6291 } 6292 6293 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv, 6294 V_VT(&varresult), func_desc->cParams, rgvt, 6295 prgpvarg, &varresult); 6296 6297 vargs_converted = 0; 6298 6299 for (i = 0; i < func_desc->cParams; i++) 6300 { 6301 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; 6302 6303 if (wParamFlags & PARAMFLAG_FLCID) 6304 continue; 6305 else if (wParamFlags & PARAMFLAG_FRETVAL) 6306 { 6307 if (TRACE_ON(ole)) 6308 { 6309 TRACE("[retval] value: "); 6310 dump_Variant(prgpvarg[i]); 6311 } 6312 6313 if (pVarResult) 6314 { 6315 VariantInit(pVarResult); 6316 /* deref return value */ 6317 hres = VariantCopyInd(pVarResult, prgpvarg[i]); 6318 } 6319 6320 /* free data stored in varresult. Note that 6321 * VariantClear doesn't do what we want because we are 6322 * working with byref types. */ 6323 /* FIXME: clear safearrays, bstrs, records and 6324 * variants here too */ 6325 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) || 6326 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF))) 6327 { 6328 if(*V_UNKNOWNREF(prgpvarg[i])) 6329 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i])); 6330 } 6331 break; 6332 } 6333 else if (vargs_converted < pDispParams->cArgs) 6334 { 6335 if (wParamFlags & PARAMFLAG_FOUT) 6336 { 6337 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]; 6338 6339 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF)) 6340 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg)); 6341 6342 if (FAILED(hres)) 6343 { 6344 ERR("failed to convert param %d to vt %d\n", i, 6345 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted])); 6346 break; 6347 } 6348 } 6349 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) && 6350 func_desc->cParamsOpt < 0 && 6351 i == func_desc->cParams-1) 6352 { 6353 SAFEARRAY *a = V_ARRAY(prgpvarg[i]); 6354 LONG j, ubound; 6355 VARIANT *v; 6356 hres = SafeArrayGetUBound(a, 1, &ubound); 6357 if (hres != S_OK) 6358 { 6359 ERR("SafeArrayGetUBound failed with %x\n", hres); 6360 break; 6361 } 6362 hres = SafeArrayAccessData(a, (LPVOID)&v); 6363 if (hres != S_OK) 6364 { 6365 ERR("SafeArrayAccessData failed with %x\n", hres); 6366 break; 6367 } 6368 for (j = 0; j <= ubound; j++) 6369 VariantClear(&v[j]); 6370 hres = SafeArrayUnaccessData(a); 6371 if (hres != S_OK) 6372 { 6373 ERR("SafeArrayUnaccessData failed with %x\n", hres); 6374 break; 6375 } 6376 } 6377 VariantClear(&rgvarg[i]); 6378 vargs_converted++; 6379 } 6380 else if (wParamFlags & PARAMFLAG_FOPT) 6381 { 6382 if (wParamFlags & PARAMFLAG_FHASDEFAULT) 6383 VariantClear(&rgvarg[i]); 6384 } 6385 } 6386 6387 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult))) 6388 { 6389 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult)); 6390 hres = DISP_E_EXCEPTION; 6391 if (pExcepInfo) 6392 { 6393 IErrorInfo *pErrorInfo; 6394 pExcepInfo->scode = V_ERROR(&varresult); 6395 if (GetErrorInfo(0, &pErrorInfo) == S_OK) 6396 { 6397 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription); 6398 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile); 6399 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource); 6400 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext); 6401 6402 IErrorInfo_Release(pErrorInfo); 6403 } 6404 } 6405 } 6406 if (V_VT(&varresult) != VT_ERROR) 6407 { 6408 TRACE("varresult value: "); 6409 dump_Variant(&varresult); 6410 6411 if (pVarResult) 6412 { 6413 VariantClear(pVarResult); 6414 *pVarResult = varresult; 6415 } 6416 else 6417 VariantClear(&varresult); 6418 } 6419 6420 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) && 6421 (func_desc->invkind & INVOKE_PROPERTYGET) && 6422 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) && 6423 (pDispParams->cArgs != 0)) 6424 { 6425 if (V_VT(pVarResult) == VT_DISPATCH) 6426 { 6427 IDispatch *pDispatch = V_DISPATCH(pVarResult); 6428 /* Note: not VariantClear; we still need the dispatch 6429 * pointer to be valid */ 6430 VariantInit(pVarResult); 6431 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, 6432 GetSystemDefaultLCID(), INVOKE_PROPERTYGET, 6433 pDispParams, pVarResult, pExcepInfo, pArgErr); 6434 IDispatch_Release(pDispatch); 6435 } 6436 else 6437 { 6438 VariantClear(pVarResult); 6439 hres = DISP_E_NOTACOLLECTION; 6440 } 6441 } 6442 6443 func_fail: 6444 HeapFree(GetProcessHeap(), 0, buffer); 6445 break; 6446 } 6447 case FUNC_DISPATCH: { 6448 IDispatch *disp; 6449 6450 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp); 6451 if (SUCCEEDED(hres)) { 6452 FIXME("Calling Invoke in IDispatch iface. untested!\n"); 6453 hres = IDispatch_Invoke( 6454 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams, 6455 pVarResult,pExcepInfo,pArgErr 6456 ); 6457 if (FAILED(hres)) 6458 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres); 6459 IDispatch_Release(disp); 6460 } else 6461 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n"); 6462 break; 6463 } 6464 default: 6465 FIXME("Unknown function invocation type %d\n", func_desc->funckind); 6466 hres = E_FAIL; 6467 break; 6468 } 6469 6470 TRACE("-- 0x%08x\n", hres); 6471 return hres; 6472 6473 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) { 6474 VARDESC *var_desc; 6475 6476 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc); 6477 if(FAILED(hres)) return hres; 6478 6479 FIXME("varseek: Found memid, but variable-based invoking not supported\n"); 6480 dump_VARDESC(var_desc); 6481 ITypeInfo2_ReleaseVarDesc(iface, var_desc); 6482 return E_NOTIMPL; 6483 } 6484 6485 /* not found, look for it in inherited interfaces */ 6486 ITypeInfo2_GetTypeKind(iface, &type_kind); 6487 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) { 6488 if(This->impltypelist) { 6489 /* recursive search */ 6490 ITypeInfo *pTInfo; 6491 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo); 6492 if(SUCCEEDED(hres)){ 6493 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); 6494 ITypeInfo_Release(pTInfo); 6495 return hres; 6496 } 6497 WARN("Could not search inherited interface!\n"); 6498 } 6499 } 6500 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags); 6501 return DISP_E_MEMBERNOTFOUND; 6502 } 6503 6504 /* ITypeInfo::GetDocumentation 6505 * 6506 * Retrieves the documentation string, the complete Help file name and path, 6507 * and the context ID for the Help topic for a specified type description. 6508 * 6509 * (Can be tested by the Visual Basic Editor in Word for instance.) 6510 */ 6511 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface, 6512 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString, 6513 DWORD *pdwHelpContext, BSTR *pBstrHelpFile) 6514 { 6515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6516 const TLBFuncDesc *pFDesc; 6517 const TLBVarDesc *pVDesc; 6518 TRACE("(%p) memid %d Name(%p) DocString(%p)" 6519 " HelpContext(%p) HelpFile(%p)\n", 6520 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile); 6521 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */ 6522 if(pBstrName) 6523 *pBstrName=SysAllocString(This->Name); 6524 if(pBstrDocString) 6525 *pBstrDocString=SysAllocString(This->DocString); 6526 if(pdwHelpContext) 6527 *pdwHelpContext=This->dwHelpContext; 6528 if(pBstrHelpFile) 6529 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */ 6530 return S_OK; 6531 }else {/* for a member */ 6532 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) 6533 if(pFDesc->funcdesc.memid==memid){ 6534 if(pBstrName) 6535 *pBstrName = SysAllocString(pFDesc->Name); 6536 if(pBstrDocString) 6537 *pBstrDocString=SysAllocString(pFDesc->HelpString); 6538 if(pdwHelpContext) 6539 *pdwHelpContext=pFDesc->helpcontext; 6540 return S_OK; 6541 } 6542 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) 6543 if(pVDesc->vardesc.memid==memid){ 6544 if(pBstrName) 6545 *pBstrName = SysAllocString(pVDesc->Name); 6546 if(pBstrDocString) 6547 *pBstrDocString=SysAllocString(pVDesc->HelpString); 6548 if(pdwHelpContext) 6549 *pdwHelpContext=pVDesc->HelpContext; 6550 return S_OK; 6551 } 6552 } 6553 6554 if(This->impltypelist && 6555 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) { 6556 /* recursive search */ 6557 ITypeInfo *pTInfo; 6558 HRESULT result; 6559 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, 6560 &pTInfo); 6561 if(SUCCEEDED(result)) { 6562 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName, 6563 pBstrDocString, pdwHelpContext, pBstrHelpFile); 6564 ITypeInfo_Release(pTInfo); 6565 return result; 6566 } 6567 WARN("Could not search inherited interface!\n"); 6568 } 6569 6570 WARN("member %d not found\n", memid); 6571 return TYPE_E_ELEMENTNOTFOUND; 6572 } 6573 6574 /* ITypeInfo::GetDllEntry 6575 * 6576 * Retrieves a description or specification of an entry point for a function 6577 * in a DLL. 6578 */ 6579 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid, 6580 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName, 6581 WORD *pwOrdinal) 6582 { 6583 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6584 const TLBFuncDesc *pFDesc; 6585 6586 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal); 6587 6588 if (pBstrDllName) *pBstrDllName = NULL; 6589 if (pBstrName) *pBstrName = NULL; 6590 if (pwOrdinal) *pwOrdinal = 0; 6591 6592 if (This->TypeAttr.typekind != TKIND_MODULE) 6593 return TYPE_E_BADMODULEKIND; 6594 6595 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) 6596 if(pFDesc->funcdesc.memid==memid){ 6597 dump_TypeInfo(This); 6598 if (TRACE_ON(ole)) 6599 dump_TLBFuncDescOne(pFDesc); 6600 6601 if (pBstrDllName) 6602 *pBstrDllName = SysAllocString(This->DllName); 6603 6604 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) { 6605 if (pBstrName) 6606 *pBstrName = SysAllocString(pFDesc->Entry); 6607 if (pwOrdinal) 6608 *pwOrdinal = -1; 6609 return S_OK; 6610 } 6611 if (pBstrName) 6612 *pBstrName = NULL; 6613 if (pwOrdinal) 6614 *pwOrdinal = (DWORD)pFDesc->Entry; 6615 return S_OK; 6616 } 6617 return TYPE_E_ELEMENTNOTFOUND; 6618 } 6619 6620 /* internal function to make the inherited interfaces' methods appear 6621 * part of the interface */ 6622 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface, 6623 HREFTYPE *hRefType, ITypeInfo **ppTInfo) 6624 { 6625 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6626 HRESULT hr; 6627 6628 TRACE("%p, 0x%x\n", iface, *hRefType); 6629 6630 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK)) 6631 { 6632 ITypeInfo *pSubTypeInfo; 6633 6634 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo); 6635 if (FAILED(hr)) 6636 return hr; 6637 6638 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo, 6639 hRefType, ppTInfo); 6640 ITypeInfo_Release(pSubTypeInfo); 6641 if (SUCCEEDED(hr)) 6642 return hr; 6643 } 6644 *hRefType -= DISPATCH_HREF_OFFSET; 6645 6646 if (!(*hRefType & DISPATCH_HREF_MASK)) 6647 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo); 6648 else 6649 return E_FAIL; 6650 } 6651 6652 /* ITypeInfo::GetRefTypeInfo 6653 * 6654 * If a type description references other type descriptions, it retrieves 6655 * the referenced type descriptions. 6656 */ 6657 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( 6658 ITypeInfo2 *iface, 6659 HREFTYPE hRefType, 6660 ITypeInfo **ppTInfo) 6661 { 6662 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6663 HRESULT result = E_FAIL; 6664 6665 if ((This->hreftype != -1) && (This->hreftype == hRefType)) 6666 { 6667 *ppTInfo = (ITypeInfo *)&This->lpVtbl; 6668 ITypeInfo_AddRef(*ppTInfo); 6669 result = S_OK; 6670 } 6671 else if (hRefType == -1 && 6672 (This->TypeAttr.typekind == TKIND_DISPATCH) && 6673 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) 6674 { 6675 /* when we meet a DUAL dispinterface, we must create the interface 6676 * version of it. 6677 */ 6678 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor(); 6679 6680 6681 /* the interface version contains the same information as the dispinterface 6682 * copy the contents of the structs. 6683 */ 6684 *pTypeInfoImpl = *This; 6685 pTypeInfoImpl->ref = 0; 6686 6687 /* change the type to interface */ 6688 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE; 6689 6690 *ppTInfo = (ITypeInfo*) pTypeInfoImpl; 6691 6692 /* we use data structures from This, so we need to keep a reference 6693 * to it to stop it being destroyed and signal to the new instance to 6694 * not free its data structures when it is destroyed */ 6695 pTypeInfoImpl->no_free_data = TRUE; 6696 pTypeInfoImpl->next = This; 6697 ITypeInfo_AddRef((ITypeInfo*) This); 6698 6699 ITypeInfo_AddRef(*ppTInfo); 6700 6701 result = S_OK; 6702 6703 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) && 6704 (This->TypeAttr.typekind == TKIND_DISPATCH) && 6705 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) 6706 { 6707 HREFTYPE href_dispatch = hRefType; 6708 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo); 6709 } else { 6710 TLBRefType *ref_type; 6711 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry) 6712 { 6713 if(ref_type->reference == hRefType) 6714 break; 6715 } 6716 if(&ref_type->entry == &This->pTypeLib->ref_list) 6717 { 6718 FIXME("Can't find pRefType for ref %x\n", hRefType); 6719 goto end; 6720 } 6721 if(hRefType != -1) { 6722 ITypeLib *pTLib = NULL; 6723 6724 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) { 6725 UINT Index; 6726 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index); 6727 } else { 6728 if(ref_type->pImpTLInfo->pImpTypeLib) { 6729 TRACE("typeinfo in imported typelib that is already loaded\n"); 6730 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib; 6731 ITypeLib2_AddRef(pTLib); 6732 result = S_OK; 6733 } else { 6734 TRACE("typeinfo in imported typelib that isn't already loaded\n"); 6735 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid, 6736 ref_type->pImpTLInfo->wVersionMajor, 6737 ref_type->pImpTLInfo->wVersionMinor, 6738 ref_type->pImpTLInfo->lcid, 6739 &pTLib); 6740 6741 if(FAILED(result)) { 6742 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name); 6743 result=LoadTypeLib(libnam, &pTLib); 6744 SysFreeString(libnam); 6745 } 6746 if(SUCCEEDED(result)) { 6747 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib; 6748 ITypeLib2_AddRef(pTLib); 6749 } 6750 } 6751 } 6752 if(SUCCEEDED(result)) { 6753 if(ref_type->index == TLB_REF_USE_GUID) 6754 result = ITypeLib2_GetTypeInfoOfGuid(pTLib, 6755 &ref_type->guid, 6756 ppTInfo); 6757 else 6758 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index, 6759 ppTInfo); 6760 } 6761 if (pTLib != NULL) 6762 ITypeLib2_Release(pTLib); 6763 } 6764 } 6765 6766 end: 6767 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType, 6768 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo); 6769 return result; 6770 } 6771 6772 /* ITypeInfo::AddressOfMember 6773 * 6774 * Retrieves the addresses of static functions or variables, such as those 6775 * defined in a DLL. 6776 */ 6777 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface, 6778 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) 6779 { 6780 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6781 HRESULT hr; 6782 BSTR dll, entry; 6783 WORD ordinal; 6784 HMODULE module; 6785 6786 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv); 6787 6788 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal); 6789 if (FAILED(hr)) 6790 return hr; 6791 6792 module = LoadLibraryW(dll); 6793 if (!module) 6794 { 6795 ERR("couldn't load %s\n", debugstr_w(dll)); 6796 SysFreeString(dll); 6797 SysFreeString(entry); 6798 return STG_E_FILENOTFOUND; 6799 } 6800 /* FIXME: store library somewhere where we can free it */ 6801 6802 if (entry) 6803 { 6804 LPSTR entryA; 6805 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL); 6806 entryA = HeapAlloc(GetProcessHeap(), 0, len); 6807 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL); 6808 6809 *ppv = GetProcAddress(module, entryA); 6810 if (!*ppv) 6811 ERR("function not found %s\n", debugstr_a(entryA)); 6812 6813 HeapFree(GetProcessHeap(), 0, entryA); 6814 } 6815 else 6816 { 6817 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal)); 6818 if (!*ppv) 6819 ERR("function not found %d\n", ordinal); 6820 } 6821 6822 SysFreeString(dll); 6823 SysFreeString(entry); 6824 6825 if (!*ppv) 6826 return TYPE_E_DLLFUNCTIONNOTFOUND; 6827 6828 return S_OK; 6829 } 6830 6831 /* ITypeInfo::CreateInstance 6832 * 6833 * Creates a new instance of a type that describes a component object class 6834 * (coclass). 6835 */ 6836 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface, 6837 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj) 6838 { 6839 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6840 HRESULT hr; 6841 TYPEATTR *pTA; 6842 6843 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj); 6844 6845 *ppvObj = NULL; 6846 6847 if(pOuterUnk) 6848 { 6849 WARN("Not able to aggregate\n"); 6850 return CLASS_E_NOAGGREGATION; 6851 } 6852 6853 hr = ITypeInfo_GetTypeAttr(iface, &pTA); 6854 if(FAILED(hr)) return hr; 6855 6856 if(pTA->typekind != TKIND_COCLASS) 6857 { 6858 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind); 6859 hr = E_INVALIDARG; 6860 goto end; 6861 } 6862 6863 hr = S_FALSE; 6864 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT) 6865 { 6866 IUnknown *pUnk; 6867 hr = GetActiveObject(&pTA->guid, NULL, &pUnk); 6868 TRACE("GetActiveObject rets %08x\n", hr); 6869 if(hr == S_OK) 6870 { 6871 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj); 6872 IUnknown_Release(pUnk); 6873 } 6874 } 6875 6876 if(hr != S_OK) 6877 hr = CoCreateInstance(&pTA->guid, NULL, 6878 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 6879 riid, ppvObj); 6880 6881 end: 6882 ITypeInfo_ReleaseTypeAttr(iface, pTA); 6883 return hr; 6884 } 6885 6886 /* ITypeInfo::GetMops 6887 * 6888 * Retrieves marshalling information. 6889 */ 6890 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, 6891 BSTR *pBstrMops) 6892 { 6893 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6894 FIXME("(%p) stub!\n", This); 6895 return S_OK; 6896 } 6897 6898 /* ITypeInfo::GetContainingTypeLib 6899 * 6900 * Retrieves the containing type library and the index of the type description 6901 * within that type library. 6902 */ 6903 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface, 6904 ITypeLib * *ppTLib, UINT *pIndex) 6905 { 6906 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6907 6908 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */ 6909 if (pIndex) { 6910 *pIndex=This->index; 6911 TRACE("returning pIndex=%d\n", *pIndex); 6912 } 6913 6914 if (ppTLib) { 6915 *ppTLib=(LPTYPELIB )(This->pTypeLib); 6916 ITypeLib2_AddRef(*ppTLib); 6917 TRACE("returning ppTLib=%p\n", *ppTLib); 6918 } 6919 6920 return S_OK; 6921 } 6922 6923 /* ITypeInfo::ReleaseTypeAttr 6924 * 6925 * Releases a TYPEATTR previously returned by GetTypeAttr. 6926 * 6927 */ 6928 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface, 6929 TYPEATTR* pTypeAttr) 6930 { 6931 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6932 TRACE("(%p)->(%p)\n", This, pTypeAttr); 6933 HeapFree(GetProcessHeap(), 0, pTypeAttr); 6934 } 6935 6936 /* ITypeInfo::ReleaseFuncDesc 6937 * 6938 * Releases a FUNCDESC previously returned by GetFuncDesc. * 6939 */ 6940 static void WINAPI ITypeInfo_fnReleaseFuncDesc( 6941 ITypeInfo2 *iface, 6942 FUNCDESC *pFuncDesc) 6943 { 6944 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6945 SHORT i; 6946 6947 TRACE("(%p)->(%p)\n", This, pFuncDesc); 6948 6949 for (i = 0; i < pFuncDesc->cParams; i++) 6950 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]); 6951 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc); 6952 6953 SysFreeString((BSTR)pFuncDesc); 6954 } 6955 6956 /* ITypeInfo::ReleaseVarDesc 6957 * 6958 * Releases a VARDESC previously returned by GetVarDesc. 6959 */ 6960 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface, 6961 VARDESC *pVarDesc) 6962 { 6963 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6964 TRACE("(%p)->(%p)\n", This, pVarDesc); 6965 6966 TLB_FreeElemDesc(&pVarDesc->elemdescVar); 6967 if (pVarDesc->varkind == VAR_CONST) 6968 VariantClear(pVarDesc->u.lpvarValue); 6969 SysFreeString((BSTR)pVarDesc); 6970 } 6971 6972 /* ITypeInfo2::GetTypeKind 6973 * 6974 * Returns the TYPEKIND enumeration quickly, without doing any allocations. 6975 * 6976 */ 6977 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface, 6978 TYPEKIND *pTypeKind) 6979 { 6980 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6981 *pTypeKind=This->TypeAttr.typekind; 6982 TRACE("(%p) type 0x%0x\n", This,*pTypeKind); 6983 return S_OK; 6984 } 6985 6986 /* ITypeInfo2::GetTypeFlags 6987 * 6988 * Returns the type flags without any allocations. This returns a DWORD type 6989 * flag, which expands the type flags without growing the TYPEATTR (type 6990 * attribute). 6991 * 6992 */ 6993 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags) 6994 { 6995 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 6996 *pTypeFlags=This->TypeAttr.wTypeFlags; 6997 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags); 6998 return S_OK; 6999 } 7000 7001 /* ITypeInfo2::GetFuncIndexOfMemId 7002 * Binds to a specific member based on a known DISPID, where the member name 7003 * is not known (for example, when binding to a default member). 7004 * 7005 */ 7006 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface, 7007 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex) 7008 { 7009 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7010 const TLBFuncDesc *pFuncInfo; 7011 int i; 7012 HRESULT result; 7013 7014 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next) 7015 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind)) 7016 break; 7017 if(pFuncInfo) { 7018 *pFuncIndex = i; 7019 result = S_OK; 7020 } else 7021 result = TYPE_E_ELEMENTNOTFOUND; 7022 7023 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This, 7024 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED"); 7025 return result; 7026 } 7027 7028 /* TypeInfo2::GetVarIndexOfMemId 7029 * 7030 * Binds to a specific member based on a known DISPID, where the member name 7031 * is not known (for example, when binding to a default member). 7032 * 7033 */ 7034 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface, 7035 MEMBERID memid, UINT *pVarIndex) 7036 { 7037 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7038 TLBVarDesc *pVarInfo; 7039 int i; 7040 HRESULT result; 7041 for(i=0, pVarInfo=This->varlist; pVarInfo && 7042 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next) 7043 ; 7044 if(pVarInfo) { 7045 *pVarIndex = i; 7046 result = S_OK; 7047 } else 7048 result = TYPE_E_ELEMENTNOTFOUND; 7049 7050 TRACE("(%p) memid 0x%08x -> %s\n", This, 7051 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED"); 7052 return result; 7053 } 7054 7055 /* ITypeInfo2::GetCustData 7056 * 7057 * Gets the custom data 7058 */ 7059 static HRESULT WINAPI ITypeInfo2_fnGetCustData( 7060 ITypeInfo2 * iface, 7061 REFGUID guid, 7062 VARIANT *pVarVal) 7063 { 7064 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7065 TLBCustData *pCData; 7066 7067 for(pCData=This->pCustData; pCData; pCData = pCData->next) 7068 if( IsEqualIID(guid, &pCData->guid)) break; 7069 7070 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 7071 7072 VariantInit( pVarVal); 7073 if (pCData) 7074 VariantCopy( pVarVal, &pCData->data); 7075 else 7076 VariantClear( pVarVal ); 7077 return S_OK; 7078 } 7079 7080 /* ITypeInfo2::GetFuncCustData 7081 * 7082 * Gets the custom data 7083 */ 7084 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( 7085 ITypeInfo2 * iface, 7086 UINT index, 7087 REFGUID guid, 7088 VARIANT *pVarVal) 7089 { 7090 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7091 TLBCustData *pCData=NULL; 7092 TLBFuncDesc * pFDesc; 7093 UINT i; 7094 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, 7095 pFDesc=pFDesc->next); 7096 7097 if(pFDesc) 7098 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next) 7099 if( IsEqualIID(guid, &pCData->guid)) break; 7100 7101 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 7102 7103 if(pCData){ 7104 VariantInit( pVarVal); 7105 VariantCopy( pVarVal, &pCData->data); 7106 return S_OK; 7107 } 7108 return E_INVALIDARG; /* FIXME: correct? */ 7109 } 7110 7111 /* ITypeInfo2::GetParamCustData 7112 * 7113 * Gets the custom data 7114 */ 7115 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( 7116 ITypeInfo2 * iface, 7117 UINT indexFunc, 7118 UINT indexParam, 7119 REFGUID guid, 7120 VARIANT *pVarVal) 7121 { 7122 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7123 TLBCustData *pCData=NULL; 7124 TLBFuncDesc * pFDesc; 7125 UINT i; 7126 7127 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next); 7128 7129 if(pFDesc && indexParam<pFDesc->funcdesc.cParams) 7130 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData; 7131 pCData = pCData->next) 7132 if( IsEqualIID(guid, &pCData->guid)) break; 7133 7134 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 7135 7136 if(pCData) 7137 { 7138 VariantInit( pVarVal); 7139 VariantCopy( pVarVal, &pCData->data); 7140 return S_OK; 7141 } 7142 return E_INVALIDARG; /* FIXME: correct? */ 7143 } 7144 7145 /* ITypeInfo2::GetVarCustData 7146 * 7147 * Gets the custom data 7148 */ 7149 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( 7150 ITypeInfo2 * iface, 7151 UINT index, 7152 REFGUID guid, 7153 VARIANT *pVarVal) 7154 { 7155 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7156 TLBCustData *pCData=NULL; 7157 TLBVarDesc * pVDesc; 7158 UINT i; 7159 7160 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next); 7161 7162 if(pVDesc) 7163 { 7164 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next) 7165 { 7166 if( IsEqualIID(guid, &pCData->guid)) break; 7167 } 7168 } 7169 7170 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 7171 7172 if(pCData) 7173 { 7174 VariantInit( pVarVal); 7175 VariantCopy( pVarVal, &pCData->data); 7176 return S_OK; 7177 } 7178 return E_INVALIDARG; /* FIXME: correct? */ 7179 } 7180 7181 /* ITypeInfo2::GetImplCustData 7182 * 7183 * Gets the custom data 7184 */ 7185 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( 7186 ITypeInfo2 * iface, 7187 UINT index, 7188 REFGUID guid, 7189 VARIANT *pVarVal) 7190 { 7191 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7192 TLBCustData *pCData=NULL; 7193 TLBImplType * pRDesc; 7194 UINT i; 7195 7196 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next); 7197 7198 if(pRDesc) 7199 { 7200 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next) 7201 { 7202 if( IsEqualIID(guid, &pCData->guid)) break; 7203 } 7204 } 7205 7206 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 7207 7208 if(pCData) 7209 { 7210 VariantInit( pVarVal); 7211 VariantCopy( pVarVal, &pCData->data); 7212 return S_OK; 7213 } 7214 return E_INVALIDARG; /* FIXME: correct? */ 7215 } 7216 7217 /* ITypeInfo2::GetDocumentation2 7218 * 7219 * Retrieves the documentation string, the complete Help file name and path, 7220 * the localization context to use, and the context ID for the library Help 7221 * topic in the Help file. 7222 * 7223 */ 7224 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( 7225 ITypeInfo2 * iface, 7226 MEMBERID memid, 7227 LCID lcid, 7228 BSTR *pbstrHelpString, 7229 DWORD *pdwHelpStringContext, 7230 BSTR *pbstrHelpStringDll) 7231 { 7232 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7233 const TLBFuncDesc *pFDesc; 7234 const TLBVarDesc *pVDesc; 7235 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) " 7236 "HelpStringContext(%p) HelpStringDll(%p)\n", 7237 This, memid, lcid, pbstrHelpString, pdwHelpStringContext, 7238 pbstrHelpStringDll ); 7239 /* the help string should be obtained from the helpstringdll, 7240 * using the _DLLGetDocumentation function, based on the supplied 7241 * lcid. Nice to do sometime... 7242 */ 7243 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */ 7244 if(pbstrHelpString) 7245 *pbstrHelpString=SysAllocString(This->Name); 7246 if(pdwHelpStringContext) 7247 *pdwHelpStringContext=This->dwHelpStringContext; 7248 if(pbstrHelpStringDll) 7249 *pbstrHelpStringDll= 7250 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */ 7251 return S_OK; 7252 }else {/* for a member */ 7253 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) 7254 if(pFDesc->funcdesc.memid==memid){ 7255 if(pbstrHelpString) 7256 *pbstrHelpString=SysAllocString(pFDesc->HelpString); 7257 if(pdwHelpStringContext) 7258 *pdwHelpStringContext=pFDesc->HelpStringContext; 7259 if(pbstrHelpStringDll) 7260 *pbstrHelpStringDll= 7261 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */ 7262 return S_OK; 7263 } 7264 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) 7265 if(pVDesc->vardesc.memid==memid){ 7266 if(pbstrHelpString) 7267 *pbstrHelpString=SysAllocString(pVDesc->HelpString); 7268 if(pdwHelpStringContext) 7269 *pdwHelpStringContext=pVDesc->HelpStringContext; 7270 if(pbstrHelpStringDll) 7271 *pbstrHelpStringDll= 7272 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */ 7273 return S_OK; 7274 } 7275 } 7276 return TYPE_E_ELEMENTNOTFOUND; 7277 } 7278 7279 /* ITypeInfo2::GetAllCustData 7280 * 7281 * Gets all custom data items for the Type info. 7282 * 7283 */ 7284 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( 7285 ITypeInfo2 * iface, 7286 CUSTDATA *pCustData) 7287 { 7288 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7289 TLBCustData *pCData; 7290 int i; 7291 7292 TRACE("(%p) returning %d items\n", This, This->ctCustData); 7293 7294 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM)); 7295 if(pCustData->prgCustData ){ 7296 pCustData->cCustData=This->ctCustData; 7297 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){ 7298 pCustData->prgCustData[i].guid=pCData->guid; 7299 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data); 7300 } 7301 }else{ 7302 ERR(" OUT OF MEMORY!\n"); 7303 return E_OUTOFMEMORY; 7304 } 7305 return S_OK; 7306 } 7307 7308 /* ITypeInfo2::GetAllFuncCustData 7309 * 7310 * Gets all custom data items for the specified Function 7311 * 7312 */ 7313 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( 7314 ITypeInfo2 * iface, 7315 UINT index, 7316 CUSTDATA *pCustData) 7317 { 7318 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7319 TLBCustData *pCData; 7320 TLBFuncDesc * pFDesc; 7321 UINT i; 7322 TRACE("(%p) index %d\n", This, index); 7323 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, 7324 pFDesc=pFDesc->next) 7325 ; 7326 if(pFDesc){ 7327 pCustData->prgCustData = 7328 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM)); 7329 if(pCustData->prgCustData ){ 7330 pCustData->cCustData=pFDesc->ctCustData; 7331 for(i=0, pCData=pFDesc->pCustData; pCData; i++, 7332 pCData = pCData->next){ 7333 pCustData->prgCustData[i].guid=pCData->guid; 7334 VariantCopy(& pCustData->prgCustData[i].varValue, 7335 & pCData->data); 7336 } 7337 }else{ 7338 ERR(" OUT OF MEMORY!\n"); 7339 return E_OUTOFMEMORY; 7340 } 7341 return S_OK; 7342 } 7343 return TYPE_E_ELEMENTNOTFOUND; 7344 } 7345 7346 /* ITypeInfo2::GetAllParamCustData 7347 * 7348 * Gets all custom data items for the Functions 7349 * 7350 */ 7351 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface, 7352 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData) 7353 { 7354 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7355 TLBCustData *pCData=NULL; 7356 TLBFuncDesc * pFDesc; 7357 UINT i; 7358 TRACE("(%p) index %d\n", This, indexFunc); 7359 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++, 7360 pFDesc=pFDesc->next) 7361 ; 7362 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){ 7363 pCustData->prgCustData = 7364 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData * 7365 sizeof(CUSTDATAITEM)); 7366 if(pCustData->prgCustData ){ 7367 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData; 7368 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData; 7369 pCData; i++, pCData = pCData->next){ 7370 pCustData->prgCustData[i].guid=pCData->guid; 7371 VariantCopy(& pCustData->prgCustData[i].varValue, 7372 & pCData->data); 7373 } 7374 }else{ 7375 ERR(" OUT OF MEMORY!\n"); 7376 return E_OUTOFMEMORY; 7377 } 7378 return S_OK; 7379 } 7380 return TYPE_E_ELEMENTNOTFOUND; 7381 } 7382 7383 /* ITypeInfo2::GetAllVarCustData 7384 * 7385 * Gets all custom data items for the specified Variable 7386 * 7387 */ 7388 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface, 7389 UINT index, CUSTDATA *pCustData) 7390 { 7391 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7392 TLBCustData *pCData; 7393 TLBVarDesc * pVDesc; 7394 UINT i; 7395 TRACE("(%p) index %d\n", This, index); 7396 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, 7397 pVDesc=pVDesc->next) 7398 ; 7399 if(pVDesc){ 7400 pCustData->prgCustData = 7401 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM)); 7402 if(pCustData->prgCustData ){ 7403 pCustData->cCustData=pVDesc->ctCustData; 7404 for(i=0, pCData=pVDesc->pCustData; pCData; i++, 7405 pCData = pCData->next){ 7406 pCustData->prgCustData[i].guid=pCData->guid; 7407 VariantCopy(& pCustData->prgCustData[i].varValue, 7408 & pCData->data); 7409 } 7410 }else{ 7411 ERR(" OUT OF MEMORY!\n"); 7412 return E_OUTOFMEMORY; 7413 } 7414 return S_OK; 7415 } 7416 return TYPE_E_ELEMENTNOTFOUND; 7417 } 7418 7419 /* ITypeInfo2::GetAllImplCustData 7420 * 7421 * Gets all custom data items for the specified implementation type 7422 * 7423 */ 7424 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( 7425 ITypeInfo2 * iface, 7426 UINT index, 7427 CUSTDATA *pCustData) 7428 { 7429 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 7430 TLBCustData *pCData; 7431 TLBImplType * pRDesc; 7432 UINT i; 7433 TRACE("(%p) index %d\n", This, index); 7434 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, 7435 pRDesc=pRDesc->next) 7436 ; 7437 if(pRDesc){ 7438 pCustData->prgCustData = 7439 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM)); 7440 if(pCustData->prgCustData ){ 7441 pCustData->cCustData=pRDesc->ctCustData; 7442 for(i=0, pCData=pRDesc->pCustData; pCData; i++, 7443 pCData = pCData->next){ 7444 pCustData->prgCustData[i].guid=pCData->guid; 7445 VariantCopy(& pCustData->prgCustData[i].varValue, 7446 & pCData->data); 7447 } 7448 }else{ 7449 ERR(" OUT OF MEMORY!\n"); 7450 return E_OUTOFMEMORY; 7451 } 7452 return S_OK; 7453 } 7454 return TYPE_E_ELEMENTNOTFOUND; 7455 } 7456 7457 static const ITypeInfo2Vtbl tinfvt = 7458 { 7459 7460 ITypeInfo_fnQueryInterface, 7461 ITypeInfo_fnAddRef, 7462 ITypeInfo_fnRelease, 7463 7464 ITypeInfo_fnGetTypeAttr, 7465 ITypeInfo_fnGetTypeComp, 7466 ITypeInfo_fnGetFuncDesc, 7467 ITypeInfo_fnGetVarDesc, 7468 ITypeInfo_fnGetNames, 7469 ITypeInfo_fnGetRefTypeOfImplType, 7470 ITypeInfo_fnGetImplTypeFlags, 7471 ITypeInfo_fnGetIDsOfNames, 7472 ITypeInfo_fnInvoke, 7473 ITypeInfo_fnGetDocumentation, 7474 ITypeInfo_fnGetDllEntry, 7475 ITypeInfo_fnGetRefTypeInfo, 7476 ITypeInfo_fnAddressOfMember, 7477 ITypeInfo_fnCreateInstance, 7478 ITypeInfo_fnGetMops, 7479 ITypeInfo_fnGetContainingTypeLib, 7480 ITypeInfo_fnReleaseTypeAttr, 7481 ITypeInfo_fnReleaseFuncDesc, 7482 ITypeInfo_fnReleaseVarDesc, 7483 7484 ITypeInfo2_fnGetTypeKind, 7485 ITypeInfo2_fnGetTypeFlags, 7486 ITypeInfo2_fnGetFuncIndexOfMemId, 7487 ITypeInfo2_fnGetVarIndexOfMemId, 7488 ITypeInfo2_fnGetCustData, 7489 ITypeInfo2_fnGetFuncCustData, 7490 ITypeInfo2_fnGetParamCustData, 7491 ITypeInfo2_fnGetVarCustData, 7492 ITypeInfo2_fnGetImplTypeCustData, 7493 ITypeInfo2_fnGetDocumentation2, 7494 ITypeInfo2_fnGetAllCustData, 7495 ITypeInfo2_fnGetAllFuncCustData, 7496 ITypeInfo2_fnGetAllParamCustData, 7497 ITypeInfo2_fnGetAllVarCustData, 7498 ITypeInfo2_fnGetAllImplTypeCustData, 7499 }; 7500 7501 /****************************************************************************** 7502 * CreateDispTypeInfo [OLEAUT32.31] 7503 * 7504 * Build type information for an object so it can be called through an 7505 * IDispatch interface. 7506 * 7507 * RETURNS 7508 * Success: S_OK. pptinfo contains the created ITypeInfo object. 7509 * Failure: E_INVALIDARG, if one or more arguments is invalid. 7510 * 7511 * NOTES 7512 * This call allows an objects methods to be accessed through IDispatch, by 7513 * building an ITypeInfo object that IDispatch can use to call through. 7514 */ 7515 HRESULT WINAPI CreateDispTypeInfo( 7516 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */ 7517 LCID lcid, /* [I] Locale Id */ 7518 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */ 7519 { 7520 ITypeInfoImpl *pTIClass, *pTIIface; 7521 ITypeLibImpl *pTypeLibImpl; 7522 unsigned int param, func; 7523 TLBFuncDesc **ppFuncDesc; 7524 TLBRefType *ref; 7525 7526 TRACE("\n"); 7527 pTypeLibImpl = TypeLibImpl_Constructor(); 7528 if (!pTypeLibImpl) return E_FAIL; 7529 7530 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor(); 7531 pTIIface->pTypeLib = pTypeLibImpl; 7532 pTIIface->index = 0; 7533 pTIIface->Name = NULL; 7534 pTIIface->dwHelpContext = -1; 7535 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID)); 7536 pTIIface->TypeAttr.lcid = lcid; 7537 pTIIface->TypeAttr.typekind = TKIND_INTERFACE; 7538 pTIIface->TypeAttr.wMajorVerNum = 0; 7539 pTIIface->TypeAttr.wMinorVerNum = 0; 7540 pTIIface->TypeAttr.cbAlignment = 2; 7541 pTIIface->TypeAttr.cbSizeInstance = -1; 7542 pTIIface->TypeAttr.cbSizeVft = -1; 7543 pTIIface->TypeAttr.cFuncs = 0; 7544 pTIIface->TypeAttr.cImplTypes = 0; 7545 pTIIface->TypeAttr.cVars = 0; 7546 pTIIface->TypeAttr.wTypeFlags = 0; 7547 7548 ppFuncDesc = &pTIIface->funclist; 7549 for(func = 0; func < pidata->cMembers; func++) { 7550 METHODDATA *md = pidata->pmethdata + func; 7551 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc)); 7552 (*ppFuncDesc)->Name = SysAllocString(md->szName); 7553 (*ppFuncDesc)->funcdesc.memid = md->dispid; 7554 (*ppFuncDesc)->funcdesc.lprgscode = NULL; 7555 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL; 7556 (*ppFuncDesc)->funcdesc.invkind = md->wFlags; 7557 (*ppFuncDesc)->funcdesc.callconv = md->cc; 7558 (*ppFuncDesc)->funcdesc.cParams = md->cArgs; 7559 (*ppFuncDesc)->funcdesc.cParamsOpt = 0; 7560 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *); 7561 (*ppFuncDesc)->funcdesc.cScodes = 0; 7562 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; 7563 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn; 7564 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE; 7565 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL; 7566 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 7567 md->cArgs * sizeof(ELEMDESC)); 7568 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 7569 md->cArgs * sizeof(TLBParDesc)); 7570 for(param = 0; param < md->cArgs; param++) { 7571 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt; 7572 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName); 7573 } 7574 (*ppFuncDesc)->helpcontext = 0; 7575 (*ppFuncDesc)->HelpStringContext = 0; 7576 (*ppFuncDesc)->HelpString = NULL; 7577 (*ppFuncDesc)->Entry = NULL; 7578 (*ppFuncDesc)->ctCustData = 0; 7579 (*ppFuncDesc)->pCustData = NULL; 7580 (*ppFuncDesc)->next = NULL; 7581 pTIIface->TypeAttr.cFuncs++; 7582 ppFuncDesc = &(*ppFuncDesc)->next; 7583 } 7584 7585 dump_TypeInfo(pTIIface); 7586 7587 pTypeLibImpl->pTypeInfo = pTIIface; 7588 pTypeLibImpl->TypeInfoCount++; 7589 7590 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor(); 7591 pTIClass->pTypeLib = pTypeLibImpl; 7592 pTIClass->index = 1; 7593 pTIClass->Name = NULL; 7594 pTIClass->dwHelpContext = -1; 7595 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID)); 7596 pTIClass->TypeAttr.lcid = lcid; 7597 pTIClass->TypeAttr.typekind = TKIND_COCLASS; 7598 pTIClass->TypeAttr.wMajorVerNum = 0; 7599 pTIClass->TypeAttr.wMinorVerNum = 0; 7600 pTIClass->TypeAttr.cbAlignment = 2; 7601 pTIClass->TypeAttr.cbSizeInstance = -1; 7602 pTIClass->TypeAttr.cbSizeVft = -1; 7603 pTIClass->TypeAttr.cFuncs = 0; 7604 pTIClass->TypeAttr.cImplTypes = 1; 7605 pTIClass->TypeAttr.cVars = 0; 7606 pTIClass->TypeAttr.wTypeFlags = 0; 7607 7608 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist)); 7609 pTIClass->impltypelist->hRef = 0; 7610 7611 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref)); 7612 ref->index = 0; 7613 ref->reference = 0; 7614 ref->pImpTLInfo = TLB_REF_INTERNAL; 7615 list_add_head(&pTypeLibImpl->ref_list, &ref->entry); 7616 7617 dump_TypeInfo(pTIClass); 7618 7619 pTIIface->next = pTIClass; 7620 pTypeLibImpl->TypeInfoCount++; 7621 7622 *pptinfo = (ITypeInfo*)pTIClass; 7623 7624 ITypeInfo_AddRef(*pptinfo); 7625 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl); 7626 7627 return S_OK; 7628 7629 } 7630 7631 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv) 7632 { 7633 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 7634 7635 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv); 7636 } 7637 7638 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface) 7639 { 7640 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 7641 7642 return ITypeInfo_AddRef((ITypeInfo *)This); 7643 } 7644 7645 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface) 7646 { 7647 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 7648 7649 return ITypeInfo_Release((ITypeInfo *)This); 7650 } 7651 7652 static HRESULT WINAPI ITypeComp_fnBind( 7653 ITypeComp * iface, 7654 OLECHAR * szName, 7655 ULONG lHash, 7656 WORD wFlags, 7657 ITypeInfo ** ppTInfo, 7658 DESCKIND * pDescKind, 7659 BINDPTR * pBindPtr) 7660 { 7661 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 7662 const TLBFuncDesc *pFDesc; 7663 const TLBVarDesc *pVDesc; 7664 HRESULT hr = DISP_E_MEMBERNOTFOUND; 7665 7666 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 7667 7668 *pDescKind = DESCKIND_NONE; 7669 pBindPtr->lpfuncdesc = NULL; 7670 *ppTInfo = NULL; 7671 7672 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next) 7673 if (!strcmpiW(pFDesc->Name, szName)) { 7674 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags)) 7675 break; 7676 else 7677 /* name found, but wrong flags */ 7678 hr = TYPE_E_TYPEMISMATCH; 7679 } 7680 7681 if (pFDesc) 7682 { 7683 HRESULT hr = TLB_AllocAndInitFuncDesc( 7684 &pFDesc->funcdesc, 7685 &pBindPtr->lpfuncdesc, 7686 This->TypeAttr.typekind == TKIND_DISPATCH); 7687 if (FAILED(hr)) 7688 return hr; 7689 *pDescKind = DESCKIND_FUNCDESC; 7690 *ppTInfo = (ITypeInfo *)&This->lpVtbl; 7691 ITypeInfo_AddRef(*ppTInfo); 7692 return S_OK; 7693 } else { 7694 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) { 7695 if (!strcmpiW(pVDesc->Name, szName)) { 7696 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc); 7697 if (FAILED(hr)) 7698 return hr; 7699 *pDescKind = DESCKIND_VARDESC; 7700 *ppTInfo = (ITypeInfo *)&This->lpVtbl; 7701 ITypeInfo_AddRef(*ppTInfo); 7702 return S_OK; 7703 } 7704 } 7705 } 7706 /* FIXME: search each inherited interface, not just the first */ 7707 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) { 7708 /* recursive search */ 7709 ITypeInfo *pTInfo; 7710 ITypeComp *pTComp; 7711 HRESULT hr; 7712 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo); 7713 if (SUCCEEDED(hr)) 7714 { 7715 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp); 7716 ITypeInfo_Release(pTInfo); 7717 } 7718 if (SUCCEEDED(hr)) 7719 { 7720 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 7721 ITypeComp_Release(pTComp); 7722 return hr; 7723 } 7724 WARN("Could not search inherited interface!\n"); 7725 } 7726 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags); 7727 return hr; 7728 } 7729 7730 static HRESULT WINAPI ITypeComp_fnBindType( 7731 ITypeComp * iface, 7732 OLECHAR * szName, 7733 ULONG lHash, 7734 ITypeInfo ** ppTInfo, 7735 ITypeComp ** ppTComp) 7736 { 7737 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp); 7738 7739 /* strange behaviour (does nothing) but like the 7740 * original */ 7741 7742 if (!ppTInfo || !ppTComp) 7743 return E_POINTER; 7744 7745 *ppTInfo = NULL; 7746 *ppTComp = NULL; 7747 7748 return S_OK; 7749 } 7750 7751 static const ITypeCompVtbl tcompvt = 7752 { 7753 7754 ITypeComp_fnQueryInterface, 7755 ITypeComp_fnAddRef, 7756 ITypeComp_fnRelease, 7757 7758 ITypeComp_fnBind, 7759 ITypeComp_fnBindType 7760 }; 7761