Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentypelib.c
Go to the documentation of this file.
00001 /* 00002 * TYPELIB 00003 * 00004 * Copyright 1997 Marcus Meissner 00005 * 1999 Rein Klazes 00006 * 2000 Francois Jacques 00007 * 2001 Huw D M Davies for CodeWeavers 00008 * 2005 Robert Shearman, for CodeWeavers 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00023 * 00024 * -------------------------------------------------------------------------------------- 00025 * Known problems (2000, Francois Jacques) 00026 * 00027 * - Tested using OLEVIEW (Platform SDK tool) only. 00028 * 00029 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are 00030 * creating by doing a straight copy of the dispinterface instance and just changing 00031 * its typekind. Pointed structures aren't copied - only the address of the pointers. 00032 * 00033 * - locale stuff is partially implemented but hasn't been tested. 00034 * 00035 * - typelib file is still read in its entirety, but it is released now. 00036 * 00037 * -------------------------------------------------------------------------------------- 00038 * Known problems left from previous implementation (1999, Rein Klazes) : 00039 * 00040 * -. Data structures are straightforward, but slow for look-ups. 00041 * -. (related) nothing is hashed 00042 * -. Most error return values are just guessed not checked with windows 00043 * behaviour. 00044 * -. lousy fatal error handling 00045 * 00046 */ 00047 00048 #include "config.h" 00049 #include "wine/port.h" 00050 00051 #include <stdlib.h> 00052 #include <string.h> 00053 #include <stdarg.h> 00054 #include <stdio.h> 00055 #include <ctype.h> 00056 00057 #define COBJMACROS 00058 #define NONAMELESSUNION 00059 #define NONAMELESSSTRUCT 00060 00061 #include "winerror.h" 00062 #include "windef.h" 00063 #include "winbase.h" 00064 #include "winnls.h" 00065 #include "winreg.h" 00066 #include "winuser.h" 00067 #include "lzexpand.h" 00068 00069 #include "wine/unicode.h" 00070 #include "objbase.h" 00071 #include "typelib.h" 00072 #include "wine/debug.h" 00073 #include "variant.h" 00074 #include "wine/list.h" 00075 00076 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00077 WINE_DECLARE_DEBUG_CHANNEL(typelib); 00078 00079 typedef struct 00080 { 00081 WORD offset; 00082 WORD length; 00083 WORD flags; 00084 WORD id; 00085 WORD handle; 00086 WORD usage; 00087 } NE_NAMEINFO; 00088 00089 typedef struct 00090 { 00091 WORD type_id; /* Type identifier */ 00092 WORD count; /* Number of resources of this type */ 00093 DWORD resloader; /* SetResourceHandler() */ 00094 /* 00095 * Name info array. 00096 */ 00097 } NE_TYPEINFO; 00098 00099 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt); 00100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr); 00101 00102 /**************************************************************************** 00103 * FromLExxx 00104 * 00105 * Takes p_iVal (which is in little endian) and returns it 00106 * in the host machine's byte order. 00107 */ 00108 #ifdef WORDS_BIGENDIAN 00109 static WORD FromLEWord(WORD p_iVal) 00110 { 00111 return (((p_iVal & 0x00FF) << 8) | 00112 ((p_iVal & 0xFF00) >> 8)); 00113 } 00114 00115 00116 static DWORD FromLEDWord(DWORD p_iVal) 00117 { 00118 return (((p_iVal & 0x000000FF) << 24) | 00119 ((p_iVal & 0x0000FF00) << 8) | 00120 ((p_iVal & 0x00FF0000) >> 8) | 00121 ((p_iVal & 0xFF000000) >> 24)); 00122 } 00123 #else 00124 #define FromLEWord(X) (X) 00125 #define FromLEDWord(X) (X) 00126 #endif 00127 00128 #define DISPATCH_HREF_OFFSET 0x01000000 00129 #define DISPATCH_HREF_MASK 0xff000000 00130 00131 /**************************************************************************** 00132 * FromLExxx 00133 * 00134 * Fix byte order in any structure if necessary 00135 */ 00136 #ifdef WORDS_BIGENDIAN 00137 static void FromLEWords(void *p_Val, int p_iSize) 00138 { 00139 WORD *Val = p_Val; 00140 00141 p_iSize /= sizeof(WORD); 00142 00143 while (p_iSize) { 00144 *Val = FromLEWord(*Val); 00145 Val++; 00146 p_iSize--; 00147 } 00148 } 00149 00150 00151 static void FromLEDWords(void *p_Val, int p_iSize) 00152 { 00153 DWORD *Val = p_Val; 00154 00155 p_iSize /= sizeof(DWORD); 00156 00157 while (p_iSize) { 00158 *Val = FromLEDWord(*Val); 00159 Val++; 00160 p_iSize--; 00161 } 00162 } 00163 #else 00164 #define FromLEWords(X,Y) /*nothing*/ 00165 #define FromLEDWords(X,Y) /*nothing*/ 00166 #endif 00167 00168 /* 00169 * Find a typelib key which matches a requested maj.min version. 00170 */ 00171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin ) 00172 { 00173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0}; 00174 WCHAR buffer[60]; 00175 char key_name[16]; 00176 DWORD len, i; 00177 INT best_maj = -1, best_min = -1; 00178 HKEY hkey; 00179 00180 memcpy( buffer, typelibW, sizeof(typelibW) ); 00181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 00182 00183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS) 00184 return FALSE; 00185 00186 len = sizeof(key_name); 00187 i = 0; 00188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) 00189 { 00190 INT v_maj, v_min; 00191 00192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2) 00193 { 00194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min); 00195 00196 if (*wMaj == 0xffff && *wMin == 0xffff) 00197 { 00198 if (v_maj > best_maj) best_maj = v_maj; 00199 if (v_min > best_min) best_min = v_min; 00200 } 00201 else if (*wMaj == v_maj) 00202 { 00203 best_maj = v_maj; 00204 00205 if (*wMin == v_min) 00206 { 00207 best_min = v_min; 00208 break; /* exact match */ 00209 } 00210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min; 00211 } 00212 } 00213 len = sizeof(key_name); 00214 } 00215 RegCloseKey( hkey ); 00216 00217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min); 00218 00219 if (*wMaj == 0xffff && *wMin == 0xffff) 00220 { 00221 if (best_maj >= 0 && best_min >= 0) 00222 { 00223 *wMaj = best_maj; 00224 *wMin = best_min; 00225 return TRUE; 00226 } 00227 } 00228 00229 if (*wMaj == best_maj && best_min >= 0) 00230 { 00231 *wMin = best_min; 00232 return TRUE; 00233 } 00234 return FALSE; 00235 } 00236 00237 /* get the path of a typelib key, in the form "Typelib\<guid>\<maj>.<min>" */ 00238 /* buffer must be at least 60 characters long */ 00239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer ) 00240 { 00241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0}; 00242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0}; 00243 00244 memcpy( buffer, TypelibW, sizeof(TypelibW) ); 00245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 00246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin ); 00247 return buffer; 00248 } 00249 00250 /* get the path of an interface key, in the form "Interface\<guid>" */ 00251 /* buffer must be at least 50 characters long */ 00252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer ) 00253 { 00254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0}; 00255 00256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) ); 00257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); 00258 return buffer; 00259 } 00260 00261 /* get the lcid subkey for a typelib, in the form "<lcid>\<syskind>" */ 00262 /* buffer must be at least 16 characters long */ 00263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer ) 00264 { 00265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0}; 00266 static const WCHAR win16W[] = {'w','i','n','1','6',0}; 00267 static const WCHAR win32W[] = {'w','i','n','3','2',0}; 00268 static const WCHAR win64W[] = {'w','i','n','6','4',0}; 00269 00270 sprintfW( buffer, LcidFormatW, lcid ); 00271 switch(syskind) 00272 { 00273 case SYS_WIN16: strcatW( buffer, win16W ); break; 00274 case SYS_WIN32: strcatW( buffer, win32W ); break; 00275 case SYS_WIN64: strcatW( buffer, win64W ); break; 00276 default: 00277 TRACE("Typelib is for unsupported syskind %i\n", syskind); 00278 return NULL; 00279 } 00280 return buffer; 00281 } 00282 00283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib); 00284 00285 00286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */ 00287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin, 00288 SYSKIND syskind, LCID lcid, LPBSTR path ) 00289 { 00290 HRESULT hr = TYPE_E_LIBNOTREGISTERED; 00291 LCID myLCID = lcid; 00292 HKEY hkey; 00293 WCHAR buffer[60]; 00294 WCHAR Path[MAX_PATH]; 00295 LONG res; 00296 00297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path); 00298 00299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED; 00300 get_typelib_key( guid, wMaj, wMin, buffer ); 00301 00302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ); 00303 if (res == ERROR_FILE_NOT_FOUND) 00304 { 00305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer)); 00306 return TYPE_E_LIBNOTREGISTERED; 00307 } 00308 else if (res != ERROR_SUCCESS) 00309 { 00310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer)); 00311 return TYPE_E_REGISTRYACCESS; 00312 } 00313 00314 while (hr != S_OK) 00315 { 00316 LONG dwPathLen = sizeof(Path); 00317 00318 get_lcid_subkey( myLCID, syskind, buffer ); 00319 00320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen)) 00321 { 00322 if (!lcid) 00323 break; 00324 else if (myLCID == lcid) 00325 { 00326 /* try with sub-langid */ 00327 myLCID = SUBLANGID(lcid); 00328 } 00329 else if ((myLCID == SUBLANGID(lcid)) && myLCID) 00330 { 00331 /* try with system langid */ 00332 myLCID = 0; 00333 } 00334 else 00335 { 00336 break; 00337 } 00338 } 00339 else 00340 { 00341 *path = SysAllocString( Path ); 00342 hr = S_OK; 00343 } 00344 } 00345 RegCloseKey( hkey ); 00346 TRACE_(typelib)("-- 0x%08x\n", hr); 00347 return hr; 00348 } 00349 00350 /**************************************************************************** 00351 * QueryPathOfRegTypeLib [OLEAUT32.164] 00352 * 00353 * Gets the path to a registered type library. 00354 * 00355 * PARAMS 00356 * guid [I] referenced guid 00357 * wMaj [I] major version 00358 * wMin [I] minor version 00359 * lcid [I] locale id 00360 * path [O] path of typelib 00361 * 00362 * RETURNS 00363 * Success: S_OK. 00364 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED 00365 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be 00366 * opened. 00367 */ 00368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path ) 00369 { 00370 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path ); 00371 } 00372 00373 /****************************************************************************** 00374 * CreateTypeLib [OLEAUT32.160] creates a typelib 00375 * 00376 * RETURNS 00377 * Success: S_OK 00378 * Failure: Status 00379 */ 00380 HRESULT WINAPI CreateTypeLib( 00381 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib 00382 ) { 00383 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib); 00384 return E_FAIL; 00385 } 00386 00387 /****************************************************************************** 00388 * LoadTypeLib [OLEAUT32.161] 00389 * 00390 * Loads a type library 00391 * 00392 * PARAMS 00393 * szFile [I] Name of file to load from. 00394 * pptLib [O] Pointer that receives ITypeLib object on success. 00395 * 00396 * RETURNS 00397 * Success: S_OK 00398 * Failure: Status 00399 * 00400 * SEE 00401 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib. 00402 */ 00403 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib) 00404 { 00405 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib); 00406 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib); 00407 } 00408 00409 /****************************************************************************** 00410 * LoadTypeLibEx [OLEAUT32.183] 00411 * 00412 * Loads and optionally registers a type library 00413 * 00414 * RETURNS 00415 * Success: S_OK 00416 * Failure: Status 00417 */ 00418 HRESULT WINAPI LoadTypeLibEx( 00419 LPCOLESTR szFile, /* [in] Name of file to load from */ 00420 REGKIND regkind, /* [in] Specify kind of registration */ 00421 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */ 00422 { 00423 WCHAR szPath[MAX_PATH+1]; 00424 HRESULT res; 00425 00426 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib); 00427 00428 *pptLib = NULL; 00429 00430 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib); 00431 00432 if (SUCCEEDED(res)) 00433 switch(regkind) 00434 { 00435 case REGKIND_DEFAULT: 00436 /* don't register typelibs supplied with full path. Experimentation confirms the following */ 00437 if (((szFile[0] == '\\') && (szFile[1] == '\\')) || 00438 (szFile[0] && (szFile[1] == ':'))) break; 00439 /* else fall-through */ 00440 00441 case REGKIND_REGISTER: 00442 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL))) 00443 { 00444 IUnknown_Release(*pptLib); 00445 *pptLib = 0; 00446 } 00447 break; 00448 case REGKIND_NONE: 00449 break; 00450 } 00451 00452 TRACE(" returns %08x\n",res); 00453 return res; 00454 } 00455 00456 /****************************************************************************** 00457 * LoadRegTypeLib [OLEAUT32.162] 00458 * 00459 * Loads a registered type library. 00460 * 00461 * PARAMS 00462 * rguid [I] GUID of the registered type library. 00463 * wVerMajor [I] major version. 00464 * wVerMinor [I] minor version. 00465 * lcid [I] locale ID. 00466 * ppTLib [O] pointer that receives an ITypeLib object on success. 00467 * 00468 * RETURNS 00469 * Success: S_OK. 00470 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or 00471 * LoadTypeLib. 00472 */ 00473 HRESULT WINAPI LoadRegTypeLib( 00474 REFGUID rguid, 00475 WORD wVerMajor, 00476 WORD wVerMinor, 00477 LCID lcid, 00478 ITypeLib **ppTLib) 00479 { 00480 BSTR bstr=NULL; 00481 HRESULT res; 00482 00483 *ppTLib = NULL; 00484 00485 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr); 00486 00487 if(SUCCEEDED(res)) 00488 { 00489 res= LoadTypeLib(bstr, ppTLib); 00490 SysFreeString(bstr); 00491 } 00492 00493 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib); 00494 00495 return res; 00496 } 00497 00498 00499 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */ 00500 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0}; 00501 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0}; 00502 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0}; 00503 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0}; 00504 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0}; 00505 00506 /****************************************************************************** 00507 * RegisterTypeLib [OLEAUT32.163] 00508 * Adds information about a type library to the System Registry 00509 * NOTES 00510 * Docs: ITypeLib FAR * ptlib 00511 * Docs: OLECHAR FAR* szFullPath 00512 * Docs: OLECHAR FAR* szHelpDir 00513 * 00514 * RETURNS 00515 * Success: S_OK 00516 * Failure: Status 00517 */ 00518 HRESULT WINAPI RegisterTypeLib( 00519 ITypeLib * ptlib, /* [in] Pointer to the library*/ 00520 OLECHAR * szFullPath, /* [in] full Path of the library*/ 00521 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library, 00522 may be NULL*/ 00523 { 00524 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-', 00525 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-', 00526 '0','0','0','0','0','0','0','0','0','0','4','6','}',0}; 00527 HRESULT res; 00528 TLIBATTR *attr; 00529 WCHAR keyName[60]; 00530 WCHAR tmp[16]; 00531 HKEY key, subKey; 00532 UINT types, tidx; 00533 TYPEKIND kind; 00534 DWORD disposition; 00535 00536 if (ptlib == NULL || szFullPath == NULL) 00537 return E_INVALIDARG; 00538 00539 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr))) 00540 return E_FAIL; 00541 00542 #ifdef _WIN64 00543 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND; 00544 #else 00545 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND; 00546 #endif 00547 00548 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName ); 00549 00550 res = S_OK; 00551 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, 00552 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) 00553 { 00554 LPOLESTR doc; 00555 00556 /* Set the human-readable name of the typelib */ 00557 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL))) 00558 res = E_FAIL; 00559 else if (doc) 00560 { 00561 if (RegSetValueExW(key, NULL, 0, REG_SZ, 00562 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) 00563 res = E_FAIL; 00564 00565 SysFreeString(doc); 00566 } 00567 00568 /* Make up the name of the typelib path subkey */ 00569 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL; 00570 00571 /* Create the typelib path subkey */ 00572 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0, 00573 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) 00574 { 00575 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 00576 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) 00577 res = E_FAIL; 00578 00579 RegCloseKey(subKey); 00580 } 00581 else 00582 res = E_FAIL; 00583 00584 /* Create the flags subkey */ 00585 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0, 00586 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) 00587 { 00588 /* FIXME: is %u correct? */ 00589 static const WCHAR formatW[] = {'%','u',0}; 00590 WCHAR buf[20]; 00591 sprintfW(buf, formatW, attr->wLibFlags); 00592 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 00593 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS) 00594 res = E_FAIL; 00595 00596 RegCloseKey(subKey); 00597 } 00598 else 00599 res = E_FAIL; 00600 00601 /* create the helpdir subkey */ 00602 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0, 00603 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS) 00604 { 00605 BOOL freeHelpDir = FALSE; 00606 OLECHAR* pIndexStr; 00607 00608 /* if we created a new key, and helpDir was null, set the helpdir 00609 to the directory which contains the typelib. However, 00610 if we just opened an existing key, we leave the helpdir alone */ 00611 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) { 00612 szHelpDir = SysAllocString(szFullPath); 00613 pIndexStr = strrchrW(szHelpDir, '\\'); 00614 if (pIndexStr) { 00615 *pIndexStr = 0; 00616 } 00617 freeHelpDir = TRUE; 00618 } 00619 00620 /* if we have an szHelpDir, set it! */ 00621 if (szHelpDir != NULL) { 00622 if (RegSetValueExW(subKey, NULL, 0, REG_SZ, 00623 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) { 00624 res = E_FAIL; 00625 } 00626 } 00627 00628 /* tidy up */ 00629 if (freeHelpDir) SysFreeString(szHelpDir); 00630 RegCloseKey(subKey); 00631 00632 } else { 00633 res = E_FAIL; 00634 } 00635 00636 RegCloseKey(key); 00637 } 00638 else 00639 res = E_FAIL; 00640 00641 /* register OLE Automation-compatible interfaces for this typelib */ 00642 types = ITypeLib_GetTypeInfoCount(ptlib); 00643 for (tidx=0; tidx<types; tidx++) { 00644 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) { 00645 LPOLESTR name = NULL; 00646 ITypeInfo *tinfo = NULL; 00647 00648 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL); 00649 00650 switch (kind) { 00651 case TKIND_INTERFACE: 00652 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name)); 00653 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); 00654 break; 00655 00656 case TKIND_DISPATCH: 00657 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name)); 00658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); 00659 break; 00660 00661 default: 00662 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name)); 00663 break; 00664 } 00665 00666 if (tinfo) { 00667 TYPEATTR *tattr = NULL; 00668 ITypeInfo_GetTypeAttr(tinfo, &tattr); 00669 00670 if (tattr) { 00671 TRACE_(typelib)("guid=%s, flags=%04x (", 00672 debugstr_guid(&tattr->guid), 00673 tattr->wTypeFlags); 00674 00675 if (TRACE_ON(typelib)) { 00676 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|"); 00677 XX(FAPPOBJECT); 00678 XX(FCANCREATE); 00679 XX(FLICENSED); 00680 XX(FPREDECLID); 00681 XX(FHIDDEN); 00682 XX(FCONTROL); 00683 XX(FDUAL); 00684 XX(FNONEXTENSIBLE); 00685 XX(FOLEAUTOMATION); 00686 XX(FRESTRICTED); 00687 XX(FAGGREGATABLE); 00688 XX(FREPLACEABLE); 00689 XX(FDISPATCHABLE); 00690 XX(FREVERSEBIND); 00691 XX(FPROXY); 00692 #undef XX 00693 MESSAGE("\n"); 00694 } 00695 00696 /* Register all dispinterfaces (which includes dual interfaces) and 00697 oleautomation interfaces */ 00698 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) || 00699 kind == TKIND_DISPATCH) 00700 { 00701 /* register interface<->typelib coupling */ 00702 get_interface_key( &tattr->guid, keyName ); 00703 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, 00704 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) 00705 { 00706 if (name) 00707 RegSetValueExW(key, NULL, 0, REG_SZ, 00708 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR)); 00709 00710 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0, 00711 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { 00712 RegSetValueExW(subKey, NULL, 0, REG_SZ, 00713 (const BYTE *)PSOA, sizeof PSOA); 00714 RegCloseKey(subKey); 00715 } 00716 00717 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0, 00718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { 00719 RegSetValueExW(subKey, NULL, 0, REG_SZ, 00720 (const BYTE *)PSOA, sizeof PSOA); 00721 RegCloseKey(subKey); 00722 } 00723 00724 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0, 00725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) 00726 { 00727 WCHAR buffer[40]; 00728 static const WCHAR fmtver[] = {'%','x','.','%','x',0 }; 00729 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0}; 00730 00731 StringFromGUID2(&attr->guid, buffer, 40); 00732 RegSetValueExW(subKey, NULL, 0, REG_SZ, 00733 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR)); 00734 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum); 00735 RegSetValueExW(subKey, VersionW, 0, REG_SZ, 00736 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR)); 00737 RegCloseKey(subKey); 00738 } 00739 00740 RegCloseKey(key); 00741 } 00742 } 00743 00744 ITypeInfo_ReleaseTypeAttr(tinfo, tattr); 00745 } 00746 00747 ITypeInfo_Release(tinfo); 00748 } 00749 00750 SysFreeString(name); 00751 } 00752 } 00753 00754 ITypeLib_ReleaseTLibAttr(ptlib, attr); 00755 00756 return res; 00757 } 00758 00759 00760 /****************************************************************************** 00761 * UnRegisterTypeLib [OLEAUT32.186] 00762 * Removes information about a type library from the System Registry 00763 * NOTES 00764 * 00765 * RETURNS 00766 * Success: S_OK 00767 * Failure: Status 00768 */ 00769 HRESULT WINAPI UnRegisterTypeLib( 00770 REFGUID libid, /* [in] Guid of the library */ 00771 WORD wVerMajor, /* [in] major version */ 00772 WORD wVerMinor, /* [in] minor version */ 00773 LCID lcid, /* [in] locale id */ 00774 SYSKIND syskind) 00775 { 00776 BSTR tlibPath = NULL; 00777 DWORD tmpLength; 00778 WCHAR keyName[60]; 00779 WCHAR subKeyName[50]; 00780 int result = S_OK; 00781 DWORD i = 0; 00782 BOOL deleteOtherStuff; 00783 HKEY key = NULL; 00784 HKEY subKey = NULL; 00785 TYPEATTR* typeAttr = NULL; 00786 TYPEKIND kind; 00787 ITypeInfo* typeInfo = NULL; 00788 ITypeLib* typeLib = NULL; 00789 int numTypes; 00790 00791 TRACE("(IID: %s)\n",debugstr_guid(libid)); 00792 00793 /* Create the path to the key */ 00794 get_typelib_key( libid, wVerMajor, wVerMinor, keyName ); 00795 00796 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64) 00797 { 00798 TRACE("Unsupported syskind %i\n", syskind); 00799 result = E_INVALIDARG; 00800 goto end; 00801 } 00802 00803 /* get the path to the typelib on disk */ 00804 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) { 00805 result = E_INVALIDARG; 00806 goto end; 00807 } 00808 00809 /* Try and open the key to the type library. */ 00810 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) { 00811 result = E_INVALIDARG; 00812 goto end; 00813 } 00814 00815 /* Try and load the type library */ 00816 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) { 00817 result = TYPE_E_INVALIDSTATE; 00818 goto end; 00819 } 00820 00821 /* remove any types registered with this typelib */ 00822 numTypes = ITypeLib_GetTypeInfoCount(typeLib); 00823 for (i=0; i<numTypes; i++) { 00824 /* get the kind of type */ 00825 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) { 00826 goto enddeleteloop; 00827 } 00828 00829 /* skip non-interfaces, and get type info for the type */ 00830 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) { 00831 goto enddeleteloop; 00832 } 00833 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) { 00834 goto enddeleteloop; 00835 } 00836 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) { 00837 goto enddeleteloop; 00838 } 00839 00840 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) || 00841 kind == TKIND_DISPATCH) 00842 { 00843 /* the path to the type */ 00844 get_interface_key( &typeAttr->guid, subKeyName ); 00845 00846 /* Delete its bits */ 00847 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) 00848 goto enddeleteloop; 00849 00850 RegDeleteKeyW(subKey, ProxyStubClsidW); 00851 RegDeleteKeyW(subKey, ProxyStubClsid32W); 00852 RegDeleteKeyW(subKey, TypeLibW); 00853 RegCloseKey(subKey); 00854 subKey = NULL; 00855 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName); 00856 } 00857 00858 enddeleteloop: 00859 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr); 00860 typeAttr = NULL; 00861 if (typeInfo) ITypeInfo_Release(typeInfo); 00862 typeInfo = NULL; 00863 } 00864 00865 /* Now, delete the type library path subkey */ 00866 get_lcid_subkey( lcid, syskind, subKeyName ); 00867 RegDeleteKeyW(key, subKeyName); 00868 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */ 00869 RegDeleteKeyW(key, subKeyName); 00870 00871 /* check if there is anything besides the FLAGS/HELPDIR keys. 00872 If there is, we don't delete them */ 00873 tmpLength = sizeof(subKeyName)/sizeof(WCHAR); 00874 deleteOtherStuff = TRUE; 00875 i = 0; 00876 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { 00877 tmpLength = sizeof(subKeyName)/sizeof(WCHAR); 00878 00879 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */ 00880 if (!strcmpW(subKeyName, FLAGSW)) continue; 00881 if (!strcmpW(subKeyName, HELPDIRW)) continue; 00882 deleteOtherStuff = FALSE; 00883 break; 00884 } 00885 00886 /* only delete the other parts of the key if we're absolutely sure */ 00887 if (deleteOtherStuff) { 00888 RegDeleteKeyW(key, FLAGSW); 00889 RegDeleteKeyW(key, HELPDIRW); 00890 RegCloseKey(key); 00891 key = NULL; 00892 00893 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName); 00894 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */ 00895 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName); 00896 } 00897 00898 end: 00899 SysFreeString(tlibPath); 00900 if (typeLib) ITypeLib_Release(typeLib); 00901 if (subKey) RegCloseKey(subKey); 00902 if (key) RegCloseKey(key); 00903 return result; 00904 } 00905 00906 /****************************************************************************** 00907 * RegisterTypeLibForUser [OLEAUT32.442] 00908 * Adds information about a type library to the user registry 00909 * NOTES 00910 * Docs: ITypeLib FAR * ptlib 00911 * Docs: OLECHAR FAR* szFullPath 00912 * Docs: OLECHAR FAR* szHelpDir 00913 * 00914 * RETURNS 00915 * Success: S_OK 00916 * Failure: Status 00917 */ 00918 HRESULT WINAPI RegisterTypeLibForUser( 00919 ITypeLib * ptlib, /* [in] Pointer to the library*/ 00920 OLECHAR * szFullPath, /* [in] full Path of the library*/ 00921 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library, 00922 may be NULL*/ 00923 { 00924 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib, 00925 debugstr_w(szFullPath), debugstr_w(szHelpDir)); 00926 return RegisterTypeLib(ptlib, szFullPath, szHelpDir); 00927 } 00928 00929 /****************************************************************************** 00930 * UnRegisterTypeLibForUser [OLEAUT32.443] 00931 * Removes information about a type library from the user registry 00932 * 00933 * RETURNS 00934 * Success: S_OK 00935 * Failure: Status 00936 */ 00937 HRESULT WINAPI UnRegisterTypeLibForUser( 00938 REFGUID libid, /* [in] GUID of the library */ 00939 WORD wVerMajor, /* [in] major version */ 00940 WORD wVerMinor, /* [in] minor version */ 00941 LCID lcid, /* [in] locale id */ 00942 SYSKIND syskind) 00943 { 00944 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n", 00945 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind); 00946 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind); 00947 } 00948 00949 /*======================= ITypeLib implementation =======================*/ 00950 00951 typedef struct tagTLBCustData 00952 { 00953 GUID guid; 00954 VARIANT data; 00955 struct tagTLBCustData* next; 00956 } TLBCustData; 00957 00958 /* data structure for import typelibs */ 00959 typedef struct tagTLBImpLib 00960 { 00961 int offset; /* offset in the file (MSFT) 00962 offset in nametable (SLTG) 00963 just used to identify library while reading 00964 data from file */ 00965 GUID guid; /* libid */ 00966 BSTR name; /* name */ 00967 00968 LCID lcid; /* lcid of imported typelib */ 00969 00970 WORD wVersionMajor; /* major version number */ 00971 WORD wVersionMinor; /* minor version number */ 00972 00973 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or 00974 NULL if not yet loaded */ 00975 struct tagTLBImpLib * next; 00976 } TLBImpLib; 00977 00978 /* internal ITypeLib data */ 00979 typedef struct tagITypeLibImpl 00980 { 00981 const ITypeLib2Vtbl *lpVtbl; 00982 const ITypeCompVtbl *lpVtblTypeComp; 00983 LONG ref; 00984 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */ 00985 LCID lcid; 00986 00987 /* strings can be stored in tlb as multibyte strings BUT they are *always* 00988 * exported to the application as a UNICODE string. 00989 */ 00990 BSTR Name; 00991 BSTR DocString; 00992 BSTR HelpFile; 00993 BSTR HelpStringDll; 00994 DWORD dwHelpContext; 00995 int TypeInfoCount; /* nr of typeinfo's in librarry */ 00996 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */ 00997 int ctCustData; /* number of items in cust data list */ 00998 TLBCustData * pCustData; /* linked list to cust data */ 00999 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */ 01000 int ctTypeDesc; /* number of items in type desc array */ 01001 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the 01002 library. Only used while reading MSFT 01003 typelibs */ 01004 struct list ref_list; /* list of ref types in this typelib */ 01005 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */ 01006 01007 01008 /* typelibs are cached, keyed by path and index, so store the linked list info within them */ 01009 struct tagITypeLibImpl *next, *prev; 01010 WCHAR *path; 01011 INT index; 01012 } ITypeLibImpl; 01013 01014 static const ITypeLib2Vtbl tlbvt; 01015 static const ITypeCompVtbl tlbtcvt; 01016 01017 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface ) 01018 { 01019 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp)); 01020 } 01021 01022 /* ITypeLib methods */ 01023 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength); 01024 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength); 01025 01026 /*======================= ITypeInfo implementation =======================*/ 01027 01028 /* data for referenced types */ 01029 typedef struct tagTLBRefType 01030 { 01031 INT index; /* Type index for internal ref or for external ref 01032 it the format is SLTG. -2 indicates to 01033 use guid */ 01034 01035 GUID guid; /* guid of the referenced type */ 01036 /* if index == TLB_REF_USE_GUID */ 01037 01038 HREFTYPE reference; /* The href of this ref */ 01039 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data 01040 TLB_REF_INTERNAL for internal refs 01041 TLB_REF_NOT_FOUND for broken refs */ 01042 01043 struct list entry; 01044 } TLBRefType; 01045 01046 #define TLB_REF_USE_GUID -2 01047 01048 #define TLB_REF_INTERNAL (void*)-2 01049 #define TLB_REF_NOT_FOUND (void*)-1 01050 01051 /* internal Parameter data */ 01052 typedef struct tagTLBParDesc 01053 { 01054 BSTR Name; 01055 int ctCustData; 01056 TLBCustData * pCustData; /* linked list to cust data */ 01057 } TLBParDesc; 01058 01059 /* internal Function data */ 01060 typedef struct tagTLBFuncDesc 01061 { 01062 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */ 01063 BSTR Name; /* the name of this function */ 01064 TLBParDesc *pParamDesc; /* array with param names and custom data */ 01065 int helpcontext; 01066 int HelpStringContext; 01067 BSTR HelpString; 01068 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */ 01069 int ctCustData; 01070 TLBCustData * pCustData; /* linked list to cust data; */ 01071 struct tagTLBFuncDesc * next; 01072 } TLBFuncDesc; 01073 01074 /* internal Variable data */ 01075 typedef struct tagTLBVarDesc 01076 { 01077 VARDESC vardesc; /* lots of info on the variable and its attributes. */ 01078 BSTR Name; /* the name of this variable */ 01079 int HelpContext; 01080 int HelpStringContext; /* FIXME: where? */ 01081 BSTR HelpString; 01082 int ctCustData; 01083 TLBCustData * pCustData;/* linked list to cust data; */ 01084 struct tagTLBVarDesc * next; 01085 } TLBVarDesc; 01086 01087 /* internal implemented interface data */ 01088 typedef struct tagTLBImplType 01089 { 01090 HREFTYPE hRef; /* hRef of interface */ 01091 int implflags; /* IMPLFLAG_*s */ 01092 int ctCustData; 01093 TLBCustData * pCustData;/* linked list to custom data; */ 01094 struct tagTLBImplType *next; 01095 } TLBImplType; 01096 01097 /* internal TypeInfo data */ 01098 typedef struct tagITypeInfoImpl 01099 { 01100 const ITypeInfo2Vtbl *lpVtbl; 01101 const ITypeCompVtbl *lpVtblTypeComp; 01102 LONG ref; 01103 BOOL not_attached_to_typelib; 01104 TYPEATTR TypeAttr ; /* _lots_ of type information. */ 01105 ITypeLibImpl * pTypeLib; /* back pointer to typelib */ 01106 int index; /* index in this typelib; */ 01107 HREFTYPE hreftype; /* hreftype for app object binding */ 01108 /* type libs seem to store the doc strings in ascii 01109 * so why should we do it in unicode? 01110 */ 01111 BSTR Name; 01112 BSTR DocString; 01113 BSTR DllName; 01114 DWORD dwHelpContext; 01115 DWORD dwHelpStringContext; 01116 01117 /* functions */ 01118 TLBFuncDesc * funclist; /* linked list with function descriptions */ 01119 01120 /* variables */ 01121 TLBVarDesc * varlist; /* linked list with variable descriptions */ 01122 01123 /* Implemented Interfaces */ 01124 TLBImplType * impltypelist; 01125 01126 int ctCustData; 01127 TLBCustData * pCustData; /* linked list to cust data; */ 01128 struct tagITypeInfoImpl * next; 01129 } ITypeInfoImpl; 01130 01131 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface ) 01132 { 01133 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp)); 01134 } 01135 01136 static const ITypeInfo2Vtbl tinfvt; 01137 static const ITypeCompVtbl tcompvt; 01138 01139 static ITypeInfo2 * ITypeInfo_Constructor(void); 01140 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This); 01141 01142 typedef struct tagTLBContext 01143 { 01144 unsigned int oStart; /* start of TLB in file */ 01145 unsigned int pos; /* current pos */ 01146 unsigned int length; /* total length */ 01147 void *mapping; /* memory mapping */ 01148 MSFT_SegDir * pTblDir; 01149 ITypeLibImpl* pLibInfo; 01150 } TLBContext; 01151 01152 01153 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset); 01154 01155 /* 01156 debug 01157 */ 01158 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) { 01159 if (pTD->vt & VT_RESERVED) 01160 szVarType += strlen(strcpy(szVarType, "reserved | ")); 01161 if (pTD->vt & VT_BYREF) 01162 szVarType += strlen(strcpy(szVarType, "ref to ")); 01163 if (pTD->vt & VT_ARRAY) 01164 szVarType += strlen(strcpy(szVarType, "array of ")); 01165 if (pTD->vt & VT_VECTOR) 01166 szVarType += strlen(strcpy(szVarType, "vector of ")); 01167 switch(pTD->vt & VT_TYPEMASK) { 01168 case VT_UI1: sprintf(szVarType, "VT_UI1"); break; 01169 case VT_I2: sprintf(szVarType, "VT_I2"); break; 01170 case VT_I4: sprintf(szVarType, "VT_I4"); break; 01171 case VT_R4: sprintf(szVarType, "VT_R4"); break; 01172 case VT_R8: sprintf(szVarType, "VT_R8"); break; 01173 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break; 01174 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break; 01175 case VT_CY: sprintf(szVarType, "VT_CY"); break; 01176 case VT_DATE: sprintf(szVarType, "VT_DATE"); break; 01177 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break; 01178 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break; 01179 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break; 01180 case VT_I1: sprintf(szVarType, "VT_I1"); break; 01181 case VT_UI2: sprintf(szVarType, "VT_UI2"); break; 01182 case VT_UI4: sprintf(szVarType, "VT_UI4"); break; 01183 case VT_INT: sprintf(szVarType, "VT_INT"); break; 01184 case VT_UINT: sprintf(szVarType, "VT_UINT"); break; 01185 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break; 01186 case VT_VOID: sprintf(szVarType, "VT_VOID"); break; 01187 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break; 01188 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x", 01189 pTD->u.hreftype); break; 01190 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break; 01191 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break; 01192 case VT_PTR: sprintf(szVarType, "ptr to "); 01193 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7); 01194 break; 01195 case VT_SAFEARRAY: sprintf(szVarType, "safearray of "); 01196 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13); 01197 break; 01198 case VT_CARRAY: sprintf(szVarType, "%d dim array of ", 01199 pTD->u.lpadesc->cDims); /* FIXME print out sizes */ 01200 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType)); 01201 break; 01202 01203 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break; 01204 } 01205 } 01206 01207 static void dump_ELEMDESC(const ELEMDESC *edesc) { 01208 char buf[200]; 01209 USHORT flags = edesc->u.paramdesc.wParamFlags; 01210 dump_TypeDesc(&edesc->tdesc,buf); 01211 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf); 01212 MESSAGE("\t\tu.paramdesc.wParamFlags"); 01213 if (!flags) MESSAGE(" PARAMFLAGS_NONE"); 01214 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN"); 01215 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT"); 01216 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID"); 01217 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL"); 01218 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT"); 01219 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT"); 01220 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA"); 01221 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex); 01222 } 01223 static void dump_FUNCDESC(const FUNCDESC *funcdesc) { 01224 int i; 01225 MESSAGE("memid is %08x\n",funcdesc->memid); 01226 for (i=0;i<funcdesc->cParams;i++) { 01227 MESSAGE("Param %d:\n",i); 01228 dump_ELEMDESC(funcdesc->lprgelemdescParam+i); 01229 } 01230 MESSAGE("\tfunckind: %d (",funcdesc->funckind); 01231 switch (funcdesc->funckind) { 01232 case FUNC_VIRTUAL: MESSAGE("virtual");break; 01233 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break; 01234 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break; 01235 case FUNC_STATIC: MESSAGE("static");break; 01236 case FUNC_DISPATCH: MESSAGE("dispatch");break; 01237 default: MESSAGE("unknown");break; 01238 } 01239 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind); 01240 switch (funcdesc->invkind) { 01241 case INVOKE_FUNC: MESSAGE("func");break; 01242 case INVOKE_PROPERTYGET: MESSAGE("property get");break; 01243 case INVOKE_PROPERTYPUT: MESSAGE("property put");break; 01244 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break; 01245 } 01246 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv); 01247 switch (funcdesc->callconv) { 01248 case CC_CDECL: MESSAGE("cdecl");break; 01249 case CC_PASCAL: MESSAGE("pascal");break; 01250 case CC_STDCALL: MESSAGE("stdcall");break; 01251 case CC_SYSCALL: MESSAGE("syscall");break; 01252 default:break; 01253 } 01254 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft); 01255 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt); 01256 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags); 01257 01258 MESSAGE("\telemdescFunc (return value type):\n"); 01259 dump_ELEMDESC(&funcdesc->elemdescFunc); 01260 } 01261 01262 static const char * const typekind_desc[] = 01263 { 01264 "TKIND_ENUM", 01265 "TKIND_RECORD", 01266 "TKIND_MODULE", 01267 "TKIND_INTERFACE", 01268 "TKIND_DISPATCH", 01269 "TKIND_COCLASS", 01270 "TKIND_ALIAS", 01271 "TKIND_UNION", 01272 "TKIND_MAX" 01273 }; 01274 01275 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd) 01276 { 01277 int i; 01278 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams); 01279 for (i=0;i<pfd->funcdesc.cParams;i++) 01280 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name)); 01281 01282 01283 dump_FUNCDESC(&(pfd->funcdesc)); 01284 01285 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString)); 01286 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry)); 01287 } 01288 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd) 01289 { 01290 while (pfd) 01291 { 01292 dump_TLBFuncDescOne(pfd); 01293 pfd = pfd->next; 01294 }; 01295 } 01296 static void dump_TLBVarDesc(const TLBVarDesc * pvd) 01297 { 01298 while (pvd) 01299 { 01300 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name)); 01301 pvd = pvd->next; 01302 }; 01303 } 01304 01305 static void dump_TLBImpLib(const TLBImpLib *import) 01306 { 01307 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)), 01308 debugstr_w(import->name)); 01309 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor, 01310 import->wVersionMinor, import->lcid, import->offset); 01311 } 01312 01313 static void dump_TLBRefType(const ITypeLibImpl *pTL) 01314 { 01315 TLBRefType *ref; 01316 01317 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry) 01318 { 01319 TRACE_(typelib)("href:0x%08x\n", ref->reference); 01320 if(ref->index == -1) 01321 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid))); 01322 else 01323 TRACE_(typelib)("type no: %d\n", ref->index); 01324 01325 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND) 01326 { 01327 TRACE_(typelib)("in lib\n"); 01328 dump_TLBImpLib(ref->pImpTLInfo); 01329 } 01330 } 01331 } 01332 01333 static void dump_TLBImplType(const TLBImplType * impl) 01334 { 01335 while (impl) { 01336 TRACE_(typelib)( 01337 "implementing/inheriting interface hRef = %x implflags %x\n", 01338 impl->hRef, impl->implflags); 01339 impl = impl->next; 01340 } 01341 } 01342 01343 static void dump_Variant(const VARIANT * pvar) 01344 { 01345 SYSTEMTIME st; 01346 01347 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar)); 01348 01349 if (pvar) 01350 { 01351 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN || 01352 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD) 01353 { 01354 TRACE(",%p", V_BYREF(pvar)); 01355 } 01356 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar)) 01357 { 01358 TRACE(",%p", V_ARRAY(pvar)); 01359 } 01360 else switch (V_TYPE(pvar)) 01361 { 01362 case VT_I1: TRACE(",%d", V_I1(pvar)); break; 01363 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break; 01364 case VT_I2: TRACE(",%d", V_I2(pvar)); break; 01365 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break; 01366 case VT_INT: 01367 case VT_I4: TRACE(",%d", V_I4(pvar)); break; 01368 case VT_UINT: 01369 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break; 01370 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32), 01371 (ULONG)(V_I8(pvar) & 0xffffffff)); break; 01372 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32), 01373 (ULONG)(V_UI8(pvar) & 0xffffffff)); break; 01374 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break; 01375 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break; 01376 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break; 01377 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break; 01378 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi, 01379 V_CY(pvar).s.Lo); break; 01380 case VT_DATE: 01381 if(!VariantTimeToSystemTime(V_DATE(pvar), &st)) 01382 TRACE(",<invalid>"); 01383 else 01384 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, 01385 st.wHour, st.wMinute, st.wSecond); 01386 break; 01387 case VT_ERROR: 01388 case VT_VOID: 01389 case VT_USERDEFINED: 01390 case VT_EMPTY: 01391 case VT_NULL: break; 01392 default: TRACE(",?"); break; 01393 } 01394 } 01395 TRACE("}\n"); 01396 } 01397 01398 static void dump_DispParms(const DISPPARAMS * pdp) 01399 { 01400 unsigned int index; 01401 01402 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs); 01403 01404 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs) 01405 { 01406 TRACE("named args:\n"); 01407 for (index = 0; index < pdp->cNamedArgs; index++) 01408 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] ); 01409 } 01410 01411 if (pdp->cArgs && pdp->rgvarg) 01412 { 01413 TRACE("args:\n"); 01414 for (index = 0; index < pdp->cArgs; index++) 01415 dump_Variant( &pdp->rgvarg[index] ); 01416 } 01417 } 01418 01419 static void dump_TypeInfo(const ITypeInfoImpl * pty) 01420 { 01421 TRACE("%p ref=%u\n", pty, pty->ref); 01422 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString)); 01423 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid))); 01424 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]); 01425 TRACE("fct:%u var:%u impl:%u\n", 01426 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes); 01427 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags); 01428 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index); 01429 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName)); 01430 if (TRACE_ON(ole)) 01431 dump_TLBFuncDesc(pty->funclist); 01432 dump_TLBVarDesc(pty->varlist); 01433 dump_TLBImplType(pty->impltypelist); 01434 } 01435 01436 static void dump_VARDESC(const VARDESC *v) 01437 { 01438 MESSAGE("memid %d\n",v->memid); 01439 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema)); 01440 MESSAGE("oInst %d\n",v->u.oInst); 01441 dump_ELEMDESC(&(v->elemdescVar)); 01442 MESSAGE("wVarFlags %x\n",v->wVarFlags); 01443 MESSAGE("varkind %d\n",v->varkind); 01444 } 01445 01446 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]= 01447 { 01448 /* VT_LPWSTR is largest type that */ 01449 /* may appear in type description*/ 01450 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4}, 01451 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9}, 01452 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14}, 01453 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19}, 01454 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24}, 01455 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29}, 01456 {{0},30},{{0},31} 01457 }; 01458 01459 static void TLB_abort(void) 01460 { 01461 DebugBreak(); 01462 } 01463 01464 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1); 01465 static void * TLB_Alloc(unsigned size) 01466 { 01467 void * ret; 01468 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){ 01469 /* FIXME */ 01470 ERR("cannot allocate memory\n"); 01471 } 01472 return ret; 01473 } 01474 01475 static void TLB_Free(void * ptr) 01476 { 01477 HeapFree(GetProcessHeap(), 0, ptr); 01478 } 01479 01480 /* returns the size required for a deep copy of a typedesc into a 01481 * flat buffer */ 01482 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space ) 01483 { 01484 SIZE_T size = 0; 01485 01486 if (alloc_initial_space) 01487 size += sizeof(TYPEDESC); 01488 01489 switch (tdesc->vt) 01490 { 01491 case VT_PTR: 01492 case VT_SAFEARRAY: 01493 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE); 01494 break; 01495 case VT_CARRAY: 01496 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]); 01497 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE); 01498 break; 01499 } 01500 return size; 01501 } 01502 01503 /* deep copy a typedesc into a flat buffer */ 01504 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer ) 01505 { 01506 if (!dest) 01507 { 01508 dest = buffer; 01509 buffer = (char *)buffer + sizeof(TYPEDESC); 01510 } 01511 01512 *dest = *src; 01513 01514 switch (src->vt) 01515 { 01516 case VT_PTR: 01517 case VT_SAFEARRAY: 01518 dest->u.lptdesc = buffer; 01519 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer); 01520 break; 01521 case VT_CARRAY: 01522 dest->u.lpadesc = buffer; 01523 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims])); 01524 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]); 01525 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer); 01526 break; 01527 } 01528 return buffer; 01529 } 01530 01531 /* free custom data allocated by MSFT_CustData */ 01532 static inline void TLB_FreeCustData(TLBCustData *pCustData) 01533 { 01534 TLBCustData *pCustDataNext; 01535 for (; pCustData; pCustData = pCustDataNext) 01536 { 01537 VariantClear(&pCustData->data); 01538 01539 pCustDataNext = pCustData->next; 01540 TLB_Free(pCustData); 01541 } 01542 } 01543 01544 static BSTR TLB_MultiByteToBSTR(const char *ptr) 01545 { 01546 DWORD len; 01547 BSTR ret; 01548 01549 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0); 01550 ret = SysAllocStringLen(NULL, len - 1); 01551 if (!ret) return ret; 01552 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len); 01553 return ret; 01554 } 01555 01556 /********************************************************************** 01557 * 01558 * Functions for reading MSFT typelibs (those created by CreateTypeLib2) 01559 */ 01560 static inline unsigned int MSFT_Tell(const TLBContext *pcx) 01561 { 01562 return pcx->pos; 01563 } 01564 01565 static inline void MSFT_Seek(TLBContext *pcx, LONG where) 01566 { 01567 if (where != DO_NOT_SEEK) 01568 { 01569 where += pcx->oStart; 01570 if (where > pcx->length) 01571 { 01572 /* FIXME */ 01573 ERR("seek beyond end (%d/%d)\n", where, pcx->length ); 01574 TLB_abort(); 01575 } 01576 pcx->pos = where; 01577 } 01578 } 01579 01580 /* read function */ 01581 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where ) 01582 { 01583 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n", 01584 pcx->pos, count, pcx->oStart, pcx->length, where); 01585 01586 MSFT_Seek(pcx, where); 01587 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos; 01588 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count ); 01589 pcx->pos += count; 01590 return count; 01591 } 01592 01593 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx, 01594 LONG where ) 01595 { 01596 DWORD ret; 01597 01598 ret = MSFT_Read(buffer, count, pcx, where); 01599 FromLEDWords(buffer, ret); 01600 01601 return ret; 01602 } 01603 01604 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx, 01605 LONG where ) 01606 { 01607 DWORD ret; 01608 01609 ret = MSFT_Read(buffer, count, pcx, where); 01610 FromLEWords(buffer, ret); 01611 01612 return ret; 01613 } 01614 01615 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx) 01616 { 01617 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){ 01618 memset(pGuid,0, sizeof(GUID)); 01619 return; 01620 } 01621 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset ); 01622 pGuid->Data1 = FromLEDWord(pGuid->Data1); 01623 pGuid->Data2 = FromLEWord(pGuid->Data2); 01624 pGuid->Data3 = FromLEWord(pGuid->Data3); 01625 TRACE_(typelib)("%s\n", debugstr_guid(pGuid)); 01626 } 01627 01628 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset ) 01629 { 01630 MSFT_NameIntro niName; 01631 01632 if (offset < 0) 01633 { 01634 ERR_(typelib)("bad offset %d\n", offset); 01635 return -1; 01636 } 01637 01638 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx, 01639 pcx->pTblDir->pNametab.offset+offset); 01640 01641 return niName.hreftype; 01642 } 01643 01644 static BSTR MSFT_ReadName( TLBContext *pcx, int offset) 01645 { 01646 char * name; 01647 MSFT_NameIntro niName; 01648 int lengthInChars; 01649 BSTR bstrName = NULL; 01650 01651 if (offset < 0) 01652 { 01653 ERR_(typelib)("bad offset %d\n", offset); 01654 return NULL; 01655 } 01656 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx, 01657 pcx->pTblDir->pNametab.offset+offset); 01658 niName.namelen &= 0xFF; /* FIXME: correct ? */ 01659 name=TLB_Alloc((niName.namelen & 0xff) +1); 01660 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK); 01661 name[niName.namelen & 0xff]='\0'; 01662 01663 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, 01664 name, -1, NULL, 0); 01665 01666 /* no invalid characters in string */ 01667 if (lengthInChars) 01668 { 01669 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR)); 01670 01671 /* don't check for invalid character since this has been done previously */ 01672 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars); 01673 } 01674 TLB_Free(name); 01675 01676 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars); 01677 return bstrName; 01678 } 01679 01680 static BSTR MSFT_ReadString( TLBContext *pcx, int offset) 01681 { 01682 char * string; 01683 INT16 length; 01684 int lengthInChars; 01685 BSTR bstr = NULL; 01686 01687 if(offset<0) return NULL; 01688 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset); 01689 if(length <= 0) return 0; 01690 string=TLB_Alloc(length +1); 01691 MSFT_Read(string, length, pcx, DO_NOT_SEEK); 01692 string[length]='\0'; 01693 01694 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, 01695 string, -1, NULL, 0); 01696 01697 /* no invalid characters in string */ 01698 if (lengthInChars) 01699 { 01700 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR)); 01701 01702 /* don't check for invalid character since this has been done previously */ 01703 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars); 01704 } 01705 TLB_Free(string); 01706 01707 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars); 01708 return bstr; 01709 } 01710 /* 01711 * read a value and fill a VARIANT structure 01712 */ 01713 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) 01714 { 01715 int size; 01716 01717 TRACE_(typelib)("\n"); 01718 01719 if(offset <0) { /* data are packed in here */ 01720 V_VT(pVar) = (offset & 0x7c000000 )>> 26; 01721 V_I4(pVar) = offset & 0x3ffffff; 01722 return; 01723 } 01724 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx, 01725 pcx->pTblDir->pCustData.offset + offset ); 01726 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar)); 01727 switch (V_VT(pVar)){ 01728 case VT_EMPTY: /* FIXME: is this right? */ 01729 case VT_NULL: /* FIXME: is this right? */ 01730 case VT_I2 : /* this should not happen */ 01731 case VT_I4 : 01732 case VT_R4 : 01733 case VT_ERROR : 01734 case VT_BOOL : 01735 case VT_I1 : 01736 case VT_UI1 : 01737 case VT_UI2 : 01738 case VT_UI4 : 01739 case VT_INT : 01740 case VT_UINT : 01741 case VT_VOID : /* FIXME: is this right? */ 01742 case VT_HRESULT : 01743 size=4; break; 01744 case VT_R8 : 01745 case VT_CY : 01746 case VT_DATE : 01747 case VT_I8 : 01748 case VT_UI8 : 01749 case VT_DECIMAL : /* FIXME: is this right? */ 01750 case VT_FILETIME : 01751 size=8;break; 01752 /* pointer types with known behaviour */ 01753 case VT_BSTR :{ 01754 char * ptr; 01755 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK ); 01756 if(size < 0) { 01757 char next; 01758 DWORD origPos = MSFT_Tell(pcx), nullPos; 01759 01760 do { 01761 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK); 01762 } while (next); 01763 nullPos = MSFT_Tell(pcx); 01764 size = nullPos - origPos; 01765 MSFT_Seek(pcx, origPos); 01766 } 01767 ptr=TLB_Alloc(size);/* allocate temp buffer */ 01768 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */ 01769 V_BSTR(pVar)=SysAllocStringLen(NULL,size); 01770 /* FIXME: do we need a AtoW conversion here? */ 01771 V_UNION(pVar, bstrVal[size])='\0'; 01772 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size]; 01773 TLB_Free(ptr); 01774 } 01775 size=-4; break; 01776 /* FIXME: this will not work AT ALL when the variant contains a pointer */ 01777 case VT_DISPATCH : 01778 case VT_VARIANT : 01779 case VT_UNKNOWN : 01780 case VT_PTR : 01781 case VT_SAFEARRAY : 01782 case VT_CARRAY : 01783 case VT_USERDEFINED : 01784 case VT_LPSTR : 01785 case VT_LPWSTR : 01786 case VT_BLOB : 01787 case VT_STREAM : 01788 case VT_STORAGE : 01789 case VT_STREAMED_OBJECT : 01790 case VT_STORED_OBJECT : 01791 case VT_BLOB_OBJECT : 01792 case VT_CF : 01793 case VT_CLSID : 01794 default: 01795 size=0; 01796 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n", 01797 V_VT(pVar)); 01798 } 01799 01800 if(size>0) /* (big|small) endian correct? */ 01801 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK ); 01802 return; 01803 } 01804 /* 01805 * create a linked list with custom data 01806 */ 01807 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData ) 01808 { 01809 MSFT_CDGuid entry; 01810 TLBCustData* pNew; 01811 int count=0; 01812 01813 TRACE_(typelib)("\n"); 01814 01815 while(offset >=0){ 01816 count++; 01817 pNew=TLB_Alloc(sizeof(TLBCustData)); 01818 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset); 01819 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx); 01820 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx); 01821 /* add new custom data at head of the list */ 01822 pNew->next=*ppCustData; 01823 *ppCustData=pNew; 01824 offset = entry.next; 01825 } 01826 return count; 01827 } 01828 01829 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd, 01830 ITypeInfoImpl *pTI) 01831 { 01832 if(type <0) 01833 pTd->vt=type & VT_TYPEMASK; 01834 else 01835 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))]; 01836 01837 if(pTd->vt == VT_USERDEFINED) 01838 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype); 01839 01840 TRACE_(typelib)("vt type = %X\n", pTd->vt); 01841 } 01842 01843 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc) 01844 { 01845 /* resolve referenced type if any */ 01846 while (lpTypeDesc) 01847 { 01848 switch (lpTypeDesc->vt) 01849 { 01850 case VT_PTR: 01851 lpTypeDesc = lpTypeDesc->u.lptdesc; 01852 break; 01853 01854 case VT_CARRAY: 01855 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem); 01856 break; 01857 01858 case VT_USERDEFINED: 01859 MSFT_DoRefType(pcx, pTI->pTypeLib, 01860 lpTypeDesc->u.hreftype); 01861 01862 lpTypeDesc = NULL; 01863 break; 01864 01865 default: 01866 lpTypeDesc = NULL; 01867 } 01868 } 01869 } 01870 01871 static void 01872 MSFT_DoFuncs(TLBContext* pcx, 01873 ITypeInfoImpl* pTI, 01874 int cFuncs, 01875 int cVars, 01876 int offset, 01877 TLBFuncDesc** pptfd) 01878 { 01879 /* 01880 * member information is stored in a data structure at offset 01881 * indicated by the memoffset field of the typeinfo structure 01882 * There are several distinctive parts. 01883 * The first part starts with a field that holds the total length 01884 * of this (first) part excluding this field. Then follow the records, 01885 * for each member there is one record. 01886 * 01887 * The first entry is always the length of the record (including this 01888 * length word). 01889 * The rest of the record depends on the type of the member. If there is 01890 * a field indicating the member type (function, variable, interface, etc) 01891 * I have not found it yet. At this time we depend on the information 01892 * in the type info and the usual order how things are stored. 01893 * 01894 * Second follows an array sized nrMEM*sizeof(INT) with a member id 01895 * for each member; 01896 * 01897 * Third is an equal sized array with file offsets to the name entry 01898 * of each member. 01899 * 01900 * The fourth and last (?) part is an array with offsets to the records 01901 * in the first part of this file segment. 01902 */ 01903 01904 int infolen, nameoffset, reclength, nrattributes, i; 01905 int recoffset = offset + sizeof(INT); 01906 01907 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff); 01908 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf; 01909 TLBFuncDesc *ptfd_prev = NULL; 01910 01911 TRACE_(typelib)("\n"); 01912 01913 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset); 01914 01915 for ( i = 0; i < cFuncs ; i++ ) 01916 { 01917 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc)); 01918 01919 /* name, eventually add to a hash table */ 01920 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx, 01921 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT)); 01922 01923 /* nameoffset is sometimes -1 on the second half of a propget/propput 01924 * pair of functions */ 01925 if ((nameoffset == -1) && (i > 0)) 01926 (*pptfd)->Name = SysAllocString(ptfd_prev->Name); 01927 else 01928 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset); 01929 01930 /* read the function information record */ 01931 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset); 01932 01933 reclength &= 0xffff; 01934 01935 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK); 01936 01937 /* do the attributes */ 01938 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18) 01939 / sizeof(int); 01940 01941 if ( nrattributes > 0 ) 01942 { 01943 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ; 01944 01945 if ( nrattributes > 1 ) 01946 { 01947 (*pptfd)->HelpString = MSFT_ReadString(pcx, 01948 pFuncRec->OptAttr[1]) ; 01949 01950 if ( nrattributes > 2 ) 01951 { 01952 if ( pFuncRec->FKCCIC & 0x2000 ) 01953 { 01954 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2])) 01955 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]); 01956 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->OptAttr[2]); 01957 } 01958 else 01959 { 01960 (*pptfd)->Entry = MSFT_ReadString(pcx, 01961 pFuncRec->OptAttr[2]); 01962 } 01963 if( nrattributes > 5 ) 01964 { 01965 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ; 01966 01967 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 ) 01968 { 01969 MSFT_CustData(pcx, 01970 pFuncRec->OptAttr[6], 01971 &(*pptfd)->pCustData); 01972 } 01973 } 01974 } 01975 else 01976 { 01977 (*pptfd)->Entry = (BSTR)-1; 01978 } 01979 } 01980 } 01981 01982 /* fill the FuncDesc Structure */ 01983 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx, 01984 offset + infolen + ( i + 1) * sizeof(INT)); 01985 01986 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7; 01987 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF; 01988 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF; 01989 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ; 01990 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ; 01991 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset; 01992 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ; 01993 01994 MSFT_GetTdesc(pcx, 01995 pFuncRec->DataType, 01996 &(*pptfd)->funcdesc.elemdescFunc.tdesc, 01997 pTI); 01998 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc); 01999 02000 /* do the parameters/arguments */ 02001 if(pFuncRec->nrargs) 02002 { 02003 int j = 0; 02004 MSFT_ParameterInfo paraminfo; 02005 02006 (*pptfd)->funcdesc.lprgelemdescParam = 02007 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC)); 02008 02009 (*pptfd)->pParamDesc = 02010 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc)); 02011 02012 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx, 02013 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo)); 02014 02015 for ( j = 0 ; j < pFuncRec->nrargs ; j++ ) 02016 { 02017 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j]; 02018 02019 MSFT_GetTdesc(pcx, 02020 paraminfo.DataType, 02021 &elemdesc->tdesc, 02022 pTI); 02023 02024 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags; 02025 02026 /* name */ 02027 if (paraminfo.oName == -1) 02028 /* this occurs for [propput] or [propget] methods, so 02029 * we should just set the name of the parameter to the 02030 * name of the method. */ 02031 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name); 02032 else 02033 (*pptfd)->pParamDesc[j].Name = 02034 MSFT_ReadName( pcx, paraminfo.oName ); 02035 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name)); 02036 02037 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc); 02038 02039 /* default value */ 02040 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) && 02041 (pFuncRec->FKCCIC & 0x1000) ) 02042 { 02043 INT* pInt = (INT *)((char *)pFuncRec + 02044 reclength - 02045 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) ); 02046 02047 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc; 02048 02049 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX)); 02050 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX); 02051 02052 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue), 02053 pInt[j], pcx); 02054 } 02055 else 02056 elemdesc->u.paramdesc.pparamdescex = NULL; 02057 /* custom info */ 02058 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 ) 02059 { 02060 MSFT_CustData(pcx, 02061 pFuncRec->OptAttr[7+j], 02062 &(*pptfd)->pParamDesc[j].pCustData); 02063 } 02064 02065 /* SEEK value = jump to offset, 02066 * from there jump to the end of record, 02067 * go back by (j-1) arguments 02068 */ 02069 MSFT_ReadLEDWords( ¶minfo , 02070 sizeof(MSFT_ParameterInfo), pcx, 02071 recoffset + reclength - ((pFuncRec->nrargs - j - 1) 02072 * sizeof(MSFT_ParameterInfo))); 02073 } 02074 } 02075 02076 /* scode is not used: archaic win16 stuff FIXME: right? */ 02077 (*pptfd)->funcdesc.cScodes = 0 ; 02078 (*pptfd)->funcdesc.lprgscode = NULL ; 02079 02080 ptfd_prev = *pptfd; 02081 pptfd = & ((*pptfd)->next); 02082 recoffset += reclength; 02083 } 02084 HeapFree(GetProcessHeap(), 0, recbuf); 02085 } 02086 02087 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs, 02088 int cVars, int offset, TLBVarDesc ** pptvd) 02089 { 02090 int infolen, nameoffset, reclength; 02091 char recbuf[256]; 02092 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf; 02093 int i; 02094 int recoffset; 02095 02096 TRACE_(typelib)("\n"); 02097 02098 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset); 02099 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen + 02100 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT)); 02101 recoffset += offset+sizeof(INT); 02102 for(i=0;i<cVars;i++){ 02103 *pptvd=TLB_Alloc(sizeof(TLBVarDesc)); 02104 /* name, eventually add to a hash table */ 02105 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx, 02106 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT)); 02107 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset); 02108 /* read the variable information record */ 02109 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset); 02110 reclength &=0xff; 02111 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK); 02112 /* Optional data */ 02113 if(reclength >(6*sizeof(INT)) ) 02114 (*pptvd)->HelpContext=pVarRec->HelpContext; 02115 if(reclength >(7*sizeof(INT)) ) 02116 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ; 02117 if(reclength >(8*sizeof(INT)) ) 02118 if(reclength >(9*sizeof(INT)) ) 02119 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext; 02120 /* fill the VarDesc Structure */ 02121 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx, 02122 offset + infolen + (cFuncs + i + 1) * sizeof(INT)); 02123 (*pptvd)->vardesc.varkind = pVarRec->VarKind; 02124 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags; 02125 MSFT_GetTdesc(pcx, pVarRec->DataType, 02126 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI); 02127 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */ 02128 if(pVarRec->VarKind == VAR_CONST ){ 02129 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT)); 02130 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue, 02131 pVarRec->OffsValue, pcx); 02132 } else 02133 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue; 02134 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc); 02135 pptvd=&((*pptvd)->next); 02136 recoffset += reclength; 02137 } 02138 } 02139 /* fill in data for a hreftype (offset). When the referenced type is contained 02140 * in the typelib, it's just an (file) offset in the type info base dir. 02141 * If comes from import, it's an offset+1 in the ImpInfo table 02142 * */ 02143 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, 02144 int offset) 02145 { 02146 TLBRefType *ref; 02147 02148 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset); 02149 02150 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry) 02151 { 02152 if(ref->reference == offset) return; 02153 } 02154 02155 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref)); 02156 list_add_tail(&pTL->ref_list, &ref->entry); 02157 02158 if(!MSFT_HREFTYPE_INTHISFILE( offset)) { 02159 /* external typelib */ 02160 MSFT_ImpInfo impinfo; 02161 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs); 02162 02163 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc)); 02164 02165 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, 02166 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc)); 02167 while (pImpLib){ /* search the known offsets of all import libraries */ 02168 if(pImpLib->offset==impinfo.oImpFile) break; 02169 pImpLib=pImpLib->next; 02170 } 02171 if(pImpLib){ 02172 ref->reference = offset; 02173 ref->pImpTLInfo = pImpLib; 02174 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) { 02175 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx); 02176 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid)); 02177 ref->index = TLB_REF_USE_GUID; 02178 } else 02179 ref->index = impinfo.oGuid; 02180 }else{ 02181 ERR("Cannot find a reference\n"); 02182 ref->reference = -1; 02183 ref->pImpTLInfo = TLB_REF_NOT_FOUND; 02184 } 02185 }else{ 02186 /* in this typelib */ 02187 ref->index = MSFT_HREFTYPE_INDEX(offset); 02188 ref->reference = offset; 02189 ref->pImpTLInfo = TLB_REF_INTERNAL; 02190 } 02191 } 02192 02193 /* process Implemented Interfaces of a com class */ 02194 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count, 02195 int offset) 02196 { 02197 int i; 02198 MSFT_RefRecord refrec; 02199 TLBImplType **ppImpl = &pTI->impltypelist; 02200 02201 TRACE_(typelib)("\n"); 02202 02203 for(i=0;i<count;i++){ 02204 if(offset<0) break; /* paranoia */ 02205 *ppImpl=TLB_Alloc(sizeof(**ppImpl)); 02206 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset); 02207 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype); 02208 (*ppImpl)->hRef = refrec.reftype; 02209 (*ppImpl)->implflags=refrec.flags; 02210 (*ppImpl)->ctCustData= 02211 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData); 02212 offset=refrec.onext; 02213 ppImpl=&((*ppImpl)->next); 02214 } 02215 } 02216 /* 02217 * process a typeinfo record 02218 */ 02219 static ITypeInfoImpl * MSFT_DoTypeInfo( 02220 TLBContext *pcx, 02221 int count, 02222 ITypeLibImpl * pLibInfo) 02223 { 02224 MSFT_TypeInfoBase tiBase; 02225 ITypeInfoImpl *ptiRet; 02226 02227 TRACE_(typelib)("count=%u\n", count); 02228 02229 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor(); 02230 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx , 02231 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase)); 02232 02233 /* this is where we are coming from */ 02234 ptiRet->pTypeLib = pLibInfo; 02235 ptiRet->index=count; 02236 /* fill in the typeattr fields */ 02237 02238 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx); 02239 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */ 02240 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */ 02241 ptiRet->TypeAttr.cbSizeInstance=tiBase.size; 02242 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF; 02243 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement); 02244 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement); 02245 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */ 02246 ptiRet->TypeAttr.wTypeFlags=tiBase.flags; 02247 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version); 02248 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version); 02249 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes; 02250 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */ 02251 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS) 02252 MSFT_GetTdesc(pcx, tiBase.datatype1, 02253 &ptiRet->TypeAttr.tdescAlias, ptiRet); 02254 02255 /* FIXME: */ 02256 /* IDLDESC idldescType; *//* never saw this one != zero */ 02257 02258 /* name, eventually add to a hash table */ 02259 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset); 02260 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset); 02261 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name)); 02262 /* help info */ 02263 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs); 02264 ptiRet->dwHelpStringContext=tiBase.helpstringcontext; 02265 ptiRet->dwHelpContext=tiBase.helpcontext; 02266 02267 if (ptiRet->TypeAttr.typekind == TKIND_MODULE) 02268 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1); 02269 02270 /* note: InfoType's Help file and HelpStringDll come from the containing 02271 * library. Further HelpString and Docstring appear to be the same thing :( 02272 */ 02273 /* functions */ 02274 if(ptiRet->TypeAttr.cFuncs >0 ) 02275 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs, 02276 ptiRet->TypeAttr.cVars, 02277 tiBase.memoffset, & ptiRet->funclist); 02278 /* variables */ 02279 if(ptiRet->TypeAttr.cVars >0 ) 02280 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs, 02281 ptiRet->TypeAttr.cVars, 02282 tiBase.memoffset, & ptiRet->varlist); 02283 if(ptiRet->TypeAttr.cImplTypes >0 ) { 02284 switch(ptiRet->TypeAttr.typekind) 02285 { 02286 case TKIND_COCLASS: 02287 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes , 02288 tiBase.datatype1); 02289 break; 02290 case TKIND_DISPATCH: 02291 /* This is not -1 when the interface is a non-base dual interface or 02292 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'. 02293 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and 02294 not this interface. 02295 */ 02296 02297 if (tiBase.datatype1 != -1) 02298 { 02299 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType)); 02300 ptiRet->impltypelist->hRef = tiBase.datatype1; 02301 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1); 02302 } 02303 break; 02304 default: 02305 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType)); 02306 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1); 02307 ptiRet->impltypelist->hRef = tiBase.datatype1; 02308 break; 02309 } 02310 } 02311 ptiRet->ctCustData= 02312 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData); 02313 02314 TRACE_(typelib)("%s guid: %s kind:%s\n", 02315 debugstr_w(ptiRet->Name), 02316 debugstr_guid(&ptiRet->TypeAttr.guid), 02317 typekind_desc[ptiRet->TypeAttr.typekind]); 02318 if (TRACE_ON(typelib)) 02319 dump_TypeInfo(ptiRet); 02320 02321 return ptiRet; 02322 } 02323 02324 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same 02325 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in 02326 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable 02327 * tradeoff here. 02328 */ 02329 static ITypeLibImpl *tlb_cache_first; 02330 static CRITICAL_SECTION cache_section; 02331 static CRITICAL_SECTION_DEBUG cache_section_debug = 02332 { 02333 0, 0, &cache_section, 02334 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList }, 02335 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") } 02336 }; 02337 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 }; 02338 02339 02340 typedef struct TLB_PEFile 02341 { 02342 const IUnknownVtbl *lpvtbl; 02343 LONG refs; 02344 HMODULE dll; 02345 HRSRC typelib_resource; 02346 HGLOBAL typelib_global; 02347 LPVOID typelib_base; 02348 } TLB_PEFile; 02349 02350 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 02351 { 02352 if (IsEqualIID(riid, &IID_IUnknown)) 02353 { 02354 *ppv = iface; 02355 IUnknown_AddRef(iface); 02356 return S_OK; 02357 } 02358 *ppv = NULL; 02359 return E_NOINTERFACE; 02360 } 02361 02362 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface) 02363 { 02364 TLB_PEFile *This = (TLB_PEFile *)iface; 02365 return InterlockedIncrement(&This->refs); 02366 } 02367 02368 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface) 02369 { 02370 TLB_PEFile *This = (TLB_PEFile *)iface; 02371 ULONG refs = InterlockedDecrement(&This->refs); 02372 if (!refs) 02373 { 02374 if (This->typelib_global) 02375 FreeResource(This->typelib_global); 02376 if (This->dll) 02377 FreeLibrary(This->dll); 02378 HeapFree(GetProcessHeap(), 0, This); 02379 } 02380 return refs; 02381 } 02382 02383 static const IUnknownVtbl TLB_PEFile_Vtable = 02384 { 02385 TLB_PEFile_QueryInterface, 02386 TLB_PEFile_AddRef, 02387 TLB_PEFile_Release 02388 }; 02389 02390 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile) 02391 { 02392 TLB_PEFile *This; 02393 02394 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 02395 if (!This) 02396 return E_OUTOFMEMORY; 02397 02398 This->lpvtbl = &TLB_PEFile_Vtable; 02399 This->refs = 1; 02400 This->dll = NULL; 02401 This->typelib_resource = NULL; 02402 This->typelib_global = NULL; 02403 This->typelib_base = NULL; 02404 02405 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES | 02406 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH); 02407 02408 if (This->dll) 02409 { 02410 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0}; 02411 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW); 02412 if (This->typelib_resource) 02413 { 02414 This->typelib_global = LoadResource(This->dll, This->typelib_resource); 02415 if (This->typelib_global) 02416 { 02417 This->typelib_base = LockResource(This->typelib_global); 02418 02419 if (This->typelib_base) 02420 { 02421 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource); 02422 *ppBase = This->typelib_base; 02423 *ppFile = (IUnknown *)&This->lpvtbl; 02424 return S_OK; 02425 } 02426 } 02427 } 02428 } 02429 02430 TLB_PEFile_Release((IUnknown *)&This->lpvtbl); 02431 return TYPE_E_CANTLOADLIBRARY; 02432 } 02433 02434 typedef struct TLB_NEFile 02435 { 02436 const IUnknownVtbl *lpvtbl; 02437 LONG refs; 02438 LPVOID typelib_base; 02439 } TLB_NEFile; 02440 02441 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 02442 { 02443 if (IsEqualIID(riid, &IID_IUnknown)) 02444 { 02445 *ppv = iface; 02446 IUnknown_AddRef(iface); 02447 return S_OK; 02448 } 02449 *ppv = NULL; 02450 return E_NOINTERFACE; 02451 } 02452 02453 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface) 02454 { 02455 TLB_NEFile *This = (TLB_NEFile *)iface; 02456 return InterlockedIncrement(&This->refs); 02457 } 02458 02459 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface) 02460 { 02461 TLB_NEFile *This = (TLB_NEFile *)iface; 02462 ULONG refs = InterlockedDecrement(&This->refs); 02463 if (!refs) 02464 { 02465 HeapFree(GetProcessHeap(), 0, This->typelib_base); 02466 HeapFree(GetProcessHeap(), 0, This); 02467 } 02468 return refs; 02469 } 02470 02471 static const IUnknownVtbl TLB_NEFile_Vtable = 02472 { 02473 TLB_NEFile_QueryInterface, 02474 TLB_NEFile_AddRef, 02475 TLB_NEFile_Release 02476 }; 02477 02478 /*********************************************************************** 02479 * read_xx_header [internal] 02480 */ 02481 static int read_xx_header( HFILE lzfd ) 02482 { 02483 IMAGE_DOS_HEADER mzh; 02484 char magic[3]; 02485 02486 LZSeek( lzfd, 0, SEEK_SET ); 02487 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) ) 02488 return 0; 02489 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE ) 02490 return 0; 02491 02492 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET ); 02493 if ( 2 != LZRead( lzfd, magic, 2 ) ) 02494 return 0; 02495 02496 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET ); 02497 02498 if ( magic[0] == 'N' && magic[1] == 'E' ) 02499 return IMAGE_OS2_SIGNATURE; 02500 if ( magic[0] == 'P' && magic[1] == 'E' ) 02501 return IMAGE_NT_SIGNATURE; 02502 02503 magic[2] = '\0'; 02504 WARN("Can't handle %s files.\n", magic ); 02505 return 0; 02506 } 02507 02508 02509 /*********************************************************************** 02510 * find_ne_resource [internal] 02511 */ 02512 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid, 02513 DWORD *resLen, DWORD *resOff ) 02514 { 02515 IMAGE_OS2_HEADER nehd; 02516 NE_TYPEINFO *typeInfo; 02517 NE_NAMEINFO *nameInfo; 02518 DWORD nehdoffset; 02519 LPBYTE resTab; 02520 DWORD resTabSize; 02521 int count; 02522 02523 /* Read in NE header */ 02524 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR ); 02525 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0; 02526 02527 resTabSize = nehd.ne_restab - nehd.ne_rsrctab; 02528 if ( !resTabSize ) 02529 { 02530 TRACE("No resources in NE dll\n" ); 02531 return FALSE; 02532 } 02533 02534 /* Read in resource table */ 02535 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize ); 02536 if ( !resTab ) return FALSE; 02537 02538 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET ); 02539 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) ) 02540 { 02541 HeapFree( GetProcessHeap(), 0, resTab ); 02542 return FALSE; 02543 } 02544 02545 /* Find resource */ 02546 typeInfo = (NE_TYPEINFO *)(resTab + 2); 02547 02548 if (!IS_INTRESOURCE(typeid)) /* named type */ 02549 { 02550 BYTE len = strlen( typeid ); 02551 while (typeInfo->type_id) 02552 { 02553 if (!(typeInfo->type_id & 0x8000)) 02554 { 02555 BYTE *p = resTab + typeInfo->type_id; 02556 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type; 02557 } 02558 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) + 02559 typeInfo->count * sizeof(NE_NAMEINFO)); 02560 } 02561 } 02562 else /* numeric type id */ 02563 { 02564 WORD id = LOWORD(typeid) | 0x8000; 02565 while (typeInfo->type_id) 02566 { 02567 if (typeInfo->type_id == id) goto found_type; 02568 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) + 02569 typeInfo->count * sizeof(NE_NAMEINFO)); 02570 } 02571 } 02572 TRACE("No typeid entry found for %p\n", typeid ); 02573 HeapFree( GetProcessHeap(), 0, resTab ); 02574 return FALSE; 02575 02576 found_type: 02577 nameInfo = (NE_NAMEINFO *)(typeInfo + 1); 02578 02579 if (!IS_INTRESOURCE(resid)) /* named resource */ 02580 { 02581 BYTE len = strlen( resid ); 02582 for (count = typeInfo->count; count > 0; count--, nameInfo++) 02583 { 02584 BYTE *p = resTab + nameInfo->id; 02585 if (nameInfo->id & 0x8000) continue; 02586 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name; 02587 } 02588 } 02589 else /* numeric resource id */ 02590 { 02591 WORD id = LOWORD(resid) | 0x8000; 02592 for (count = typeInfo->count; count > 0; count--, nameInfo++) 02593 if (nameInfo->id == id) goto found_name; 02594 } 02595 TRACE("No resid entry found for %p\n", typeid ); 02596 HeapFree( GetProcessHeap(), 0, resTab ); 02597 return FALSE; 02598 02599 found_name: 02600 /* Return resource data */ 02601 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab; 02602 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab; 02603 02604 HeapFree( GetProcessHeap(), 0, resTab ); 02605 return TRUE; 02606 } 02607 02608 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){ 02609 02610 HFILE lzfd = -1; 02611 OFSTRUCT ofs; 02612 HRESULT hr = TYPE_E_CANTLOADLIBRARY; 02613 TLB_NEFile *This = NULL; 02614 02615 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 02616 if (!This) return E_OUTOFMEMORY; 02617 02618 This->lpvtbl = &TLB_NEFile_Vtable; 02619 This->refs = 1; 02620 This->typelib_base = NULL; 02621 02622 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ ); 02623 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE ) 02624 { 02625 DWORD reslen, offset; 02626 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) ) 02627 { 02628 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen); 02629 if( !This->typelib_base ) 02630 hr = E_OUTOFMEMORY; 02631 else 02632 { 02633 LZSeek( lzfd, offset, SEEK_SET ); 02634 reslen = LZRead( lzfd, This->typelib_base, reslen ); 02635 LZClose( lzfd ); 02636 *ppBase = This->typelib_base; 02637 *pdwTLBLength = reslen; 02638 *ppFile = (IUnknown *)&This->lpvtbl; 02639 return S_OK; 02640 } 02641 } 02642 } 02643 02644 if( lzfd >= 0) LZClose( lzfd ); 02645 TLB_NEFile_Release((IUnknown *)&This->lpvtbl); 02646 return hr; 02647 } 02648 02649 typedef struct TLB_Mapping 02650 { 02651 const IUnknownVtbl *lpvtbl; 02652 LONG refs; 02653 HANDLE file; 02654 HANDLE mapping; 02655 LPVOID typelib_base; 02656 } TLB_Mapping; 02657 02658 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 02659 { 02660 if (IsEqualIID(riid, &IID_IUnknown)) 02661 { 02662 *ppv = iface; 02663 IUnknown_AddRef(iface); 02664 return S_OK; 02665 } 02666 *ppv = NULL; 02667 return E_NOINTERFACE; 02668 } 02669 02670 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface) 02671 { 02672 TLB_Mapping *This = (TLB_Mapping *)iface; 02673 return InterlockedIncrement(&This->refs); 02674 } 02675 02676 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface) 02677 { 02678 TLB_Mapping *This = (TLB_Mapping *)iface; 02679 ULONG refs = InterlockedDecrement(&This->refs); 02680 if (!refs) 02681 { 02682 if (This->typelib_base) 02683 UnmapViewOfFile(This->typelib_base); 02684 if (This->mapping) 02685 CloseHandle(This->mapping); 02686 if (This->file != INVALID_HANDLE_VALUE) 02687 CloseHandle(This->file); 02688 HeapFree(GetProcessHeap(), 0, This); 02689 } 02690 return refs; 02691 } 02692 02693 static const IUnknownVtbl TLB_Mapping_Vtable = 02694 { 02695 TLB_Mapping_QueryInterface, 02696 TLB_Mapping_AddRef, 02697 TLB_Mapping_Release 02698 }; 02699 02700 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile) 02701 { 02702 TLB_Mapping *This; 02703 02704 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 02705 if (!This) 02706 return E_OUTOFMEMORY; 02707 02708 This->lpvtbl = &TLB_Mapping_Vtable; 02709 This->refs = 1; 02710 This->file = INVALID_HANDLE_VALUE; 02711 This->mapping = NULL; 02712 This->typelib_base = NULL; 02713 02714 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 02715 if (INVALID_HANDLE_VALUE != This->file) 02716 { 02717 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 02718 if (This->mapping) 02719 { 02720 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0); 02721 if(This->typelib_base) 02722 { 02723 /* retrieve file size */ 02724 *pdwTLBLength = GetFileSize(This->file, NULL); 02725 *ppBase = This->typelib_base; 02726 *ppFile = (IUnknown *)&This->lpvtbl; 02727 return S_OK; 02728 } 02729 } 02730 } 02731 02732 IUnknown_Release((IUnknown *)&This->lpvtbl); 02733 return TYPE_E_CANTLOADLIBRARY; 02734 } 02735 02736 /**************************************************************************** 02737 * TLB_ReadTypeLib 02738 * 02739 * find the type of the typelib file and map the typelib resource into 02740 * the memory 02741 */ 02742 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */ 02743 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */ 02744 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib) 02745 { 02746 ITypeLibImpl *entry; 02747 HRESULT ret; 02748 INT index = 1; 02749 LPWSTR index_str, file = (LPWSTR)pszFileName; 02750 LPVOID pBase = NULL; 02751 DWORD dwTLBLength = 0; 02752 IUnknown *pFile = NULL; 02753 02754 *ppTypeLib = NULL; 02755 02756 index_str = strrchrW(pszFileName, '\\'); 02757 if(index_str && *++index_str != '\0') 02758 { 02759 LPWSTR end_ptr; 02760 LONG idx = strtolW(index_str, &end_ptr, 10); 02761 if(*end_ptr == '\0') 02762 { 02763 int str_len = index_str - pszFileName - 1; 02764 index = idx; 02765 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR)); 02766 memcpy(file, pszFileName, str_len * sizeof(WCHAR)); 02767 file[str_len] = 0; 02768 } 02769 } 02770 02771 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL)) 02772 { 02773 if(strchrW(file, '\\')) 02774 { 02775 lstrcpyW(pszPath, file); 02776 } 02777 else 02778 { 02779 int len = GetSystemDirectoryW(pszPath, cchPath); 02780 pszPath[len] = '\\'; 02781 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR)); 02782 } 02783 } 02784 02785 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file); 02786 02787 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index); 02788 02789 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */ 02790 EnterCriticalSection(&cache_section); 02791 for (entry = tlb_cache_first; entry != NULL; entry = entry->next) 02792 { 02793 if (!strcmpiW(entry->path, pszPath) && entry->index == index) 02794 { 02795 TRACE("cache hit\n"); 02796 *ppTypeLib = (ITypeLib2*)entry; 02797 ITypeLib_AddRef(*ppTypeLib); 02798 LeaveCriticalSection(&cache_section); 02799 return S_OK; 02800 } 02801 } 02802 LeaveCriticalSection(&cache_section); 02803 02804 /* now actually load and parse the typelib */ 02805 02806 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile); 02807 if (ret == TYPE_E_CANTLOADLIBRARY) 02808 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile); 02809 if (ret == TYPE_E_CANTLOADLIBRARY) 02810 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile); 02811 if (SUCCEEDED(ret)) 02812 { 02813 if (dwTLBLength >= 4) 02814 { 02815 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase)); 02816 if (dwSignature == MSFT_SIGNATURE) 02817 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); 02818 else if (dwSignature == SLTG_SIGNATURE) 02819 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); 02820 else 02821 { 02822 FIXME("Header type magic 0x%08x not supported.\n",dwSignature); 02823 ret = TYPE_E_CANTLOADLIBRARY; 02824 } 02825 } 02826 else 02827 ret = TYPE_E_CANTLOADLIBRARY; 02828 IUnknown_Release(pFile); 02829 } 02830 02831 if(*ppTypeLib) { 02832 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib; 02833 02834 TRACE("adding to cache\n"); 02835 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR)); 02836 lstrcpyW(impl->path, pszPath); 02837 /* We should really canonicalise the path here. */ 02838 impl->index = index; 02839 02840 /* FIXME: check if it has added already in the meantime */ 02841 EnterCriticalSection(&cache_section); 02842 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl; 02843 impl->prev = NULL; 02844 tlb_cache_first = impl; 02845 LeaveCriticalSection(&cache_section); 02846 ret = S_OK; 02847 } else 02848 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError()); 02849 02850 return ret; 02851 } 02852 02853 /*================== ITypeLib(2) Methods ===================================*/ 02854 02855 static ITypeLibImpl* TypeLibImpl_Constructor(void) 02856 { 02857 ITypeLibImpl* pTypeLibImpl; 02858 02859 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl)); 02860 if (!pTypeLibImpl) return NULL; 02861 02862 pTypeLibImpl->lpVtbl = &tlbvt; 02863 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt; 02864 pTypeLibImpl->ref = 1; 02865 02866 list_init(&pTypeLibImpl->ref_list); 02867 pTypeLibImpl->dispatch_href = -1; 02868 02869 return pTypeLibImpl; 02870 } 02871 02872 /**************************************************************************** 02873 * ITypeLib2_Constructor_MSFT 02874 * 02875 * loading an MSFT typelib from an in-memory image 02876 */ 02877 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength) 02878 { 02879 TLBContext cx; 02880 LONG lPSegDir; 02881 MSFT_Header tlbHeader; 02882 MSFT_SegDir tlbSegDir; 02883 ITypeLibImpl * pTypeLibImpl; 02884 02885 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength); 02886 02887 pTypeLibImpl = TypeLibImpl_Constructor(); 02888 if (!pTypeLibImpl) return NULL; 02889 02890 /* get pointer to beginning of typelib data */ 02891 cx.pos = 0; 02892 cx.oStart=0; 02893 cx.mapping = pLib; 02894 cx.pLibInfo = pTypeLibImpl; 02895 cx.length = dwTLBLength; 02896 02897 /* read header */ 02898 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0); 02899 TRACE_(typelib)("header:\n"); 02900 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 ); 02901 if (tlbHeader.magic1 != MSFT_SIGNATURE) { 02902 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1); 02903 return NULL; 02904 } 02905 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos); 02906 02907 /* there is a small amount of information here until the next important 02908 * part: 02909 * the segment directory . Try to calculate the amount of data */ 02910 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0); 02911 02912 /* now read the segment directory */ 02913 TRACE("read segment directory (at %d)\n",lPSegDir); 02914 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir); 02915 cx.pTblDir = &tlbSegDir; 02916 02917 /* just check two entries */ 02918 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F) 02919 { 02920 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir); 02921 HeapFree(GetProcessHeap(),0,pTypeLibImpl); 02922 return NULL; 02923 } 02924 02925 /* now fill our internal data */ 02926 /* TLIBATTR fields */ 02927 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx); 02928 02929 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2; 02930 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */ 02931 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version); 02932 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version); 02933 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */ 02934 02935 pTypeLibImpl->lcid = tlbHeader.lcid; 02936 02937 /* name, eventually add to a hash table */ 02938 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset); 02939 02940 /* help info */ 02941 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring); 02942 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile); 02943 02944 if( tlbHeader.varflags & HELPDLLFLAG) 02945 { 02946 int offset; 02947 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader)); 02948 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset); 02949 } 02950 02951 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext; 02952 02953 /* custom data */ 02954 if(tlbHeader.CustomDataOffset >= 0) 02955 { 02956 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData); 02957 } 02958 02959 /* fill in type descriptions */ 02960 if(tlbSegDir.pTypdescTab.length > 0) 02961 { 02962 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT)); 02963 INT16 td[4]; 02964 pTypeLibImpl->ctTypeDesc = cTD; 02965 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC)); 02966 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset); 02967 for(i=0; i<cTD; ) 02968 { 02969 /* FIXME: add several sanity checks here */ 02970 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK; 02971 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY) 02972 { 02973 /* FIXME: check safearray */ 02974 if(td[3] < 0) 02975 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]]; 02976 else 02977 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8]; 02978 } 02979 else if(td[0] == VT_CARRAY) 02980 { 02981 /* array descr table here */ 02982 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/ 02983 } 02984 else if(td[0] == VT_USERDEFINED) 02985 { 02986 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]); 02987 } 02988 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK); 02989 } 02990 02991 /* second time around to fill the array subscript info */ 02992 for(i=0;i<cTD;i++) 02993 { 02994 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue; 02995 if(tlbSegDir.pArrayDescriptions.offset>0) 02996 { 02997 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc); 02998 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1)); 02999 03000 if(td[1]<0) 03001 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK; 03002 else 03003 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))]; 03004 03005 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2]; 03006 03007 for(j = 0; j<td[2]; j++) 03008 { 03009 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements, 03010 sizeof(INT), &cx, DO_NOT_SEEK); 03011 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound, 03012 sizeof(INT), &cx, DO_NOT_SEEK); 03013 } 03014 } 03015 else 03016 { 03017 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL; 03018 ERR("didn't find array description data\n"); 03019 } 03020 } 03021 } 03022 03023 /* imported type libs */ 03024 if(tlbSegDir.pImpFiles.offset>0) 03025 { 03026 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs); 03027 int oGuid, offset = tlbSegDir.pImpFiles.offset; 03028 UINT16 size; 03029 03030 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length) 03031 { 03032 char *name; 03033 03034 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib)); 03035 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset; 03036 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset); 03037 03038 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK); 03039 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK); 03040 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK); 03041 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK); 03042 03043 size >>= 2; 03044 name = TLB_Alloc(size+1); 03045 MSFT_Read(name, size, &cx, DO_NOT_SEEK); 03046 (*ppImpLib)->name = TLB_MultiByteToBSTR(name); 03047 TLB_Free(name); 03048 03049 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx); 03050 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3; 03051 03052 ppImpLib = &(*ppImpLib)->next; 03053 } 03054 } 03055 03056 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos; 03057 if(pTypeLibImpl->dispatch_href != -1) 03058 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href); 03059 03060 /* type info's */ 03061 if(tlbHeader.nrtypeinfos >= 0 ) 03062 { 03063 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */ 03064 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo); 03065 int i; 03066 03067 for(i = 0; i < tlbHeader.nrtypeinfos; i++) 03068 { 03069 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl); 03070 03071 ppTI = &((*ppTI)->next); 03072 (pTypeLibImpl->TypeInfoCount)++; 03073 } 03074 } 03075 03076 TRACE("(%p)\n", pTypeLibImpl); 03077 return (ITypeLib2*) pTypeLibImpl; 03078 } 03079 03080 03081 static BOOL TLB_GUIDFromString(const char *str, GUID *guid) 03082 { 03083 char b[3]; 03084 int i; 03085 short s; 03086 03087 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) { 03088 FIXME("Can't parse guid %s\n", debugstr_guid(guid)); 03089 return FALSE; 03090 } 03091 03092 guid->Data4[0] = s >> 8; 03093 guid->Data4[1] = s & 0xff; 03094 03095 b[2] = '\0'; 03096 for(i = 0; i < 6; i++) { 03097 memcpy(b, str + 24 + 2 * i, 2); 03098 guid->Data4[i + 2] = strtol(b, NULL, 16); 03099 } 03100 return TRUE; 03101 } 03102 03103 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr) 03104 { 03105 WORD bytelen; 03106 DWORD len; 03107 03108 *pBstr = NULL; 03109 bytelen = *(const WORD*)ptr; 03110 if(bytelen == 0xffff) return 2; 03111 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0); 03112 *pBstr = SysAllocStringLen(NULL, len); 03113 if (*pBstr) 03114 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len); 03115 return bytelen + 2; 03116 } 03117 03118 static WORD SLTG_ReadStringA(const char *ptr, char **str) 03119 { 03120 WORD bytelen; 03121 03122 *str = NULL; 03123 bytelen = *(const WORD*)ptr; 03124 if(bytelen == 0xffff) return 2; 03125 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1); 03126 memcpy(*str, ptr + 2, bytelen); 03127 (*str)[bytelen] = '\0'; 03128 return bytelen + 2; 03129 } 03130 03131 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl) 03132 { 03133 char *ptr = pLibBlk; 03134 WORD w; 03135 03136 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) { 03137 FIXME("libblk magic = %04x\n", w); 03138 return 0; 03139 } 03140 03141 ptr += 6; 03142 if((w = *(WORD*)ptr) != 0xffff) { 03143 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w); 03144 ptr += w; 03145 } 03146 ptr += 2; 03147 03148 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString); 03149 03150 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile); 03151 03152 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr; 03153 ptr += 4; 03154 03155 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr; 03156 ptr += 2; 03157 03158 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL) 03159 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0); 03160 else 03161 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0; 03162 ptr += 2; 03163 03164 ptr += 4; /* skip res12 */ 03165 03166 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr; 03167 ptr += 2; 03168 03169 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr; 03170 ptr += 2; 03171 03172 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr; 03173 ptr += 2; 03174 03175 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID)); 03176 ptr += sizeof(GUID); 03177 03178 return ptr - (char*)pLibBlk; 03179 } 03180 03181 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */ 03182 typedef struct 03183 { 03184 unsigned int num; 03185 HREFTYPE refs[1]; 03186 } sltg_ref_lookup_t; 03187 03188 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref, 03189 HREFTYPE *typelib_ref) 03190 { 03191 if(table && typeinfo_ref < table->num) 03192 { 03193 *typelib_ref = table->refs[typeinfo_ref]; 03194 return S_OK; 03195 } 03196 03197 ERR_(typelib)("Unable to find reference\n"); 03198 *typelib_ref = -1; 03199 return E_FAIL; 03200 } 03201 03202 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup) 03203 { 03204 BOOL done = FALSE; 03205 03206 while(!done) { 03207 if((*pType & 0xe00) == 0xe00) { 03208 pTD->vt = VT_PTR; 03209 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03210 sizeof(TYPEDESC)); 03211 pTD = pTD->u.lptdesc; 03212 } 03213 switch(*pType & 0x3f) { 03214 case VT_PTR: 03215 pTD->vt = VT_PTR; 03216 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03217 sizeof(TYPEDESC)); 03218 pTD = pTD->u.lptdesc; 03219 break; 03220 03221 case VT_USERDEFINED: 03222 pTD->vt = VT_USERDEFINED; 03223 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype); 03224 done = TRUE; 03225 break; 03226 03227 case VT_CARRAY: 03228 { 03229 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of 03230 array */ 03231 03232 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType)); 03233 03234 pTD->vt = VT_CARRAY; 03235 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03236 sizeof(ARRAYDESC) + 03237 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND)); 03238 pTD->u.lpadesc->cDims = pSA->cDims; 03239 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound, 03240 pSA->cDims * sizeof(SAFEARRAYBOUND)); 03241 03242 pTD = &pTD->u.lpadesc->tdescElem; 03243 break; 03244 } 03245 03246 case VT_SAFEARRAY: 03247 { 03248 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this 03249 useful? */ 03250 03251 pType++; 03252 pTD->vt = VT_SAFEARRAY; 03253 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03254 sizeof(TYPEDESC)); 03255 pTD = pTD->u.lptdesc; 03256 break; 03257 } 03258 default: 03259 pTD->vt = *pType & 0x3f; 03260 done = TRUE; 03261 break; 03262 } 03263 pType++; 03264 } 03265 return pType; 03266 } 03267 03268 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, 03269 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup) 03270 { 03271 /* Handle [in/out] first */ 03272 if((*pType & 0xc000) == 0xc000) 03273 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE; 03274 else if(*pType & 0x8000) 03275 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT; 03276 else if(*pType & 0x4000) 03277 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT; 03278 else 03279 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN; 03280 03281 if(*pType & 0x2000) 03282 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID; 03283 03284 if(*pType & 0x80) 03285 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL; 03286 03287 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup); 03288 } 03289 03290 03291 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL, 03292 char *pNameTable) 03293 { 03294 unsigned int ref; 03295 char *name; 03296 TLBRefType *ref_type; 03297 sltg_ref_lookup_t *table; 03298 HREFTYPE typelib_ref; 03299 03300 if(pRef->magic != SLTG_REF_MAGIC) { 03301 FIXME("Ref magic = %x\n", pRef->magic); 03302 return NULL; 03303 } 03304 name = ( (char*)pRef->names + pRef->number); 03305 03306 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0])); 03307 table->num = pRef->number >> 3; 03308 03309 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */ 03310 03311 /* We don't want the first href to be 0 */ 03312 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2; 03313 03314 for(ref = 0; ref < pRef->number >> 3; ref++) { 03315 char *refname; 03316 unsigned int lib_offs, type_num; 03317 03318 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type)); 03319 03320 name += SLTG_ReadStringA(name, &refname); 03321 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2) 03322 FIXME_(typelib)("Can't sscanf ref\n"); 03323 if(lib_offs != 0xffff) { 03324 TLBImpLib **import = &pTL->pImpLibs; 03325 03326 while(*import) { 03327 if((*import)->offset == lib_offs) 03328 break; 03329 import = &(*import)->next; 03330 } 03331 if(!*import) { 03332 char fname[MAX_PATH+1]; 03333 int len; 03334 03335 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03336 sizeof(**import)); 03337 (*import)->offset = lib_offs; 03338 TLB_GUIDFromString( pNameTable + lib_offs + 4, 03339 &(*import)->guid); 03340 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s", 03341 &(*import)->wVersionMajor, 03342 &(*import)->wVersionMinor, 03343 &(*import)->lcid, fname) != 4) { 03344 FIXME_(typelib)("can't sscanf ref %s\n", 03345 pNameTable + lib_offs + 40); 03346 } 03347 len = strlen(fname); 03348 if(fname[len-1] != '#') 03349 FIXME("fname = %s\n", fname); 03350 fname[len-1] = '\0'; 03351 (*import)->name = TLB_MultiByteToBSTR(fname); 03352 } 03353 ref_type->pImpTLInfo = *import; 03354 03355 /* Store a reference to IDispatch */ 03356 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4) 03357 pTL->dispatch_href = typelib_ref; 03358 03359 } else { /* internal ref */ 03360 ref_type->pImpTLInfo = TLB_REF_INTERNAL; 03361 } 03362 ref_type->reference = typelib_ref; 03363 ref_type->index = type_num; 03364 03365 HeapFree(GetProcessHeap(), 0, refname); 03366 list_add_tail(&pTL->ref_list, &ref_type->entry); 03367 03368 table->refs[ref] = typelib_ref; 03369 typelib_ref += 4; 03370 } 03371 if((BYTE)*name != SLTG_REF_MAGIC) 03372 FIXME_(typelib)("End of ref block magic = %x\n", *name); 03373 dump_TLBRefType(pTL); 03374 return table; 03375 } 03376 03377 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI, 03378 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup) 03379 { 03380 SLTG_ImplInfo *info; 03381 TLBImplType **ppImplType = &pTI->impltypelist; 03382 /* I don't really get this structure, usually it's 0x16 bytes 03383 long, but iuser.tlb contains some that are 0x18 bytes long. 03384 That's ok because we can use the next ptr to jump to the next 03385 one. But how do we know the length of the last one? The WORD 03386 at offs 0x8 might be the clue. For now I'm just assuming that 03387 the last one is the regular 0x16 bytes. */ 03388 03389 info = (SLTG_ImplInfo*)pBlk; 03390 while(1) { 03391 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03392 sizeof(**ppImplType)); 03393 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef); 03394 (*ppImplType)->implflags = info->impltypeflags; 03395 pTI->TypeAttr.cImplTypes++; 03396 ppImplType = &(*ppImplType)->next; 03397 03398 if(info->next == 0xffff) 03399 break; 03400 if(OneOnly) 03401 FIXME_(typelib)("Interface inheriting more than one interface\n"); 03402 info = (SLTG_ImplInfo*)(pBlk + info->next); 03403 } 03404 info++; /* see comment at top of function */ 03405 return (char*)info; 03406 } 03407 03408 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, 03409 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup) 03410 { 03411 TLBVarDesc **ppVarDesc = &pTI->varlist; 03412 BSTR bstrPrevName = NULL; 03413 SLTG_Variable *pItem; 03414 unsigned short i; 03415 WORD *pType; 03416 03417 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars; 03418 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) { 03419 03420 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03421 sizeof(**ppVarDesc)); 03422 (*ppVarDesc)->vardesc.memid = pItem->memid; 03423 03424 if (pItem->magic != SLTG_VAR_MAGIC && 03425 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) { 03426 FIXME_(typelib)("var magic = %02x\n", pItem->magic); 03427 return; 03428 } 03429 03430 if (pItem->name == 0xfffe) 03431 (*ppVarDesc)->Name = SysAllocString(bstrPrevName); 03432 else 03433 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable); 03434 03435 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name)); 03436 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs); 03437 TRACE_(typelib)("memid = 0x%x\n", pItem->memid); 03438 03439 if(pItem->flags & 0x02) 03440 pType = &pItem->type; 03441 else 03442 pType = (WORD*)(pBlk + pItem->type); 03443 03444 if (pItem->flags & ~0xda) 03445 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda); 03446 03447 SLTG_DoElem(pType, pBlk, 03448 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup); 03449 03450 if (TRACE_ON(typelib)) { 03451 char buf[300]; 03452 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf); 03453 TRACE_(typelib)("elemdescVar: %s\n", buf); 03454 } 03455 03456 if (pItem->flags & 0x40) { 03457 TRACE_(typelib)("VAR_DISPATCH\n"); 03458 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH; 03459 } 03460 else if (pItem->flags & 0x10) { 03461 TRACE_(typelib)("VAR_CONST\n"); 03462 (*ppVarDesc)->vardesc.varkind = VAR_CONST; 03463 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0, 03464 sizeof(VARIANT)); 03465 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT; 03466 if (pItem->flags & 0x08) 03467 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs; 03468 else { 03469 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt) 03470 { 03471 case VT_LPSTR: 03472 case VT_LPWSTR: 03473 case VT_BSTR: 03474 { 03475 WORD len = *(WORD *)(pBlk + pItem->byte_offs); 03476 BSTR str; 03477 TRACE_(typelib)("len = %u\n", len); 03478 if (len == 0xffff) { 03479 str = NULL; 03480 } else { 03481 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0); 03482 str = SysAllocStringLen(NULL, alloc_len); 03483 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len); 03484 } 03485 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR; 03486 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str; 03487 break; 03488 } 03489 case VT_I2: 03490 case VT_UI2: 03491 case VT_I4: 03492 case VT_UI4: 03493 case VT_INT: 03494 case VT_UINT: 03495 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = 03496 *(INT*)(pBlk + pItem->byte_offs); 03497 break; 03498 default: 03499 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt); 03500 } 03501 } 03502 } 03503 else { 03504 TRACE_(typelib)("VAR_PERINSTANCE\n"); 03505 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs; 03506 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE; 03507 } 03508 03509 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC) 03510 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags; 03511 03512 if (pItem->flags & 0x80) 03513 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY; 03514 03515 bstrPrevName = (*ppVarDesc)->Name; 03516 ppVarDesc = &((*ppVarDesc)->next); 03517 } 03518 pTI->TypeAttr.cVars = cVars; 03519 } 03520 03521 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, 03522 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup) 03523 { 03524 SLTG_Function *pFunc; 03525 unsigned short i; 03526 TLBFuncDesc **ppFuncDesc = &pTI->funclist; 03527 03528 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs; 03529 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) { 03530 03531 int param; 03532 WORD *pType, *pArg; 03533 03534 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03535 sizeof(**ppFuncDesc)); 03536 03537 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) { 03538 case SLTG_FUNCTION_MAGIC: 03539 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL; 03540 break; 03541 case SLTG_DISPATCH_FUNCTION_MAGIC: 03542 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH; 03543 break; 03544 case SLTG_STATIC_FUNCTION_MAGIC: 03545 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC; 03546 break; 03547 default: 03548 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT); 03549 HeapFree(GetProcessHeap(), 0, *ppFuncDesc); 03550 *ppFuncDesc = NULL; 03551 return; 03552 } 03553 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable); 03554 03555 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid; 03556 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4; 03557 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7; 03558 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3; 03559 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1; 03560 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos; 03561 03562 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT) 03563 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags; 03564 03565 if(pFunc->retnextopt & 0x80) 03566 pType = &pFunc->rettype; 03567 else 03568 pType = (WORD*)(pBlk + pFunc->rettype); 03569 03570 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup); 03571 03572 (*ppFuncDesc)->funcdesc.lprgelemdescParam = 03573 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03574 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC)); 03575 (*ppFuncDesc)->pParamDesc = 03576 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03577 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc)); 03578 03579 pArg = (WORD*)(pBlk + pFunc->arg_off); 03580 03581 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) { 03582 char *paramName = pNameTable + *pArg; 03583 BOOL HaveOffs; 03584 /* If arg type follows then paramName points to the 2nd 03585 letter of the name, else the next WORD is an offset to 03586 the arg type and paramName points to the first letter. 03587 So let's take one char off paramName and see if we're 03588 pointing at an alpha-numeric char. However if *pArg is 03589 0xffff or 0xfffe then the param has no name, the former 03590 meaning that the next WORD is the type, the latter 03591 meaning that the next WORD is an offset to the type. */ 03592 03593 HaveOffs = FALSE; 03594 if(*pArg == 0xffff) 03595 paramName = NULL; 03596 else if(*pArg == 0xfffe) { 03597 paramName = NULL; 03598 HaveOffs = TRUE; 03599 } 03600 else if(paramName[-1] && !isalnum(paramName[-1])) 03601 HaveOffs = TRUE; 03602 03603 pArg++; 03604 03605 if(HaveOffs) { /* the next word is an offset to type */ 03606 pType = (WORD*)(pBlk + *pArg); 03607 SLTG_DoElem(pType, pBlk, 03608 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup); 03609 pArg++; 03610 } else { 03611 if(paramName) 03612 paramName--; 03613 pArg = SLTG_DoElem(pArg, pBlk, 03614 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup); 03615 } 03616 03617 /* Are we an optional param ? */ 03618 if((*ppFuncDesc)->funcdesc.cParams - param <= 03619 (*ppFuncDesc)->funcdesc.cParamsOpt) 03620 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT; 03621 03622 if(paramName) { 03623 (*ppFuncDesc)->pParamDesc[param].Name = 03624 TLB_MultiByteToBSTR(paramName); 03625 } else { 03626 (*ppFuncDesc)->pParamDesc[param].Name = 03627 SysAllocString((*ppFuncDesc)->Name); 03628 } 03629 } 03630 03631 ppFuncDesc = &((*ppFuncDesc)->next); 03632 if(pFunc->next == 0xffff) break; 03633 } 03634 pTI->TypeAttr.cFuncs = cFuncs; 03635 } 03636 03637 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI, 03638 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 03639 SLTG_TypeInfoTail *pTITail) 03640 { 03641 char *pFirstItem; 03642 sltg_ref_lookup_t *ref_lookup = NULL; 03643 03644 if(pTIHeader->href_table != 0xffffffff) { 03645 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 03646 pNameTable); 03647 } 03648 03649 pFirstItem = pBlk; 03650 03651 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) { 03652 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup); 03653 } 03654 HeapFree(GetProcessHeap(), 0, ref_lookup); 03655 } 03656 03657 03658 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI, 03659 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 03660 const SLTG_TypeInfoTail *pTITail) 03661 { 03662 char *pFirstItem; 03663 sltg_ref_lookup_t *ref_lookup = NULL; 03664 03665 if(pTIHeader->href_table != 0xffffffff) { 03666 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 03667 pNameTable); 03668 } 03669 03670 pFirstItem = pBlk; 03671 03672 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) { 03673 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup); 03674 } 03675 03676 if (pTITail->funcs_off != 0xffff) 03677 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); 03678 03679 HeapFree(GetProcessHeap(), 0, ref_lookup); 03680 03681 if (TRACE_ON(typelib)) 03682 dump_TLBFuncDesc(pTI->funclist); 03683 } 03684 03685 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI, 03686 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 03687 const SLTG_TypeInfoTail *pTITail) 03688 { 03689 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL); 03690 } 03691 03692 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI, 03693 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 03694 const SLTG_TypeInfoTail *pTITail) 03695 { 03696 WORD *pType; 03697 sltg_ref_lookup_t *ref_lookup = NULL; 03698 03699 if (pTITail->simple_alias) { 03700 /* if simple alias, no more processing required */ 03701 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt; 03702 return; 03703 } 03704 03705 if(pTIHeader->href_table != 0xffffffff) { 03706 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 03707 pNameTable); 03708 } 03709 03710 /* otherwise it is an offset to a type */ 03711 pType = (WORD *)(pBlk + pTITail->tdescalias_vt); 03712 03713 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup); 03714 03715 HeapFree(GetProcessHeap(), 0, ref_lookup); 03716 } 03717 03718 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI, 03719 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 03720 const SLTG_TypeInfoTail *pTITail) 03721 { 03722 sltg_ref_lookup_t *ref_lookup = NULL; 03723 if (pTIHeader->href_table != 0xffffffff) 03724 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 03725 pNameTable); 03726 03727 if (pTITail->vars_off != 0xffff) 03728 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup); 03729 03730 if (pTITail->funcs_off != 0xffff) 03731 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); 03732 03733 if (pTITail->impls_off != 0xffff) 03734 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup); 03735 03736 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number 03737 * of dispinterface functions including the IDispatch ones, so 03738 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */ 03739 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *); 03740 03741 HeapFree(GetProcessHeap(), 0, ref_lookup); 03742 if (TRACE_ON(typelib)) 03743 dump_TLBFuncDesc(pTI->funclist); 03744 } 03745 03746 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI, 03747 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 03748 const SLTG_TypeInfoTail *pTITail) 03749 { 03750 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL); 03751 } 03752 03753 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI, 03754 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader, 03755 const SLTG_TypeInfoTail *pTITail) 03756 { 03757 sltg_ref_lookup_t *ref_lookup = NULL; 03758 if (pTIHeader->href_table != 0xffffffff) 03759 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib, 03760 pNameTable); 03761 03762 if (pTITail->vars_off != 0xffff) 03763 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup); 03764 03765 if (pTITail->funcs_off != 0xffff) 03766 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); 03767 HeapFree(GetProcessHeap(), 0, ref_lookup); 03768 if (TRACE_ON(typelib)) 03769 dump_TypeInfo(pTI); 03770 } 03771 03772 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more 03773 managable copy of it into this */ 03774 typedef struct { 03775 WORD small_no; 03776 char *index_name; 03777 char *other_name; 03778 WORD res1a; 03779 WORD name_offs; 03780 WORD more_bytes; 03781 char *extra; 03782 WORD res20; 03783 DWORD helpcontext; 03784 WORD res26; 03785 GUID uuid; 03786 } SLTG_InternalOtherTypeInfo; 03787 03788 /**************************************************************************** 03789 * ITypeLib2_Constructor_SLTG 03790 * 03791 * loading a SLTG typelib from an in-memory image 03792 */ 03793 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) 03794 { 03795 ITypeLibImpl *pTypeLibImpl; 03796 SLTG_Header *pHeader; 03797 SLTG_BlkEntry *pBlkEntry; 03798 SLTG_Magic *pMagic; 03799 SLTG_Index *pIndex; 03800 SLTG_Pad9 *pPad9; 03801 LPVOID pBlk, pFirstBlk; 03802 SLTG_LibBlk *pLibBlk; 03803 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks; 03804 char *pAfterOTIBlks = NULL; 03805 char *pNameTable, *ptr; 03806 int i; 03807 DWORD len, order; 03808 ITypeInfoImpl **ppTypeInfoImpl; 03809 03810 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength); 03811 03812 03813 pTypeLibImpl = TypeLibImpl_Constructor(); 03814 if (!pTypeLibImpl) return NULL; 03815 03816 pHeader = pLib; 03817 03818 TRACE_(typelib)("header:\n"); 03819 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic, 03820 pHeader->nrOfFileBlks ); 03821 if (pHeader->SLTG_magic != SLTG_SIGNATURE) { 03822 FIXME_(typelib)("Header type magic 0x%08x not supported.\n", 03823 pHeader->SLTG_magic); 03824 return NULL; 03825 } 03826 03827 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */ 03828 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2; 03829 03830 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */ 03831 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1); 03832 03833 /* Next we have a magic block */ 03834 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1); 03835 03836 /* Let's see if we're still in sync */ 03837 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC, 03838 sizeof(SLTG_COMPOBJ_MAGIC))) { 03839 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic); 03840 return NULL; 03841 } 03842 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC, 03843 sizeof(SLTG_DIR_MAGIC))) { 03844 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic); 03845 return NULL; 03846 } 03847 03848 pIndex = (SLTG_Index*)(pMagic+1); 03849 03850 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount); 03851 03852 pFirstBlk = pPad9 + 1; 03853 03854 /* We'll set up a ptr to the main library block, which is the last one. */ 03855 03856 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0; 03857 pBlkEntry[order].next != 0; 03858 order = pBlkEntry[order].next - 1, i++) { 03859 pBlk = (char*)pBlk + pBlkEntry[order].len; 03860 } 03861 pLibBlk = pBlk; 03862 03863 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl); 03864 03865 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount 03866 interspersed */ 03867 03868 len += 0x40; 03869 03870 /* And now TypeInfoCount of SLTG_OtherTypeInfo */ 03871 03872 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 03873 sizeof(*pOtherTypeInfoBlks) * 03874 pTypeLibImpl->TypeInfoCount); 03875 03876 03877 ptr = (char*)pLibBlk + len; 03878 03879 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) { 03880 WORD w, extra; 03881 len = 0; 03882 03883 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr; 03884 03885 w = *(WORD*)(ptr + 2); 03886 if(w != 0xffff) { 03887 len += w; 03888 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0, 03889 w+1); 03890 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w); 03891 pOtherTypeInfoBlks[i].index_name[w] = '\0'; 03892 } 03893 w = *(WORD*)(ptr + 4 + len); 03894 if(w != 0xffff) { 03895 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w)); 03896 len += w; 03897 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0, 03898 w+1); 03899 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w); 03900 pOtherTypeInfoBlks[i].other_name[w] = '\0'; 03901 } 03902 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6); 03903 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8); 03904 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len); 03905 if(extra) { 03906 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0, 03907 extra); 03908 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra); 03909 len += extra; 03910 } 03911 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len); 03912 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len); 03913 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len); 03914 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID)); 03915 len += sizeof(SLTG_OtherTypeInfo); 03916 ptr += len; 03917 } 03918 03919 pAfterOTIBlks = ptr; 03920 03921 /* Skip this WORD and get the next DWORD */ 03922 len = *(DWORD*)(pAfterOTIBlks + 2); 03923 03924 /* Now add this to pLibBLk look at what we're pointing at and 03925 possibly add 0x20, then add 0x216, sprinkle a bit a magic 03926 dust and we should be pointing at the beginning of the name 03927 table */ 03928 03929 pNameTable = (char*)pLibBlk + len; 03930 03931 switch(*(WORD*)pNameTable) { 03932 case 0xffff: 03933 break; 03934 case 0x0200: 03935 pNameTable += 0x20; 03936 break; 03937 default: 03938 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable); 03939 break; 03940 } 03941 03942 pNameTable += 0x216; 03943 03944 pNameTable += 2; 03945 03946 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name); 03947 03948 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name); 03949 03950 03951 /* Hopefully we now have enough ptrs set up to actually read in 03952 some TypeInfos. It's not clear which order to do them in, so 03953 I'll just follow the links along the BlkEntry chain and read 03954 them in the order in which they are in the file */ 03955 03956 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo); 03957 03958 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0; 03959 pBlkEntry[order].next != 0; 03960 order = pBlkEntry[order].next - 1, i++) { 03961 03962 SLTG_TypeInfoHeader *pTIHeader; 03963 SLTG_TypeInfoTail *pTITail; 03964 SLTG_MemberHeader *pMemHeader; 03965 03966 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, 03967 pOtherTypeInfoBlks[i].index_name)) { 03968 FIXME_(typelib)("Index strings don't match\n"); 03969 return NULL; 03970 } 03971 03972 pTIHeader = pBlk; 03973 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) { 03974 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic); 03975 return NULL; 03976 } 03977 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, " 03978 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n", 03979 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e); 03980 03981 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor(); 03982 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl; 03983 (*ppTypeInfoImpl)->index = i; 03984 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR( 03985 pOtherTypeInfoBlks[i].name_offs + 03986 pNameTable); 03987 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext; 03988 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid; 03989 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind; 03990 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version; 03991 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version; 03992 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags = 03993 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5); 03994 03995 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL) 03996 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH; 03997 03998 if((pTIHeader->typeflags1 & 7) != 2) 03999 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1); 04000 if(pTIHeader->typeflags3 != 2) 04001 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3); 04002 04003 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n", 04004 debugstr_w((*ppTypeInfoImpl)->Name), 04005 typekind_desc[pTIHeader->typekind], 04006 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid), 04007 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags); 04008 04009 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table); 04010 04011 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra); 04012 04013 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment; 04014 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance; 04015 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft; 04016 04017 switch(pTIHeader->typekind) { 04018 case TKIND_ENUM: 04019 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 04020 pTIHeader, pTITail); 04021 break; 04022 04023 case TKIND_RECORD: 04024 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 04025 pTIHeader, pTITail); 04026 break; 04027 04028 case TKIND_INTERFACE: 04029 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 04030 pTIHeader, pTITail); 04031 break; 04032 04033 case TKIND_COCLASS: 04034 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 04035 pTIHeader, pTITail); 04036 break; 04037 04038 case TKIND_ALIAS: 04039 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 04040 pTIHeader, pTITail); 04041 break; 04042 04043 case TKIND_DISPATCH: 04044 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 04045 pTIHeader, pTITail); 04046 break; 04047 04048 case TKIND_MODULE: 04049 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable, 04050 pTIHeader, pTITail); 04051 break; 04052 04053 default: 04054 FIXME("Not processing typekind %d\n", pTIHeader->typekind); 04055 break; 04056 04057 } 04058 04059 /* could get cFuncs, cVars and cImplTypes from here 04060 but we've already set those */ 04061 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x); 04062 X(06); 04063 X(16); 04064 X(18); 04065 X(1a); 04066 X(1e); 04067 X(24); 04068 X(26); 04069 X(2a); 04070 X(2c); 04071 X(2e); 04072 X(30); 04073 X(32); 04074 X(34); 04075 #undef X 04076 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next); 04077 pBlk = (char*)pBlk + pBlkEntry[order].len; 04078 } 04079 04080 if(i != pTypeLibImpl->TypeInfoCount) { 04081 FIXME("Somehow processed %d TypeInfos\n", i); 04082 return NULL; 04083 } 04084 04085 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks); 04086 return (ITypeLib2*)pTypeLibImpl; 04087 } 04088 04089 /* ITypeLib::QueryInterface 04090 */ 04091 static HRESULT WINAPI ITypeLib2_fnQueryInterface( 04092 ITypeLib2 * iface, 04093 REFIID riid, 04094 VOID **ppvObject) 04095 { 04096 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04097 04098 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid)); 04099 04100 *ppvObject=NULL; 04101 if(IsEqualIID(riid, &IID_IUnknown) || 04102 IsEqualIID(riid,&IID_ITypeLib)|| 04103 IsEqualIID(riid,&IID_ITypeLib2)) 04104 { 04105 *ppvObject = This; 04106 } 04107 04108 if(*ppvObject) 04109 { 04110 ITypeLib2_AddRef(iface); 04111 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject); 04112 return S_OK; 04113 } 04114 TRACE("-- Interface: E_NOINTERFACE\n"); 04115 return E_NOINTERFACE; 04116 } 04117 04118 /* ITypeLib::AddRef 04119 */ 04120 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface) 04121 { 04122 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04123 ULONG ref = InterlockedIncrement(&This->ref); 04124 04125 TRACE("(%p)->ref was %u\n",This, ref - 1); 04126 04127 return ref; 04128 } 04129 04130 /* ITypeLib::Release 04131 */ 04132 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) 04133 { 04134 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04135 ULONG ref = InterlockedDecrement(&This->ref); 04136 04137 TRACE("(%p)->(%u)\n",This, ref); 04138 04139 if (!ref) 04140 { 04141 TLBImpLib *pImpLib, *pImpLibNext; 04142 TLBCustData *pCustData, *pCustDataNext; 04143 TLBRefType *ref_type; 04144 void *cursor2; 04145 int i; 04146 ITypeInfoImpl *pTI, *pTINext; 04147 04148 /* remove cache entry */ 04149 if(This->path) 04150 { 04151 TRACE("removing from cache list\n"); 04152 EnterCriticalSection(&cache_section); 04153 if (This->next) This->next->prev = This->prev; 04154 if (This->prev) This->prev->next = This->next; 04155 else tlb_cache_first = This->next; 04156 LeaveCriticalSection(&cache_section); 04157 HeapFree(GetProcessHeap(), 0, This->path); 04158 } 04159 TRACE(" destroying ITypeLib(%p)\n",This); 04160 04161 SysFreeString(This->Name); 04162 This->Name = NULL; 04163 04164 SysFreeString(This->DocString); 04165 This->DocString = NULL; 04166 04167 SysFreeString(This->HelpFile); 04168 This->HelpFile = NULL; 04169 04170 SysFreeString(This->HelpStringDll); 04171 This->HelpStringDll = NULL; 04172 04173 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext) 04174 { 04175 VariantClear(&pCustData->data); 04176 04177 pCustDataNext = pCustData->next; 04178 TLB_Free(pCustData); 04179 } 04180 04181 for (i = 0; i < This->ctTypeDesc; i++) 04182 if (This->pTypeDesc[i].vt == VT_CARRAY) 04183 TLB_Free(This->pTypeDesc[i].u.lpadesc); 04184 04185 TLB_Free(This->pTypeDesc); 04186 04187 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext) 04188 { 04189 if (pImpLib->pImpTypeLib) 04190 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib); 04191 SysFreeString(pImpLib->name); 04192 04193 pImpLibNext = pImpLib->next; 04194 TLB_Free(pImpLib); 04195 } 04196 04197 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry) 04198 { 04199 list_remove(&ref_type->entry); 04200 TLB_Free(ref_type); 04201 } 04202 04203 for (pTI = This->pTypeInfo; pTI; pTI = pTINext) 04204 { 04205 pTINext = pTI->next; 04206 ITypeInfo_fnDestroy(pTI); 04207 } 04208 HeapFree(GetProcessHeap(),0,This); 04209 return 0; 04210 } 04211 04212 return ref; 04213 } 04214 04215 /* ITypeLib::GetTypeInfoCount 04216 * 04217 * Returns the number of type descriptions in the type library 04218 */ 04219 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface) 04220 { 04221 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04222 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount); 04223 return This->TypeInfoCount; 04224 } 04225 04226 /* ITypeLib::GetTypeInfo 04227 * 04228 * retrieves the specified type description in the library. 04229 */ 04230 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo( 04231 ITypeLib2 *iface, 04232 UINT index, 04233 ITypeInfo **ppTInfo) 04234 { 04235 UINT i; 04236 04237 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04238 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; 04239 04240 TRACE("(%p)->(index=%d)\n", This, index); 04241 04242 if (!ppTInfo) return E_INVALIDARG; 04243 04244 /* search element n in list */ 04245 for(i=0; i < index; i++) 04246 { 04247 pTypeInfo = pTypeInfo->next; 04248 if (!pTypeInfo) 04249 { 04250 TRACE("-- element not found\n"); 04251 return TYPE_E_ELEMENTNOTFOUND; 04252 } 04253 } 04254 04255 *ppTInfo = (ITypeInfo *) pTypeInfo; 04256 04257 ITypeInfo_AddRef(*ppTInfo); 04258 TRACE("-- found (%p)\n",*ppTInfo); 04259 return S_OK; 04260 } 04261 04262 04263 /* ITypeLibs::GetTypeInfoType 04264 * 04265 * Retrieves the type of a type description. 04266 */ 04267 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType( 04268 ITypeLib2 *iface, 04269 UINT index, 04270 TYPEKIND *pTKind) 04271 { 04272 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04273 UINT i; 04274 ITypeInfoImpl *pTInfo = This->pTypeInfo; 04275 04276 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) 04277 return TYPE_E_ELEMENTNOTFOUND; 04278 04279 TRACE("(%p) index %d\n", This, index); 04280 04281 if(!pTKind) return E_INVALIDARG; 04282 04283 /* search element n in list */ 04284 for(i=0; i < index; i++) 04285 { 04286 if(!pTInfo) 04287 { 04288 TRACE("-- element not found\n"); 04289 return TYPE_E_ELEMENTNOTFOUND; 04290 } 04291 pTInfo = pTInfo->next; 04292 } 04293 04294 *pTKind = pTInfo->TypeAttr.typekind; 04295 TRACE("-- found Type (%d)\n", *pTKind); 04296 return S_OK; 04297 } 04298 04299 /* ITypeLib::GetTypeInfoOfGuid 04300 * 04301 * Retrieves the type description that corresponds to the specified GUID. 04302 * 04303 */ 04304 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid( 04305 ITypeLib2 *iface, 04306 REFGUID guid, 04307 ITypeInfo **ppTInfo) 04308 { 04309 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04310 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */ 04311 04312 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid)); 04313 04314 if (!pTypeInfo) 04315 { 04316 WARN("-- element not found\n"); 04317 return TYPE_E_ELEMENTNOTFOUND; 04318 } 04319 04320 /* search linked list for guid */ 04321 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) ) 04322 { 04323 pTypeInfo = pTypeInfo->next; 04324 04325 if (!pTypeInfo) 04326 { 04327 /* end of list reached */ 04328 WARN("-- element not found\n"); 04329 return TYPE_E_ELEMENTNOTFOUND; 04330 } 04331 } 04332 04333 TRACE("-- found (%p, %s)\n", 04334 pTypeInfo, 04335 debugstr_w(pTypeInfo->Name)); 04336 04337 *ppTInfo = (ITypeInfo*)pTypeInfo; 04338 ITypeInfo_AddRef(*ppTInfo); 04339 return S_OK; 04340 } 04341 04342 /* ITypeLib::GetLibAttr 04343 * 04344 * Retrieves the structure that contains the library's attributes. 04345 * 04346 */ 04347 static HRESULT WINAPI ITypeLib2_fnGetLibAttr( 04348 ITypeLib2 *iface, 04349 LPTLIBATTR *ppTLibAttr) 04350 { 04351 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04352 TRACE("(%p)\n",This); 04353 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr)); 04354 **ppTLibAttr = This->LibAttr; 04355 return S_OK; 04356 } 04357 04358 /* ITypeLib::GetTypeComp 04359 * 04360 * Enables a client compiler to bind to a library's types, variables, 04361 * constants, and global functions. 04362 * 04363 */ 04364 static HRESULT WINAPI ITypeLib2_fnGetTypeComp( 04365 ITypeLib2 *iface, 04366 ITypeComp **ppTComp) 04367 { 04368 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04369 04370 TRACE("(%p)->(%p)\n",This,ppTComp); 04371 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp; 04372 ITypeComp_AddRef(*ppTComp); 04373 04374 return S_OK; 04375 } 04376 04377 /* ITypeLib::GetDocumentation 04378 * 04379 * Retrieves the library's documentation string, the complete Help file name 04380 * and path, and the context identifier for the library Help topic in the Help 04381 * file. 04382 * 04383 * On a successful return all non-null BSTR pointers will have been set, 04384 * possibly to NULL. 04385 */ 04386 static HRESULT WINAPI ITypeLib2_fnGetDocumentation( 04387 ITypeLib2 *iface, 04388 INT index, 04389 BSTR *pBstrName, 04390 BSTR *pBstrDocString, 04391 DWORD *pdwHelpContext, 04392 BSTR *pBstrHelpFile) 04393 { 04394 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04395 04396 HRESULT result = E_INVALIDARG; 04397 04398 ITypeInfo *pTInfo; 04399 04400 04401 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n", 04402 This, index, 04403 pBstrName, pBstrDocString, 04404 pdwHelpContext, pBstrHelpFile); 04405 04406 if(index<0) 04407 { 04408 /* documentation for the typelib */ 04409 if(pBstrName) 04410 { 04411 if (This->Name) 04412 { 04413 if(!(*pBstrName = SysAllocString(This->Name))) 04414 goto memerr1; 04415 } 04416 else 04417 *pBstrName = NULL; 04418 } 04419 if(pBstrDocString) 04420 { 04421 if (This->DocString) 04422 { 04423 if(!(*pBstrDocString = SysAllocString(This->DocString))) 04424 goto memerr2; 04425 } 04426 else if (This->Name) 04427 { 04428 if(!(*pBstrDocString = SysAllocString(This->Name))) 04429 goto memerr2; 04430 } 04431 else 04432 *pBstrDocString = NULL; 04433 } 04434 if(pdwHelpContext) 04435 { 04436 *pdwHelpContext = This->dwHelpContext; 04437 } 04438 if(pBstrHelpFile) 04439 { 04440 if (This->HelpFile) 04441 { 04442 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) 04443 goto memerr3; 04444 } 04445 else 04446 *pBstrHelpFile = NULL; 04447 } 04448 04449 result = S_OK; 04450 } 04451 else 04452 { 04453 /* for a typeinfo */ 04454 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo); 04455 04456 if(SUCCEEDED(result)) 04457 { 04458 result = ITypeInfo_GetDocumentation(pTInfo, 04459 MEMBERID_NIL, 04460 pBstrName, 04461 pBstrDocString, 04462 pdwHelpContext, pBstrHelpFile); 04463 04464 ITypeInfo_Release(pTInfo); 04465 } 04466 } 04467 return result; 04468 memerr3: 04469 if (pBstrDocString) SysFreeString (*pBstrDocString); 04470 memerr2: 04471 if (pBstrName) SysFreeString (*pBstrName); 04472 memerr1: 04473 return STG_E_INSUFFICIENTMEMORY; 04474 } 04475 04476 /* ITypeLib::IsName 04477 * 04478 * Indicates whether a passed-in string contains the name of a type or member 04479 * described in the library. 04480 * 04481 */ 04482 static HRESULT WINAPI ITypeLib2_fnIsName( 04483 ITypeLib2 *iface, 04484 LPOLESTR szNameBuf, 04485 ULONG lHashVal, 04486 BOOL *pfName) 04487 { 04488 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04489 ITypeInfoImpl *pTInfo; 04490 TLBFuncDesc *pFInfo; 04491 TLBVarDesc *pVInfo; 04492 int i; 04493 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR); 04494 04495 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal, 04496 pfName); 04497 04498 *pfName=TRUE; 04499 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){ 04500 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit; 04501 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) { 04502 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit; 04503 for(i=0;i<pFInfo->funcdesc.cParams;i++) 04504 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen)) 04505 goto ITypeLib2_fnIsName_exit; 04506 } 04507 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) 04508 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit; 04509 04510 } 04511 *pfName=FALSE; 04512 04513 ITypeLib2_fnIsName_exit: 04514 TRACE("(%p)slow! search for %s: %s found!\n", This, 04515 debugstr_w(szNameBuf), *pfName?"NOT":""); 04516 04517 return S_OK; 04518 } 04519 04520 /* ITypeLib::FindName 04521 * 04522 * Finds occurrences of a type description in a type library. This may be used 04523 * to quickly verify that a name exists in a type library. 04524 * 04525 */ 04526 static HRESULT WINAPI ITypeLib2_fnFindName( 04527 ITypeLib2 *iface, 04528 LPOLESTR szNameBuf, 04529 ULONG lHashVal, 04530 ITypeInfo **ppTInfo, 04531 MEMBERID *rgMemId, 04532 UINT16 *pcFound) 04533 { 04534 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04535 ITypeInfoImpl *pTInfo; 04536 TLBFuncDesc *pFInfo; 04537 TLBVarDesc *pVInfo; 04538 int i,j = 0; 04539 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR); 04540 04541 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){ 04542 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit; 04543 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) { 04544 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit; 04545 for(i=0;i<pFInfo->funcdesc.cParams;i++) { 04546 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen)) 04547 goto ITypeLib2_fnFindName_exit; 04548 } 04549 } 04550 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) 04551 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit; 04552 continue; 04553 ITypeLib2_fnFindName_exit: 04554 ITypeInfo_AddRef((ITypeInfo*)pTInfo); 04555 ppTInfo[j]=(LPTYPEINFO)pTInfo; 04556 j++; 04557 } 04558 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n", 04559 This, *pcFound, debugstr_w(szNameBuf), j); 04560 04561 *pcFound=j; 04562 04563 return S_OK; 04564 } 04565 04566 /* ITypeLib::ReleaseTLibAttr 04567 * 04568 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr. 04569 * 04570 */ 04571 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr( 04572 ITypeLib2 *iface, 04573 TLIBATTR *pTLibAttr) 04574 { 04575 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04576 TRACE("freeing (%p)\n",This); 04577 HeapFree(GetProcessHeap(),0,pTLibAttr); 04578 04579 } 04580 04581 /* ITypeLib2::GetCustData 04582 * 04583 * gets the custom data 04584 */ 04585 static HRESULT WINAPI ITypeLib2_fnGetCustData( 04586 ITypeLib2 * iface, 04587 REFGUID guid, 04588 VARIANT *pVarVal) 04589 { 04590 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04591 TLBCustData *pCData; 04592 04593 for(pCData=This->pCustData; pCData; pCData = pCData->next) 04594 { 04595 if( IsEqualIID(guid, &pCData->guid)) break; 04596 } 04597 04598 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 04599 04600 if(pCData) 04601 { 04602 VariantInit( pVarVal); 04603 VariantCopy( pVarVal, &pCData->data); 04604 return S_OK; 04605 } 04606 return E_INVALIDARG; /* FIXME: correct? */ 04607 } 04608 04609 /* ITypeLib2::GetLibStatistics 04610 * 04611 * Returns statistics about a type library that are required for efficient 04612 * sizing of hash tables. 04613 * 04614 */ 04615 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics( 04616 ITypeLib2 * iface, 04617 ULONG *pcUniqueNames, 04618 ULONG *pcchUniqueNames) 04619 { 04620 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04621 04622 FIXME("(%p): stub!\n", This); 04623 04624 if(pcUniqueNames) *pcUniqueNames=1; 04625 if(pcchUniqueNames) *pcchUniqueNames=1; 04626 return S_OK; 04627 } 04628 04629 /* ITypeLib2::GetDocumentation2 04630 * 04631 * Retrieves the library's documentation string, the complete Help file name 04632 * and path, the localization context to use, and the context ID for the 04633 * library Help topic in the Help file. 04634 * 04635 */ 04636 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2( 04637 ITypeLib2 * iface, 04638 INT index, 04639 LCID lcid, 04640 BSTR *pbstrHelpString, 04641 DWORD *pdwHelpStringContext, 04642 BSTR *pbstrHelpStringDll) 04643 { 04644 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04645 HRESULT result; 04646 ITypeInfo *pTInfo; 04647 04648 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid); 04649 04650 /* the help string should be obtained from the helpstringdll, 04651 * using the _DLLGetDocumentation function, based on the supplied 04652 * lcid. Nice to do sometime... 04653 */ 04654 if(index<0) 04655 { 04656 /* documentation for the typelib */ 04657 if(pbstrHelpString) 04658 *pbstrHelpString=SysAllocString(This->DocString); 04659 if(pdwHelpStringContext) 04660 *pdwHelpStringContext=This->dwHelpContext; 04661 if(pbstrHelpStringDll) 04662 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll); 04663 04664 result = S_OK; 04665 } 04666 else 04667 { 04668 /* for a typeinfo */ 04669 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo); 04670 04671 if(SUCCEEDED(result)) 04672 { 04673 ITypeInfo2 * pTInfo2; 04674 result = ITypeInfo_QueryInterface(pTInfo, 04675 &IID_ITypeInfo2, 04676 (LPVOID*) &pTInfo2); 04677 04678 if(SUCCEEDED(result)) 04679 { 04680 result = ITypeInfo2_GetDocumentation2(pTInfo2, 04681 MEMBERID_NIL, 04682 lcid, 04683 pbstrHelpString, 04684 pdwHelpStringContext, 04685 pbstrHelpStringDll); 04686 04687 ITypeInfo2_Release(pTInfo2); 04688 } 04689 04690 ITypeInfo_Release(pTInfo); 04691 } 04692 } 04693 return result; 04694 } 04695 04696 /* ITypeLib2::GetAllCustData 04697 * 04698 * Gets all custom data items for the library. 04699 * 04700 */ 04701 static HRESULT WINAPI ITypeLib2_fnGetAllCustData( 04702 ITypeLib2 * iface, 04703 CUSTDATA *pCustData) 04704 { 04705 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04706 TLBCustData *pCData; 04707 int i; 04708 TRACE("(%p) returning %d items\n", This, This->ctCustData); 04709 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM)); 04710 if(pCustData->prgCustData ){ 04711 pCustData->cCustData=This->ctCustData; 04712 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){ 04713 pCustData->prgCustData[i].guid=pCData->guid; 04714 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data); 04715 } 04716 }else{ 04717 ERR(" OUT OF MEMORY!\n"); 04718 return E_OUTOFMEMORY; 04719 } 04720 return S_OK; 04721 } 04722 04723 static const ITypeLib2Vtbl tlbvt = { 04724 ITypeLib2_fnQueryInterface, 04725 ITypeLib2_fnAddRef, 04726 ITypeLib2_fnRelease, 04727 ITypeLib2_fnGetTypeInfoCount, 04728 ITypeLib2_fnGetTypeInfo, 04729 ITypeLib2_fnGetTypeInfoType, 04730 ITypeLib2_fnGetTypeInfoOfGuid, 04731 ITypeLib2_fnGetLibAttr, 04732 ITypeLib2_fnGetTypeComp, 04733 ITypeLib2_fnGetDocumentation, 04734 ITypeLib2_fnIsName, 04735 ITypeLib2_fnFindName, 04736 ITypeLib2_fnReleaseTLibAttr, 04737 04738 ITypeLib2_fnGetCustData, 04739 ITypeLib2_fnGetLibStatistics, 04740 ITypeLib2_fnGetDocumentation2, 04741 ITypeLib2_fnGetAllCustData 04742 }; 04743 04744 04745 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv) 04746 { 04747 ITypeLibImpl *This = impl_from_ITypeComp(iface); 04748 04749 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv); 04750 } 04751 04752 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface) 04753 { 04754 ITypeLibImpl *This = impl_from_ITypeComp(iface); 04755 04756 return ITypeLib2_AddRef((ITypeLib2 *)This); 04757 } 04758 04759 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface) 04760 { 04761 ITypeLibImpl *This = impl_from_ITypeComp(iface); 04762 04763 return ITypeLib2_Release((ITypeLib2 *)This); 04764 } 04765 04766 static HRESULT WINAPI ITypeLibComp_fnBind( 04767 ITypeComp * iface, 04768 OLECHAR * szName, 04769 ULONG lHash, 04770 WORD wFlags, 04771 ITypeInfo ** ppTInfo, 04772 DESCKIND * pDescKind, 04773 BINDPTR * pBindPtr) 04774 { 04775 ITypeLibImpl *This = impl_from_ITypeComp(iface); 04776 ITypeInfoImpl *pTypeInfo; 04777 int typemismatch=0; 04778 04779 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 04780 04781 *pDescKind = DESCKIND_NONE; 04782 pBindPtr->lptcomp = NULL; 04783 *ppTInfo = NULL; 04784 04785 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next) 04786 { 04787 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name)); 04788 04789 /* FIXME: check wFlags here? */ 04790 /* FIXME: we should use a hash table to look this info up using lHash 04791 * instead of an O(n) search */ 04792 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) || 04793 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE)) 04794 { 04795 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName)) 04796 { 04797 *pDescKind = DESCKIND_TYPECOMP; 04798 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; 04799 ITypeComp_AddRef(pBindPtr->lptcomp); 04800 TRACE("module or enum: %s\n", debugstr_w(szName)); 04801 return S_OK; 04802 } 04803 } 04804 04805 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) || 04806 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM)) 04807 { 04808 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; 04809 HRESULT hr; 04810 04811 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 04812 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE)) 04813 { 04814 TRACE("found in module or in enum: %s\n", debugstr_w(szName)); 04815 return S_OK; 04816 } 04817 else if (hr == TYPE_E_TYPEMISMATCH) 04818 typemismatch = 1; 04819 } 04820 04821 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) && 04822 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT)) 04823 { 04824 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; 04825 HRESULT hr; 04826 ITypeInfo *subtypeinfo; 04827 BINDPTR subbindptr; 04828 DESCKIND subdesckind; 04829 04830 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, 04831 &subtypeinfo, &subdesckind, &subbindptr); 04832 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE)) 04833 { 04834 TYPEDESC tdesc_appobject; 04835 const VARDESC vardesc_appobject = 04836 { 04837 -2, /* memid */ 04838 NULL, /* lpstrSchema */ 04839 { 04840 0 /* oInst */ 04841 }, 04842 { 04843 /* ELEMDESC */ 04844 { 04845 /* TYPEDESC */ 04846 { 04847 &tdesc_appobject 04848 }, 04849 VT_PTR 04850 }, 04851 }, 04852 0, /* wVarFlags */ 04853 VAR_STATIC /* varkind */ 04854 }; 04855 04856 tdesc_appobject.u.hreftype = pTypeInfo->hreftype; 04857 tdesc_appobject.vt = VT_USERDEFINED; 04858 04859 TRACE("found in implicit app object: %s\n", debugstr_w(szName)); 04860 04861 /* cleanup things filled in by Bind call so we can put our 04862 * application object data in there instead */ 04863 switch (subdesckind) 04864 { 04865 case DESCKIND_FUNCDESC: 04866 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc); 04867 break; 04868 case DESCKIND_VARDESC: 04869 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc); 04870 break; 04871 default: 04872 break; 04873 } 04874 if (subtypeinfo) ITypeInfo_Release(subtypeinfo); 04875 04876 if (pTypeInfo->hreftype == -1) 04877 FIXME("no hreftype for interface %p\n", pTypeInfo); 04878 04879 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc); 04880 if (FAILED(hr)) 04881 return hr; 04882 04883 *pDescKind = DESCKIND_IMPLICITAPPOBJ; 04884 *ppTInfo = (ITypeInfo *)pTypeInfo; 04885 ITypeInfo_AddRef(*ppTInfo); 04886 return S_OK; 04887 } 04888 else if (hr == TYPE_E_TYPEMISMATCH) 04889 typemismatch = 1; 04890 } 04891 } 04892 04893 if (typemismatch) 04894 { 04895 TRACE("type mismatch %s\n", debugstr_w(szName)); 04896 return TYPE_E_TYPEMISMATCH; 04897 } 04898 else 04899 { 04900 TRACE("name not found %s\n", debugstr_w(szName)); 04901 return S_OK; 04902 } 04903 } 04904 04905 static HRESULT WINAPI ITypeLibComp_fnBindType( 04906 ITypeComp * iface, 04907 OLECHAR * szName, 04908 ULONG lHash, 04909 ITypeInfo ** ppTInfo, 04910 ITypeComp ** ppTComp) 04911 { 04912 ITypeLibImpl *This = impl_from_ITypeComp(iface); 04913 ITypeInfoImpl *pTypeInfo; 04914 04915 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp); 04916 04917 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next) 04918 { 04919 /* FIXME: should use lHash to do the search */ 04920 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName)) 04921 { 04922 TRACE("returning %p\n", pTypeInfo); 04923 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl; 04924 ITypeInfo_AddRef(*ppTInfo); 04925 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; 04926 ITypeComp_AddRef(*ppTComp); 04927 return S_OK; 04928 } 04929 } 04930 04931 TRACE("not found\n"); 04932 *ppTInfo = NULL; 04933 *ppTComp = NULL; 04934 return S_OK; 04935 } 04936 04937 static const ITypeCompVtbl tlbtcvt = 04938 { 04939 04940 ITypeLibComp_fnQueryInterface, 04941 ITypeLibComp_fnAddRef, 04942 ITypeLibComp_fnRelease, 04943 04944 ITypeLibComp_fnBind, 04945 ITypeLibComp_fnBindType 04946 }; 04947 04948 /*================== ITypeInfo(2) Methods ===================================*/ 04949 static ITypeInfo2 * ITypeInfo_Constructor(void) 04950 { 04951 ITypeInfoImpl * pTypeInfoImpl; 04952 04953 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl)); 04954 if (pTypeInfoImpl) 04955 { 04956 pTypeInfoImpl->lpVtbl = &tinfvt; 04957 pTypeInfoImpl->lpVtblTypeComp = &tcompvt; 04958 pTypeInfoImpl->ref = 0; 04959 pTypeInfoImpl->hreftype = -1; 04960 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL; 04961 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL; 04962 } 04963 TRACE("(%p)\n", pTypeInfoImpl); 04964 return (ITypeInfo2*) pTypeInfoImpl; 04965 } 04966 04967 /* ITypeInfo::QueryInterface 04968 */ 04969 static HRESULT WINAPI ITypeInfo_fnQueryInterface( 04970 ITypeInfo2 *iface, 04971 REFIID riid, 04972 VOID **ppvObject) 04973 { 04974 ITypeLibImpl *This = (ITypeLibImpl *)iface; 04975 04976 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid)); 04977 04978 *ppvObject=NULL; 04979 if(IsEqualIID(riid, &IID_IUnknown) || 04980 IsEqualIID(riid,&IID_ITypeInfo)|| 04981 IsEqualIID(riid,&IID_ITypeInfo2)) 04982 *ppvObject = This; 04983 04984 if(*ppvObject){ 04985 ITypeInfo_AddRef(iface); 04986 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject); 04987 return S_OK; 04988 } 04989 TRACE("-- Interface: E_NOINTERFACE\n"); 04990 return E_NOINTERFACE; 04991 } 04992 04993 /* ITypeInfo::AddRef 04994 */ 04995 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface) 04996 { 04997 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 04998 ULONG ref = InterlockedIncrement(&This->ref); 04999 05000 TRACE("(%p)->ref is %u\n",This, ref); 05001 05002 if (ref == 1 /* incremented from 0 */) 05003 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib); 05004 05005 return ref; 05006 } 05007 05008 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This) 05009 { 05010 TLBFuncDesc *pFInfo, *pFInfoNext; 05011 TLBVarDesc *pVInfo, *pVInfoNext; 05012 TLBImplType *pImpl, *pImplNext; 05013 05014 TRACE("destroying ITypeInfo(%p)\n",This); 05015 05016 SysFreeString(This->Name); 05017 This->Name = NULL; 05018 05019 SysFreeString(This->DocString); 05020 This->DocString = NULL; 05021 05022 SysFreeString(This->DllName); 05023 This->DllName = NULL; 05024 05025 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext) 05026 { 05027 INT i; 05028 for(i = 0;i < pFInfo->funcdesc.cParams; i++) 05029 { 05030 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i]; 05031 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 05032 { 05033 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue); 05034 TLB_Free(elemdesc->u.paramdesc.pparamdescex); 05035 } 05036 SysFreeString(pFInfo->pParamDesc[i].Name); 05037 } 05038 TLB_Free(pFInfo->funcdesc.lprgelemdescParam); 05039 TLB_Free(pFInfo->pParamDesc); 05040 TLB_FreeCustData(pFInfo->pCustData); 05041 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1) 05042 SysFreeString(pFInfo->Entry); 05043 SysFreeString(pFInfo->HelpString); 05044 SysFreeString(pFInfo->Name); 05045 05046 pFInfoNext = pFInfo->next; 05047 TLB_Free(pFInfo); 05048 } 05049 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext) 05050 { 05051 if (pVInfo->vardesc.varkind == VAR_CONST) 05052 { 05053 VariantClear(pVInfo->vardesc.u.lpvarValue); 05054 TLB_Free(pVInfo->vardesc.u.lpvarValue); 05055 } 05056 TLB_FreeCustData(pVInfo->pCustData); 05057 SysFreeString(pVInfo->Name); 05058 pVInfoNext = pVInfo->next; 05059 TLB_Free(pVInfo); 05060 } 05061 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext) 05062 { 05063 TLB_FreeCustData(pImpl->pCustData); 05064 pImplNext = pImpl->next; 05065 TLB_Free(pImpl); 05066 } 05067 TLB_FreeCustData(This->pCustData); 05068 05069 HeapFree(GetProcessHeap(), 0, This); 05070 } 05071 05072 /* ITypeInfo::Release 05073 */ 05074 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface) 05075 { 05076 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05077 ULONG ref = InterlockedDecrement(&This->ref); 05078 05079 TRACE("(%p)->(%u)\n",This, ref); 05080 05081 if (!ref) 05082 { 05083 BOOL not_attached_to_typelib = This->not_attached_to_typelib; 05084 ITypeLib2_Release((ITypeLib2*)This->pTypeLib); 05085 if (not_attached_to_typelib) 05086 HeapFree(GetProcessHeap(), 0, This); 05087 /* otherwise This will be freed when typelib is freed */ 05088 } 05089 05090 return ref; 05091 } 05092 05093 /* ITypeInfo::GetTypeAttr 05094 * 05095 * Retrieves a TYPEATTR structure that contains the attributes of the type 05096 * description. 05097 * 05098 */ 05099 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface, 05100 LPTYPEATTR *ppTypeAttr) 05101 { 05102 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05103 SIZE_T size; 05104 05105 TRACE("(%p)\n",This); 05106 05107 size = sizeof(**ppTypeAttr); 05108 if (This->TypeAttr.typekind == TKIND_ALIAS) 05109 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE); 05110 05111 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size); 05112 if (!*ppTypeAttr) 05113 return E_OUTOFMEMORY; 05114 05115 **ppTypeAttr = This->TypeAttr; 05116 05117 if (This->TypeAttr.typekind == TKIND_ALIAS) 05118 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, 05119 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1); 05120 05121 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) { 05122 /* This should include all the inherited funcs */ 05123 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *); 05124 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */ 05125 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION; 05126 } 05127 return S_OK; 05128 } 05129 05130 /* ITypeInfo::GetTypeComp 05131 * 05132 * Retrieves the ITypeComp interface for the type description, which enables a 05133 * client compiler to bind to the type description's members. 05134 * 05135 */ 05136 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface, 05137 ITypeComp * *ppTComp) 05138 { 05139 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05140 05141 TRACE("(%p)->(%p)\n", This, ppTComp); 05142 05143 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp; 05144 ITypeComp_AddRef(*ppTComp); 05145 return S_OK; 05146 } 05147 05148 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc ) 05149 { 05150 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE); 05151 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 05152 size += sizeof(*elemdesc->u.paramdesc.pparamdescex); 05153 return size; 05154 } 05155 05156 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer ) 05157 { 05158 *dest = *src; 05159 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer); 05160 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 05161 { 05162 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex; 05163 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer; 05164 *buffer += sizeof(PARAMDESCEX); 05165 *pparamdescex_dest = *pparamdescex_src; 05166 VariantInit(&pparamdescex_dest->varDefaultValue); 05167 return VariantCopy(&pparamdescex_dest->varDefaultValue, 05168 (VARIANTARG *)&pparamdescex_src->varDefaultValue); 05169 } 05170 else 05171 dest->u.paramdesc.pparamdescex = NULL; 05172 return S_OK; 05173 } 05174 05175 static void TLB_FreeElemDesc( ELEMDESC *elemdesc ) 05176 { 05177 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) 05178 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue); 05179 } 05180 05181 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface ) 05182 { 05183 FUNCDESC *dest; 05184 char *buffer; 05185 SIZE_T size = sizeof(*src); 05186 SHORT i; 05187 HRESULT hr; 05188 05189 size += sizeof(*src->lprgscode) * src->cScodes; 05190 size += TLB_SizeElemDesc(&src->elemdescFunc); 05191 for (i = 0; i < src->cParams; i++) 05192 { 05193 size += sizeof(ELEMDESC); 05194 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]); 05195 } 05196 05197 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size); 05198 if (!dest) return E_OUTOFMEMORY; 05199 05200 *dest = *src; 05201 if (dispinterface) /* overwrite funckind */ 05202 dest->funckind = FUNC_DISPATCH; 05203 buffer = (char *)(dest + 1); 05204 05205 dest->lprgscode = (SCODE *)buffer; 05206 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes); 05207 buffer += sizeof(*src->lprgscode) * src->cScodes; 05208 05209 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer); 05210 if (FAILED(hr)) 05211 { 05212 SysFreeString((BSTR)dest); 05213 return hr; 05214 } 05215 05216 dest->lprgelemdescParam = (ELEMDESC *)buffer; 05217 buffer += sizeof(ELEMDESC) * src->cParams; 05218 for (i = 0; i < src->cParams; i++) 05219 { 05220 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer); 05221 if (FAILED(hr)) 05222 break; 05223 } 05224 if (FAILED(hr)) 05225 { 05226 /* undo the above actions */ 05227 for (i = i - 1; i >= 0; i--) 05228 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]); 05229 TLB_FreeElemDesc(&dest->elemdescFunc); 05230 SysFreeString((BSTR)dest); 05231 return hr; 05232 } 05233 05234 /* special treatment for dispinterfaces: this makes functions appear 05235 * to return their [retval] value when it is really returning an 05236 * HRESULT */ 05237 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT) 05238 { 05239 if (dest->cParams && 05240 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL)) 05241 { 05242 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1]; 05243 if (elemdesc->tdesc.vt != VT_PTR) 05244 { 05245 ERR("elemdesc should have started with VT_PTR instead of:\n"); 05246 if (ERR_ON(ole)) 05247 dump_ELEMDESC(elemdesc); 05248 return E_UNEXPECTED; 05249 } 05250 05251 /* copy last parameter to the return value. we are using a flat 05252 * buffer so there is no danger of leaking memory in 05253 * elemdescFunc */ 05254 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc; 05255 05256 /* remove the last parameter */ 05257 dest->cParams--; 05258 } 05259 else 05260 /* otherwise this function is made to appear to have no return 05261 * value */ 05262 dest->elemdescFunc.tdesc.vt = VT_VOID; 05263 05264 } 05265 05266 *dest_ptr = dest; 05267 return S_OK; 05268 } 05269 05270 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc ) 05271 { 05272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05273 const TLBFuncDesc *pFDesc; 05274 UINT i; 05275 05276 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next) 05277 ; 05278 05279 if (pFDesc) 05280 { 05281 *ppFuncDesc = &pFDesc->funcdesc; 05282 return S_OK; 05283 } 05284 05285 return TYPE_E_ELEMENTNOTFOUND; 05286 } 05287 05288 /* internal function to make the inherited interfaces' methods appear 05289 * part of the interface */ 05290 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface, 05291 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset) 05292 { 05293 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05294 HRESULT hr; 05295 UINT implemented_funcs = 0; 05296 05297 if (funcs) 05298 *funcs = 0; 05299 else 05300 *hrefoffset = DISPATCH_HREF_OFFSET; 05301 05302 if(This->impltypelist) 05303 { 05304 ITypeInfo *pSubTypeInfo; 05305 UINT sub_funcs; 05306 05307 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo); 05308 if (FAILED(hr)) 05309 return hr; 05310 05311 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo, 05312 index, 05313 ppFuncDesc, 05314 &sub_funcs, hrefoffset); 05315 implemented_funcs += sub_funcs; 05316 ITypeInfo_Release(pSubTypeInfo); 05317 if (SUCCEEDED(hr)) 05318 return hr; 05319 *hrefoffset += DISPATCH_HREF_OFFSET; 05320 } 05321 05322 if (funcs) 05323 *funcs = implemented_funcs + This->TypeAttr.cFuncs; 05324 else 05325 *hrefoffset = 0; 05326 05327 if (index < implemented_funcs) 05328 return E_INVALIDARG; 05329 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs, 05330 ppFuncDesc); 05331 } 05332 05333 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset) 05334 { 05335 TYPEDESC *pTypeDesc = &pElemDesc->tdesc; 05336 while (TRUE) 05337 { 05338 switch (pTypeDesc->vt) 05339 { 05340 case VT_USERDEFINED: 05341 pTypeDesc->u.hreftype += hrefoffset; 05342 return; 05343 case VT_PTR: 05344 case VT_SAFEARRAY: 05345 pTypeDesc = pTypeDesc->u.lptdesc; 05346 break; 05347 case VT_CARRAY: 05348 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem; 05349 break; 05350 default: 05351 return; 05352 } 05353 } 05354 } 05355 05356 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset) 05357 { 05358 SHORT i; 05359 for (i = 0; i < pFuncDesc->cParams; i++) 05360 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset); 05361 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset); 05362 } 05363 05364 /* ITypeInfo::GetFuncDesc 05365 * 05366 * Retrieves the FUNCDESC structure that contains information about a 05367 * specified function. 05368 * 05369 */ 05370 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index, 05371 LPFUNCDESC *ppFuncDesc) 05372 { 05373 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05374 const FUNCDESC *internal_funcdesc; 05375 HRESULT hr; 05376 UINT hrefoffset = 0; 05377 05378 TRACE("(%p) index %d\n", This, index); 05379 05380 if (This->TypeAttr.typekind == TKIND_DISPATCH) 05381 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index, 05382 &internal_funcdesc, NULL, 05383 &hrefoffset); 05384 else 05385 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, 05386 &internal_funcdesc); 05387 if (FAILED(hr)) 05388 { 05389 WARN("description for function %d not found\n", index); 05390 return hr; 05391 } 05392 05393 hr = TLB_AllocAndInitFuncDesc( 05394 internal_funcdesc, 05395 ppFuncDesc, 05396 This->TypeAttr.typekind == TKIND_DISPATCH); 05397 05398 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset) 05399 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset); 05400 05401 TRACE("-- 0x%08x\n", hr); 05402 return hr; 05403 } 05404 05405 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr ) 05406 { 05407 VARDESC *dest; 05408 char *buffer; 05409 SIZE_T size = sizeof(*src); 05410 HRESULT hr; 05411 05412 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR); 05413 if (src->varkind == VAR_CONST) 05414 size += sizeof(VARIANT); 05415 size += TLB_SizeElemDesc(&src->elemdescVar); 05416 05417 dest = (VARDESC *)SysAllocStringByteLen(NULL, size); 05418 if (!dest) return E_OUTOFMEMORY; 05419 05420 *dest = *src; 05421 buffer = (char *)(dest + 1); 05422 if (src->lpstrSchema) 05423 { 05424 int len; 05425 dest->lpstrSchema = (LPOLESTR)buffer; 05426 len = strlenW(src->lpstrSchema); 05427 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR)); 05428 buffer += (len + 1) * sizeof(WCHAR); 05429 } 05430 05431 if (src->varkind == VAR_CONST) 05432 { 05433 HRESULT hr; 05434 05435 dest->u.lpvarValue = (VARIANT *)buffer; 05436 *dest->u.lpvarValue = *src->u.lpvarValue; 05437 buffer += sizeof(VARIANT); 05438 VariantInit(dest->u.lpvarValue); 05439 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue); 05440 if (FAILED(hr)) 05441 { 05442 SysFreeString((BSTR)dest); 05443 return hr; 05444 } 05445 } 05446 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer); 05447 if (FAILED(hr)) 05448 { 05449 if (src->varkind == VAR_CONST) 05450 VariantClear(dest->u.lpvarValue); 05451 SysFreeString((BSTR)dest); 05452 return hr; 05453 } 05454 *dest_ptr = dest; 05455 return S_OK; 05456 } 05457 05458 /* ITypeInfo::GetVarDesc 05459 * 05460 * Retrieves a VARDESC structure that describes the specified variable. 05461 * 05462 */ 05463 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index, 05464 LPVARDESC *ppVarDesc) 05465 { 05466 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05467 UINT i; 05468 const TLBVarDesc *pVDesc; 05469 05470 TRACE("(%p) index %d\n", This, index); 05471 05472 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next) 05473 ; 05474 05475 if (pVDesc) 05476 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc); 05477 05478 return E_INVALIDARG; 05479 } 05480 05481 /* ITypeInfo_GetNames 05482 * 05483 * Retrieves the variable with the specified member ID (or the name of the 05484 * property or method and its parameters) that correspond to the specified 05485 * function ID. 05486 */ 05487 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid, 05488 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames) 05489 { 05490 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05491 const TLBFuncDesc *pFDesc; 05492 const TLBVarDesc *pVDesc; 05493 int i; 05494 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames); 05495 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next); 05496 if(pFDesc) 05497 { 05498 /* function found, now return function and parameter names */ 05499 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++) 05500 { 05501 if(!i) 05502 *rgBstrNames=SysAllocString(pFDesc->Name); 05503 else 05504 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name); 05505 } 05506 *pcNames=i; 05507 } 05508 else 05509 { 05510 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next); 05511 if(pVDesc) 05512 { 05513 *rgBstrNames=SysAllocString(pVDesc->Name); 05514 *pcNames=1; 05515 } 05516 else 05517 { 05518 if(This->impltypelist && 05519 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) { 05520 /* recursive search */ 05521 ITypeInfo *pTInfo; 05522 HRESULT result; 05523 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, 05524 &pTInfo); 05525 if(SUCCEEDED(result)) 05526 { 05527 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames); 05528 ITypeInfo_Release(pTInfo); 05529 return result; 05530 } 05531 WARN("Could not search inherited interface!\n"); 05532 } 05533 else 05534 { 05535 WARN("no names found\n"); 05536 } 05537 *pcNames=0; 05538 return TYPE_E_ELEMENTNOTFOUND; 05539 } 05540 } 05541 return S_OK; 05542 } 05543 05544 05545 /* ITypeInfo::GetRefTypeOfImplType 05546 * 05547 * If a type description describes a COM class, it retrieves the type 05548 * description of the implemented interface types. For an interface, 05549 * GetRefTypeOfImplType returns the type information for inherited interfaces, 05550 * if any exist. 05551 * 05552 */ 05553 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( 05554 ITypeInfo2 *iface, 05555 UINT index, 05556 HREFTYPE *pRefType) 05557 { 05558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05559 UINT i; 05560 HRESULT hr = S_OK; 05561 const TLBImplType *pImpl = This->impltypelist; 05562 05563 TRACE("(%p) index %d\n", This, index); 05564 if (TRACE_ON(ole)) dump_TypeInfo(This); 05565 05566 if(index==(UINT)-1) 05567 { 05568 /* only valid on dual interfaces; 05569 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH 05570 */ 05571 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG; 05572 05573 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL) 05574 { 05575 *pRefType = -1; 05576 } 05577 else 05578 { 05579 hr = TYPE_E_ELEMENTNOTFOUND; 05580 } 05581 } 05582 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH) 05583 { 05584 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */ 05585 *pRefType = This->pTypeLib->dispatch_href; 05586 } 05587 else 05588 { 05589 /* get element n from linked list */ 05590 for(i=0; pImpl && i<index; i++) 05591 { 05592 pImpl = pImpl->next; 05593 } 05594 05595 if (pImpl) 05596 *pRefType = pImpl->hRef; 05597 else 05598 hr = TYPE_E_ELEMENTNOTFOUND; 05599 } 05600 05601 if(TRACE_ON(ole)) 05602 { 05603 if(SUCCEEDED(hr)) 05604 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType ); 05605 else 05606 TRACE("FAILURE -- hresult = 0x%08x\n", hr); 05607 } 05608 05609 return hr; 05610 } 05611 05612 /* ITypeInfo::GetImplTypeFlags 05613 * 05614 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface 05615 * or base interface in a type description. 05616 */ 05617 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface, 05618 UINT index, INT *pImplTypeFlags) 05619 { 05620 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05621 UINT i; 05622 TLBImplType *pImpl; 05623 05624 TRACE("(%p) index %d\n", This, index); 05625 for(i=0, pImpl=This->impltypelist; i<index && pImpl; 05626 i++, pImpl=pImpl->next) 05627 ; 05628 if(i==index && pImpl){ 05629 *pImplTypeFlags=pImpl->implflags; 05630 return S_OK; 05631 } 05632 *pImplTypeFlags=0; 05633 05634 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index) 05635 return S_OK; 05636 05637 WARN("ImplType %d not found\n", index); 05638 return TYPE_E_ELEMENTNOTFOUND; 05639 } 05640 05641 /* GetIDsOfNames 05642 * Maps between member names and member IDs, and parameter names and 05643 * parameter IDs. 05644 */ 05645 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface, 05646 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId) 05647 { 05648 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 05649 const TLBFuncDesc *pFDesc; 05650 const TLBVarDesc *pVDesc; 05651 HRESULT ret=S_OK; 05652 UINT i; 05653 05654 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames), 05655 cNames); 05656 05657 /* init out parameters in case of failure */ 05658 for (i = 0; i < cNames; i++) 05659 pMemId[i] = MEMBERID_NIL; 05660 05661 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) { 05662 int j; 05663 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) { 05664 if(cNames) *pMemId=pFDesc->funcdesc.memid; 05665 for(i=1; i < cNames; i++){ 05666 for(j=0; j<pFDesc->funcdesc.cParams; j++) 05667 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name)) 05668 break; 05669 if( j<pFDesc->funcdesc.cParams) 05670 pMemId[i]=j; 05671 else 05672 ret=DISP_E_UNKNOWNNAME; 05673 }; 05674 TRACE("-- 0x%08x\n", ret); 05675 return ret; 05676 } 05677 } 05678 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) { 05679 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) { 05680 if(cNames) *pMemId=pVDesc->vardesc.memid; 05681 return ret; 05682 } 05683 } 05684 /* not found, see if it can be found in an inherited interface */ 05685 if(This->impltypelist) { 05686 /* recursive search */ 05687 ITypeInfo *pTInfo; 05688 ret=ITypeInfo_GetRefTypeInfo(iface, 05689 This->impltypelist->hRef, &pTInfo); 05690 if(SUCCEEDED(ret)){ 05691 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId ); 05692 ITypeInfo_Release(pTInfo); 05693 return ret; 05694 } 05695 WARN("Could not search inherited interface!\n"); 05696 } else 05697 WARN("no names found\n"); 05698 return DISP_E_UNKNOWNNAME; 05699 } 05700 05701 05702 #ifdef __i386__ 05703 05704 extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args ); 05705 __ASM_GLOBAL_FUNC( call_method, 05706 "pushl %ebp\n\t" 05707 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") 05708 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") 05709 "movl %esp,%ebp\n\t" 05710 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") 05711 "pushl %esi\n\t" 05712 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t") 05713 "pushl %edi\n\t" 05714 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t") 05715 "movl 12(%ebp),%edx\n\t" 05716 "shll $2,%edx\n\t" 05717 "jz 1f\n\t" 05718 "subl %edx,%esp\n\t" 05719 "andl $~15,%esp\n\t" 05720 "movl 12(%ebp),%ecx\n\t" 05721 "movl 16(%ebp),%esi\n\t" 05722 "movl %esp,%edi\n\t" 05723 "cld\n\t" 05724 "rep; movsl\n" 05725 "1:\tcall *8(%ebp)\n\t" 05726 "leal -8(%ebp),%esp\n\t" 05727 "popl %edi\n\t" 05728 __ASM_CFI(".cfi_same_value %edi\n\t") 05729 "popl %esi\n\t" 05730 __ASM_CFI(".cfi_same_value %esi\n\t") 05731 "popl %ebp\n\t" 05732 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") 05733 __ASM_CFI(".cfi_same_value %ebp\n\t") 05734 "ret" ) 05735 05736 /* ITypeInfo::Invoke 05737 * 05738 * Invokes a method, or accesses a property of an object, that implements the 05739 * interface described by the type description. 05740 */ 05741 DWORD 05742 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) { 05743 DWORD res; 05744 05745 if (TRACE_ON(ole)) { 05746 int i; 05747 TRACE("Calling %p(",func); 05748 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]); 05749 if (nrargs > 30) TRACE("..."); 05750 TRACE(")\n"); 05751 } 05752 05753 switch (callconv) { 05754 case CC_STDCALL: 05755 case CC_CDECL: 05756 res = call_method( func, nrargs, args ); 05757 break; 05758 default: 05759 FIXME("unsupported calling convention %d\n",callconv); 05760 res = -1; 05761 break; 05762 } 05763 TRACE("returns %08x\n",res); 05764 return res; 05765 } 05766 05767 /* The size of the argument on the stack in DWORD units (in all x86 call 05768 * convetions the arguments on the stack are DWORD-aligned) 05769 */ 05770 static int _dispargsize(VARTYPE vt) 05771 { 05772 switch (vt) { 05773 case VT_I8: 05774 case VT_UI8: 05775 return 8/sizeof(DWORD); 05776 case VT_R8: 05777 return sizeof(double)/sizeof(DWORD); 05778 case VT_DECIMAL: 05779 return (sizeof(DECIMAL)+3)/sizeof(DWORD); 05780 case VT_CY: 05781 return sizeof(CY)/sizeof(DWORD); 05782 case VT_DATE: 05783 return sizeof(DATE)/sizeof(DWORD); 05784 case VT_VARIANT: 05785 return (sizeof(VARIANT)+3)/sizeof(DWORD); 05786 case VT_RECORD: 05787 FIXME("VT_RECORD not implemented\n"); 05788 return 1; 05789 default: 05790 return 1; 05791 } 05792 } 05793 #endif /* __i386__ */ 05794 05795 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt) 05796 { 05797 HRESULT hr = S_OK; 05798 ITypeInfo *tinfo2 = NULL; 05799 TYPEATTR *tattr = NULL; 05800 05801 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2); 05802 if (hr) 05803 { 05804 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, " 05805 "hr = 0x%08x\n", 05806 tdesc->u.hreftype, hr); 05807 return hr; 05808 } 05809 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr); 05810 if (hr) 05811 { 05812 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr); 05813 ITypeInfo_Release(tinfo2); 05814 return hr; 05815 } 05816 05817 switch (tattr->typekind) 05818 { 05819 case TKIND_ENUM: 05820 *vt |= VT_I4; 05821 break; 05822 05823 case TKIND_ALIAS: 05824 tdesc = &tattr->tdescAlias; 05825 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt); 05826 break; 05827 05828 case TKIND_INTERFACE: 05829 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE) 05830 *vt |= VT_DISPATCH; 05831 else 05832 *vt |= VT_UNKNOWN; 05833 break; 05834 05835 case TKIND_DISPATCH: 05836 *vt |= VT_DISPATCH; 05837 break; 05838 05839 case TKIND_COCLASS: 05840 *vt |= VT_DISPATCH; 05841 break; 05842 05843 case TKIND_RECORD: 05844 FIXME("TKIND_RECORD unhandled.\n"); 05845 hr = E_NOTIMPL; 05846 break; 05847 05848 case TKIND_UNION: 05849 FIXME("TKIND_UNION unhandled.\n"); 05850 hr = E_NOTIMPL; 05851 break; 05852 05853 default: 05854 FIXME("TKIND %d unhandled.\n",tattr->typekind); 05855 hr = E_NOTIMPL; 05856 break; 05857 } 05858 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr); 05859 ITypeInfo_Release(tinfo2); 05860 return hr; 05861 } 05862 05863 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt) 05864 { 05865 HRESULT hr = S_OK; 05866 05867 /* enforce only one level of pointer indirection */ 05868 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR)) 05869 { 05870 tdesc = tdesc->u.lptdesc; 05871 05872 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or 05873 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into 05874 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */ 05875 if ((tdesc->vt == VT_USERDEFINED) || 05876 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED))) 05877 { 05878 VARTYPE vt_userdefined = 0; 05879 const TYPEDESC *tdesc_userdefined = tdesc; 05880 if (tdesc->vt == VT_PTR) 05881 { 05882 vt_userdefined = VT_BYREF; 05883 tdesc_userdefined = tdesc->u.lptdesc; 05884 } 05885 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined); 05886 if ((hr == S_OK) && 05887 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) || 05888 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH))) 05889 { 05890 *vt |= vt_userdefined; 05891 return S_OK; 05892 } 05893 } 05894 *vt = VT_BYREF; 05895 } 05896 05897 switch (tdesc->vt) 05898 { 05899 case VT_HRESULT: 05900 *vt |= VT_ERROR; 05901 break; 05902 case VT_USERDEFINED: 05903 hr = userdefined_to_variantvt(tinfo, tdesc, vt); 05904 break; 05905 case VT_VOID: 05906 case VT_CARRAY: 05907 case VT_PTR: 05908 case VT_LPSTR: 05909 case VT_LPWSTR: 05910 ERR("cannot convert type %d into variant VT\n", tdesc->vt); 05911 hr = DISP_E_BADVARTYPE; 05912 break; 05913 case VT_SAFEARRAY: 05914 *vt |= VT_ARRAY; 05915 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt); 05916 break; 05917 case VT_INT: 05918 *vt |= VT_I4; 05919 break; 05920 case VT_UINT: 05921 *vt |= VT_UI4; 05922 break; 05923 default: 05924 *vt |= tdesc->vt; 05925 break; 05926 } 05927 return hr; 05928 } 05929 05930 /*********************************************************************** 05931 * DispCallFunc (OLEAUT32.@) 05932 * 05933 * Invokes a function of the specified calling convention, passing the 05934 * specified arguments and returns the result. 05935 * 05936 * PARAMS 05937 * pvInstance [I] Optional pointer to the instance whose function to invoke. 05938 * oVft [I] The offset in the vtable. See notes. 05939 * cc [I] Calling convention of the function to call. 05940 * vtReturn [I] The return type of the function. 05941 * cActuals [I] Number of parameters. 05942 * prgvt [I] The types of the parameters to pass. This is used for sizing only. 05943 * prgpvarg [I] The arguments to pass. 05944 * pvargResult [O] The return value of the function. Can be NULL. 05945 * 05946 * RETURNS 05947 * Success: S_OK. 05948 * Failure: HRESULT code. 05949 * 05950 * NOTES 05951 * The HRESULT return value of this function is not affected by the return 05952 * value of the user supplied function, which is returned in pvargResult. 05953 * 05954 * If pvInstance is NULL then a non-object function is to be called and oVft 05955 * is the address of the function to call. 05956 * 05957 * The cc parameter can be one of the following values: 05958 *|CC_FASTCALL 05959 *|CC_CDECL 05960 *|CC_PASCAL 05961 *|CC_STDCALL 05962 *|CC_FPFASTCALL 05963 *|CC_SYSCALL 05964 *|CC_MPWCDECL 05965 *|CC_MPWPASCAL 05966 * 05967 */ 05968 HRESULT WINAPI 05969 DispCallFunc( 05970 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals, 05971 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult) 05972 { 05973 #ifdef __i386__ 05974 int argsize, argspos; 05975 UINT i; 05976 DWORD *args; 05977 HRESULT hres; 05978 05979 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n", 05980 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, 05981 pvargResult, V_VT(pvargResult)); 05982 05983 argsize = 0; 05984 if (pvInstance) 05985 argsize++; /* for This pointer */ 05986 05987 for (i=0;i<cActuals;i++) 05988 { 05989 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i])); 05990 dump_Variant(prgpvarg[i]); 05991 argsize += _dispargsize(prgvt[i]); 05992 } 05993 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize); 05994 05995 argspos = 0; 05996 if (pvInstance) 05997 { 05998 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */ 05999 argspos++; 06000 } 06001 06002 for (i=0;i<cActuals;i++) 06003 { 06004 VARIANT *arg = prgpvarg[i]; 06005 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]); 06006 if (prgvt[i] == VT_VARIANT) 06007 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD)); 06008 else 06009 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD)); 06010 argspos += _dispargsize(prgvt[i]); 06011 } 06012 06013 if (pvInstance) 06014 { 06015 FARPROC *vtable = *(FARPROC**)pvInstance; 06016 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args); 06017 } 06018 else 06019 /* if we aren't invoking an object then the function pointer is stored 06020 * in oVft */ 06021 hres = _invoke((FARPROC)oVft, cc, argsize, args); 06022 06023 if (pvargResult && (vtReturn != VT_EMPTY)) 06024 { 06025 TRACE("Method returned 0x%08x\n",hres); 06026 V_VT(pvargResult) = vtReturn; 06027 V_UI4(pvargResult) = hres; 06028 } 06029 HeapFree(GetProcessHeap(),0,args); 06030 return S_OK; 06031 #else 06032 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n", 06033 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)); 06034 return E_NOTIMPL; 06035 #endif 06036 } 06037 06038 #define INVBUF_ELEMENT_SIZE \ 06039 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE)) 06040 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer) 06041 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \ 06042 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params))) 06043 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \ 06044 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params))) 06045 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \ 06046 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params))) 06047 06048 static HRESULT WINAPI ITypeInfo_fnInvoke( 06049 ITypeInfo2 *iface, 06050 VOID *pIUnk, 06051 MEMBERID memid, 06052 UINT16 wFlags, 06053 DISPPARAMS *pDispParams, 06054 VARIANT *pVarResult, 06055 EXCEPINFO *pExcepInfo, 06056 UINT *pArgErr) 06057 { 06058 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06059 int i; 06060 unsigned int var_index; 06061 TYPEKIND type_kind; 06062 HRESULT hres; 06063 const TLBFuncDesc *pFuncInfo; 06064 06065 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n", 06066 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr 06067 ); 06068 06069 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED ) 06070 return DISP_E_MEMBERNOTFOUND; 06071 06072 if (!pDispParams) 06073 { 06074 ERR("NULL pDispParams not allowed\n"); 06075 return E_INVALIDARG; 06076 } 06077 06078 dump_DispParms(pDispParams); 06079 06080 if (pDispParams->cNamedArgs > pDispParams->cArgs) 06081 { 06082 ERR("named argument array cannot be bigger than argument array (%d/%d)\n", 06083 pDispParams->cNamedArgs, pDispParams->cArgs); 06084 return E_INVALIDARG; 06085 } 06086 06087 /* we do this instead of using GetFuncDesc since it will return a fake 06088 * FUNCDESC for dispinterfaces and we want the real function description */ 06089 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next) 06090 if ((memid == pFuncInfo->funcdesc.memid) && 06091 (wFlags & pFuncInfo->funcdesc.invkind) && 06092 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0) 06093 break; 06094 06095 if (pFuncInfo) { 06096 const FUNCDESC *func_desc = &pFuncInfo->funcdesc; 06097 06098 if (TRACE_ON(ole)) 06099 { 06100 TRACE("invoking:\n"); 06101 dump_TLBFuncDescOne(pFuncInfo); 06102 } 06103 06104 switch (func_desc->funckind) { 06105 case FUNC_PUREVIRTUAL: 06106 case FUNC_VIRTUAL: { 06107 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams); 06108 VARIANT varresult; 06109 VARIANT retval; /* pointer for storing byref retvals in */ 06110 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams); 06111 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams); 06112 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams); 06113 UINT cNamedArgs = pDispParams->cNamedArgs; 06114 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs; 06115 UINT vargs_converted=0; 06116 06117 hres = S_OK; 06118 06119 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF)) 06120 { 06121 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT)) 06122 { 06123 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n"); 06124 hres = DISP_E_PARAMNOTFOUND; 06125 goto func_fail; 06126 } 06127 } 06128 06129 if (func_desc->cParamsOpt < 0 && cNamedArgs) 06130 { 06131 ERR("functions with the vararg attribute do not support named arguments\n"); 06132 hres = DISP_E_NONAMEDARGS; 06133 goto func_fail; 06134 } 06135 06136 for (i = 0; i < func_desc->cParams; i++) 06137 { 06138 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; 06139 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]); 06140 if (FAILED(hres)) 06141 goto func_fail; 06142 } 06143 06144 TRACE("changing args\n"); 06145 for (i = 0; i < func_desc->cParams; i++) 06146 { 06147 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; 06148 VARIANTARG *src_arg; 06149 06150 if (wParamFlags & PARAMFLAG_FLCID) 06151 { 06152 VARIANTARG *arg; 06153 arg = prgpvarg[i] = &rgvarg[i]; 06154 V_VT(arg) = VT_I4; 06155 V_I4(arg) = This->pTypeLib->lcid; 06156 continue; 06157 } 06158 06159 src_arg = NULL; 06160 06161 if (cNamedArgs) 06162 { 06163 USHORT j; 06164 for (j = 0; j < cNamedArgs; j++) 06165 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT)) 06166 { 06167 src_arg = &pDispParams->rgvarg[j]; 06168 break; 06169 } 06170 } 06171 06172 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs) 06173 { 06174 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]; 06175 vargs_converted++; 06176 } 06177 06178 if (wParamFlags & PARAMFLAG_FRETVAL) 06179 { 06180 /* under most conditions the caller is not allowed to 06181 * pass in a dispparam arg in the index of what would be 06182 * the retval parameter. however, there is an exception 06183 * where the extra parameter is used in an extra 06184 * IDispatch::Invoke below */ 06185 if ((i < pDispParams->cArgs) && 06186 ((func_desc->cParams != 1) || !pVarResult || 06187 !(func_desc->invkind & INVOKE_PROPERTYGET))) 06188 { 06189 hres = DISP_E_BADPARAMCOUNT; 06190 break; 06191 } 06192 06193 /* note: this check is placed so that if the caller passes 06194 * in a VARIANTARG for the retval we just ignore it, like 06195 * native does */ 06196 if (i == func_desc->cParams - 1) 06197 { 06198 VARIANTARG *arg; 06199 arg = prgpvarg[i] = &rgvarg[i]; 06200 memset(arg, 0, sizeof(*arg)); 06201 V_VT(arg) = rgvt[i]; 06202 memset(&retval, 0, sizeof(retval)); 06203 V_BYREF(arg) = &retval; 06204 } 06205 else 06206 { 06207 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams); 06208 hres = E_UNEXPECTED; 06209 break; 06210 } 06211 } 06212 else if (src_arg) 06213 { 06214 dump_Variant(src_arg); 06215 06216 if (rgvt[i] == VT_VARIANT) 06217 hres = VariantCopy(&rgvarg[i], src_arg); 06218 else if (rgvt[i] == (VT_VARIANT | VT_BYREF)) 06219 { 06220 if (rgvt[i] == V_VT(src_arg)) 06221 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg); 06222 else 06223 { 06224 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 06225 if (wParamFlags & PARAMFLAG_FIN) 06226 hres = VariantCopy(&missing_arg[i], src_arg); 06227 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i]; 06228 } 06229 V_VT(&rgvarg[i]) = rgvt[i]; 06230 } 06231 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1) 06232 { 06233 SAFEARRAY *a; 06234 SAFEARRAYBOUND bound; 06235 VARIANT *v; 06236 LONG j; 06237 bound.lLbound = 0; 06238 bound.cElements = pDispParams->cArgs-i; 06239 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound))) 06240 { 06241 ERR("SafeArrayCreate failed\n"); 06242 break; 06243 } 06244 hres = SafeArrayAccessData(a, (LPVOID)&v); 06245 if (hres != S_OK) 06246 { 06247 ERR("SafeArrayAccessData failed with %x\n", hres); 06248 break; 06249 } 06250 for (j = 0; j < bound.cElements; j++) 06251 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]); 06252 hres = SafeArrayUnaccessData(a); 06253 if (hres != S_OK) 06254 { 06255 ERR("SafeArrayUnaccessData failed with %x\n", hres); 06256 break; 06257 } 06258 V_ARRAY(&rgvarg[i]) = a; 06259 V_VT(&rgvarg[i]) = rgvt[i]; 06260 } 06261 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg)) 06262 { 06263 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 06264 if (wParamFlags & PARAMFLAG_FIN) 06265 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF); 06266 else 06267 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF; 06268 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]); 06269 V_VT(&rgvarg[i]) = rgvt[i]; 06270 } 06271 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg))) 06272 { 06273 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg); 06274 V_VT(&rgvarg[i]) = rgvt[i]; 06275 } 06276 else 06277 { 06278 /* FIXME: this doesn't work for VT_BYREF arguments if 06279 * they are not the same type as in the paramdesc */ 06280 V_VT(&rgvarg[i]) = V_VT(src_arg); 06281 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]); 06282 V_VT(&rgvarg[i]) = rgvt[i]; 06283 } 06284 06285 if (FAILED(hres)) 06286 { 06287 ERR("failed to convert param %d to %s%s from %s%s\n", i, 06288 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]), 06289 debugstr_VT(src_arg), debugstr_VF(src_arg)); 06290 break; 06291 } 06292 prgpvarg[i] = &rgvarg[i]; 06293 } 06294 else if (wParamFlags & PARAMFLAG_FOPT) 06295 { 06296 VARIANTARG *arg; 06297 arg = prgpvarg[i] = &rgvarg[i]; 06298 if (wParamFlags & PARAMFLAG_FHASDEFAULT) 06299 { 06300 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue); 06301 if (FAILED(hres)) 06302 break; 06303 } 06304 else 06305 { 06306 VARIANTARG *missing_arg; 06307 /* if the function wants a pointer to a variant then 06308 * set that up, otherwise just pass the VT_ERROR in 06309 * the argument by value */ 06310 if (rgvt[i] & VT_BYREF) 06311 { 06312 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i; 06313 V_VT(arg) = VT_VARIANT | VT_BYREF; 06314 V_VARIANTREF(arg) = missing_arg; 06315 } 06316 else 06317 missing_arg = arg; 06318 V_VT(missing_arg) = VT_ERROR; 06319 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND; 06320 } 06321 } 06322 else 06323 { 06324 hres = DISP_E_BADPARAMCOUNT; 06325 break; 06326 } 06327 } 06328 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ 06329 06330 /* VT_VOID is a special case for return types, so it is not 06331 * handled in the general function */ 06332 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID) 06333 V_VT(&varresult) = VT_EMPTY; 06334 else 06335 { 06336 V_VT(&varresult) = 0; 06337 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult)); 06338 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */ 06339 } 06340 06341 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv, 06342 V_VT(&varresult), func_desc->cParams, rgvt, 06343 prgpvarg, &varresult); 06344 06345 vargs_converted = 0; 06346 06347 for (i = 0; i < func_desc->cParams; i++) 06348 { 06349 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; 06350 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 06351 06352 if (wParamFlags & PARAMFLAG_FLCID) 06353 continue; 06354 else if (wParamFlags & PARAMFLAG_FRETVAL) 06355 { 06356 if (TRACE_ON(ole)) 06357 { 06358 TRACE("[retval] value: "); 06359 dump_Variant(prgpvarg[i]); 06360 } 06361 06362 if (pVarResult) 06363 { 06364 VariantInit(pVarResult); 06365 /* deref return value */ 06366 hres = VariantCopyInd(pVarResult, prgpvarg[i]); 06367 } 06368 06369 VARIANT_ClearInd(prgpvarg[i]); 06370 } 06371 else if (vargs_converted < pDispParams->cArgs) 06372 { 06373 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]; 06374 if (wParamFlags & PARAMFLAG_FOUT) 06375 { 06376 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF)) 06377 { 06378 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg)); 06379 06380 if (FAILED(hres)) 06381 { 06382 ERR("failed to convert param %d to vt %d\n", i, 06383 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted])); 06384 break; 06385 } 06386 } 06387 } 06388 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) && 06389 func_desc->cParamsOpt < 0 && 06390 i == func_desc->cParams-1) 06391 { 06392 SAFEARRAY *a = V_ARRAY(prgpvarg[i]); 06393 LONG j, ubound; 06394 VARIANT *v; 06395 hres = SafeArrayGetUBound(a, 1, &ubound); 06396 if (hres != S_OK) 06397 { 06398 ERR("SafeArrayGetUBound failed with %x\n", hres); 06399 break; 06400 } 06401 hres = SafeArrayAccessData(a, (LPVOID)&v); 06402 if (hres != S_OK) 06403 { 06404 ERR("SafeArrayAccessData failed with %x\n", hres); 06405 break; 06406 } 06407 for (j = 0; j <= ubound; j++) 06408 VariantClear(&v[j]); 06409 hres = SafeArrayUnaccessData(a); 06410 if (hres != S_OK) 06411 { 06412 ERR("SafeArrayUnaccessData failed with %x\n", hres); 06413 break; 06414 } 06415 } 06416 VariantClear(&rgvarg[i]); 06417 vargs_converted++; 06418 } 06419 else if (wParamFlags & PARAMFLAG_FOPT) 06420 { 06421 if (wParamFlags & PARAMFLAG_FHASDEFAULT) 06422 VariantClear(&rgvarg[i]); 06423 } 06424 06425 VariantClear(&missing_arg[i]); 06426 } 06427 06428 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult))) 06429 { 06430 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult)); 06431 hres = DISP_E_EXCEPTION; 06432 if (pExcepInfo) 06433 { 06434 IErrorInfo *pErrorInfo; 06435 pExcepInfo->scode = V_ERROR(&varresult); 06436 if (GetErrorInfo(0, &pErrorInfo) == S_OK) 06437 { 06438 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription); 06439 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile); 06440 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource); 06441 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext); 06442 06443 IErrorInfo_Release(pErrorInfo); 06444 } 06445 } 06446 } 06447 if (V_VT(&varresult) != VT_ERROR) 06448 { 06449 TRACE("varresult value: "); 06450 dump_Variant(&varresult); 06451 06452 if (pVarResult) 06453 { 06454 VariantClear(pVarResult); 06455 *pVarResult = varresult; 06456 } 06457 else 06458 VariantClear(&varresult); 06459 } 06460 06461 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) && 06462 (func_desc->invkind & INVOKE_PROPERTYGET) && 06463 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) && 06464 (pDispParams->cArgs != 0)) 06465 { 06466 if (V_VT(pVarResult) == VT_DISPATCH) 06467 { 06468 IDispatch *pDispatch = V_DISPATCH(pVarResult); 06469 /* Note: not VariantClear; we still need the dispatch 06470 * pointer to be valid */ 06471 VariantInit(pVarResult); 06472 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, 06473 GetSystemDefaultLCID(), INVOKE_PROPERTYGET, 06474 pDispParams, pVarResult, pExcepInfo, pArgErr); 06475 IDispatch_Release(pDispatch); 06476 } 06477 else 06478 { 06479 VariantClear(pVarResult); 06480 hres = DISP_E_NOTACOLLECTION; 06481 } 06482 } 06483 06484 func_fail: 06485 HeapFree(GetProcessHeap(), 0, buffer); 06486 break; 06487 } 06488 case FUNC_DISPATCH: { 06489 IDispatch *disp; 06490 06491 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp); 06492 if (SUCCEEDED(hres)) { 06493 FIXME("Calling Invoke in IDispatch iface. untested!\n"); 06494 hres = IDispatch_Invoke( 06495 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams, 06496 pVarResult,pExcepInfo,pArgErr 06497 ); 06498 if (FAILED(hres)) 06499 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres); 06500 IDispatch_Release(disp); 06501 } else 06502 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n"); 06503 break; 06504 } 06505 default: 06506 FIXME("Unknown function invocation type %d\n", func_desc->funckind); 06507 hres = E_FAIL; 06508 break; 06509 } 06510 06511 TRACE("-- 0x%08x\n", hres); 06512 return hres; 06513 06514 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) { 06515 VARDESC *var_desc; 06516 06517 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc); 06518 if(FAILED(hres)) return hres; 06519 06520 FIXME("varseek: Found memid, but variable-based invoking not supported\n"); 06521 dump_VARDESC(var_desc); 06522 ITypeInfo2_ReleaseVarDesc(iface, var_desc); 06523 return E_NOTIMPL; 06524 } 06525 06526 /* not found, look for it in inherited interfaces */ 06527 ITypeInfo2_GetTypeKind(iface, &type_kind); 06528 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) { 06529 if(This->impltypelist) { 06530 /* recursive search */ 06531 ITypeInfo *pTInfo; 06532 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo); 06533 if(SUCCEEDED(hres)){ 06534 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); 06535 ITypeInfo_Release(pTInfo); 06536 return hres; 06537 } 06538 WARN("Could not search inherited interface!\n"); 06539 } 06540 } 06541 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags); 06542 return DISP_E_MEMBERNOTFOUND; 06543 } 06544 06545 /* ITypeInfo::GetDocumentation 06546 * 06547 * Retrieves the documentation string, the complete Help file name and path, 06548 * and the context ID for the Help topic for a specified type description. 06549 * 06550 * (Can be tested by the Visual Basic Editor in Word for instance.) 06551 */ 06552 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface, 06553 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString, 06554 DWORD *pdwHelpContext, BSTR *pBstrHelpFile) 06555 { 06556 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06557 const TLBFuncDesc *pFDesc; 06558 const TLBVarDesc *pVDesc; 06559 TRACE("(%p) memid %d Name(%p) DocString(%p)" 06560 " HelpContext(%p) HelpFile(%p)\n", 06561 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile); 06562 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */ 06563 if(pBstrName) 06564 *pBstrName=SysAllocString(This->Name); 06565 if(pBstrDocString) 06566 *pBstrDocString=SysAllocString(This->DocString); 06567 if(pdwHelpContext) 06568 *pdwHelpContext=This->dwHelpContext; 06569 if(pBstrHelpFile) 06570 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */ 06571 return S_OK; 06572 }else {/* for a member */ 06573 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) 06574 if(pFDesc->funcdesc.memid==memid){ 06575 if(pBstrName) 06576 *pBstrName = SysAllocString(pFDesc->Name); 06577 if(pBstrDocString) 06578 *pBstrDocString=SysAllocString(pFDesc->HelpString); 06579 if(pdwHelpContext) 06580 *pdwHelpContext=pFDesc->helpcontext; 06581 return S_OK; 06582 } 06583 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) 06584 if(pVDesc->vardesc.memid==memid){ 06585 if(pBstrName) 06586 *pBstrName = SysAllocString(pVDesc->Name); 06587 if(pBstrDocString) 06588 *pBstrDocString=SysAllocString(pVDesc->HelpString); 06589 if(pdwHelpContext) 06590 *pdwHelpContext=pVDesc->HelpContext; 06591 return S_OK; 06592 } 06593 } 06594 06595 if(This->impltypelist && 06596 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) { 06597 /* recursive search */ 06598 ITypeInfo *pTInfo; 06599 HRESULT result; 06600 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, 06601 &pTInfo); 06602 if(SUCCEEDED(result)) { 06603 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName, 06604 pBstrDocString, pdwHelpContext, pBstrHelpFile); 06605 ITypeInfo_Release(pTInfo); 06606 return result; 06607 } 06608 WARN("Could not search inherited interface!\n"); 06609 } 06610 06611 WARN("member %d not found\n", memid); 06612 return TYPE_E_ELEMENTNOTFOUND; 06613 } 06614 06615 /* ITypeInfo::GetDllEntry 06616 * 06617 * Retrieves a description or specification of an entry point for a function 06618 * in a DLL. 06619 */ 06620 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid, 06621 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName, 06622 WORD *pwOrdinal) 06623 { 06624 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06625 const TLBFuncDesc *pFDesc; 06626 06627 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal); 06628 06629 if (pBstrDllName) *pBstrDllName = NULL; 06630 if (pBstrName) *pBstrName = NULL; 06631 if (pwOrdinal) *pwOrdinal = 0; 06632 06633 if (This->TypeAttr.typekind != TKIND_MODULE) 06634 return TYPE_E_BADMODULEKIND; 06635 06636 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) 06637 if(pFDesc->funcdesc.memid==memid){ 06638 dump_TypeInfo(This); 06639 if (TRACE_ON(ole)) 06640 dump_TLBFuncDescOne(pFDesc); 06641 06642 if (pBstrDllName) 06643 *pBstrDllName = SysAllocString(This->DllName); 06644 06645 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) { 06646 if (pBstrName) 06647 *pBstrName = SysAllocString(pFDesc->Entry); 06648 if (pwOrdinal) 06649 *pwOrdinal = -1; 06650 return S_OK; 06651 } 06652 if (pBstrName) 06653 *pBstrName = NULL; 06654 if (pwOrdinal) 06655 *pwOrdinal = LOWORD(pFDesc->Entry); 06656 return S_OK; 06657 } 06658 return TYPE_E_ELEMENTNOTFOUND; 06659 } 06660 06661 /* internal function to make the inherited interfaces' methods appear 06662 * part of the interface */ 06663 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface, 06664 HREFTYPE *hRefType, ITypeInfo **ppTInfo) 06665 { 06666 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06667 HRESULT hr; 06668 06669 TRACE("%p, 0x%x\n", iface, *hRefType); 06670 06671 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK)) 06672 { 06673 ITypeInfo *pSubTypeInfo; 06674 06675 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo); 06676 if (FAILED(hr)) 06677 return hr; 06678 06679 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo, 06680 hRefType, ppTInfo); 06681 ITypeInfo_Release(pSubTypeInfo); 06682 if (SUCCEEDED(hr)) 06683 return hr; 06684 } 06685 *hRefType -= DISPATCH_HREF_OFFSET; 06686 06687 if (!(*hRefType & DISPATCH_HREF_MASK)) 06688 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo); 06689 else 06690 return E_FAIL; 06691 } 06692 06693 /* ITypeInfo::GetRefTypeInfo 06694 * 06695 * If a type description references other type descriptions, it retrieves 06696 * the referenced type descriptions. 06697 */ 06698 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( 06699 ITypeInfo2 *iface, 06700 HREFTYPE hRefType, 06701 ITypeInfo **ppTInfo) 06702 { 06703 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06704 HRESULT result = E_FAIL; 06705 06706 if ((This->hreftype != -1) && (This->hreftype == hRefType)) 06707 { 06708 *ppTInfo = (ITypeInfo *)&This->lpVtbl; 06709 ITypeInfo_AddRef(*ppTInfo); 06710 result = S_OK; 06711 } 06712 else if (hRefType == -1 && 06713 (This->TypeAttr.typekind == TKIND_DISPATCH) && 06714 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) 06715 { 06716 /* when we meet a DUAL dispinterface, we must create the interface 06717 * version of it. 06718 */ 06719 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor(); 06720 06721 06722 /* the interface version contains the same information as the dispinterface 06723 * copy the contents of the structs. 06724 */ 06725 *pTypeInfoImpl = *This; 06726 pTypeInfoImpl->ref = 0; 06727 06728 /* change the type to interface */ 06729 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE; 06730 06731 *ppTInfo = (ITypeInfo*) pTypeInfoImpl; 06732 06733 /* the AddRef implicitly adds a reference to the parent typelib, which 06734 * stops the copied data from being destroyed until the new typeinfo's 06735 * refcount goes to zero, but we need to signal to the new instance to 06736 * not free its data structures when it is destroyed */ 06737 pTypeInfoImpl->not_attached_to_typelib = TRUE; 06738 06739 ITypeInfo_AddRef(*ppTInfo); 06740 06741 result = S_OK; 06742 06743 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) && 06744 (This->TypeAttr.typekind == TKIND_DISPATCH)) 06745 { 06746 HREFTYPE href_dispatch = hRefType; 06747 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo); 06748 } else { 06749 TLBRefType *ref_type; 06750 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry) 06751 { 06752 if(ref_type->reference == hRefType) 06753 break; 06754 } 06755 if(&ref_type->entry == &This->pTypeLib->ref_list) 06756 { 06757 FIXME("Can't find pRefType for ref %x\n", hRefType); 06758 goto end; 06759 } 06760 if(hRefType != -1) { 06761 ITypeLib *pTLib = NULL; 06762 06763 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) { 06764 UINT Index; 06765 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index); 06766 } else { 06767 if(ref_type->pImpTLInfo->pImpTypeLib) { 06768 TRACE("typeinfo in imported typelib that is already loaded\n"); 06769 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib; 06770 ITypeLib2_AddRef(pTLib); 06771 result = S_OK; 06772 } else { 06773 TRACE("typeinfo in imported typelib that isn't already loaded\n"); 06774 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid, 06775 ref_type->pImpTLInfo->wVersionMajor, 06776 ref_type->pImpTLInfo->wVersionMinor, 06777 ref_type->pImpTLInfo->lcid, 06778 &pTLib); 06779 06780 if(FAILED(result)) { 06781 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name); 06782 result=LoadTypeLib(libnam, &pTLib); 06783 SysFreeString(libnam); 06784 } 06785 if(SUCCEEDED(result)) { 06786 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib; 06787 ITypeLib2_AddRef(pTLib); 06788 } 06789 } 06790 } 06791 if(SUCCEEDED(result)) { 06792 if(ref_type->index == TLB_REF_USE_GUID) 06793 result = ITypeLib2_GetTypeInfoOfGuid(pTLib, 06794 &ref_type->guid, 06795 ppTInfo); 06796 else 06797 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index, 06798 ppTInfo); 06799 } 06800 if (pTLib != NULL) 06801 ITypeLib2_Release(pTLib); 06802 } 06803 } 06804 06805 end: 06806 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType, 06807 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo); 06808 return result; 06809 } 06810 06811 /* ITypeInfo::AddressOfMember 06812 * 06813 * Retrieves the addresses of static functions or variables, such as those 06814 * defined in a DLL. 06815 */ 06816 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface, 06817 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) 06818 { 06819 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06820 HRESULT hr; 06821 BSTR dll, entry; 06822 WORD ordinal; 06823 HMODULE module; 06824 06825 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv); 06826 06827 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal); 06828 if (FAILED(hr)) 06829 return hr; 06830 06831 module = LoadLibraryW(dll); 06832 if (!module) 06833 { 06834 ERR("couldn't load %s\n", debugstr_w(dll)); 06835 SysFreeString(dll); 06836 SysFreeString(entry); 06837 return STG_E_FILENOTFOUND; 06838 } 06839 /* FIXME: store library somewhere where we can free it */ 06840 06841 if (entry) 06842 { 06843 LPSTR entryA; 06844 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL); 06845 entryA = HeapAlloc(GetProcessHeap(), 0, len); 06846 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL); 06847 06848 *ppv = GetProcAddress(module, entryA); 06849 if (!*ppv) 06850 ERR("function not found %s\n", debugstr_a(entryA)); 06851 06852 HeapFree(GetProcessHeap(), 0, entryA); 06853 } 06854 else 06855 { 06856 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal)); 06857 if (!*ppv) 06858 ERR("function not found %d\n", ordinal); 06859 } 06860 06861 SysFreeString(dll); 06862 SysFreeString(entry); 06863 06864 if (!*ppv) 06865 return TYPE_E_DLLFUNCTIONNOTFOUND; 06866 06867 return S_OK; 06868 } 06869 06870 /* ITypeInfo::CreateInstance 06871 * 06872 * Creates a new instance of a type that describes a component object class 06873 * (coclass). 06874 */ 06875 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface, 06876 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj) 06877 { 06878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06879 HRESULT hr; 06880 TYPEATTR *pTA; 06881 06882 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj); 06883 06884 *ppvObj = NULL; 06885 06886 if(pOuterUnk) 06887 { 06888 WARN("Not able to aggregate\n"); 06889 return CLASS_E_NOAGGREGATION; 06890 } 06891 06892 hr = ITypeInfo_GetTypeAttr(iface, &pTA); 06893 if(FAILED(hr)) return hr; 06894 06895 if(pTA->typekind != TKIND_COCLASS) 06896 { 06897 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind); 06898 hr = E_INVALIDARG; 06899 goto end; 06900 } 06901 06902 hr = S_FALSE; 06903 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT) 06904 { 06905 IUnknown *pUnk; 06906 hr = GetActiveObject(&pTA->guid, NULL, &pUnk); 06907 TRACE("GetActiveObject rets %08x\n", hr); 06908 if(hr == S_OK) 06909 { 06910 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj); 06911 IUnknown_Release(pUnk); 06912 } 06913 } 06914 06915 if(hr != S_OK) 06916 hr = CoCreateInstance(&pTA->guid, NULL, 06917 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 06918 riid, ppvObj); 06919 06920 end: 06921 ITypeInfo_ReleaseTypeAttr(iface, pTA); 06922 return hr; 06923 } 06924 06925 /* ITypeInfo::GetMops 06926 * 06927 * Retrieves marshalling information. 06928 */ 06929 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid, 06930 BSTR *pBstrMops) 06931 { 06932 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06933 FIXME("(%p %d) stub!\n", This, memid); 06934 *pBstrMops = NULL; 06935 return S_OK; 06936 } 06937 06938 /* ITypeInfo::GetContainingTypeLib 06939 * 06940 * Retrieves the containing type library and the index of the type description 06941 * within that type library. 06942 */ 06943 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface, 06944 ITypeLib * *ppTLib, UINT *pIndex) 06945 { 06946 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06947 06948 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */ 06949 if (pIndex) { 06950 *pIndex=This->index; 06951 TRACE("returning pIndex=%d\n", *pIndex); 06952 } 06953 06954 if (ppTLib) { 06955 *ppTLib=(LPTYPELIB )(This->pTypeLib); 06956 ITypeLib2_AddRef(*ppTLib); 06957 TRACE("returning ppTLib=%p\n", *ppTLib); 06958 } 06959 06960 return S_OK; 06961 } 06962 06963 /* ITypeInfo::ReleaseTypeAttr 06964 * 06965 * Releases a TYPEATTR previously returned by GetTypeAttr. 06966 * 06967 */ 06968 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface, 06969 TYPEATTR* pTypeAttr) 06970 { 06971 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06972 TRACE("(%p)->(%p)\n", This, pTypeAttr); 06973 HeapFree(GetProcessHeap(), 0, pTypeAttr); 06974 } 06975 06976 /* ITypeInfo::ReleaseFuncDesc 06977 * 06978 * Releases a FUNCDESC previously returned by GetFuncDesc. * 06979 */ 06980 static void WINAPI ITypeInfo_fnReleaseFuncDesc( 06981 ITypeInfo2 *iface, 06982 FUNCDESC *pFuncDesc) 06983 { 06984 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 06985 SHORT i; 06986 06987 TRACE("(%p)->(%p)\n", This, pFuncDesc); 06988 06989 for (i = 0; i < pFuncDesc->cParams; i++) 06990 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]); 06991 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc); 06992 06993 SysFreeString((BSTR)pFuncDesc); 06994 } 06995 06996 /* ITypeInfo::ReleaseVarDesc 06997 * 06998 * Releases a VARDESC previously returned by GetVarDesc. 06999 */ 07000 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface, 07001 VARDESC *pVarDesc) 07002 { 07003 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07004 TRACE("(%p)->(%p)\n", This, pVarDesc); 07005 07006 TLB_FreeElemDesc(&pVarDesc->elemdescVar); 07007 if (pVarDesc->varkind == VAR_CONST) 07008 VariantClear(pVarDesc->u.lpvarValue); 07009 SysFreeString((BSTR)pVarDesc); 07010 } 07011 07012 /* ITypeInfo2::GetTypeKind 07013 * 07014 * Returns the TYPEKIND enumeration quickly, without doing any allocations. 07015 * 07016 */ 07017 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface, 07018 TYPEKIND *pTypeKind) 07019 { 07020 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07021 *pTypeKind=This->TypeAttr.typekind; 07022 TRACE("(%p) type 0x%0x\n", This,*pTypeKind); 07023 return S_OK; 07024 } 07025 07026 /* ITypeInfo2::GetTypeFlags 07027 * 07028 * Returns the type flags without any allocations. This returns a DWORD type 07029 * flag, which expands the type flags without growing the TYPEATTR (type 07030 * attribute). 07031 * 07032 */ 07033 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags) 07034 { 07035 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07036 *pTypeFlags=This->TypeAttr.wTypeFlags; 07037 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags); 07038 return S_OK; 07039 } 07040 07041 /* ITypeInfo2::GetFuncIndexOfMemId 07042 * Binds to a specific member based on a known DISPID, where the member name 07043 * is not known (for example, when binding to a default member). 07044 * 07045 */ 07046 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface, 07047 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex) 07048 { 07049 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07050 const TLBFuncDesc *pFuncInfo; 07051 int i; 07052 HRESULT result; 07053 07054 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next) 07055 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind)) 07056 break; 07057 if(pFuncInfo) { 07058 *pFuncIndex = i; 07059 result = S_OK; 07060 } else 07061 result = TYPE_E_ELEMENTNOTFOUND; 07062 07063 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This, 07064 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED"); 07065 return result; 07066 } 07067 07068 /* TypeInfo2::GetVarIndexOfMemId 07069 * 07070 * Binds to a specific member based on a known DISPID, where the member name 07071 * is not known (for example, when binding to a default member). 07072 * 07073 */ 07074 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface, 07075 MEMBERID memid, UINT *pVarIndex) 07076 { 07077 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07078 TLBVarDesc *pVarInfo; 07079 int i; 07080 HRESULT result; 07081 for(i=0, pVarInfo=This->varlist; pVarInfo && 07082 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next) 07083 ; 07084 if(pVarInfo) { 07085 *pVarIndex = i; 07086 result = S_OK; 07087 } else 07088 result = TYPE_E_ELEMENTNOTFOUND; 07089 07090 TRACE("(%p) memid 0x%08x -> %s\n", This, 07091 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED"); 07092 return result; 07093 } 07094 07095 /* ITypeInfo2::GetCustData 07096 * 07097 * Gets the custom data 07098 */ 07099 static HRESULT WINAPI ITypeInfo2_fnGetCustData( 07100 ITypeInfo2 * iface, 07101 REFGUID guid, 07102 VARIANT *pVarVal) 07103 { 07104 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07105 TLBCustData *pCData; 07106 07107 for(pCData=This->pCustData; pCData; pCData = pCData->next) 07108 if( IsEqualIID(guid, &pCData->guid)) break; 07109 07110 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 07111 07112 VariantInit( pVarVal); 07113 if (pCData) 07114 VariantCopy( pVarVal, &pCData->data); 07115 else 07116 VariantClear( pVarVal ); 07117 return S_OK; 07118 } 07119 07120 /* ITypeInfo2::GetFuncCustData 07121 * 07122 * Gets the custom data 07123 */ 07124 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( 07125 ITypeInfo2 * iface, 07126 UINT index, 07127 REFGUID guid, 07128 VARIANT *pVarVal) 07129 { 07130 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07131 TLBCustData *pCData=NULL; 07132 TLBFuncDesc * pFDesc; 07133 UINT i; 07134 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, 07135 pFDesc=pFDesc->next); 07136 07137 if(pFDesc) 07138 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next) 07139 if( IsEqualIID(guid, &pCData->guid)) break; 07140 07141 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 07142 07143 if(pCData){ 07144 VariantInit( pVarVal); 07145 VariantCopy( pVarVal, &pCData->data); 07146 return S_OK; 07147 } 07148 return E_INVALIDARG; /* FIXME: correct? */ 07149 } 07150 07151 /* ITypeInfo2::GetParamCustData 07152 * 07153 * Gets the custom data 07154 */ 07155 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( 07156 ITypeInfo2 * iface, 07157 UINT indexFunc, 07158 UINT indexParam, 07159 REFGUID guid, 07160 VARIANT *pVarVal) 07161 { 07162 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07163 TLBCustData *pCData=NULL; 07164 TLBFuncDesc * pFDesc; 07165 UINT i; 07166 07167 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next); 07168 07169 if(pFDesc && indexParam<pFDesc->funcdesc.cParams) 07170 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData; 07171 pCData = pCData->next) 07172 if( IsEqualIID(guid, &pCData->guid)) break; 07173 07174 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 07175 07176 if(pCData) 07177 { 07178 VariantInit( pVarVal); 07179 VariantCopy( pVarVal, &pCData->data); 07180 return S_OK; 07181 } 07182 return E_INVALIDARG; /* FIXME: correct? */ 07183 } 07184 07185 /* ITypeInfo2::GetVarCustData 07186 * 07187 * Gets the custom data 07188 */ 07189 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( 07190 ITypeInfo2 * iface, 07191 UINT index, 07192 REFGUID guid, 07193 VARIANT *pVarVal) 07194 { 07195 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07196 TLBCustData *pCData=NULL; 07197 TLBVarDesc * pVDesc; 07198 UINT i; 07199 07200 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next); 07201 07202 if(pVDesc) 07203 { 07204 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next) 07205 { 07206 if( IsEqualIID(guid, &pCData->guid)) break; 07207 } 07208 } 07209 07210 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 07211 07212 if(pCData) 07213 { 07214 VariantInit( pVarVal); 07215 VariantCopy( pVarVal, &pCData->data); 07216 return S_OK; 07217 } 07218 return E_INVALIDARG; /* FIXME: correct? */ 07219 } 07220 07221 /* ITypeInfo2::GetImplCustData 07222 * 07223 * Gets the custom data 07224 */ 07225 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( 07226 ITypeInfo2 * iface, 07227 UINT index, 07228 REFGUID guid, 07229 VARIANT *pVarVal) 07230 { 07231 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07232 TLBCustData *pCData=NULL; 07233 TLBImplType * pRDesc; 07234 UINT i; 07235 07236 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next); 07237 07238 if(pRDesc) 07239 { 07240 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next) 07241 { 07242 if( IsEqualIID(guid, &pCData->guid)) break; 07243 } 07244 } 07245 07246 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT"); 07247 07248 if(pCData) 07249 { 07250 VariantInit( pVarVal); 07251 VariantCopy( pVarVal, &pCData->data); 07252 return S_OK; 07253 } 07254 return E_INVALIDARG; /* FIXME: correct? */ 07255 } 07256 07257 /* ITypeInfo2::GetDocumentation2 07258 * 07259 * Retrieves the documentation string, the complete Help file name and path, 07260 * the localization context to use, and the context ID for the library Help 07261 * topic in the Help file. 07262 * 07263 */ 07264 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( 07265 ITypeInfo2 * iface, 07266 MEMBERID memid, 07267 LCID lcid, 07268 BSTR *pbstrHelpString, 07269 DWORD *pdwHelpStringContext, 07270 BSTR *pbstrHelpStringDll) 07271 { 07272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07273 const TLBFuncDesc *pFDesc; 07274 const TLBVarDesc *pVDesc; 07275 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) " 07276 "HelpStringContext(%p) HelpStringDll(%p)\n", 07277 This, memid, lcid, pbstrHelpString, pdwHelpStringContext, 07278 pbstrHelpStringDll ); 07279 /* the help string should be obtained from the helpstringdll, 07280 * using the _DLLGetDocumentation function, based on the supplied 07281 * lcid. Nice to do sometime... 07282 */ 07283 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */ 07284 if(pbstrHelpString) 07285 *pbstrHelpString=SysAllocString(This->Name); 07286 if(pdwHelpStringContext) 07287 *pdwHelpStringContext=This->dwHelpStringContext; 07288 if(pbstrHelpStringDll) 07289 *pbstrHelpStringDll= 07290 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */ 07291 return S_OK; 07292 }else {/* for a member */ 07293 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) 07294 if(pFDesc->funcdesc.memid==memid){ 07295 if(pbstrHelpString) 07296 *pbstrHelpString=SysAllocString(pFDesc->HelpString); 07297 if(pdwHelpStringContext) 07298 *pdwHelpStringContext=pFDesc->HelpStringContext; 07299 if(pbstrHelpStringDll) 07300 *pbstrHelpStringDll= 07301 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */ 07302 return S_OK; 07303 } 07304 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) 07305 if(pVDesc->vardesc.memid==memid){ 07306 if(pbstrHelpString) 07307 *pbstrHelpString=SysAllocString(pVDesc->HelpString); 07308 if(pdwHelpStringContext) 07309 *pdwHelpStringContext=pVDesc->HelpStringContext; 07310 if(pbstrHelpStringDll) 07311 *pbstrHelpStringDll= 07312 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */ 07313 return S_OK; 07314 } 07315 } 07316 return TYPE_E_ELEMENTNOTFOUND; 07317 } 07318 07319 /* ITypeInfo2::GetAllCustData 07320 * 07321 * Gets all custom data items for the Type info. 07322 * 07323 */ 07324 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( 07325 ITypeInfo2 * iface, 07326 CUSTDATA *pCustData) 07327 { 07328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07329 TLBCustData *pCData; 07330 int i; 07331 07332 TRACE("(%p) returning %d items\n", This, This->ctCustData); 07333 07334 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM)); 07335 if(pCustData->prgCustData ){ 07336 pCustData->cCustData=This->ctCustData; 07337 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){ 07338 pCustData->prgCustData[i].guid=pCData->guid; 07339 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data); 07340 } 07341 }else{ 07342 ERR(" OUT OF MEMORY!\n"); 07343 return E_OUTOFMEMORY; 07344 } 07345 return S_OK; 07346 } 07347 07348 /* ITypeInfo2::GetAllFuncCustData 07349 * 07350 * Gets all custom data items for the specified Function 07351 * 07352 */ 07353 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( 07354 ITypeInfo2 * iface, 07355 UINT index, 07356 CUSTDATA *pCustData) 07357 { 07358 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07359 TLBCustData *pCData; 07360 TLBFuncDesc * pFDesc; 07361 UINT i; 07362 TRACE("(%p) index %d\n", This, index); 07363 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, 07364 pFDesc=pFDesc->next) 07365 ; 07366 if(pFDesc){ 07367 pCustData->prgCustData = 07368 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM)); 07369 if(pCustData->prgCustData ){ 07370 pCustData->cCustData=pFDesc->ctCustData; 07371 for(i=0, pCData=pFDesc->pCustData; pCData; i++, 07372 pCData = pCData->next){ 07373 pCustData->prgCustData[i].guid=pCData->guid; 07374 VariantCopy(& pCustData->prgCustData[i].varValue, 07375 & pCData->data); 07376 } 07377 }else{ 07378 ERR(" OUT OF MEMORY!\n"); 07379 return E_OUTOFMEMORY; 07380 } 07381 return S_OK; 07382 } 07383 return TYPE_E_ELEMENTNOTFOUND; 07384 } 07385 07386 /* ITypeInfo2::GetAllParamCustData 07387 * 07388 * Gets all custom data items for the Functions 07389 * 07390 */ 07391 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface, 07392 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData) 07393 { 07394 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07395 TLBCustData *pCData=NULL; 07396 TLBFuncDesc * pFDesc; 07397 UINT i; 07398 TRACE("(%p) index %d\n", This, indexFunc); 07399 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++, 07400 pFDesc=pFDesc->next) 07401 ; 07402 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){ 07403 pCustData->prgCustData = 07404 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData * 07405 sizeof(CUSTDATAITEM)); 07406 if(pCustData->prgCustData ){ 07407 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData; 07408 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData; 07409 pCData; i++, pCData = pCData->next){ 07410 pCustData->prgCustData[i].guid=pCData->guid; 07411 VariantCopy(& pCustData->prgCustData[i].varValue, 07412 & pCData->data); 07413 } 07414 }else{ 07415 ERR(" OUT OF MEMORY!\n"); 07416 return E_OUTOFMEMORY; 07417 } 07418 return S_OK; 07419 } 07420 return TYPE_E_ELEMENTNOTFOUND; 07421 } 07422 07423 /* ITypeInfo2::GetAllVarCustData 07424 * 07425 * Gets all custom data items for the specified Variable 07426 * 07427 */ 07428 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface, 07429 UINT index, CUSTDATA *pCustData) 07430 { 07431 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07432 TLBCustData *pCData; 07433 TLBVarDesc * pVDesc; 07434 UINT i; 07435 TRACE("(%p) index %d\n", This, index); 07436 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, 07437 pVDesc=pVDesc->next) 07438 ; 07439 if(pVDesc){ 07440 pCustData->prgCustData = 07441 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM)); 07442 if(pCustData->prgCustData ){ 07443 pCustData->cCustData=pVDesc->ctCustData; 07444 for(i=0, pCData=pVDesc->pCustData; pCData; i++, 07445 pCData = pCData->next){ 07446 pCustData->prgCustData[i].guid=pCData->guid; 07447 VariantCopy(& pCustData->prgCustData[i].varValue, 07448 & pCData->data); 07449 } 07450 }else{ 07451 ERR(" OUT OF MEMORY!\n"); 07452 return E_OUTOFMEMORY; 07453 } 07454 return S_OK; 07455 } 07456 return TYPE_E_ELEMENTNOTFOUND; 07457 } 07458 07459 /* ITypeInfo2::GetAllImplCustData 07460 * 07461 * Gets all custom data items for the specified implementation type 07462 * 07463 */ 07464 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( 07465 ITypeInfo2 * iface, 07466 UINT index, 07467 CUSTDATA *pCustData) 07468 { 07469 ITypeInfoImpl *This = (ITypeInfoImpl *)iface; 07470 TLBCustData *pCData; 07471 TLBImplType * pRDesc; 07472 UINT i; 07473 TRACE("(%p) index %d\n", This, index); 07474 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, 07475 pRDesc=pRDesc->next) 07476 ; 07477 if(pRDesc){ 07478 pCustData->prgCustData = 07479 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM)); 07480 if(pCustData->prgCustData ){ 07481 pCustData->cCustData=pRDesc->ctCustData; 07482 for(i=0, pCData=pRDesc->pCustData; pCData; i++, 07483 pCData = pCData->next){ 07484 pCustData->prgCustData[i].guid=pCData->guid; 07485 VariantCopy(& pCustData->prgCustData[i].varValue, 07486 & pCData->data); 07487 } 07488 }else{ 07489 ERR(" OUT OF MEMORY!\n"); 07490 return E_OUTOFMEMORY; 07491 } 07492 return S_OK; 07493 } 07494 return TYPE_E_ELEMENTNOTFOUND; 07495 } 07496 07497 static const ITypeInfo2Vtbl tinfvt = 07498 { 07499 07500 ITypeInfo_fnQueryInterface, 07501 ITypeInfo_fnAddRef, 07502 ITypeInfo_fnRelease, 07503 07504 ITypeInfo_fnGetTypeAttr, 07505 ITypeInfo_fnGetTypeComp, 07506 ITypeInfo_fnGetFuncDesc, 07507 ITypeInfo_fnGetVarDesc, 07508 ITypeInfo_fnGetNames, 07509 ITypeInfo_fnGetRefTypeOfImplType, 07510 ITypeInfo_fnGetImplTypeFlags, 07511 ITypeInfo_fnGetIDsOfNames, 07512 ITypeInfo_fnInvoke, 07513 ITypeInfo_fnGetDocumentation, 07514 ITypeInfo_fnGetDllEntry, 07515 ITypeInfo_fnGetRefTypeInfo, 07516 ITypeInfo_fnAddressOfMember, 07517 ITypeInfo_fnCreateInstance, 07518 ITypeInfo_fnGetMops, 07519 ITypeInfo_fnGetContainingTypeLib, 07520 ITypeInfo_fnReleaseTypeAttr, 07521 ITypeInfo_fnReleaseFuncDesc, 07522 ITypeInfo_fnReleaseVarDesc, 07523 07524 ITypeInfo2_fnGetTypeKind, 07525 ITypeInfo2_fnGetTypeFlags, 07526 ITypeInfo2_fnGetFuncIndexOfMemId, 07527 ITypeInfo2_fnGetVarIndexOfMemId, 07528 ITypeInfo2_fnGetCustData, 07529 ITypeInfo2_fnGetFuncCustData, 07530 ITypeInfo2_fnGetParamCustData, 07531 ITypeInfo2_fnGetVarCustData, 07532 ITypeInfo2_fnGetImplTypeCustData, 07533 ITypeInfo2_fnGetDocumentation2, 07534 ITypeInfo2_fnGetAllCustData, 07535 ITypeInfo2_fnGetAllFuncCustData, 07536 ITypeInfo2_fnGetAllParamCustData, 07537 ITypeInfo2_fnGetAllVarCustData, 07538 ITypeInfo2_fnGetAllImplTypeCustData, 07539 }; 07540 07541 /****************************************************************************** 07542 * CreateDispTypeInfo [OLEAUT32.31] 07543 * 07544 * Build type information for an object so it can be called through an 07545 * IDispatch interface. 07546 * 07547 * RETURNS 07548 * Success: S_OK. pptinfo contains the created ITypeInfo object. 07549 * Failure: E_INVALIDARG, if one or more arguments is invalid. 07550 * 07551 * NOTES 07552 * This call allows an objects methods to be accessed through IDispatch, by 07553 * building an ITypeInfo object that IDispatch can use to call through. 07554 */ 07555 HRESULT WINAPI CreateDispTypeInfo( 07556 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */ 07557 LCID lcid, /* [I] Locale Id */ 07558 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */ 07559 { 07560 ITypeInfoImpl *pTIClass, *pTIIface; 07561 ITypeLibImpl *pTypeLibImpl; 07562 unsigned int param, func; 07563 TLBFuncDesc **ppFuncDesc; 07564 TLBRefType *ref; 07565 07566 TRACE("\n"); 07567 pTypeLibImpl = TypeLibImpl_Constructor(); 07568 if (!pTypeLibImpl) return E_FAIL; 07569 07570 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor(); 07571 pTIIface->pTypeLib = pTypeLibImpl; 07572 pTIIface->index = 0; 07573 pTIIface->Name = NULL; 07574 pTIIface->dwHelpContext = -1; 07575 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID)); 07576 pTIIface->TypeAttr.lcid = lcid; 07577 pTIIface->TypeAttr.typekind = TKIND_INTERFACE; 07578 pTIIface->TypeAttr.wMajorVerNum = 0; 07579 pTIIface->TypeAttr.wMinorVerNum = 0; 07580 pTIIface->TypeAttr.cbAlignment = 2; 07581 pTIIface->TypeAttr.cbSizeInstance = -1; 07582 pTIIface->TypeAttr.cbSizeVft = -1; 07583 pTIIface->TypeAttr.cFuncs = 0; 07584 pTIIface->TypeAttr.cImplTypes = 0; 07585 pTIIface->TypeAttr.cVars = 0; 07586 pTIIface->TypeAttr.wTypeFlags = 0; 07587 07588 ppFuncDesc = &pTIIface->funclist; 07589 for(func = 0; func < pidata->cMembers; func++) { 07590 METHODDATA *md = pidata->pmethdata + func; 07591 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc)); 07592 (*ppFuncDesc)->Name = SysAllocString(md->szName); 07593 (*ppFuncDesc)->funcdesc.memid = md->dispid; 07594 (*ppFuncDesc)->funcdesc.lprgscode = NULL; 07595 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL; 07596 (*ppFuncDesc)->funcdesc.invkind = md->wFlags; 07597 (*ppFuncDesc)->funcdesc.callconv = md->cc; 07598 (*ppFuncDesc)->funcdesc.cParams = md->cArgs; 07599 (*ppFuncDesc)->funcdesc.cParamsOpt = 0; 07600 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *); 07601 (*ppFuncDesc)->funcdesc.cScodes = 0; 07602 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; 07603 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn; 07604 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE; 07605 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL; 07606 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 07607 md->cArgs * sizeof(ELEMDESC)); 07608 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 07609 md->cArgs * sizeof(TLBParDesc)); 07610 for(param = 0; param < md->cArgs; param++) { 07611 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt; 07612 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName); 07613 } 07614 (*ppFuncDesc)->helpcontext = 0; 07615 (*ppFuncDesc)->HelpStringContext = 0; 07616 (*ppFuncDesc)->HelpString = NULL; 07617 (*ppFuncDesc)->Entry = NULL; 07618 (*ppFuncDesc)->ctCustData = 0; 07619 (*ppFuncDesc)->pCustData = NULL; 07620 (*ppFuncDesc)->next = NULL; 07621 pTIIface->TypeAttr.cFuncs++; 07622 ppFuncDesc = &(*ppFuncDesc)->next; 07623 } 07624 07625 dump_TypeInfo(pTIIface); 07626 07627 pTypeLibImpl->pTypeInfo = pTIIface; 07628 pTypeLibImpl->TypeInfoCount++; 07629 07630 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor(); 07631 pTIClass->pTypeLib = pTypeLibImpl; 07632 pTIClass->index = 1; 07633 pTIClass->Name = NULL; 07634 pTIClass->dwHelpContext = -1; 07635 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID)); 07636 pTIClass->TypeAttr.lcid = lcid; 07637 pTIClass->TypeAttr.typekind = TKIND_COCLASS; 07638 pTIClass->TypeAttr.wMajorVerNum = 0; 07639 pTIClass->TypeAttr.wMinorVerNum = 0; 07640 pTIClass->TypeAttr.cbAlignment = 2; 07641 pTIClass->TypeAttr.cbSizeInstance = -1; 07642 pTIClass->TypeAttr.cbSizeVft = -1; 07643 pTIClass->TypeAttr.cFuncs = 0; 07644 pTIClass->TypeAttr.cImplTypes = 1; 07645 pTIClass->TypeAttr.cVars = 0; 07646 pTIClass->TypeAttr.wTypeFlags = 0; 07647 07648 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist)); 07649 pTIClass->impltypelist->hRef = 0; 07650 07651 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref)); 07652 ref->index = 0; 07653 ref->reference = 0; 07654 ref->pImpTLInfo = TLB_REF_INTERNAL; 07655 list_add_head(&pTypeLibImpl->ref_list, &ref->entry); 07656 07657 dump_TypeInfo(pTIClass); 07658 07659 pTIIface->next = pTIClass; 07660 pTypeLibImpl->TypeInfoCount++; 07661 07662 *pptinfo = (ITypeInfo*)pTIClass; 07663 07664 ITypeInfo_AddRef(*pptinfo); 07665 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl); 07666 07667 return S_OK; 07668 07669 } 07670 07671 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv) 07672 { 07673 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 07674 07675 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv); 07676 } 07677 07678 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface) 07679 { 07680 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 07681 07682 return ITypeInfo_AddRef((ITypeInfo *)This); 07683 } 07684 07685 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface) 07686 { 07687 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 07688 07689 return ITypeInfo_Release((ITypeInfo *)This); 07690 } 07691 07692 static HRESULT WINAPI ITypeComp_fnBind( 07693 ITypeComp * iface, 07694 OLECHAR * szName, 07695 ULONG lHash, 07696 WORD wFlags, 07697 ITypeInfo ** ppTInfo, 07698 DESCKIND * pDescKind, 07699 BINDPTR * pBindPtr) 07700 { 07701 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface); 07702 const TLBFuncDesc *pFDesc; 07703 const TLBVarDesc *pVDesc; 07704 HRESULT hr = S_OK; 07705 07706 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 07707 07708 *pDescKind = DESCKIND_NONE; 07709 pBindPtr->lpfuncdesc = NULL; 07710 *ppTInfo = NULL; 07711 07712 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next) 07713 if (!strcmpiW(pFDesc->Name, szName)) { 07714 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags)) 07715 break; 07716 else 07717 /* name found, but wrong flags */ 07718 hr = TYPE_E_TYPEMISMATCH; 07719 } 07720 07721 if (pFDesc) 07722 { 07723 HRESULT hr = TLB_AllocAndInitFuncDesc( 07724 &pFDesc->funcdesc, 07725 &pBindPtr->lpfuncdesc, 07726 This->TypeAttr.typekind == TKIND_DISPATCH); 07727 if (FAILED(hr)) 07728 return hr; 07729 *pDescKind = DESCKIND_FUNCDESC; 07730 *ppTInfo = (ITypeInfo *)&This->lpVtbl; 07731 ITypeInfo_AddRef(*ppTInfo); 07732 return S_OK; 07733 } else { 07734 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) { 07735 if (!strcmpiW(pVDesc->Name, szName)) { 07736 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc); 07737 if (FAILED(hr)) 07738 return hr; 07739 *pDescKind = DESCKIND_VARDESC; 07740 *ppTInfo = (ITypeInfo *)&This->lpVtbl; 07741 ITypeInfo_AddRef(*ppTInfo); 07742 return S_OK; 07743 } 07744 } 07745 } 07746 /* FIXME: search each inherited interface, not just the first */ 07747 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) { 07748 /* recursive search */ 07749 ITypeInfo *pTInfo; 07750 ITypeComp *pTComp; 07751 HRESULT hr; 07752 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo); 07753 if (SUCCEEDED(hr)) 07754 { 07755 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp); 07756 ITypeInfo_Release(pTInfo); 07757 } 07758 if (SUCCEEDED(hr)) 07759 { 07760 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr); 07761 ITypeComp_Release(pTComp); 07762 return hr; 07763 } 07764 WARN("Could not search inherited interface!\n"); 07765 } 07766 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags); 07767 return hr; 07768 } 07769 07770 static HRESULT WINAPI ITypeComp_fnBindType( 07771 ITypeComp * iface, 07772 OLECHAR * szName, 07773 ULONG lHash, 07774 ITypeInfo ** ppTInfo, 07775 ITypeComp ** ppTComp) 07776 { 07777 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp); 07778 07779 /* strange behaviour (does nothing) but like the 07780 * original */ 07781 07782 if (!ppTInfo || !ppTComp) 07783 return E_POINTER; 07784 07785 *ppTInfo = NULL; 07786 *ppTComp = NULL; 07787 07788 return S_OK; 07789 } 07790 07791 static const ITypeCompVtbl tcompvt = 07792 { 07793 07794 ITypeComp_fnQueryInterface, 07795 ITypeComp_fnAddRef, 07796 ITypeComp_fnRelease, 07797 07798 ITypeComp_fnBind, 07799 ITypeComp_fnBindType 07800 }; Generated on Sat May 26 2012 04:24:18 for ReactOS by
1.7.6.1
|