Leaked source code of windows server 2003
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.

1313 lines
44 KiB

  1. /*++
  2. Copyright (c) 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. bool IsNtDosPath(PCWSTR s)
  19. {
  20. return (s[0] == L'\\' && s[1] == L'?' && s[2] == L'?' && s[3] == '\\');
  21. }
  22. //
  23. // before calls to this function, the caller has checked that the ext of this file is .dll or .exe
  24. //
  25. BOOL IsBinaryFileContainManifestInResource(PCWSTR ManifestPath, bool & rfManifestInResource)
  26. {
  27. FN_PROLOG_WIN32
  28. bool fFailedToFindManifestInResource = FALSE;
  29. rfManifestInResource = false;
  30. // NTRAID#NTBUG9 - 573793 - jonwis - 2002/04/25 - Use impersonation here!
  31. CSmartPtr<CResourceStream> ResourceStream;
  32. IFW32FALSE_EXIT(ResourceStream.Win32Allocate(__FILE__, __LINE__));
  33. IFW32FALSE_EXIT_UNLESS2(ResourceStream->Initialize(ManifestPath, MAKEINTRESOURCEW(RT_MANIFEST)),
  34. LIST_2(ERROR_RESOURCE_TYPE_NOT_FOUND, ERROR_RESOURCE_DATA_NOT_FOUND),
  35. fFailedToFindManifestInResource);
  36. rfManifestInResource = !fFailedToFindManifestInResource;
  37. FN_EPILOG
  38. }
  39. //
  40. // ISSUE: jonwis 3/11/2002 - Should these reinitialize their member variables? Or at least error
  41. // if they're being reinitialized?
  42. //
  43. BOOL
  44. CProbedAssemblyInformation::Initialize(PCACTCTXGENCTX pGenCtx)
  45. {
  46. FN_PROLOG_WIN32
  47. IFW32FALSE_EXIT(Base::Initialize());
  48. this->m_pActCtxGenCtx = pGenCtx;
  49. FN_EPILOG
  50. }
  51. BOOL
  52. CProbedAssemblyInformation::Initialize(
  53. const CAssemblyReference &r,
  54. PCACTCTXGENCTX pGenCtx
  55. )
  56. {
  57. FN_PROLOG_WIN32
  58. IFW32FALSE_EXIT(Base::Initialize(r));
  59. m_pActCtxGenCtx = pGenCtx;
  60. FN_EPILOG
  61. }
  62. // "copy initializer"
  63. BOOL
  64. CProbedAssemblyInformation::Initialize(
  65. const CProbedAssemblyInformation &r
  66. )
  67. {
  68. FN_PROLOG_WIN32
  69. IFW32FALSE_EXIT(this->Assign(r));
  70. FN_EPILOG
  71. }
  72. // "copy initializer"
  73. BOOL
  74. CProbedAssemblyInformation::InitializeTakeValue(
  75. CProbedAssemblyInformation &r
  76. )
  77. {
  78. FN_PROLOG_WIN32
  79. IFW32FALSE_EXIT(this->TakeValue(r));
  80. FN_EPILOG
  81. }
  82. BOOL
  83. CProbedAssemblyInformation::Assign(
  84. const CProbedAssemblyInformation &r
  85. )
  86. {
  87. FN_PROLOG_WIN32
  88. IFW32FALSE_EXIT(Base::Assign(r));
  89. // manifest
  90. IFW32FALSE_EXIT(m_ManifestPathBuffer.Win32Assign(r.m_ManifestPathBuffer));
  91. m_ManifestPathType = r.m_ManifestPathType;
  92. m_ManifestLastWriteTime = r.m_ManifestLastWriteTime;
  93. m_ManifestStream = r.m_ManifestStream;
  94. m_ManifestFlags = r.m_ManifestFlags;
  95. // policy
  96. IFW32FALSE_EXIT(m_PolicyPathBuffer.Win32Assign(r.m_PolicyPathBuffer));
  97. m_PolicyPathType = r.m_PolicyPathType;
  98. m_PolicyLastWriteTime = r.m_PolicyLastWriteTime;
  99. m_PolicyStream = r.m_PolicyStream;
  100. m_PolicyFlags = r.m_PolicyFlags;
  101. m_PolicySource = r.m_PolicySource;
  102. m_pActCtxGenCtx = r.m_pActCtxGenCtx;
  103. FN_EPILOG
  104. }
  105. BOOL
  106. CProbedAssemblyInformation::TakeValue(
  107. CProbedAssemblyInformation &r
  108. )
  109. {
  110. FN_PROLOG_WIN32
  111. IFW32FALSE_EXIT(Base::TakeValue(r));
  112. // manifest
  113. IFW32FALSE_EXIT(m_ManifestPathBuffer.Win32Assign(r.m_ManifestPathBuffer));
  114. m_ManifestPathType = r.m_ManifestPathType;
  115. m_ManifestLastWriteTime = r.m_ManifestLastWriteTime;
  116. m_ManifestStream = r.m_ManifestStream;
  117. m_ManifestFlags = r.m_ManifestFlags;
  118. // policy
  119. IFW32FALSE_EXIT(m_PolicyPathBuffer.Win32Assign(r.m_PolicyPathBuffer));
  120. m_PolicyPathType = r.m_PolicyPathType;
  121. m_PolicyLastWriteTime = r.m_PolicyLastWriteTime;
  122. m_PolicyStream = r.m_PolicyStream;
  123. m_PolicyFlags = r.m_PolicyFlags;
  124. m_PolicySource = r.m_PolicySource;
  125. m_pActCtxGenCtx = r.m_pActCtxGenCtx;
  126. FN_EPILOG
  127. }
  128. BOOL
  129. CProbedAssemblyInformation::SetPolicyPath(
  130. ULONG PathType,
  131. PCWSTR Path,
  132. SIZE_T PathCch
  133. )
  134. {
  135. FN_PROLOG_WIN32
  136. PARAMETER_CHECK(PathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE);
  137. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  138. IFW32FALSE_EXIT(m_PolicyPathBuffer.Win32Assign(Path, PathCch));
  139. m_PolicyPathType = PathType;
  140. FN_EPILOG
  141. }
  142. BOOL
  143. CProbedAssemblyInformation::SetManifestPath(
  144. ULONG PathType,
  145. const CBaseStringBuffer &rbuff
  146. )
  147. {
  148. FN_PROLOG_WIN32
  149. PARAMETER_CHECK(PathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE);
  150. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  151. IFW32FALSE_EXIT(this->SetManifestPath(PathType, rbuff, rbuff.Cch()));
  152. FN_EPILOG
  153. }
  154. //
  155. // ISSUE: jonwis 3/11/2002 - Consider redoing the class hierarchy here and making all the things
  156. // that take/return PCWSTR/SIZE_T or PCWSTR&/SIZE_T and have them actually use stringbuffers
  157. // properly. It'd be cheap/free, and you'd shrink stack sizes as well as (potentially)
  158. // speeding up assignments if/when we ever do things like combining string buffers under
  159. // the hood.
  160. //
  161. BOOL
  162. CProbedAssemblyInformation::SetManifestPath(
  163. ULONG PathType,
  164. PCWSTR path,
  165. SIZE_T path_t
  166. )
  167. {
  168. FN_PROLOG_WIN32
  169. PARAMETER_CHECK(PathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE);
  170. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  171. IFW32FALSE_EXIT(m_ManifestPathBuffer.Win32Assign(path, path_t));
  172. m_ManifestPathType = PathType;
  173. FN_EPILOG
  174. }
  175. BOOL
  176. CProbedAssemblyInformation::ProbeManifestExistence(
  177. const CImpersonationData &ImpersonationData,
  178. BOOL fIsPrivateAssembly, // [in]
  179. bool &rfManifestExistsOut, // [out]
  180. bool &rfPrivateAssemblyManifestInResource // [out]
  181. ) const
  182. {
  183. FN_PROLOG_WIN32
  184. WIN32_FILE_ATTRIBUTE_DATA wfad;
  185. CImpersonate impersonate(ImpersonationData);
  186. bool ManifestExistsTemp = false; // used to hold eventual value to pass out
  187. bool fPrivateAssemblyManifestInResourceTemp = false;
  188. bool fNotFound = false;
  189. rfManifestExistsOut = false;
  190. rfPrivateAssemblyManifestInResource = false;
  191. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  192. //
  193. // if we have a stream that implements Stat, use that
  194. // also, if we have a nonzero time and the stream doesn't implement Stat,
  195. // just stick with the nonzero time we already have
  196. //
  197. if (m_ManifestStream != NULL)
  198. {
  199. ManifestExistsTemp = true;
  200. }
  201. else
  202. {
  203. PCWSTR ManifestPath = m_ManifestPathBuffer;
  204. PARAMETER_CHECK(!IsNtDosPath(ManifestPath));
  205. IFW32FALSE_EXIT(impersonate.Impersonate());
  206. IFW32FALSE_EXIT_UNLESS2(
  207. ::GetFileAttributesExW(m_ManifestPathBuffer, GetFileExInfoStandard, &wfad),
  208. LIST_2(ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND),
  209. fNotFound);
  210. if (!fNotFound)
  211. {
  212. ManifestExistsTemp = true;
  213. if (fIsPrivateAssembly)
  214. {
  215. //
  216. // check the probed private assembly filename is a binary file(.dll or .mui),
  217. // if so, open the dll and check whether it has manifest resource inside
  218. //
  219. // ISSUE: jonwis 3/11/2002 - Consider using sbFileExtension.Win32Equals here
  220. // instead, as it will do a "better thing" going forward.
  221. //
  222. CSmallStringBuffer sbFileExtension;
  223. IFW32FALSE_EXIT(m_ManifestPathBuffer.Win32GetPathExtension(sbFileExtension));
  224. if (::FusionpEqualStrings(
  225. sbFileExtension, sbFileExtension.Cch(),
  226. L"DLL", NUMBER_OF(L"DLL") -1,
  227. TRUE // case-insensitive
  228. ) ||
  229. ::FusionpEqualStrings( // this depends on our private-assembly probing alg, otherwise, it is not enough to check "mui" ,we need check "mui.dll", xiaoyuw@11/22/2000
  230. sbFileExtension, sbFileExtension.Cch(),
  231. L"MUI", NUMBER_OF(L"MUI") -1,
  232. TRUE // case-insensitive
  233. ))
  234. {
  235. //
  236. // check the resource of this binary
  237. //
  238. IFW32FALSE_EXIT(IsBinaryFileContainManifestInResource(m_ManifestPathBuffer, fPrivateAssemblyManifestInResourceTemp));
  239. ManifestExistsTemp = fPrivateAssemblyManifestInResourceTemp;
  240. }
  241. }
  242. }
  243. }
  244. rfManifestExistsOut = ManifestExistsTemp;
  245. rfPrivateAssemblyManifestInResource = fPrivateAssemblyManifestInResourceTemp;
  246. IFW32FALSE_EXIT(impersonate.Unimpersonate());
  247. FN_EPILOG
  248. }
  249. BOOL
  250. CProbedAssemblyInformation::SetManifestLastWriteTime(
  251. const CImpersonationData &ImpersonationData,
  252. BOOL fDuringBindingAndProbingPrivateManifest)
  253. {
  254. FN_PROLOG_WIN32
  255. WIN32_FILE_ATTRIBUTE_DATA wfad;
  256. CImpersonate impersonate(ImpersonationData);
  257. INTERNAL_ERROR_CHECK(m_pAssemblyIdentity != NULL);
  258. PARAMETER_CHECK(!IsNtDosPath(m_ManifestPathBuffer));
  259. //
  260. // if we have a stream that implements Stat, use that
  261. // also, if we have a nonzero time and the stream doesn't implement Stat,
  262. // just stick with the nonzero time we already have
  263. //
  264. if (m_ManifestStream != NULL)
  265. {
  266. STATSTG stat;
  267. HRESULT hr;
  268. hr = m_ManifestStream->Stat(&stat, STATFLAG_NONAME);
  269. if (hr == E_NOTIMPL && m_ManifestLastWriteTime != 0)
  270. {
  271. FN_SUCCESSFUL_EXIT();
  272. }
  273. if (hr != E_NOTIMPL)
  274. {
  275. IFCOMFAILED_EXIT(hr);
  276. m_ManifestLastWriteTime = stat.mtime;
  277. FN_SUCCESSFUL_EXIT();
  278. }
  279. }
  280. IFW32FALSE_EXIT(impersonate.Impersonate());
  281. PARAMETER_CHECK(!IsNtDosPath(m_ManifestPathBuffer));
  282. if (fDuringBindingAndProbingPrivateManifest)
  283. {
  284. //check whether there is a reparse point cross the path
  285. BOOL CrossesReparsePoint = FALSE;
  286. IFW32FALSE_EXIT(
  287. ::SxspDoesPathCrossReparsePoint(
  288. m_pActCtxGenCtx ? static_cast<PCWSTR>(m_pActCtxGenCtx->m_ApplicationDirectoryBuffer) : NULL,
  289. m_pActCtxGenCtx ? m_pActCtxGenCtx->m_ApplicationDirectoryBuffer.Cch() : 0,
  290. m_ManifestPathBuffer,
  291. m_ManifestPathBuffer.Cch(),
  292. CrossesReparsePoint));
  293. if (CrossesReparsePoint) // report error instead of ignore and continue
  294. {
  295. ORIGINATE_WIN32_FAILURE_AND_EXIT(CProbedAssemblyInformation::SetManifestLastWriteTime, ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT);
  296. }
  297. }
  298. // BUGBUGBUG!
  299. //
  300. // ISSUE: jonwis 3/11/2002 - I think the logic for guarding against reparse points should be done
  301. // in all cases, not just when we're probing for private manifests. What if someone does
  302. // a dastardly thing and makes WinSxS a hard link to somewhere else in the tree? We'll spin
  303. // forever trying to access it (if the object is gone) or otherwise do something bad to
  304. // the user. I'm pretty sure the 'does path cross reparse point' logic runs all the way
  305. // through to to the end, so maybe we should use it instead.
  306. //
  307. IFW32FALSE_ORIGINATE_AND_EXIT(::GetFileAttributesExW(m_ManifestPathBuffer, GetFileExInfoStandard, &wfad));
  308. if( wfad.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
  309. {
  310. ORIGINATE_WIN32_FAILURE_AND_EXIT(CProbedAssemblyInformation::SetManifestLastWriteTime, ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT);
  311. }
  312. m_ManifestLastWriteTime = wfad.ftLastWriteTime;
  313. IFW32FALSE_EXIT(impersonate.Unimpersonate());
  314. FN_EPILOG
  315. }
  316. BOOL
  317. CProbedAssemblyInformation::ProbeAssembly(
  318. DWORD dwFlags,
  319. PACTCTXGENCTX pActCtxGenCtx,
  320. LanguageProbeType lpt,
  321. bool &rfFound
  322. )
  323. {
  324. FN_PROLOG_WIN32
  325. PCWSTR Slash = 0;
  326. ULONG index = 0;
  327. BOOL fPrivateAssembly = false;
  328. bool fManifestExists = false;
  329. bool fDone = false;
  330. bool fAppPolicyApplied = false;
  331. bool fPublisherPolicyApplied = false;
  332. bool fPolicyApplied = false;
  333. ULONG ApplicationDirectoryPathType;
  334. DWORD dwGenerateManifestPathFlags = 0;
  335. bool fPrivateAssemblyManifestInResource = false;
  336. PROBING_ATTRIBUTE_CACHE pac = { 0 };
  337. rfFound = false;
  338. bool fAppRunningInSafeMode = false;
  339. bool fComponentRunningInSafeMode = false;
  340. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  341. PARAMETER_CHECK((dwFlags & ~(ProbeAssembly_SkipPrivateAssemblies)) == 0);
  342. //
  343. // Policy from the win32 gac -always- wins over the NDP gac, period.
  344. //
  345. IFW32FALSE_EXIT(this->LookForAppPolicy(pActCtxGenCtx, fAppPolicyApplied, fAppRunningInSafeMode, fComponentRunningInSafeMode));
  346. #if DBG
  347. {
  348. CStringBuffer sbTextualIdentity;
  349. IFW32FALSE_EXIT(SxspGenerateTextualIdentity(
  350. 0,
  351. m_pAssemblyIdentity,
  352. sbTextualIdentity));
  353. ::FusionpDbgPrintEx(
  354. FUSION_DBG_LEVEL_SAFEMODE,
  355. "SXS.DLL: the current App is %s running in SafeMode, for assembly, %S, there is %s policy applied\n",
  356. fAppRunningInSafeMode? "truely" : "not",
  357. static_cast<PCWSTR>(sbTextualIdentity),
  358. fAppPolicyApplied? "truly" : "no");
  359. }
  360. #endif
  361. //
  362. // if not found in app config or found but app is running in non-safemode, continue
  363. // searching policy from winsxs and NDP policy
  364. //
  365. if (!fAppRunningInSafeMode && !fComponentRunningInSafeMode)
  366. {
  367. IFW32FALSE_EXIT(this->LookForSxsWin32Policy(pActCtxGenCtx, fAppPolicyApplied, fPublisherPolicyApplied));
  368. if (!fPublisherPolicyApplied)
  369. {
  370. IFW32FALSE_EXIT(this->LookForNDPWin32Policy(pActCtxGenCtx, fPublisherPolicyApplied));
  371. }
  372. }
  373. fPolicyApplied = (fAppPolicyApplied || fPublisherPolicyApplied);
  374. if (pActCtxGenCtx->m_ManifestOperation == MANIFEST_OPERATION_INSTALL)
  375. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_NO_APPLICATION_ROOT_PATH_REQUIRED;
  376. if (dwFlags & ProbeAssembly_SkipPrivateAssemblies)
  377. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_PRIVATE_ASSEMBLIES;
  378. ApplicationDirectoryPathType = pActCtxGenCtx->m_ApplicationDirectoryPathType;
  379. if ((lpt != eExplicitBind) && (lpt != eLanguageNeutral))
  380. {
  381. if (!pActCtxGenCtx->m_ApplicationDirectoryHasBeenProbedForLanguageSubdirs)
  382. {
  383. SIZE_T cch = 0;
  384. CSmallStringBuffer buffTemp;
  385. IFW32FALSE_EXIT(buffTemp.Win32Assign(pActCtxGenCtx->m_ApplicationDirectoryBuffer));
  386. cch = buffTemp.Cch();
  387. // Ok, let's see what's there.
  388. IFW32FALSE_EXIT(this->ProbeLanguageDir(buffTemp, pActCtxGenCtx->m_SpecificLanguage, pActCtxGenCtx->m_ApplicationDirectoryHasSpecificLanguageSubdir));
  389. buffTemp.Left(cch);
  390. IFW32FALSE_EXIT(this->ProbeLanguageDir(buffTemp, pActCtxGenCtx->m_GenericLanguage, pActCtxGenCtx->m_ApplicationDirectoryHasGenericLanguageSubdir));
  391. buffTemp.Left(cch);
  392. IFW32FALSE_EXIT(this->ProbeLanguageDir(buffTemp, pActCtxGenCtx->m_SpecificSystemLanguage, pActCtxGenCtx->m_ApplicationDirectoryHasSpecificSystemLanguageSubdir));
  393. buffTemp.Left(cch);
  394. IFW32FALSE_EXIT(this->ProbeLanguageDir(buffTemp, pActCtxGenCtx->m_GenericSystemLanguage, pActCtxGenCtx->m_ApplicationDirectoryHasGenericSystemLanguageSubdir));
  395. pActCtxGenCtx->m_ApplicationDirectoryHasBeenProbedForLanguageSubdirs = true;
  396. }
  397. switch (lpt)
  398. {
  399. case eSpecificLanguage:
  400. if (!pActCtxGenCtx->m_ApplicationDirectoryHasSpecificLanguageSubdir)
  401. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_LANGUAGE_SUBDIRS;
  402. break;
  403. case eGenericLanguage:
  404. if (!pActCtxGenCtx->m_ApplicationDirectoryHasGenericLanguageSubdir)
  405. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_LANGUAGE_SUBDIRS;
  406. break;
  407. case eSpecificSystemLanguage:
  408. if (!pActCtxGenCtx->m_ApplicationDirectoryHasSpecificSystemLanguageSubdir)
  409. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_LANGUAGE_SUBDIRS;
  410. break;
  411. case eGenericSystemLanguage:
  412. if (!pActCtxGenCtx->m_ApplicationDirectoryHasGenericSystemLanguageSubdir)
  413. dwGenerateManifestPathFlags |= SXS_GENERATE_MANIFEST_PATH_FOR_PROBING_SKIP_LANGUAGE_SUBDIRS;
  414. break;
  415. }
  416. }
  417. for (index=0; !fDone; index++)
  418. {
  419. IFW32FALSE_EXIT(
  420. ::SxspGenerateManifestPathForProbing(
  421. index,
  422. dwGenerateManifestPathFlags,
  423. pActCtxGenCtx->m_AssemblyRootDirectoryBuffer,
  424. pActCtxGenCtx->m_AssemblyRootDirectoryBuffer.Cch(),
  425. ApplicationDirectoryPathType,
  426. pActCtxGenCtx->m_ApplicationDirectoryBuffer,
  427. pActCtxGenCtx->m_ApplicationDirectoryBuffer.Cch(),
  428. m_pAssemblyIdentity,
  429. &pac,
  430. m_ManifestPathBuffer,
  431. &fPrivateAssembly,
  432. fDone));
  433. // The SxspGenerateManifestPathForProbing() call might not have generated a candidate; only probe for the manifest
  434. // if it makes sense.
  435. if (m_ManifestPathBuffer.Cch() != 0)
  436. {
  437. ::FusionpDbgPrintEx(
  438. FUSION_DBG_LEVEL_PROBING,
  439. "SXS.DLL: Probing for manifest: %S\n", static_cast<PCWSTR>(m_ManifestPathBuffer));
  440. /*
  441. verify minimal access, and get last write time in
  442. case caller asked for it
  443. */
  444. IFW32FALSE_EXIT(this->ProbeManifestExistence(pActCtxGenCtx->m_ImpersonationData, fPrivateAssembly, fManifestExists, fPrivateAssemblyManifestInResource));
  445. if (fManifestExists)
  446. {
  447. ::FusionpDbgPrintEx(
  448. FUSION_DBG_LEVEL_PROBING,
  449. "SXS.DLL: Probed manifest: %S is FOUND !!!\n", static_cast<PCWSTR>(m_ManifestPathBuffer));
  450. break;
  451. }
  452. }
  453. }
  454. if (fManifestExists)
  455. {
  456. m_ManifestPathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  457. m_ManifestFlags = ASSEMBLY_MANIFEST_FILETYPE_AUTO_DETECT;
  458. IFW32FALSE_EXIT(this->SetManifestLastWriteTime(pActCtxGenCtx->m_ImpersonationData, fPrivateAssembly));
  459. INTERNAL_ERROR_CHECK(m_ManifestPathBuffer.ContainsCharacter(L'\\'));
  460. if (fPrivateAssemblyManifestInResource) // only private manifest has such problem : manifst type could be FILE or RESOURCE
  461. m_ManifestFlags = ASSEMBLY_MANIFEST_FILETYPE_RESOURCE;
  462. if (fPrivateAssembly)
  463. { // manifest file is found from private dirs
  464. m_ManifestFlags |= ASSEMBLY_PRIVATE_MANIFEST;
  465. }
  466. }
  467. rfFound = fManifestExists;
  468. FN_EPILOG
  469. }
  470. #define GENERATE_NDP_PATH_NO_ROOT (0x00000001)
  471. #define GENERATE_NDP_PATH_WILDCARD_VERSION (0x00000002)
  472. #define GENERATE_NDP_PATH_PATH_ONLY (0x00000004)
  473. #define GENERATE_NDP_PATH_IS_POLICY (0x00000008)
  474. #define GENERATE_NDP_PATH_ASSEMBLY_NAME_ONLY (0x00000010)
  475. BOOL
  476. SxspGenerateNDPGacPath(
  477. ULONG ulFlags,
  478. PCASSEMBLY_IDENTITY pAsmIdent,
  479. CBaseStringBuffer *psbAssemblyRoot,
  480. CBaseStringBuffer &rsbOutput
  481. )
  482. {
  483. FN_PROLOG_WIN32
  484. typedef struct _STRING_AND_LENGTH {
  485. _STRING_AND_LENGTH() : pcwsz(NULL), cch(0) { }
  486. ~_STRING_AND_LENGTH() { }
  487. PCWSTR pcwsz;
  488. SIZE_T cch;
  489. } STRING_AND_LENGTH;
  490. CSmallStringBuffer GlobalGacPath;
  491. SIZE_T cchRequired = 0;
  492. STRING_AND_LENGTH Name;
  493. STRING_AND_LENGTH Version;
  494. STRING_AND_LENGTH Language;
  495. STRING_AND_LENGTH PublicKeyToken;
  496. STRING_AND_LENGTH AssemblyRoot;
  497. bool fRootNeedsSlash = false;
  498. rsbOutput.Clear();
  499. if ((psbAssemblyRoot == NULL) && ((ulFlags & GENERATE_NDP_PATH_NO_ROOT) == 0))
  500. {
  501. IFW32FALSE_EXIT(SxspGetNDPGacRootDirectory(GlobalGacPath));
  502. psbAssemblyRoot = &GlobalGacPath;
  503. }
  504. if (psbAssemblyRoot)
  505. {
  506. AssemblyRoot.pcwsz = *psbAssemblyRoot;
  507. AssemblyRoot.cch = psbAssemblyRoot->Cch();
  508. fRootNeedsSlash = !psbAssemblyRoot->HasTrailingPathSeparator();
  509. }
  510. else
  511. {
  512. AssemblyRoot.pcwsz = NULL;
  513. AssemblyRoot.cch = 0;
  514. }
  515. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  516. 0,
  517. pAsmIdent,
  518. &s_IdentityAttribute_name,
  519. &Name.pcwsz, &Name.cch));
  520. if ((ulFlags & GENERATE_NDP_PATH_WILDCARD_VERSION) == 0)
  521. {
  522. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  523. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  524. pAsmIdent,
  525. &s_IdentityAttribute_version,
  526. &Version.pcwsz, &Version.cch));
  527. }
  528. else
  529. {
  530. Version.pcwsz = L"*";
  531. Version.cch = 1;
  532. }
  533. //
  534. // Allow for international language - in the NDP, this is the "blank" value.
  535. //
  536. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  537. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  538. pAsmIdent,
  539. &s_IdentityAttribute_language,
  540. &Language.pcwsz, &Language.cch));
  541. //
  542. // If we got back "international", use the blank string instead.
  543. //
  544. if (::FusionpEqualStringsI(Language.pcwsz, Language.cch, SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_LANGUAGE_MISSING_VALUE, NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_LANGUAGE_MISSING_VALUE) - 1))
  545. {
  546. Language.pcwsz = 0;
  547. Language.cch = 0;
  548. }
  549. IFW32FALSE_EXIT(SxspGetAssemblyIdentityAttributeValue(
  550. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  551. pAsmIdent,
  552. &s_IdentityAttribute_publicKeyToken,
  553. &PublicKeyToken.pcwsz, &PublicKeyToken.cch));
  554. if (PublicKeyToken.pcwsz == NULL)
  555. {
  556. PublicKeyToken.pcwsz = SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE;
  557. PublicKeyToken.cch = NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE) - 1;
  558. }
  559. //
  560. // Calcuate the required length:
  561. // %gacpath%\{name}\{version}_{language}_{pkt}\{name}.dll
  562. //
  563. cchRequired = (AssemblyRoot.cch + 1) + (Name.cch + 1 + Version.cch + 1 + PublicKeyToken.cch);
  564. //
  565. // They want the whole path to the DLL
  566. //
  567. if ((ulFlags & GENERATE_NDP_PATH_PATH_ONLY) == 0)
  568. {
  569. cchRequired += (Name.cch + 1 + (NUMBER_OF(ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX_DLL) - 1));
  570. }
  571. //
  572. // Build the string
  573. //
  574. IFW32FALSE_EXIT(rsbOutput.Win32ResizeBuffer(cchRequired, eDoNotPreserveBufferContents));
  575. //
  576. // If they want the full path, that's 12 components. Otherwise, just 9.
  577. //
  578. IFW32FALSE_EXIT(rsbOutput.Win32AssignW(
  579. ((ulFlags & GENERATE_NDP_PATH_PATH_ONLY) ? ((ulFlags & GENERATE_NDP_PATH_ASSEMBLY_NAME_ONLY) ? 3 : 9) : 12),
  580. AssemblyRoot.pcwsz, AssemblyRoot.cch, // Root path
  581. L"\\", (fRootNeedsSlash ? 1 : 0), // Slash
  582. Name.pcwsz, Name.cch,
  583. L"\\", 1,
  584. Version.pcwsz, Version.cch,
  585. L"_", 1,
  586. Language.pcwsz, Language.cch,
  587. L"_", 1,
  588. PublicKeyToken.pcwsz, PublicKeyToken.cch,
  589. L"\\", 1,
  590. Name.pcwsz, Name.cch,
  591. ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX_DLL, NUMBER_OF(ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX_DLL)-1));
  592. FN_EPILOG
  593. }
  594. BOOL
  595. CProbedAssemblyInformation::LookForNDPWin32Policy(
  596. PACTCTXGENCTX pActCtxGenCtx,
  597. bool &rfPolicyApplied
  598. )
  599. /*++
  600. Purpose:
  601. 1. Get the location of the GAC
  602. 2. Create a path of the form %gac%\Policy.Vmajor.Vminor.AssemblyName\*_{language}_{pubkeytoken}
  603. 3. Find all directories that match the wildcard, find the version with the highest value
  604. 4. Find %thatpath%\Policy.VMajor.VMinor.AssemblyName.Dll
  605. 5. Look for a win32 policy manifest in resource ID 1, type RT_MANIFEST
  606. --*/
  607. {
  608. FN_PROLOG_WIN32
  609. CPolicyStatement *pFoundPolicyStatement = NULL;
  610. CSmallStringBuffer Prober;
  611. CStringBuffer &EncodedPolicyIdentity = pActCtxGenCtx->CProbedAssemblyInformationLookForPolicy.EncodedPolicyIdentity;
  612. CFindFile FindFiles;
  613. ASSEMBLY_VERSION HighestAssemblyVersion = {0};
  614. WIN32_FIND_DATAW FindData;
  615. bool fNotFound = false;
  616. bool fPolicyFound = false;
  617. bool fFound = false;
  618. BOOL fCrossesReparse = FALSE;
  619. CSmartPtrWithNamedDestructor<ASSEMBLY_IDENTITY, &::SxsDestroyAssemblyIdentity> PolicyIdentity;
  620. CProbedAssemblyInformation ProbedAssembly;
  621. rfPolicyApplied = false;
  622. //
  623. // Generate the textual and non-textual policy identity from the actual identity. This
  624. // does the thing twice, but because they're different identities (one to probe for
  625. // app policy and one for actual policy to probe) that's ok. Ordering is important -
  626. // we don't really want the first (policy.1.0.foo) encoded identity, we want the second
  627. // encoding (Policy.foo)
  628. //
  629. IFW32FALSE_EXIT(SxspMapAssemblyIdentityToPolicyIdentity(0, m_pAssemblyIdentity, &PolicyIdentity));
  630. //
  631. // EncodedPolicyIdentity must be calculated during LookForAppPolicy and updated during LookForSxsWin32Policy
  632. //
  633. ASSERT(!EncodedPolicyIdentity.IsEmpty());
  634. //
  635. // See if the base path to the pattern-matcher contains reparse points
  636. //
  637. IFW32FALSE_EXIT(SxspGenerateNDPGacPath(
  638. GENERATE_NDP_PATH_ASSEMBLY_NAME_ONLY,
  639. PolicyIdentity,
  640. NULL,
  641. Prober));
  642. //
  643. // See if the generated path actually exists first.
  644. //
  645. IFW32FALSE_EXIT(SxspDoesFileExist(0, Prober, fFound));
  646. if (!fFound)
  647. {
  648. #if DBG
  649. FusionpDbgPrintEx(
  650. FUSION_DBG_LEVEL_PROBING,
  651. "Sxs.dll: %s could not locate path %ls, bailing on probe.\n",
  652. __FUNCTION__,
  653. static_cast<PCWSTR>(Prober));
  654. #endif
  655. FN_SUCCESSFUL_EXIT();
  656. }
  657. IFW32FALSE_EXIT_UNLESS2(
  658. SxspDoesPathCrossReparsePoint(NULL, 0, Prober, Prober.Cch(), fCrossesReparse),
  659. LIST_4(ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, ERROR_BAD_NET_NAME),
  660. fNotFound
  661. );
  662. if (fCrossesReparse || !fNotFound)
  663. {
  664. #if DBG
  665. FusionpDbgPrintEx(
  666. FUSION_DBG_LEVEL_PROBING,
  667. "Sxs.dll: %s path %ls crosses a reparse point, can't use it, bailing out.\n",
  668. __FUNCTION__,
  669. static_cast<PCWSTR>(Prober));
  670. #endif
  671. FN_SUCCESSFUL_EXIT();
  672. }
  673. //
  674. // Otherwise, we have to go look in the GAC for a policy for this assembly
  675. //
  676. IFW32FALSE_EXIT(SxspGenerateNDPGacPath(
  677. GENERATE_NDP_PATH_WILDCARD_VERSION | GENERATE_NDP_PATH_PATH_ONLY,
  678. PolicyIdentity,
  679. NULL,
  680. Prober));
  681. //
  682. // Now let's find all the directories in the GAC that match this wildcard
  683. //
  684. IFW32FALSE_EXIT_UNLESS2(
  685. FindFiles.Win32FindFirstFile(Prober, &FindData),
  686. LIST_2(ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND),
  687. fNotFound);
  688. if (!fNotFound) do
  689. {
  690. ASSEMBLY_VERSION ThisVersion;
  691. bool fValid = false;
  692. //
  693. // Skip non-directories and dot/dotdot
  694. //
  695. if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  696. continue;
  697. else if (FusionpIsDotOrDotDot(FindData.cFileName))
  698. continue;
  699. //
  700. // Neat, found a match to that pattern. Tease apart the "version" part of the directory - should
  701. // be everything up to the first underscore in the path
  702. //
  703. PCWSTR pcwszFirstUnderscore = StringFindChar(FindData.cFileName, L'_');
  704. //
  705. // Oops, that wasn't a valid path, we'll ignore it quietly
  706. //
  707. if (pcwszFirstUnderscore == NULL)
  708. continue;
  709. IFW32FALSE_EXIT(CFusionParser::ParseVersion(
  710. ThisVersion,
  711. FindData.cFileName,
  712. pcwszFirstUnderscore - FindData.cFileName,
  713. fValid));
  714. //
  715. // Sneaky buggers, putting something that's not a version up front.
  716. //
  717. if (!fValid)
  718. continue;
  719. //
  720. // Spiffy, we found something that's a version number - is it what we're looking
  721. // for?
  722. //
  723. if (!fPolicyFound || (ThisVersion > HighestAssemblyVersion))
  724. {
  725. HighestAssemblyVersion = ThisVersion;
  726. fPolicyFound = true;
  727. }
  728. } while (::FindNextFileW(FindFiles, &FindData));
  729. //
  730. // Make sure that we quit out nicely here
  731. //
  732. if (!fNotFound && (::FusionpGetLastWin32Error() != ERROR_NO_MORE_FILES))
  733. {
  734. ORIGINATE_WIN32_FAILURE_AND_EXIT(FindNextFile, ::FusionpGetLastWin32Error());
  735. }
  736. //
  737. // Otherwise, let's parse the statement we found, if there was one.
  738. //
  739. if (fPolicyFound)
  740. {
  741. //
  742. // Ensure we have space for 65535.65535.65535.65535
  743. //
  744. IFW32FALSE_EXIT(Prober.Win32ResizeBuffer((5 * 4) + 3, eDoNotPreserveBufferContents));
  745. IFW32FALSE_EXIT(Prober.Win32Format(L"%u.%u.%u.%u",
  746. HighestAssemblyVersion.Major,
  747. HighestAssemblyVersion.Minor,
  748. HighestAssemblyVersion.Revision,
  749. HighestAssemblyVersion.Build));
  750. //
  751. // Ok, now we have the 'highest version' available for the policy. Let's go swizzle the
  752. // policy identity and re-generate the path with that new version
  753. //
  754. IFW32FALSE_EXIT(ProbedAssembly.Initialize(pActCtxGenCtx));
  755. IFW32FALSE_EXIT(SxspSetAssemblyIdentityAttributeValue(
  756. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  757. PolicyIdentity,
  758. &s_IdentityAttribute_version,
  759. static_cast<PCWSTR>(Prober),
  760. Prober.Cch()));
  761. #if DBG
  762. ::FusionpDbgPrintEx(
  763. FUSION_DBG_LEVEL_POLICY,
  764. "%s(%d) : Should find this policy identity in the GAC\n",
  765. __FILE__,
  766. __LINE__);
  767. SxspDbgPrintAssemblyIdentity(FUSION_DBG_LEVEL_POLICY, PolicyIdentity);
  768. #endif
  769. //
  770. // Now regenerate the path, set it into the actual prober
  771. //
  772. IFW32FALSE_EXIT(SxspGenerateNDPGacPath(0, PolicyIdentity, NULL, Prober));
  773. //
  774. // Caution! If this path crosses a reparse point, we could really ham up the
  775. // system while it tries to get to the file, or we could have a security hole
  776. // where someone has created a reparse point to somewhere untrusted in the
  777. // filesystem. Disallow this here.
  778. //
  779. IFW32FALSE_EXIT(SxspDoesPathCrossReparsePoint(NULL, 0, Prober, Prober.Cch(), fCrossesReparse));
  780. if (fCrossesReparse)
  781. {
  782. FN_SUCCESSFUL_EXIT();
  783. }
  784. IFW32FALSE_EXIT(ProbedAssembly.SetManifestPath(ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, Prober));
  785. IFW32FALSE_EXIT(ProbedAssembly.SetProbedIdentity(PolicyIdentity));
  786. IFW32FALSE_EXIT(SxspParseNdpGacComponentPolicy(0, pActCtxGenCtx, ProbedAssembly, pFoundPolicyStatement));
  787. IFW32FALSE_EXIT(pFoundPolicyStatement->ApplyPolicy(m_pAssemblyIdentity, rfPolicyApplied));
  788. IFW32FALSE_EXIT(pActCtxGenCtx->m_ComponentPolicyTable.Insert(EncodedPolicyIdentity, pFoundPolicyStatement));
  789. }
  790. // pActCtxGenCtx->m_ComponentPolicyTable owns pFoundPolicyStatement
  791. pFoundPolicyStatement = NULL;
  792. FN_EPILOG
  793. }
  794. BOOL
  795. CProbedAssemblyInformation::LookForAppPolicy(
  796. PACTCTXGENCTX pActCtxGenCtx,
  797. bool &rfPolicyApplied,
  798. bool &fAppRunningInSafeMode,
  799. bool &fComponentRunningInSafeMode
  800. )
  801. {
  802. FN_PROLOG_WIN32
  803. CStringBuffer &EncodedPolicyIdentity = pActCtxGenCtx->CProbedAssemblyInformationLookForPolicy.EncodedPolicyIdentity;
  804. EncodedPolicyIdentity.Clear();
  805. CSmartPtrWithNamedDestructor<ASSEMBLY_IDENTITY, &::SxsDestroyAssemblyIdentity> PolicyIdentity;
  806. CPolicyStatement *pPolicyStatement = NULL;
  807. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  808. fAppRunningInSafeMode = false;
  809. rfPolicyApplied = false;
  810. //
  811. // Get the policy identity to probe for
  812. //
  813. IFW32FALSE_EXIT(::SxspMapAssemblyIdentityToPolicyIdentity(0, m_pAssemblyIdentity, &PolicyIdentity));
  814. //
  815. // Get the key that we should find in the app policy table
  816. //
  817. IFW32FALSE_EXIT(
  818. ::SxspGenerateTextuallyEncodedPolicyIdentityFromAssemblyIdentity(
  819. SXSP_GENERATE_TEXTUALLY_ENCODED_POLICY_IDENTITY_FROM_ASSEMBLY_IDENTITY_FLAG_OMIT_ENTIRE_VERSION,
  820. m_pAssemblyIdentity,
  821. EncodedPolicyIdentity,
  822. NULL));
  823. IFW32FALSE_EXIT(pActCtxGenCtx->m_ApplicationPolicyTable.Find(EncodedPolicyIdentity, pPolicyStatement));
  824. if (pPolicyStatement != NULL)
  825. {
  826. IFW32FALSE_EXIT(pPolicyStatement->ApplyPolicy(m_pAssemblyIdentity, rfPolicyApplied));
  827. }
  828. if (pActCtxGenCtx->m_fAppApplyPublisherPolicy == SXS_PUBLISHER_POLICY_APPLY_NO)
  829. {
  830. fAppRunningInSafeMode = true;
  831. }else
  832. {
  833. if (rfPolicyApplied)
  834. {
  835. if (pPolicyStatement->m_fApplyPublisherPolicy == false)
  836. {
  837. //app is running in safemode, no further looking for publisher policy
  838. fComponentRunningInSafeMode = true;
  839. }
  840. }
  841. }
  842. FN_EPILOG
  843. }
  844. BOOL
  845. CProbedAssemblyInformation::LookForSxsWin32Policy(
  846. PACTCTXGENCTX pActCtxGenCtx,
  847. bool fAppPolicyApplied,
  848. bool &rfPolicyApplied
  849. )
  850. {
  851. FN_PROLOG_WIN32
  852. CStringBuffer &EncodedPolicyIdentity = pActCtxGenCtx->CProbedAssemblyInformationLookForPolicy.EncodedPolicyIdentity;
  853. CFindFile hFind;
  854. SIZE_T CandidatePolicyDirectoryCch = 0;
  855. CPolicyStatement *pPolicyStatement = NULL;
  856. bool fAnyPoliciesFound = false;
  857. bool fAnyFilesFound = false;
  858. CSmartPtrWithNamedDestructor<ASSEMBLY_IDENTITY, SxsDestroyAssemblyIdentity> PolicyIdentity;
  859. BOOL fAreWeInOSSetupMode = FALSE;
  860. rfPolicyApplied = false;
  861. //
  862. // app policy, foo.exe.config
  863. //
  864. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  865. //
  866. // Get the policy identity to probe for
  867. //
  868. IFW32FALSE_EXIT(::SxspMapAssemblyIdentityToPolicyIdentity(0, m_pAssemblyIdentity, &PolicyIdentity));
  869. if (fAppPolicyApplied)
  870. {
  871. //
  872. // must to recalculate EncodedPolicyIdentity because app policy applied,
  873. // otherwise, LookforAppPolicy has calculated this value
  874. //
  875. EncodedPolicyIdentity.Clear();
  876. IFW32FALSE_EXIT(
  877. ::SxspGenerateTextuallyEncodedPolicyIdentityFromAssemblyIdentity(
  878. SXSP_GENERATE_TEXTUALLY_ENCODED_POLICY_IDENTITY_FROM_ASSEMBLY_IDENTITY_FLAG_OMIT_ENTIRE_VERSION,
  879. m_pAssemblyIdentity,
  880. EncodedPolicyIdentity,
  881. NULL));
  882. }
  883. //
  884. // search winsxs policies
  885. //
  886. //
  887. // We probe only in SetupPolicies if we're in setup.
  888. // But not if we are in MiniSetup.
  889. //
  890. IFW32FALSE_EXIT(::FusionpAreWeInOSSetupMode(&fAreWeInOSSetupMode));
  891. if (fAreWeInOSSetupMode)
  892. {
  893. BOOL fAreWeInMiniSetupMode = FALSE;
  894. IFW32FALSE_EXIT(::FusionpAreWeInMiniSetupMode(&fAreWeInMiniSetupMode));
  895. if (fAreWeInMiniSetupMode)
  896. {
  897. fAreWeInOSSetupMode = FALSE;
  898. }
  899. }
  900. // See if there's a policy statement already available for this...
  901. IFW32FALSE_EXIT(pActCtxGenCtx->m_ComponentPolicyTable.Find(EncodedPolicyIdentity, pPolicyStatement));
  902. if (pPolicyStatement == NULL)
  903. {
  904. CStringBuffer &CandidatePolicyDirectory = pActCtxGenCtx->CProbedAssemblyInformationLookForPolicy.CandidatePolicyDirectory;
  905. CandidatePolicyDirectory.Clear();
  906. IFW32FALSE_EXIT(
  907. ::SxspGenerateSxsPath(
  908. 0,
  909. fAreWeInOSSetupMode ? SXSP_GENERATE_SXS_PATH_PATHTYPE_SETUP_POLICY : SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY,
  910. pActCtxGenCtx->m_AssemblyRootDirectoryBuffer,
  911. pActCtxGenCtx->m_AssemblyRootDirectoryBuffer.Cch(),
  912. PolicyIdentity,
  913. NULL,
  914. CandidatePolicyDirectory));
  915. // Save the number of characters up through and including the slash so that
  916. // we can repeatedly append and then call .Left() on the string buffer.
  917. CandidatePolicyDirectoryCch = CandidatePolicyDirectory.Cch();
  918. IFW32FALSE_EXIT(CandidatePolicyDirectory.Win32Append(L"*" POLICY_FILE_EXTENSION, 1 + (NUMBER_OF(POLICY_FILE_EXTENSION) - 1)));
  919. {
  920. WIN32_FIND_DATAW wfd;
  921. CFindFile hFind;
  922. // NTRAID#NTBUG9 - 531507 - jonwis - 2002/04/25 - Impersonate before findfirstfile
  923. hFind = ::FindFirstFileW(CandidatePolicyDirectory, &wfd);
  924. if (!hFind.IsValid())
  925. {
  926. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  927. if ((dwLastError != ERROR_PATH_NOT_FOUND) && (dwLastError != ERROR_FILE_NOT_FOUND))
  928. {
  929. ORIGINATE_WIN32_FAILURE_AND_EXIT(FindFirstFileW, dwLastError);
  930. }
  931. ::FusionpSetLastWin32Error(ERROR_NO_MORE_FILES);
  932. }
  933. else
  934. {
  935. fAnyFilesFound = true;
  936. }
  937. ASSEMBLY_VERSION avHighestVersionFound = { 0, 0, 0, 0 };
  938. if (hFind.IsValid())
  939. {
  940. for (;;)
  941. {
  942. // Skip any directories we find; this will skip "." and ".."
  943. if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  944. {
  945. ASSEMBLY_VERSION avTemp;
  946. bool fValid = false;
  947. SIZE_T cchFileName = ::wcslen(wfd.cFileName);
  948. if (cchFileName > NUMBER_OF(POLICY_FILE_EXTENSION))
  949. {
  950. IFW32FALSE_EXIT(
  951. CFusionParser::ParseVersion(
  952. avTemp,
  953. wfd.cFileName,
  954. cchFileName - (NUMBER_OF(POLICY_FILE_EXTENSION) - 1),
  955. fValid));
  956. // If there are randomly named files in the directory, we just skip them.
  957. if (fValid)
  958. {
  959. if ((!fAnyPoliciesFound) ||
  960. (avTemp > avHighestVersionFound))
  961. {
  962. fAnyPoliciesFound = true;
  963. CandidatePolicyDirectory.Left(CandidatePolicyDirectoryCch);
  964. IFW32FALSE_EXIT(CandidatePolicyDirectory.Win32Append(wfd.cFileName, cchFileName));
  965. avHighestVersionFound = avTemp;
  966. }
  967. }
  968. }
  969. }
  970. if (!::FindNextFileW(hFind, &wfd))
  971. {
  972. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  973. if (dwLastError != ERROR_NO_MORE_FILES)
  974. {
  975. TRACE_WIN32_FAILURE_ORIGINATION(FindNextFileW);
  976. goto Exit;
  977. }
  978. IFW32FALSE_EXIT(hFind.Win32Close());
  979. break;
  980. }
  981. }
  982. }
  983. }
  984. if (fAnyFilesFound)
  985. {
  986. if (fAnyPoliciesFound)
  987. {
  988. CProbedAssemblyInformation PolicyAssemblyInformation;
  989. IFW32FALSE_EXIT(PolicyAssemblyInformation.Initialize(pActCtxGenCtx));
  990. IFW32FALSE_EXIT(PolicyAssemblyInformation.SetManifestPath(ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, CandidatePolicyDirectory));
  991. // For one thing, let's set the version number...
  992. IFW32FALSE_EXIT(
  993. ::SxspSetAssemblyIdentityAttributeValue(
  994. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  995. PolicyIdentity,
  996. &s_IdentityAttribute_version,
  997. static_cast<PCWSTR>(CandidatePolicyDirectory) + CandidatePolicyDirectoryCch,
  998. CandidatePolicyDirectory.Cch() - CandidatePolicyDirectoryCch - (NUMBER_OF(POLICY_FILE_EXTENSION) - 1)));
  999. IFW32FALSE_EXIT(PolicyAssemblyInformation.SetProbedIdentity(PolicyIdentity));
  1000. // We found one! Let's parse it, looking for a remapping of our identity.
  1001. IFW32FALSE_EXIT(
  1002. ::SxspParseComponentPolicy(
  1003. 0,
  1004. pActCtxGenCtx,
  1005. PolicyAssemblyInformation,
  1006. pPolicyStatement));
  1007. IFW32FALSE_EXIT(pActCtxGenCtx->m_ComponentPolicyTable.Insert(EncodedPolicyIdentity, pPolicyStatement, ERROR_SXS_DUPLICATE_ASSEMBLY_NAME));
  1008. }
  1009. }
  1010. }
  1011. // If there was a component policy statement, let's try it out!
  1012. if (pPolicyStatement != NULL)
  1013. IFW32FALSE_EXIT(pPolicyStatement->ApplyPolicy(m_pAssemblyIdentity, rfPolicyApplied));
  1014. IFW32FALSE_EXIT(hFind.Win32Close());
  1015. FN_EPILOG
  1016. }
  1017. BOOL
  1018. CProbedAssemblyInformation::SetProbedIdentity(
  1019. PCASSEMBLY_IDENTITY AssemblyIdentity
  1020. )
  1021. {
  1022. FN_PROLOG_WIN32
  1023. PARAMETER_CHECK(AssemblyIdentity != NULL);
  1024. IFW32FALSE_EXIT(Base::SetAssemblyIdentity(AssemblyIdentity));
  1025. FN_EPILOG
  1026. }
  1027. BOOL
  1028. CProbedAssemblyInformation::ApplyPolicyDestination(
  1029. const CAssemblyReference &r,
  1030. SXS_POLICY_SOURCE s,
  1031. const GUID & g
  1032. )
  1033. {
  1034. FN_PROLOG_WIN32
  1035. PCASSEMBLY_IDENTITY OldIdentity = m_pAssemblyIdentity;
  1036. INTERNAL_ERROR_CHECK(this->IsInitialized());
  1037. INTERNAL_ERROR_CHECK(r.IsInitialized());
  1038. // Simply put, take anything in r that's specified and override our settings with it.
  1039. IFW32FALSE_EXIT(
  1040. ::SxsDuplicateAssemblyIdentity(
  1041. 0,
  1042. r.GetAssemblyIdentity(),
  1043. &m_pAssemblyIdentity));
  1044. m_PolicySource = s;
  1045. m_SystemPolicyGuid = g;
  1046. ::SxsDestroyAssemblyIdentity(const_cast<PASSEMBLY_IDENTITY>(OldIdentity));
  1047. if (OldIdentity != NULL)
  1048. ::SxsDestroyAssemblyIdentity(const_cast<PASSEMBLY_IDENTITY>(OldIdentity));
  1049. FN_EPILOG
  1050. }
  1051. //
  1052. // ISSUE: jonwis 3/11/2002 - This function should know about cleaning up its parameter,
  1053. // rather than assuming the caller will know about removing what it added. Seems
  1054. // like there's no explicit contract here in the interface, so it's not so bad.
  1055. // Just seems like either a) we should use our own stringbuffer and twiddle it
  1056. // or b) we should be the ones cleaning it up.
  1057. //
  1058. BOOL
  1059. CProbedAssemblyInformation::ProbeLanguageDir(
  1060. CBaseStringBuffer &rbuffApplicationDirectory,
  1061. const CBaseStringBuffer &rbuffLanguage,
  1062. bool &rfFound
  1063. )
  1064. {
  1065. FN_PROLOG_WIN32
  1066. DWORD dwFileAttributes = 0;
  1067. rfFound = false;
  1068. IFW32FALSE_EXIT(rbuffApplicationDirectory.Win32Append(rbuffLanguage));
  1069. //
  1070. // ISSUE: jonwis 3/11/2002 - Ick. Use SxspGetFileAttributes instead, don't compare against -1.
  1071. //
  1072. // NTRAID#NTBUG9 - 531507 - jonwis - 2002/04/25 - Use existing function to do this
  1073. // NTRAID#NTBUG9 - 531507 - jonwis - 2002/04/25 - Use impersonation when making this determination
  1074. dwFileAttributes = ::GetFileAttributesW(rbuffApplicationDirectory);
  1075. if (dwFileAttributes == ((DWORD) -1))
  1076. {
  1077. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  1078. if (dwLastError != ERROR_FILE_NOT_FOUND)
  1079. ORIGINATE_WIN32_FAILURE_AND_EXIT(GetFileAttributes, dwLastError);
  1080. }
  1081. else
  1082. {
  1083. if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1084. rfFound = true;
  1085. }
  1086. FN_EPILOG
  1087. }