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.

1206 lines
38 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. probedassemblyinformation.cpp
  5. Abstract:
  6. Class that contains all the relevant information about an assembly
  7. that has been found in the assembly store.
  8. Author:
  9. Michael J. Grier (MGrier) 11-May-2000
  10. Revision History:
  11. --*/
  12. #include "stdinc.h"
  13. #include <windows.h>
  14. #include "sxsp.h"
  15. #include "probedassemblyinformation.h"
  16. #include "fusionparser.h"
  17. #define POLICY_FILE_EXTENSION L".policy"
  18. #define IS_NT_DOS_PATH(_x) (((_x)[0] == L'\\') && ((_x)[1] == L'?') && ((_x)[2] == L'?') && \
  19. ((_x)[3] == '\\'))
  20. CProbedAssemblyInformation::~CProbedAssemblyInformation()
  21. {
  22. }
  23. BOOL
  24. CProbedAssemblyInformation::Initialize()
  25. {
  26. BOOL fSuccess = FALSE;
  27. FN_TRACE_WIN32(fSuccess);
  28. IFW32FALSE_EXIT(m_OriginalReference.Initialize());
  29. IFW32FALSE_EXIT(m_CheckpointedReference.Initialize());
  30. IFW32FALSE_EXIT(Base::Initialize());
  31. fSuccess = TRUE;
  32. Exit:
  33. return fSuccess;
  34. }
  35. BOOL
  36. CProbedAssemblyInformation::Initialize(
  37. const CAssemblyReference &r
  38. )
  39. {
  40. BOOL fSuccess = FALSE;
  41. FN_TRACE_WIN32(fSuccess);
  42. IFW32FALSE_EXIT(m_OriginalReference.Initialize(r));
  43. IFW32FALSE_EXIT(m_CheckpointedReference.Initialize());
  44. IFW32FALSE_EXIT(Base::Initialize(r));
  45. fSuccess = TRUE;
  46. Exit:
  47. return fSuccess;
  48. }
  49. // "copy initializer"
  50. BOOL
  51. CProbedAssemblyInformation::Initialize(
  52. const CProbedAssemblyInformation &r
  53. )
  54. {
  55. BOOL fSuccess = FALSE;
  56. FN_TRACE_WIN32(fSuccess);
  57. IFW32FALSE_EXIT(this->Initialize());
  58. IFW32FALSE_EXIT(this->Assign(r));
  59. fSuccess = TRUE;
  60. Exit:
  61. return fSuccess;
  62. }
  63. BOOL
  64. CProbedAssemblyInformation::SetOriginalReference(
  65. const CAssemblyReference &r,
  66. bool fCopySpecifiedFieldsFromOriginal
  67. )
  68. {
  69. BOOL fSuccess = FALSE;
  70. FN_TRACE_WIN32(fSuccess);
  71. CStringBuffer OriginalAssemblyName;
  72. if (fCopySpecifiedFieldsFromOriginal)
  73. {
  74. PCWSTR OldName;
  75. SIZE_T OldCch;
  76. IFW32FALSE_EXIT(r.GetAssemblyName(&OldName, &OldCch));
  77. IFW32FALSE_EXIT(OriginalAssemblyName.Win32Assign(OldName, OldCch));
  78. }
  79. IFW32FALSE_EXIT(m_OriginalReference.Assign(r));
  80. // nothing that can fail should appear below here in this function
  81. m_ManifestPathBuffer.Clear();
  82. if (fCopySpecifiedFieldsFromOriginal)
  83. {
  84. //
  85. // Caution - this scorches the original assembly information, but it
  86. // looks like in semantics of this function, that's what we want to
  87. // do.
  88. //
  89. if (m_pAssemblyIdentity != NULL)
  90. {
  91. ::SxsDestroyAssemblyIdentity(m_pAssemblyIdentity);
  92. m_pAssemblyIdentity = NULL;
  93. }
  94. IFW32FALSE_EXIT(
  95. ::SxsDuplicateAssemblyIdentity(
  96. 0,
  97. r.GetAssemblyIdentity(),
  98. &m_pAssemblyIdentity));
  99. }
  100. fSuccess = TRUE;
  101. Exit:
  102. return fSuccess;
  103. }
  104. BOOL
  105. CProbedAssemblyInformation::ResetProbedToOriginal()
  106. {
  107. BOOL fSuccess = FALSE;
  108. FN_TRACE_WIN32(fSuccess);
  109. IFW32FALSE_EXIT(Base::Assign(m_OriginalReference));
  110. fSuccess = TRUE;
  111. Exit:
  112. return fSuccess;
  113. }
  114. BOOL
  115. CProbedAssemblyInformation::Assign(
  116. const CProbedAssemblyInformation &r
  117. )
  118. {
  119. BOOL fSuccess = FALSE;
  120. FN_TRACE_WIN32(fSuccess);
  121. IFW32FALSE_EXIT(Base::Assign(r));
  122. // manifest
  123. IFW32FALSE_EXIT(m_ManifestPathBuffer.Win32Assign(r.m_ManifestPathBuffer));
  124. m_ManifestPathType = r.m_ManifestPathType;
  125. m_ManifestLastWriteTime = r.m_ManifestLastWriteTime;
  126. m_ManifestStream = r.m_ManifestStream;
  127. m_ManifestFlags = r.m_ManifestFlags;
  128. // policy
  129. IFW32FALSE_EXIT(m_PolicyPathBuffer.Win32Assign(r.m_PolicyPathBuffer));
  130. m_PolicyPathType = r.m_PolicyPathType;
  131. m_PolicyLastWriteTime = r.m_PolicyLastWriteTime;
  132. m_PolicyStream = r.m_PolicyStream;
  133. m_PolicyFlags = r.m_PolicyFlags;
  134. m_PolicySource = r.m_PolicySource;
  135. IFW32FALSE_EXIT(m_OriginalReference.Assign(r.m_OriginalReference));
  136. fSuccess = TRUE;
  137. Exit:
  138. return fSuccess;
  139. }
  140. BOOL
  141. CProbedAssemblyInformation::SetPolicyPath(
  142. ULONG PathType,
  143. PCWSTR Path,
  144. SIZE_T PathCch
  145. )
  146. {
  147. BOOL fSuccess = FALSE;
  148. FN_TRACE_WIN32(fSuccess);
  149. PARAMETER_CHECK(PathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE);
  150. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  151. IFW32FALSE_EXIT(m_PolicyPathBuffer.Win32Assign(Path, PathCch));
  152. m_PolicyPathType = PathType;
  153. fSuccess = TRUE;
  154. Exit:
  155. return fSuccess;
  156. }
  157. BOOL
  158. CProbedAssemblyInformation::SetManifestPath(
  159. ULONG PathType,
  160. const CBaseStringBuffer &rbuff
  161. )
  162. {
  163. BOOL fSuccess = FALSE;
  164. FN_TRACE_WIN32(fSuccess);
  165. PARAMETER_CHECK(PathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE);
  166. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  167. IFW32FALSE_EXIT(this->SetManifestPath(PathType, rbuff, rbuff.Cch()));
  168. fSuccess = TRUE;
  169. Exit:
  170. return fSuccess;
  171. }
  172. BOOL
  173. CProbedAssemblyInformation::SetManifestPath(
  174. ULONG PathType,
  175. PCWSTR path,
  176. SIZE_T path_t
  177. )
  178. {
  179. BOOL fSuccess = FALSE;
  180. FN_TRACE_WIN32(fSuccess);
  181. PARAMETER_CHECK(PathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE);
  182. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  183. IFW32FALSE_EXIT(m_ManifestPathBuffer.Win32Assign(path, path_t));
  184. m_ManifestPathType = PathType;
  185. fSuccess = TRUE;
  186. Exit:
  187. return fSuccess;
  188. }
  189. BOOL
  190. CProbedAssemblyInformation::ProbeManifestExistence(
  191. const CImpersonationData &ImpersonationData,
  192. bool &rfManifestExistsOut
  193. ) const
  194. {
  195. BOOL fSuccess = FALSE;
  196. FN_TRACE_WIN32(fSuccess);
  197. WIN32_FILE_ATTRIBUTE_DATA wfad;
  198. CImpersonate impersonate(ImpersonationData);
  199. bool ManifestExistsTemp = false; // used to hold eventual value to pass out
  200. bool fNotFound = false;
  201. rfManifestExistsOut = false;
  202. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  203. //
  204. // if we have a stream that implements Stat, use that
  205. // also, if we have a nonzero time and the stream doesn't implement Stat,
  206. // just stick with the nonzero time we already have
  207. //
  208. if (m_ManifestStream != NULL)
  209. {
  210. ManifestExistsTemp = true;
  211. }
  212. else
  213. {
  214. PCWSTR ManifestPath = m_ManifestPathBuffer;
  215. PARAMETER_CHECK(IS_NT_DOS_PATH(ManifestPath) == FALSE);
  216. IFW32FALSE_EXIT(impersonate.Impersonate());
  217. IFW32FALSE_EXIT_UNLESS2(
  218. ::GetFileAttributesExW(m_ManifestPathBuffer, GetFileExInfoStandard, &wfad),
  219. LIST_2(ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND),
  220. fNotFound);
  221. if (!fNotFound)
  222. ManifestExistsTemp = true;
  223. IFW32FALSE_EXIT(impersonate.Unimpersonate());
  224. }
  225. rfManifestExistsOut = ManifestExistsTemp;
  226. fSuccess = TRUE;
  227. Exit:
  228. return fSuccess;
  229. }
  230. BOOL
  231. CProbedAssemblyInformation::SetManifestLastWriteTime(
  232. PACTCTXGENCTX pActCtxGenCtx,
  233. BOOL fDuringBindingAndProbingPrivateManifest)
  234. {
  235. BOOL fSuccess = FALSE;
  236. FN_TRACE_WIN32(fSuccess);
  237. WIN32_FILE_ATTRIBUTE_DATA wfad;
  238. CImpersonate impersonate(pActCtxGenCtx->m_ImpersonationData);
  239. PCWSTR ManifestPath = m_ManifestPathBuffer;
  240. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  241. PARAMETER_CHECK(!IS_NT_DOS_PATH(ManifestPath));
  242. //
  243. // if we have a stream that implements Stat, use that
  244. // also, if we have a nonzero time and the stream doesn't implement Stat,
  245. // just stick with the nonzero time we already have
  246. //
  247. if (m_ManifestStream != NULL)
  248. {
  249. STATSTG stat;
  250. HRESULT hr;
  251. hr = m_ManifestStream->Stat(&stat, STATFLAG_NONAME);
  252. if (hr == E_NOTIMPL && m_ManifestLastWriteTime != 0)
  253. {
  254. fSuccess = TRUE;
  255. goto Exit;
  256. }
  257. if (hr != E_NOTIMPL)
  258. {
  259. IFCOMFAILED_EXIT(hr);
  260. m_ManifestLastWriteTime = stat.mtime;
  261. fSuccess = TRUE;
  262. goto Exit;
  263. }
  264. }
  265. IFW32FALSE_EXIT(impersonate.Impersonate());
  266. PARAMETER_CHECK(IS_NT_DOS_PATH(ManifestPath) == FALSE);
  267. BOOL CrossesReparsePoint;
  268. if (fDuringBindingAndProbingPrivateManifest)
  269. {
  270. //check whether there is a reparse point cross the path
  271. CrossesReparsePoint = FALSE;
  272. IFW32FALSE_EXIT(
  273. ::SxspDoesPathCrossReparsePoint(
  274. pActCtxGenCtx->m_ApplicationDirectoryBuffer,
  275. pActCtxGenCtx->m_ApplicationDirectoryBuffer.Cch(),
  276. ManifestPath,
  277. wcslen(ManifestPath),
  278. CrossesReparsePoint));
  279. if (CrossesReparsePoint) // report error instead of ignore and continue
  280. {
  281. ::FusionpSetLastWin32Error(ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT);
  282. goto Exit;
  283. }
  284. }
  285. // BUGBUGBUG!
  286. IFW32FALSE_ORIGINATE_AND_EXIT(::GetFileAttributesExW(ManifestPath, GetFileExInfoStandard, &wfad));
  287. if( wfad.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
  288. {
  289. ::FusionpSetLastWin32Error(ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT);
  290. goto Exit;
  291. }
  292. m_ManifestLastWriteTime = wfad.ftLastWriteTime;
  293. IFW32FALSE_EXIT(impersonate.Unimpersonate());
  294. fSuccess = TRUE;
  295. Exit:
  296. return fSuccess;
  297. }
  298. BOOL
  299. CProbedAssemblyInformation::ProbeAssembly(
  300. DWORD dwFlags,
  301. PACTCTXGENCTX pActCtxGenCtx,
  302. LanguageProbeType lpt,
  303. bool &rfFound
  304. )
  305. {
  306. BOOL fSuccess = FALSE;
  307. FN_TRACE_WIN32(fSuccess);
  308. PCWSTR Slash;
  309. ULONG index;
  310. BOOL fPrivateAssembly = FALSE;
  311. bool fManifestExists = false;
  312. bool fDone = false;
  313. ULONG ApplicationDirectoryPathType;
  314. DWORD dwGenerateManifestPathFlags = 0;
  315. rfFound = false;
  316. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  317. PARAMETER_CHECK((dwFlags & ~(ProbeAssembly_SkipPrivateAssemblies)) == 0);
  318. IFW32FALSE_EXIT(this->LookForPolicy(pActCtxGenCtx));
  319. IFW32FALSE_EXIT(this->LookForNDPWin32Policy(pActCtxGenCtx));
  320. if (pActCtxGenCtx->m_ManifestOperation == MANIFEST_OPERATION_INSTALL)
  321. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_NO_APPLICATION_ROOT_PATH_REQUIRED;
  322. if (dwFlags & ProbeAssembly_SkipPrivateAssemblies)
  323. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_PRIVATE_ASSEMBLIES;
  324. ApplicationDirectoryPathType = pActCtxGenCtx->m_ApplicationDirectoryPathType;
  325. if ((lpt != eExplicitBind) && (lpt != eLanguageNeutral))
  326. {
  327. if (!pActCtxGenCtx->m_ApplicationDirectoryHasBeenProbedForLanguageSubdirs)
  328. {
  329. SIZE_T cch;
  330. CSmallStringBuffer buffTemp;
  331. IFW32FALSE_EXIT(buffTemp.Win32Assign(pActCtxGenCtx->m_ApplicationDirectoryBuffer));
  332. cch = buffTemp.Cch();
  333. // Ok, let's see what's there.
  334. IFW32FALSE_EXIT(this->ProbeLanguageDir(buffTemp, pActCtxGenCtx->m_SpecificLanguage, pActCtxGenCtx->m_ApplicationDirectoryHasSpecificLanguageSubdir));
  335. buffTemp.Left(cch);
  336. IFW32FALSE_EXIT(this->ProbeLanguageDir(buffTemp, pActCtxGenCtx->m_GenericLanguage, pActCtxGenCtx->m_ApplicationDirectoryHasGenericLanguageSubdir));
  337. buffTemp.Left(cch);
  338. IFW32FALSE_EXIT(this->ProbeLanguageDir(buffTemp, pActCtxGenCtx->m_SpecificSystemLanguage, pActCtxGenCtx->m_ApplicationDirectoryHasSpecificSystemLanguageSubdir));
  339. buffTemp.Left(cch);
  340. IFW32FALSE_EXIT(this->ProbeLanguageDir(buffTemp, pActCtxGenCtx->m_GenericSystemLanguage, pActCtxGenCtx->m_ApplicationDirectoryHasGenericSystemLanguageSubdir));
  341. pActCtxGenCtx->m_ApplicationDirectoryHasBeenProbedForLanguageSubdirs = true;
  342. }
  343. switch (lpt)
  344. {
  345. case eSpecificLanguage:
  346. if (!pActCtxGenCtx->m_ApplicationDirectoryHasSpecificLanguageSubdir)
  347. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_LANGUAGE_SUBDIRS;
  348. break;
  349. case eGenericLanguage:
  350. if (!pActCtxGenCtx->m_ApplicationDirectoryHasGenericLanguageSubdir)
  351. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_LANGUAGE_SUBDIRS;
  352. break;
  353. case eSpecificSystemLanguage:
  354. if (!pActCtxGenCtx->m_ApplicationDirectoryHasSpecificSystemLanguageSubdir)
  355. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_LANGUAGE_SUBDIRS;
  356. break;
  357. case eGenericSystemLanguage:
  358. if (!pActCtxGenCtx->m_ApplicationDirectoryHasGenericSystemLanguageSubdir)
  359. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_LANGUAGE_SUBDIRS;
  360. break;
  361. }
  362. }
  363. for (index=0; !fDone; index++)
  364. {
  365. IFW32FALSE_EXIT(
  366. ::SxspGenerateManifestPathForProbing(
  367. index,
  368. dwGenerateManifestPathFlags,
  369. pActCtxGenCtx->m_AssemblyRootDirectoryBuffer,
  370. pActCtxGenCtx->m_AssemblyRootDirectoryBuffer.Cch(),
  371. ApplicationDirectoryPathType,
  372. pActCtxGenCtx->m_ApplicationDirectoryBuffer,
  373. pActCtxGenCtx->m_ApplicationDirectoryBuffer.Cch(),
  374. m_pAssemblyIdentity,
  375. m_ManifestPathBuffer,
  376. &fPrivateAssembly,
  377. fDone));
  378. // The SxspGenerateManifestPathForProbing() call might not have generated a candidate; only probe for the manifest
  379. // if it makes sense.
  380. if (m_ManifestPathBuffer.Cch() != 0)
  381. {
  382. ::FusionpDbgPrintEx(
  383. FUSION_DBG_LEVEL_PROBING,
  384. "SXS.DLL: Probing for manifest: %S\n", static_cast<PCWSTR>(m_ManifestPathBuffer));
  385. /*
  386. verify minimal access, and get last write time in
  387. case caller asked for it
  388. */
  389. IFW32FALSE_EXIT(this->ProbeManifestExistence(pActCtxGenCtx->m_ImpersonationData, fManifestExists));
  390. if (fManifestExists)
  391. {
  392. ::FusionpDbgPrintEx(
  393. FUSION_DBG_LEVEL_PROBING,
  394. "SXS.DLL: Probed manifest: %S is FOUND !!!\n", static_cast<PCWSTR>(m_ManifestPathBuffer));
  395. break;
  396. }
  397. }
  398. }
  399. if (fManifestExists)
  400. {
  401. CSmallStringBuffer sbFileExtension;
  402. m_ManifestPathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  403. IFW32FALSE_EXIT(this->SetManifestLastWriteTime(pActCtxGenCtx, fPrivateAssembly));
  404. // find an existed manifest-file
  405. Slash = wcsrchr(m_ManifestPathBuffer, L'\\');
  406. INTERNAL_ERROR_CHECK(Slash != NULL);
  407. IFW32FALSE_EXIT(m_ManifestPathBuffer.Win32GetPathExtension(sbFileExtension));
  408. //
  409. // Now that we're doing GAC probing, and assemblies in there live in DLLs, we
  410. // need to loosen this restriction somewhat. If the filename ends in DLL or MUI,
  411. // then it's got to have its manifest in resources. Otherwise, it's probably
  412. // a file - we can autodetect
  413. //
  414. if (FusionpEqualStrings(sbFileExtension, sbFileExtension.Cch(), L"DLL", 3, true) ||
  415. FusionpEqualStrings(sbFileExtension, sbFileExtension.Cch(), L"MUI", 3, true))
  416. {
  417. m_ManifestFlags = ASSEMBLY_MANIFEST_FILETYPE_RESOURCE;
  418. }
  419. else {
  420. m_ManifestFlags = ASSEMBLY_MANIFEST_FILETYPE_AUTO_DETECT;
  421. }
  422. if (fPrivateAssembly) { // manifest file is found from private dirs
  423. m_ManifestFlags |= ASSEMBLY_PRIVATE_MANIFEST;
  424. }
  425. }
  426. rfFound = fManifestExists;
  427. fSuccess = TRUE;
  428. Exit:
  429. return fSuccess;
  430. }
  431. #define GENERATE_NDP_PATH_NO_ROOT (0x00000001)
  432. #define GENERATE_NDP_PATH_WILDCARD_VERSION (0x00000002)
  433. #define GENERATE_NDP_PATH_PATH_ONLY (0x00000004)
  434. #define GENERATE_NDP_PATH_IS_POLICY (0x00000008)
  435. #define GENERATE_NDP_PATH_ASSEMBLY_NAME_ONLY (0x00000010)
  436. BOOL
  437. SxspGenerateNDPGacPath(
  438. ULONG ulFlags,
  439. PCASSEMBLY_IDENTITY pAsmIdent,
  440. CBaseStringBuffer *psbAssemblyRoot,
  441. CBaseStringBuffer &rsbOutput
  442. )
  443. {
  444. FN_PROLOG_WIN32;
  445. typedef struct _STRING_AND_LENGTH {
  446. PCWSTR pcwsz;
  447. SIZE_T cch;
  448. } STRING_AND_LENGTH;
  449. CSmallStringBuffer GlobalGacPath;
  450. SIZE_T cchRequired;
  451. STRING_AND_LENGTH Name, Version, Language, PublicKeyToken, AssemblyRoot;
  452. bool fRootNeedsSlash = false;
  453. rsbOutput.Clear();
  454. if ((psbAssemblyRoot == NULL) && ((ulFlags & GENERATE_NDP_PATH_NO_ROOT) == 0))
  455. {
  456. IFW32FALSE_EXIT(SxspGetNDPGacRootDirectory(GlobalGacPath));
  457. psbAssemblyRoot = &GlobalGacPath;
  458. }
  459. if (psbAssemblyRoot)
  460. {
  461. AssemblyRoot.pcwsz = *psbAssemblyRoot;
  462. AssemblyRoot.cch = psbAssemblyRoot->Cch();
  463. fRootNeedsSlash = !psbAssemblyRoot->HasTrailingPathSeparator();
  464. }
  465. else
  466. {
  467. AssemblyRoot.pcwsz = NULL;
  468. AssemblyRoot.cch = 0;
  469. }
  470. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  471. 0,
  472. pAsmIdent,
  473. &s_IdentityAttribute_name,
  474. &Name.pcwsz, &Name.cch));
  475. if ((ulFlags & GENERATE_NDP_PATH_WILDCARD_VERSION) == 0)
  476. {
  477. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  478. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  479. pAsmIdent,
  480. &s_IdentityAttribute_version,
  481. &Version.pcwsz, &Version.cch));
  482. }
  483. else
  484. {
  485. Version.pcwsz = L"*";
  486. Version.cch = 1;
  487. }
  488. //
  489. // Allow for international language - in the NDP, this is the "blank" value.
  490. //
  491. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  492. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  493. pAsmIdent,
  494. &s_IdentityAttribute_language,
  495. &Language.pcwsz, &Language.cch));
  496. //
  497. // If we got back "international", use the blank string instead.
  498. //
  499. if (FusionpEqualStrings(Language.pcwsz, Language.cch, SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_LANGUAGE_MISSING_VALUE, NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_LANGUAGE_MISSING_VALUE) - 1, true))
  500. {
  501. Language.pcwsz = 0;
  502. Language.cch = 0;
  503. }
  504. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  505. 0,
  506. pAsmIdent,
  507. &s_IdentityAttribute_publicKeyToken,
  508. &PublicKeyToken.pcwsz, &PublicKeyToken.cch));
  509. //
  510. // Calcuate the required length:
  511. // %gacpath%\{name}\{version}_{language}_{pkt}\{name}.dll
  512. //
  513. cchRequired = (AssemblyRoot.cch + 1) + (Name.cch + 1 + Version.cch + 1 + PublicKeyToken.cch);
  514. //
  515. // They want the whole path to the DLL
  516. //
  517. if ((ulFlags & GENERATE_NDP_PATH_PATH_ONLY) == 0)
  518. {
  519. cchRequired += (Name.cch + 1 + (NUMBER_OF(ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX_DLL) - 1));
  520. }
  521. //
  522. // Build the string
  523. //
  524. IFW32FALSE_EXIT(rsbOutput.Win32ResizeBuffer(cchRequired, eDoNotPreserveBufferContents));
  525. //
  526. // If they want the full path, that's 12 components. Otherwise, just 9.
  527. //
  528. IFW32FALSE_EXIT(rsbOutput.Win32AssignW(
  529. ((ulFlags & GENERATE_NDP_PATH_PATH_ONLY) ? ((ulFlags & GENERATE_NDP_PATH_ASSEMBLY_NAME_ONLY) ? 3 : 9) : 12),
  530. AssemblyRoot.pcwsz, AssemblyRoot.cch, // Root path
  531. L"\\", (fRootNeedsSlash ? 1 : 0), // Slash
  532. Name.pcwsz, Name.cch,
  533. L"\\", 1,
  534. Version.pcwsz, Version.cch,
  535. L"_", 1,
  536. Language.pcwsz, Language.cch,
  537. L"_", 1,
  538. PublicKeyToken.pcwsz, PublicKeyToken.cch,
  539. L"\\", 1,
  540. Name.pcwsz, Name.cch,
  541. ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX_DLL, NUMBER_OF(ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX_DLL)-1));
  542. FN_EPILOG;
  543. }
  544. BOOL
  545. CProbedAssemblyInformation::LookForNDPWin32Policy(
  546. PACTCTXGENCTX pActCtxGenCtx
  547. )
  548. /*++
  549. Purpose:
  550. 1. Get the location of the GAC
  551. 2. Create a path of the form %gac%\Policy.Vmajor.Vminor.AssemblyName\*_{language}_{pubkeytoken}
  552. 3. Find all directories that match the wildcard, find the version with the highest value
  553. 4. Find %thatpath%\Policy.VMajor.VMinor.AssemblyName.Dll
  554. 5. Look for a win32 policy manifest in resource ID 1, type RT_MANIFEST
  555. --*/
  556. {
  557. BOOL fSuccess = FALSE;
  558. FN_TRACE_WIN32(fSuccess);
  559. CPolicyStatement *pFoundPolicyStatement = NULL;
  560. CSmallStringBuffer Prober;
  561. CSmallStringBuffer EncodedPolicyIdentity;
  562. CFindFile FindFiles;
  563. ASSEMBLY_VERSION HighestAssemblyVersion = {0};
  564. WIN32_FIND_DATAW FindData;
  565. bool fNotFound = false, fPolicyFound = false, fPolicyApplied = false, fFound = false;
  566. BOOL fCrossesReparse = FALSE;
  567. DWORD dwCrossError = 0;
  568. CSxsPointerWithNamedDestructor<ASSEMBLY_IDENTITY, &::SxsDestroyAssemblyIdentity> PolicyIdentity;
  569. CProbedAssemblyInformation ProbedAssembly;
  570. //
  571. // If there's no public key token in the current assembly identity, then we can't
  572. // possibly look for it in any public places - stop right now.
  573. //
  574. {
  575. PCWSTR Version;
  576. SIZE_T cchVersion;
  577. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  578. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  579. m_pAssemblyIdentity,
  580. &s_IdentityAttribute_publicKeyToken,
  581. &Version, &cchVersion));
  582. if ((Version == NULL) || (cchVersion == 0) || ::FusionpEqualStrings(
  583. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE,
  584. NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE) - 1,
  585. Version, cchVersion, true))
  586. {
  587. FN_SUCCESSFUL_EXIT();
  588. }
  589. }
  590. //
  591. // Generate the textual and non-textual policy identity from the actual identity
  592. //
  593. IFW32FALSE_EXIT(SxspGenerateTextuallyEncodedPolicyIdentityFromAssemblyIdentity(
  594. 0,
  595. m_pAssemblyIdentity,
  596. EncodedPolicyIdentity,
  597. &PolicyIdentity));
  598. //
  599. // See if we've got policy already
  600. //
  601. IFW32FALSE_EXIT(pActCtxGenCtx->m_ApplicationPolicyTable.Find(EncodedPolicyIdentity, pFoundPolicyStatement));
  602. if (pFoundPolicyStatement != NULL)
  603. {
  604. CPolicyStatement *pTempStatement = pFoundPolicyStatement;
  605. pFoundPolicyStatement = NULL;
  606. IFW32FALSE_EXIT(pTempStatement->ApplyPolicy(m_pAssemblyIdentity, fPolicyApplied));
  607. if (fPolicyApplied)
  608. FN_SUCCESSFUL_EXIT();
  609. }
  610. //
  611. // Otherwise, we have to go look in the GAC for a policy for this assembly
  612. //
  613. IFW32FALSE_EXIT(SxspGenerateNDPGacPath(
  614. GENERATE_NDP_PATH_WILDCARD_VERSION | GENERATE_NDP_PATH_PATH_ONLY,
  615. PolicyIdentity,
  616. NULL,
  617. Prober));
  618. //
  619. // Now let's find all the directories in the GAC that match this wildcard
  620. //
  621. IFW32FALSE_EXIT_UNLESS2(
  622. FindFiles.Win32FindFirstFile(Prober, &FindData),
  623. LIST_2(ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND),
  624. fNotFound);
  625. if (!fNotFound) do
  626. {
  627. ASSEMBLY_VERSION ThisVersion;
  628. bool fValid = false;
  629. //
  630. // Skip non-directories and dot/dotdot
  631. //
  632. if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  633. continue;
  634. else if (FusionpIsDotOrDotDot(FindData.cFileName))
  635. continue;
  636. //
  637. // Neat, found a match to that pattern. Tease apart the "version" part of the directory - should
  638. // be everything up to the first underscore in the path
  639. //
  640. PCWSTR pcwszFirstUnderscore = StringFindChar(FindData.cFileName, L'_');
  641. //
  642. // Oops, that wasn't a valid path, we'll ignore it quietly
  643. //
  644. if (pcwszFirstUnderscore == NULL)
  645. continue;
  646. IFW32FALSE_EXIT(CFusionParser::ParseVersion(
  647. ThisVersion,
  648. FindData.cFileName,
  649. pcwszFirstUnderscore - FindData.cFileName,
  650. fValid));
  651. //
  652. // Sneaky buggers, putting something that's not a version up front.
  653. //
  654. if (!fValid)
  655. continue;
  656. //
  657. // Spiffy, we found something that's a version number - is it what we're looking
  658. // for?
  659. //
  660. if (!fPolicyFound || (ThisVersion > HighestAssemblyVersion))
  661. {
  662. HighestAssemblyVersion = ThisVersion;
  663. fPolicyFound = true;
  664. }
  665. } while (::FindNextFileW(FindFiles, &FindData));
  666. //
  667. // Make sure that we quit out nicely here
  668. //
  669. if (!fNotFound && (::FusionpGetLastWin32Error() != ERROR_NO_MORE_FILES))
  670. {
  671. ORIGINATE_WIN32_FAILURE_AND_EXIT(FindNextFile, ::FusionpGetLastWin32Error());
  672. }
  673. //
  674. // Otherwise, let's parse the statement we found, if there was one.
  675. //
  676. if (fPolicyFound)
  677. {
  678. //
  679. // Ensure we have space for 65535.65535.65535.65535
  680. //
  681. IFW32FALSE_EXIT(Prober.Win32ResizeBuffer((5 * 4) + 3, eDoNotPreserveBufferContents));
  682. IFW32FALSE_EXIT(Prober.Win32Format(L"%u.%u.%u.%u",
  683. HighestAssemblyVersion.Major,
  684. HighestAssemblyVersion.Minor,
  685. HighestAssemblyVersion.Revision,
  686. HighestAssemblyVersion.Build));
  687. //
  688. // Ok, now we have the 'highest version' available for the policy. Let's go swizzle the
  689. // policy identity and re-generate the path with that new version
  690. //
  691. IFW32FALSE_EXIT(ProbedAssembly.Initialize());
  692. IFW32FALSE_EXIT(SxspSetAssemblyIdentityAttributeValue(
  693. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  694. PolicyIdentity,
  695. &s_IdentityAttribute_version,
  696. static_cast<PCWSTR>(Prober),
  697. Prober.Cch()));
  698. #if DBG
  699. ::FusionpDbgPrintEx(
  700. FUSION_DBG_LEVEL_POLICY,
  701. "%s(%d) : Should find this policy identity in the GAC\n",
  702. __FILE__,
  703. __LINE__);
  704. SxspDbgPrintAssemblyIdentity(FUSION_DBG_LEVEL_POLICY, PolicyIdentity);
  705. #endif
  706. //
  707. // Now regenerate the path, set it into the actual prober
  708. //
  709. IFW32FALSE_EXIT(SxspGenerateNDPGacPath(0, PolicyIdentity, NULL, Prober));
  710. //
  711. // Caution! If this path crosses a reparse point, we could really ham up the
  712. // system while it tries to get to the file, or we could have a security hole
  713. // where someone has created a reparse point to somewhere untrusted in the
  714. // filesystem. Disallow this here.
  715. //
  716. IFW32FALSE_EXIT(SxspDoesPathCrossReparsePoint(NULL, 0, Prober, Prober.Cch(), fCrossesReparse));
  717. if (fCrossesReparse)
  718. {
  719. FN_SUCCESSFUL_EXIT();
  720. }
  721. IFW32FALSE_EXIT(ProbedAssembly.SetManifestPath(ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, Prober));
  722. IFW32FALSE_EXIT(ProbedAssembly.SetProbedIdentity(PolicyIdentity));
  723. IFW32FALSE_EXIT(SxspParseNdpGacComponentPolicy(0, pActCtxGenCtx, ProbedAssembly, pFoundPolicyStatement));
  724. IFW32FALSE_EXIT(pFoundPolicyStatement->ApplyPolicy(m_pAssemblyIdentity, fPolicyApplied));
  725. IFW32FALSE_EXIT(pActCtxGenCtx->m_ComponentPolicyTable.Insert(EncodedPolicyIdentity, pFoundPolicyStatement));
  726. // pActCtxGenCtx->m_ComponentPolicyTable owns pFoundPolicyStatement
  727. pFoundPolicyStatement = NULL;
  728. }
  729. fSuccess = TRUE;
  730. FusionpClearLastWin32Error();
  731. Exit:
  732. if (pFoundPolicyStatement)
  733. {
  734. CSxsPreserveLastError ple;
  735. delete pFoundPolicyStatement;
  736. pFoundPolicyStatement = NULL;
  737. ple.Restore();
  738. }
  739. return fSuccess;
  740. }
  741. BOOL
  742. CProbedAssemblyInformation::LookForPolicy(
  743. PACTCTXGENCTX pActCtxGenCtx
  744. )
  745. {
  746. BOOL fSuccess = FALSE;
  747. FN_TRACE_WIN32(fSuccess);
  748. CStringBuffer EncodedPolicyIdentity;
  749. HANDLE hFind = INVALID_HANDLE_VALUE;
  750. SIZE_T CandidatePolicyDirectoryCch;
  751. CPolicyStatement *pPolicyStatement = NULL;
  752. bool fPolicyApplied = false;
  753. bool fAnyPoliciesFound = false;
  754. bool fAnyFilesFound = false;
  755. PASSEMBLY_IDENTITY PolicyIdentity = NULL;
  756. BOOL fAreWeInOSSetupMode = FALSE;
  757. //
  758. // app policy, foo.exe.config
  759. //
  760. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  761. IFW32FALSE_EXIT(
  762. ::SxspGenerateTextuallyEncodedPolicyIdentityFromAssemblyIdentity(
  763. SXSP_GENERATE_TEXTUALLY_ENCODED_POLICY_IDENTITY_FROM_ASSEMBLY_IDENTITY_FLAG_OMIT_ENTIRE_VERSION,
  764. m_pAssemblyIdentity,
  765. EncodedPolicyIdentity,
  766. NULL));
  767. IFW32FALSE_EXIT(pActCtxGenCtx->m_ApplicationPolicyTable.Find(EncodedPolicyIdentity, pPolicyStatement));
  768. if (pPolicyStatement != NULL)
  769. {
  770. CPolicyStatement *pTempPolicyStatement = pPolicyStatement;
  771. pPolicyStatement = NULL; // so we don't delete it in the exit path if ApplyPolicy fails...
  772. IFW32FALSE_EXIT(pTempPolicyStatement->ApplyPolicy(m_pAssemblyIdentity, fPolicyApplied));
  773. }
  774. //
  775. // publisher policy %windir%\winsxs\Policy\...
  776. //
  777. if (!fPolicyApplied)
  778. IFW32FALSE_EXIT(FusionpAreWeInOSSetupMode(&fAreWeInOSSetupMode));
  779. if (!fPolicyApplied && !fAreWeInOSSetupMode)
  780. {
  781. IFW32FALSE_EXIT(
  782. ::SxspGenerateTextuallyEncodedPolicyIdentityFromAssemblyIdentity(
  783. 0,
  784. m_pAssemblyIdentity,
  785. EncodedPolicyIdentity,
  786. &PolicyIdentity));
  787. // See if there's a policy statement already available for this...
  788. IFW32FALSE_EXIT(pActCtxGenCtx->m_ComponentPolicyTable.Find(EncodedPolicyIdentity, pPolicyStatement));
  789. if (pPolicyStatement == NULL)
  790. {
  791. CStringBuffer CandidatePolicyDirectory;
  792. IFW32FALSE_EXIT(
  793. ::SxspGenerateSxsPath(
  794. 0,
  795. SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY,
  796. pActCtxGenCtx->m_AssemblyRootDirectoryBuffer,
  797. pActCtxGenCtx->m_AssemblyRootDirectoryBuffer.Cch(),
  798. PolicyIdentity,
  799. CandidatePolicyDirectory));
  800. // Save the number of characters up through and including the slash so that
  801. // we can repeatedly append and then call .Left() on the string buffer.
  802. CandidatePolicyDirectoryCch = CandidatePolicyDirectory.Cch();
  803. IFW32FALSE_EXIT(CandidatePolicyDirectory.Win32Append(L"*" POLICY_FILE_EXTENSION, 1 + (NUMBER_OF(POLICY_FILE_EXTENSION) - 1)));
  804. {
  805. WIN32_FIND_DATAW wfd;
  806. hFind = ::FindFirstFileW(CandidatePolicyDirectory, &wfd);
  807. if (hFind == INVALID_HANDLE_VALUE)
  808. {
  809. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  810. if ((dwLastError != ERROR_PATH_NOT_FOUND) &&
  811. (dwLastError != ERROR_FILE_NOT_FOUND))
  812. {
  813. ::FusionpDbgPrintEx(
  814. FUSION_DBG_LEVEL_ERROR,
  815. "SXS.DLL:%s FindFirstFileW(%ls)\n",
  816. __FUNCTION__,
  817. static_cast<PCWSTR>(CandidatePolicyDirectory)
  818. );
  819. TRACE_WIN32_FAILURE_ORIGINATION(FindFirstFileW);
  820. goto Exit;
  821. }
  822. }
  823. if (hFind != INVALID_HANDLE_VALUE)
  824. {
  825. fAnyFilesFound = true;
  826. ASSEMBLY_VERSION avHighestVersionFound = { 0, 0, 0, 0 };
  827. for (;;)
  828. {
  829. // Skip any directories we find; this will skip "." and ".."
  830. if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  831. {
  832. ASSEMBLY_VERSION avTemp;
  833. bool fValid;
  834. SIZE_T cchFileName = ::wcslen(wfd.cFileName);
  835. if (cchFileName > NUMBER_OF(POLICY_FILE_EXTENSION))
  836. {
  837. IFW32FALSE_EXIT(
  838. CFusionParser::ParseVersion(
  839. avTemp,
  840. wfd.cFileName,
  841. cchFileName - (NUMBER_OF(POLICY_FILE_EXTENSION) - 1),
  842. fValid));
  843. // If there are randomly named files in the directory, we just skip them.
  844. if (fValid)
  845. {
  846. if ((!fAnyPoliciesFound) ||
  847. (avTemp > avHighestVersionFound))
  848. {
  849. fAnyPoliciesFound = true;
  850. CandidatePolicyDirectory.Left(CandidatePolicyDirectoryCch);
  851. IFW32FALSE_EXIT(CandidatePolicyDirectory.Win32Append(wfd.cFileName, cchFileName));
  852. avHighestVersionFound = avTemp;
  853. }
  854. }
  855. }
  856. }
  857. if (!::FindNextFileW(hFind, &wfd))
  858. {
  859. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  860. BOOL fTemp;
  861. if (dwLastError != ERROR_NO_MORE_FILES)
  862. {
  863. TRACE_WIN32_FAILURE_ORIGINATION(FindNextFileW);
  864. goto Exit;
  865. }
  866. fTemp = ::FindClose(hFind);
  867. hFind = INVALID_HANDLE_VALUE;
  868. if (!fTemp)
  869. {
  870. TRACE_WIN32_FAILURE_ORIGINATION(FindClose);
  871. goto Exit;
  872. }
  873. break;
  874. }
  875. }
  876. }
  877. }
  878. if (fAnyFilesFound)
  879. {
  880. if (fAnyPoliciesFound)
  881. {
  882. CProbedAssemblyInformation PolicyAssemblyInformation;
  883. IFW32FALSE_EXIT(PolicyAssemblyInformation.Initialize());
  884. IFW32FALSE_EXIT(PolicyAssemblyInformation.SetOriginalReference(PolicyIdentity));
  885. IFW32FALSE_EXIT(PolicyAssemblyInformation.SetManifestPath(ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, CandidatePolicyDirectory));
  886. // For one thing, let's set the version number...
  887. IFW32FALSE_EXIT(
  888. ::SxspSetAssemblyIdentityAttributeValue(
  889. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  890. PolicyIdentity,
  891. &s_IdentityAttribute_version,
  892. static_cast<PCWSTR>(CandidatePolicyDirectory) + CandidatePolicyDirectoryCch,
  893. CandidatePolicyDirectory.Cch() - CandidatePolicyDirectoryCch - (NUMBER_OF(POLICY_FILE_EXTENSION) - 1)));
  894. IFW32FALSE_EXIT(PolicyAssemblyInformation.SetProbedIdentity(PolicyIdentity));
  895. // We found one! Let's parse it, looking for a remapping of our identity.
  896. IFW32FALSE_EXIT(
  897. ::SxspParseComponentPolicy(
  898. 0,
  899. pActCtxGenCtx,
  900. PolicyAssemblyInformation,
  901. pPolicyStatement));
  902. }
  903. else
  904. {
  905. IFALLOCFAILED_EXIT(pPolicyStatement = new CPolicyStatement);
  906. IFW32FALSE_EXIT(pPolicyStatement->Initialize());
  907. }
  908. IFW32FALSE_EXIT(pActCtxGenCtx->m_ComponentPolicyTable.Insert(EncodedPolicyIdentity, pPolicyStatement, ERROR_SXS_DUPLICATE_ASSEMBLY_NAME));
  909. }
  910. }
  911. // If there was a component policy statement, let's try it out!
  912. if (pPolicyStatement != NULL)
  913. IFW32FALSE_EXIT(pPolicyStatement->ApplyPolicy(m_pAssemblyIdentity, fPolicyApplied));
  914. }
  915. fSuccess = TRUE;
  916. Exit:
  917. if (PolicyIdentity != NULL)
  918. ::SxsDestroyAssemblyIdentity(PolicyIdentity);
  919. if (hFind != INVALID_HANDLE_VALUE)
  920. {
  921. CSxsPreserveLastError ple;
  922. ::FindClose(hFind);
  923. hFind = INVALID_HANDLE_VALUE;
  924. ple.Restore();
  925. }
  926. return fSuccess;
  927. }
  928. BOOL
  929. CProbedAssemblyInformation::SetOriginalReference(
  930. PCASSEMBLY_IDENTITY AssemblyIdentity
  931. )
  932. {
  933. BOOL fSuccess = FALSE;
  934. FN_TRACE_WIN32(fSuccess);
  935. PARAMETER_CHECK(AssemblyIdentity != NULL);
  936. IFW32FALSE_EXIT(m_OriginalReference.SetAssemblyIdentity(AssemblyIdentity));
  937. fSuccess = TRUE;
  938. Exit:
  939. return fSuccess;
  940. }
  941. BOOL
  942. CProbedAssemblyInformation::SetProbedIdentity(
  943. PCASSEMBLY_IDENTITY AssemblyIdentity
  944. )
  945. {
  946. BOOL fSuccess = FALSE;
  947. FN_TRACE_WIN32(fSuccess);
  948. PARAMETER_CHECK(AssemblyIdentity != NULL);
  949. IFW32FALSE_EXIT(Base::SetAssemblyIdentity(AssemblyIdentity));
  950. fSuccess = TRUE;
  951. Exit:
  952. return fSuccess;
  953. }
  954. BOOL
  955. CProbedAssemblyInformation::ApplyPolicyDestination(
  956. const CAssemblyReference &r,
  957. SXS_POLICY_SOURCE s,
  958. const GUID & g
  959. )
  960. {
  961. BOOL fSuccess = FALSE;
  962. FN_TRACE_WIN32(fSuccess);
  963. PCASSEMBLY_IDENTITY OldIdentity = m_pAssemblyIdentity;
  964. INTERNAL_ERROR_CHECK(this->IsInitialized());
  965. INTERNAL_ERROR_CHECK(r.IsInitialized());
  966. // Simply put, take anything in r that's specified and override our settings with it.
  967. IFW32FALSE_EXIT(
  968. ::SxsDuplicateAssemblyIdentity(
  969. 0,
  970. r.GetAssemblyIdentity(),
  971. &m_pAssemblyIdentity));
  972. m_PolicySource = s;
  973. m_SystemPolicyGuid = g;
  974. if (OldIdentity != NULL)
  975. ::SxsDestroyAssemblyIdentity(const_cast<PASSEMBLY_IDENTITY>(OldIdentity));
  976. fSuccess = TRUE;
  977. Exit:
  978. return fSuccess;
  979. }
  980. BOOL
  981. CProbedAssemblyInformation::ProbeLanguageDir(
  982. CBaseStringBuffer &rbuffApplicationDirectory,
  983. const CBaseStringBuffer &rbuffLanguage,
  984. bool &rfFound
  985. )
  986. {
  987. BOOL fSuccess = FALSE;
  988. FN_TRACE_WIN32(fSuccess);
  989. DWORD dwFileAttributes;
  990. rfFound = false;
  991. IFW32FALSE_EXIT(rbuffApplicationDirectory.Win32Append(rbuffLanguage));
  992. dwFileAttributes = ::GetFileAttributesW(rbuffApplicationDirectory);
  993. if (dwFileAttributes == ((DWORD) -1))
  994. {
  995. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  996. if (dwLastError != ERROR_FILE_NOT_FOUND)
  997. ORIGINATE_WIN32_FAILURE_AND_EXIT(GetFileAttributes, dwLastError);
  998. }
  999. else
  1000. {
  1001. if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1002. rfFound = true;
  1003. }
  1004. fSuccess = TRUE;
  1005. Exit:
  1006. return fSuccess;
  1007. }