Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

526 lines
13 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. sxsoleaut.cpp
  5. Abstract:
  6. Implementation of helper functions called by oleaut32.dll to
  7. get type library and clsid isolation.
  8. Author:
  9. Michael J. Grier (MGrier) 19-May-2000
  10. Revision History:
  11. Jay Krell (JayKrell) November 2001
  12. fixed typelibrary redirection
  13. key typelibraries by guid only, then verify language
  14. --*/
  15. #include "stdinc.h"
  16. #include <windows.h>
  17. #include "sxsp.h"
  18. #include "fusionhandle.h"
  19. typedef const GUID * PCGUID;
  20. extern "C"
  21. {
  22. extern const CLSID CLSID_PSDispatch;
  23. extern const CLSID CLSID_PSAutomation;
  24. };
  25. HRESULT
  26. FusionpWin32GetAssemblyDirectory(
  27. PCACTCTX_SECTION_KEYED_DATA askd,
  28. CBaseStringBuffer & rbuf
  29. );
  30. HRESULT
  31. HrFusionpWin32GetAssemblyDirectory(
  32. PCACTCTX_SECTION_KEYED_DATA askd,
  33. CBaseStringBuffer & rbuff
  34. );
  35. BOOL
  36. FusionpHasAssemblyDirectory(
  37. PCACTCTX_SECTION_KEYED_DATA askd
  38. );
  39. inline
  40. HRESULT
  41. HrFusionpOleaut_CopyString(
  42. PWSTR Buffer,
  43. SIZE_T * BufferSize,
  44. PCWSTR String,
  45. SIZE_T Length
  46. )
  47. {
  48. HRESULT hr;
  49. if (*BufferSize >= (Length + 1))
  50. {
  51. ::memcpy(Buffer, String, (Length * sizeof(WCHAR)));
  52. Buffer[Length] = L'\0';
  53. *BufferSize = Length;
  54. hr = NOERROR;
  55. }
  56. else
  57. {
  58. // Need ... more .... room!
  59. *BufferSize = (Length + 1);
  60. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  61. goto Exit;
  62. }
  63. Exit:
  64. return hr;
  65. }
  66. inline
  67. HRESULT
  68. HrFusionpOleaut_GetTypeLibraryName(
  69. PCACTCTX_SECTION_KEYED_DATA askd,
  70. PCWSTR * ppsz,
  71. SIZE_T * pcch
  72. )
  73. {
  74. HRESULT hr = E_UNEXPECTED;
  75. FN_TRACE_HR(hr);
  76. ULONG cch;
  77. PCWSTR psz;
  78. if (ppsz != NULL)
  79. *ppsz = NULL;
  80. if (pcch != NULL)
  81. *pcch = 0;
  82. INTERNAL_ERROR_CHECK(askd != NULL);
  83. INTERNAL_ERROR_CHECK(ppsz != NULL);
  84. INTERNAL_ERROR_CHECK(pcch != NULL);
  85. PCACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION Data = reinterpret_cast<PCACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION>(askd->lpData);
  86. if (Data->NameOffset == 0)
  87. {
  88. psz = NULL;
  89. cch = 0;
  90. }
  91. else
  92. {
  93. psz = reinterpret_cast<PCWSTR>(reinterpret_cast<ULONG_PTR>(askd->lpSectionBase) + Data->NameOffset);
  94. cch = Data->NameLength / sizeof(WCHAR);
  95. if (cch != 0 && psz[cch - 1] == 0)
  96. cch -= 1;
  97. }
  98. *ppsz = psz;
  99. *pcch = cch;
  100. hr = NOERROR;
  101. Exit:
  102. return hr;
  103. }
  104. HRESULT
  105. HrFusionpOleaut_GetTypeLibraryFullPath(
  106. PCACTCTX_SECTION_KEYED_DATA askd,
  107. CBaseStringBuffer & rbuff
  108. )
  109. {
  110. FN_PROLOG_HR;
  111. PCWSTR TypeLibraryName = NULL;
  112. SIZE_T TypeLibraryNameLength = 0;
  113. HANDLE ActivationContextHandle = NULL;
  114. IFCOMFAILED_EXIT(HrFusionpOleaut_GetTypeLibraryName(askd, &TypeLibraryName, &TypeLibraryNameLength));
  115. IFW32FALSE_EXIT(FusionpGetActivationContextFromFindResult(askd, &ActivationContextHandle));
  116. IFW32FALSE_EXIT(FusionpSearchPath(
  117. FUSIONP_SEARCH_PATH_ACTCTX,
  118. NULL, // path to search
  119. TypeLibraryName,
  120. NULL, // extension
  121. rbuff,
  122. NULL, // offset to file part
  123. ActivationContextHandle
  124. ));
  125. FN_EPILOG;
  126. }
  127. #define FUSIONP_OLEAUT_HANDLE_FIND_ERROR() \
  128. do { \
  129. const DWORD dwLastError = ::FusionpGetLastWin32Error(); \
  130. \
  131. if ((dwLastError == ERROR_SXS_KEY_NOT_FOUND) || (dwLastError == ERROR_SXS_SECTION_NOT_FOUND)) \
  132. { \
  133. hr = S_FALSE; \
  134. goto Exit; \
  135. } \
  136. \
  137. hr = HRESULT_FROM_WIN32(dwLastError); \
  138. goto Exit; \
  139. } while(0)
  140. EXTERN_C
  141. HRESULT
  142. STDAPICALLTYPE
  143. SxsOleAut32MapReferenceClsidToConfiguredClsid(
  144. REFCLSID rclsidIn,
  145. CLSID *pclsidOut
  146. )
  147. {
  148. HRESULT hr = NOERROR;
  149. ACTCTX_SECTION_KEYED_DATA askd;
  150. PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION Data = NULL;
  151. askd.cbSize = sizeof(askd);
  152. if (!::FindActCtxSectionGuid(
  153. 0,
  154. NULL,
  155. ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
  156. &rclsidIn,
  157. &askd))
  158. {
  159. FUSIONP_OLEAUT_HANDLE_FIND_ERROR();
  160. }
  161. Data = (PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION) askd.lpData;
  162. if ((askd.ulDataFormatVersion != ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_FORMAT_WHISTLER) ||
  163. (askd.ulLength < sizeof(ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION)) ||
  164. (Data->Size < sizeof(ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION)))
  165. {
  166. hr = HRESULT_FROM_WIN32(ERROR_SXS_INVALID_ACTCTXDATA_FORMAT);
  167. goto Exit;
  168. }
  169. // We should be clear to go now.
  170. if (pclsidOut != NULL)
  171. *pclsidOut = Data->ConfiguredClsid;
  172. hr = NOERROR;
  173. Exit:
  174. return hr;
  175. }
  176. HRESULT
  177. SxspOleAut32RedirectTypeLibrary(
  178. LPCOLESTR szGuid,
  179. WORD wMaj,
  180. WORD wMin,
  181. LANGID langid,
  182. SIZE_T *pcchFileName,
  183. LPOLESTR rgFileName
  184. )
  185. {
  186. HRESULT hr = E_UNEXPECTED;
  187. FN_TRACE_HR(hr);
  188. GUID Guid;
  189. CSmallStringBuffer buff;
  190. CFusionActCtxHandle ActCtxHandle;
  191. PARAMETER_CHECK(szGuid != NULL);
  192. PARAMETER_CHECK(pcchFileName != NULL);
  193. PARAMETER_CHECK((rgFileName != NULL) || (*pcchFileName));
  194. ACTCTX_SECTION_KEYED_DATA askd;
  195. PCACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION Data = NULL;
  196. PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER AssemblyRosterHeader = NULL;
  197. PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY AssemblyRosterEntry = NULL;
  198. askd.cbSize = sizeof(askd);
  199. askd.hActCtx = NULL;
  200. IFW32FALSE_EXIT(SxspParseGUID(szGuid, ::wcslen(szGuid), Guid));
  201. if (!::FindActCtxSectionGuid(
  202. FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
  203. | FIND_ACTCTX_SECTION_KEY_RETURN_FLAGS
  204. | FIND_ACTCTX_SECTION_KEY_RETURN_ASSEMBLY_METADATA,
  205. NULL,
  206. ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION,
  207. &Guid,
  208. &askd))
  209. {
  210. FUSIONP_OLEAUT_HANDLE_FIND_ERROR();
  211. }
  212. ActCtxHandle = askd.hActCtx; // ReleaseActCtx in destructor
  213. Data = (PCACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION) askd.lpData;
  214. if ((askd.ulDataFormatVersion != ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION_FORMAT_WHISTLER) ||
  215. (askd.ulLength < sizeof(ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION)) ||
  216. (Data->Size < sizeof(ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION)))
  217. {
  218. hr = HRESULT_FROM_WIN32(ERROR_SXS_INVALID_ACTCTXDATA_FORMAT);
  219. goto Exit;
  220. }
  221. if (langid != MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL))
  222. {
  223. ULONG LanguageLength = 0;
  224. PCACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION AssemblyInformation = NULL;
  225. AssemblyInformation = reinterpret_cast<PCACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION>(askd.AssemblyMetadata.lpInformation);
  226. LanguageLength = (AssemblyInformation->LanguageLength / sizeof(WCHAR));
  227. if (LanguageLength != 0)
  228. {
  229. CSmallStringBuffer Cultures[2];
  230. PCWSTR LanguageString = NULL;
  231. // we should do bounds checking here against AssemblyMetadata.ulSectionLength
  232. LanguageString = reinterpret_cast<PCWSTR>(AssemblyInformation->LanguageOffset + reinterpret_cast<PCBYTE>(askd.AssemblyMetadata.lpSectionBase));
  233. IFW32FALSE_EXIT(SxspMapLANGIDToCultures(langid, Cultures[0], Cultures[1]));
  234. if (LanguageLength != 0 && LanguageString[LanguageLength - 1] == 0)
  235. LanguageLength -= 1;
  236. if ( !FusionpEqualStrings(LanguageString, LanguageLength, Cultures[0], Cultures[0].Cch(), true)
  237. && !FusionpEqualStrings(LanguageString, LanguageLength, Cultures[1], Cultures[1].Cch(), true)
  238. )
  239. {
  240. hr = S_FALSE;
  241. goto Exit;
  242. }
  243. }
  244. }
  245. if (wMaj != 0 || wMin != 0)
  246. {
  247. if (wMaj != Data->Version.Major)
  248. {
  249. hr = S_FALSE;
  250. goto Exit;
  251. }
  252. if (wMin > Data->Version.Minor)
  253. {
  254. hr = S_FALSE;
  255. goto Exit;
  256. }
  257. }
  258. IFCOMFAILED_EXIT(HrFusionpOleaut_GetTypeLibraryFullPath(&askd, buff));
  259. IFCOMFAILED_EXIT(
  260. HrFusionpOleaut_CopyString(
  261. rgFileName,
  262. pcchFileName,
  263. static_cast<PCWSTR>(buff),
  264. buff.Cch()
  265. ));
  266. hr = NOERROR;
  267. Exit:
  268. return hr;
  269. }
  270. LANGID
  271. FusionpLanguageIdFromLocaleId(
  272. LCID lcid
  273. )
  274. {
  275. //
  276. // LANGIDFROMLCID does not actually remove non default sort.
  277. //
  278. LANGID Language = LANGIDFROMLCID(lcid);
  279. ULONG PrimaryLanguage = PRIMARYLANGID(Language);
  280. ULONG SubLanguage = SUBLANGID(Language);
  281. Language = MAKELANGID(PrimaryLanguage, SubLanguage);
  282. return Language;
  283. }
  284. EXTERN_C
  285. HRESULT
  286. STDAPICALLTYPE
  287. SxsOleAut32RedirectTypeLibrary(
  288. LPCOLESTR szGuid,
  289. WORD wMaj,
  290. WORD wMin,
  291. LCID lcid,
  292. BOOL /*fHighest*/,
  293. SIZE_T *pcchFileName,
  294. LPOLESTR rgFileName
  295. )
  296. {
  297. HRESULT hr = E_UNEXPECTED;
  298. FN_TRACE_HR(hr);
  299. IFCOMFAILED_EXIT(hr = ::SxspOleAut32RedirectTypeLibrary(szGuid, wMaj, wMin, FusionpLanguageIdFromLocaleId(lcid), pcchFileName, rgFileName));
  300. Exit:
  301. return hr;
  302. }
  303. HRESULT
  304. HrFusionpOleaut_MapIIDToTLBID(
  305. REFIID riid,
  306. PCGUID* ppctlbid
  307. )
  308. {
  309. HRESULT hr = E_UNEXPECTED;
  310. FN_TRACE_HR(hr);
  311. ACTCTX_SECTION_KEYED_DATA askd;
  312. PCACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION Data;
  313. PARAMETER_CHECK(&riid != NULL);
  314. PARAMETER_CHECK(ppctlbid != NULL);
  315. *ppctlbid = NULL;
  316. askd.cbSize = sizeof(askd);
  317. if (!::FindActCtxSectionGuid(
  318. 0,
  319. NULL,
  320. ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
  321. &riid,
  322. &askd))
  323. {
  324. FUSIONP_OLEAUT_HANDLE_FIND_ERROR();
  325. }
  326. Data = reinterpret_cast<PCACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION>(askd.lpData);
  327. *ppctlbid = &Data->TypeLibraryId;
  328. hr = NOERROR;
  329. Exit:
  330. return hr;
  331. }
  332. EXTERN_C
  333. HRESULT
  334. STDAPICALLTYPE
  335. SxsOleAut32MapIIDToTLBPath(
  336. REFIID riid,
  337. SIZE_T cchBuffer,
  338. WCHAR *pBuffer,
  339. SIZE_T *pcchWrittenOrRequired
  340. )
  341. {
  342. HRESULT hr = E_UNEXPECTED;
  343. FN_TRACE_HR(hr);
  344. ACTCTX_SECTION_KEYED_DATA askd;
  345. PCGUID pctlbid = NULL;
  346. CSmallStringBuffer buff;
  347. CFusionActCtxHandle ActCtxHandle;
  348. PARAMETER_CHECK(&riid != NULL);
  349. PARAMETER_CHECK(pBuffer != NULL);
  350. PARAMETER_CHECK(pcchWrittenOrRequired != NULL);
  351. PARAMETER_CHECK(cchBuffer != 0);
  352. IFCOMFAILED_EXIT(hr = HrFusionpOleaut_MapIIDToTLBID(riid, &pctlbid));
  353. if (hr == S_FALSE)
  354. {
  355. goto Exit;
  356. }
  357. askd.cbSize = sizeof(askd);
  358. if (!::FindActCtxSectionGuid(
  359. FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
  360. | FIND_ACTCTX_SECTION_KEY_RETURN_FLAGS,
  361. NULL,
  362. ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION,
  363. pctlbid,
  364. &askd))
  365. {
  366. FUSIONP_OLEAUT_HANDLE_FIND_ERROR();
  367. }
  368. ActCtxHandle = askd.hActCtx; // ReleaseActCtx in destructor
  369. IFCOMFAILED_EXIT(HrFusionpOleaut_GetTypeLibraryFullPath(&askd, buff));
  370. //
  371. // We do not care about version or language in this case.
  372. //
  373. IFCOMFAILED_EXIT(
  374. HrFusionpOleaut_CopyString(
  375. pBuffer,
  376. pcchWrittenOrRequired,
  377. static_cast<PCWSTR>(buff),
  378. buff.Cch()
  379. ));
  380. hr = NOERROR;
  381. Exit:
  382. return hr;
  383. }
  384. EXTERN_C
  385. HRESULT
  386. STDAPICALLTYPE
  387. SxsOleAut32MapIIDToProxyStubCLSID(
  388. REFIID riid,
  389. CLSID * pclsidOut
  390. )
  391. {
  392. HRESULT hr = E_UNEXPECTED;
  393. FN_TRACE_HR(hr);
  394. ACTCTX_SECTION_KEYED_DATA askd;
  395. PCACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION Data;
  396. if (pclsidOut != NULL)
  397. *pclsidOut = GUID_NULL;
  398. PARAMETER_CHECK(&riid != NULL);
  399. PARAMETER_CHECK(pclsidOut != NULL);
  400. askd.cbSize = sizeof(askd);
  401. if (!::FindActCtxSectionGuid(
  402. 0,
  403. NULL,
  404. ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
  405. &riid,
  406. &askd))
  407. {
  408. FUSIONP_OLEAUT_HANDLE_FIND_ERROR();
  409. }
  410. Data = reinterpret_cast<PCACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION>(askd.lpData);
  411. *pclsidOut = Data->ProxyStubClsid32;
  412. //
  413. // There are only USUALLY two acceptable answers here.
  414. // (but there is one bit of code in oleaut32.dll that is
  415. // actually look for anything but these two.)
  416. //
  417. // CLSID_PSDispatch {00020424-0000-0000-C000-000000000046}
  418. // CLSID_PSAutomation {00020420-0000-0000-C000-000000000046}
  419. //
  420. #if DBG
  421. {
  422. ULONG i;
  423. const static struct
  424. {
  425. const GUID * Guid;
  426. STRING Name;
  427. } GuidNameMap[] =
  428. {
  429. { NULL, RTL_CONSTANT_STRING("unknown") },
  430. { &CLSID_PSDispatch, RTL_CONSTANT_STRING("CLSID_PSDispatch") },
  431. { &CLSID_PSAutomation, RTL_CONSTANT_STRING("CLSID_PSAutomation") }
  432. };
  433. for (i = 1 ; i != RTL_NUMBER_OF(GuidNameMap) ; ++i)
  434. if (Data->ProxyStubClsid32 == *GuidNameMap[i].Guid)
  435. break;
  436. if (i == RTL_NUMBER_OF(GuidNameMap))
  437. i = 0;
  438. ::FusionpDbgPrintEx(
  439. FUSION_DBG_LEVEL_VERBOSE | FUSION_DBG_LEVEL_INFO,
  440. "SXS: %s returning %Z\n",
  441. __FUNCTION__,
  442. &GuidNameMap[i].Name
  443. );
  444. }
  445. #endif
  446. hr = NOERROR;
  447. Exit:
  448. return hr;
  449. }