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.

666 lines
25 KiB

  1. #include "stdinc.h"
  2. #include "macros.h"
  3. #include "util.h"
  4. #include "fusionbuffer.h"
  5. #include "fusionhandle.h"
  6. #include "idp.h"
  7. #include "sxsid.h"
  8. #include "sxsutil.h"
  9. #undef FUSION_DEBUG_HEAP
  10. #define ULONG_STRING_LENGTH 8
  11. #define ULONG_STRING_FORMAT L"%08lx"
  12. #define MANIFEST_ROOT_DIRECTORY_NAME L"Manifests"
  13. #define POLICY_ROOT_DIRECTORY_NAME L"Policies"
  14. #define ASSEMBLY_LONGEST_MANIFEST_FILE_NAME_SUFFIX L".Manifest"
  15. #define ASSEMBLY_POLICY_FILE_NAME_SUFFIX L".Policy"
  16. #define ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX L".Manifest"
  17. #define ASSEMBLY_TYPE_WIN32 L"win32"
  18. #define ASSEMBLY_TYPE_WIN32_CCH (NUMBER_OF(ASSEMBLY_TYPE_WIN32) - 1)
  19. #define ASSEMBLY_TYPE_WIN32_POLICY L"win32-policy"
  20. #define ASSEMBLY_TYPE_WIN32_POLICY_CCH (NUMBER_OF(ASSEMBLY_TYPE_WIN32_POLICY) - 1)
  21. //
  22. // functions copied from sxs.dll
  23. //
  24. //
  25. extern BOOL
  26. SxspGetAssemblyIdentityAttributeValue(
  27. DWORD Flags,
  28. PCASSEMBLY_IDENTITY AssemblyIdentity,
  29. PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
  30. OUT PCWSTR *StringOut,
  31. OUT SIZE_T *CchOut OPTIONAL
  32. );
  33. ///////////////////////////////////////////////////////////////////////////////
  34. // function about delete a non-empty directory recursively
  35. ///////////////////////////////////////////////////////////////////////////////
  36. static VOID
  37. SxspDeleteDirectoryHelper(
  38. CStringBuffer &dir,
  39. WIN32_FIND_DATAW &wfd,
  40. DWORD &dwFirstError
  41. )
  42. {
  43. //
  44. // the reason to add this call here is that if installation ends successfully, the directory
  45. // would be
  46. // C:\WINDOWS\WINSXS\INSTALLTEMP\15349016
  47. // +---Manifests
  48. //
  49. // and they are "empty" directories (no files). Manifests is a SH dir so set it to be
  50. // FILE_ATTRIBUTE_NORMAL be more efficient.
  51. //
  52. //
  53. SetFileAttributesW(dir, FILE_ATTRIBUTE_NORMAL);
  54. if (RemoveDirectoryW(dir)) // empty dir
  55. return;
  56. //
  57. // this is the *only* "valid" reason for DeleteDirectory fail
  58. // but I am not sure about "only"
  59. //
  60. DWORD dwLastError = ::GetLastError();
  61. if ( dwLastError != ERROR_DIR_NOT_EMPTY)
  62. {
  63. if (dwFirstError == 0)
  64. dwFirstError = dwLastError;
  65. return;
  66. }
  67. const static WCHAR SlashStar[] = L"\\*";
  68. SIZE_T length = dir.Cch();
  69. CFindFile findFile;
  70. if (!dir.Win32Append(SlashStar, NUMBER_OF(SlashStar) - 1))
  71. {
  72. if (dwFirstError == NO_ERROR)
  73. dwFirstError = ::GetLastError();
  74. goto Exit;
  75. }
  76. if (!findFile.Win32FindFirstFile(dir, &wfd))
  77. {
  78. if (dwFirstError == NO_ERROR)
  79. dwFirstError = ::GetLastError();
  80. goto Exit;
  81. }
  82. do
  83. {
  84. if (FusionpIsDotOrDotDot(wfd.cFileName))
  85. continue;
  86. DWORD dwFileAttributes = wfd.dwFileAttributes;
  87. // Trim back to the slash...
  88. dir.Left(length + 1);
  89. if (dir.Win32Append(wfd.cFileName, ::wcslen(wfd.cFileName)))
  90. {
  91. if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  92. {
  93. // recurse
  94. SxspDeleteDirectoryHelper(dir, wfd, dwFirstError);
  95. }
  96. else
  97. {
  98. if (!DeleteFileW(dir))
  99. {
  100. SetFileAttributesW(dir, FILE_ATTRIBUTE_NORMAL);
  101. if (!DeleteFileW(dir))
  102. {
  103. if (dwFirstError == NO_ERROR)
  104. {
  105. //
  106. // continue even in delete file ( delete files as much as possible)
  107. // and record the errorCode for first failure
  108. //
  109. dwFirstError = ::GetLastError();
  110. }
  111. }
  112. }
  113. }
  114. }
  115. } while (::FindNextFileW(findFile, &wfd));
  116. if (::GetLastError() != ERROR_NO_MORE_FILES)
  117. {
  118. if (dwFirstError == NO_ERROR)
  119. dwFirstError = ::GetLastError();
  120. }
  121. Exit:
  122. if (!findFile.Win32Close()) // otherwise RemoveDirectory fails
  123. if (dwFirstError == NO_ERROR)
  124. dwFirstError = ::GetLastError();
  125. dir.Left(length);
  126. if (!RemoveDirectoryW(dir)) // the dir must be empty and NORMAL_ATTRIBUTE : ready to delete
  127. {
  128. if (dwFirstError == NO_ERROR)
  129. dwFirstError = ::GetLastError();
  130. }
  131. }
  132. /*-----------------------------------------------------------------------------
  133. delete a directory recursively, continues upon errors, but returns
  134. FALSE if there were any.
  135. -----------------------------------------------------------------------------*/
  136. HRESULT
  137. ca_SxspDeleteDirectory(
  138. const CStringBuffer &dir
  139. )
  140. {
  141. HRESULT hr = S_OK;
  142. CStringBuffer mutableDir;
  143. WIN32_FIND_DATAW wfd = {0};
  144. DWORD dwFirstError = ERROR_SUCCESS;
  145. IFFALSE_EXIT(mutableDir.Win32Assign(dir));
  146. IFFALSE_EXIT(mutableDir.Win32RemoveTrailingPathSeparators());
  147. ::SxspDeleteDirectoryHelper(
  148. mutableDir,
  149. wfd,
  150. dwFirstError);
  151. //
  152. // Set wFirstError to Teb->LastWin32Error
  153. //
  154. if (dwFirstError != ERROR_SUCCESS)
  155. goto Exit;
  156. Exit:
  157. return hr;
  158. }
  159. ///////////////////////////////////////////////////////////////////////////////
  160. // function about assembly Identity
  161. ///////////////////////////////////////////////////////////////////////////////
  162. HRESULT
  163. ca_SxspFormatULONG(
  164. ULONG ul,
  165. SIZE_T CchBuffer,
  166. WCHAR Buffer[],
  167. SIZE_T *CchWrittenOrRequired
  168. )
  169. {
  170. HRESULT hr = S_OK;
  171. int cch;
  172. if (CchWrittenOrRequired != NULL)
  173. *CchWrittenOrRequired = 0;
  174. PARAMETER_CHECK_NTC(Buffer != NULL);
  175. if (CchBuffer < (ULONG_STRING_LENGTH + 1))
  176. {
  177. if (CchWrittenOrRequired != NULL)
  178. *CchWrittenOrRequired = ULONG_STRING_LENGTH + 1;
  179. SET_HRERR_AND_EXIT(ERROR_INSUFFICIENT_BUFFER);
  180. }
  181. cch = _snwprintf(Buffer, CchBuffer, ULONG_STRING_FORMAT, ul);
  182. INTERNAL_ERROR_CHECK_NTC(cch > 0);
  183. if (CchWrittenOrRequired != NULL)
  184. *CchWrittenOrRequired = cch;
  185. Exit:
  186. return hr;
  187. }
  188. ///////////////////////////////////////////////////////////////////////////////
  189. // function about assembly Identity
  190. ///////////////////////////////////////////////////////////////////////////////
  191. #define ASSEMBLY_NAME_VALID_SPECIAL_CHARACTERS L".-"
  192. #define ASSEMBLY_NAME_PRIM_MAX_LENGTH 64
  193. #define ASSEMBLY_NAME_VALID_SEPARATORS L"."
  194. #define ASSEMBLY_NAME_TRIM_INDICATOR_LENGTH 2
  195. #define ASSEMBLY_NAME_TRIM_INDICATOR L".."
  196. #define SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE L"no-public-key"
  197. BOOL
  198. IsValidAssemblyNameCharacter(WCHAR ch)
  199. {
  200. if (((ch >= L'A') && (ch <= L'Z')) ||
  201. ((ch >= L'a') && (ch <= L'z')) ||
  202. ((ch >= L'0') && (ch <= L'9')) ||
  203. (wcschr(ASSEMBLY_NAME_VALID_SPECIAL_CHARACTERS, ch)!= NULL))
  204. {
  205. return TRUE;
  206. } else
  207. return FALSE;
  208. /*
  209. if (wcschr(ASSEMBLY_NAME_VALID_SPECIAL_CHARACTERS, ch))
  210. return FALSE;
  211. else
  212. return TRUE;
  213. */
  214. }
  215. HRESULT ca_SxspGenerateAssemblyNamePrimeFromName(
  216. PCWSTR pszAssemblyName,
  217. SIZE_T CchAssemblyName,
  218. CBaseStringBuffer *Buffer
  219. )
  220. {
  221. HRESULT hr = S_OK;
  222. PWSTR pStart = NULL, pEnd = NULL;
  223. PWSTR qEnd = NULL, pszBuffer = NULL;
  224. ULONG i, j, len, ulSpaceLeft;
  225. ULONG cch;
  226. PWSTR pLeftEnd = NULL, pRightStart = NULL, PureNameEnd = NULL, PureNameStart = NULL;
  227. CStringBuffer buffTemp;
  228. CStringBufferAccessor accessor;
  229. PARAMETER_CHECK_NTC(pszAssemblyName != NULL);
  230. PARAMETER_CHECK_NTC(Buffer != NULL);
  231. // See how many characters we need max in the temporary buffer.
  232. cch = 0;
  233. for (i=0; i<CchAssemblyName; i++)
  234. {
  235. if (::IsValidAssemblyNameCharacter(pszAssemblyName[i]))
  236. cch++;
  237. }
  238. IFFALSE_EXIT(buffTemp.Win32ResizeBuffer(cch + 1, eDoNotPreserveBufferContents));
  239. accessor.Attach(&buffTemp);
  240. pszBuffer = accessor.GetBufferPtr();
  241. j = 0;
  242. for (i=0; i<CchAssemblyName; i++)
  243. {
  244. if (::IsValidAssemblyNameCharacter(pszAssemblyName[i]))
  245. {
  246. pszBuffer[j] = pszAssemblyName[i];
  247. j++;
  248. }
  249. }
  250. ASSERT_NTC(j == cch);
  251. pszBuffer[j] = L'\0';
  252. // if the name is not too long, just return ;
  253. if (j < ASSEMBLY_NAME_PRIM_MAX_LENGTH)
  254. { // less or equal 64
  255. IFFALSE_EXIT(Buffer->Win32Assign(pszBuffer, cch));
  256. }
  257. else
  258. {
  259. // name is too long, have to trim a little bit
  260. ulSpaceLeft = ASSEMBLY_NAME_PRIM_MAX_LENGTH;
  261. PureNameStart = pszBuffer;
  262. PureNameEnd = pszBuffer + j;
  263. pLeftEnd = PureNameStart;
  264. pRightStart = PureNameEnd;
  265. while (PureNameStart < PureNameEnd)
  266. {
  267. // left end
  268. pStart = PureNameStart;
  269. i = 0;
  270. while ((wcschr(ASSEMBLY_NAME_VALID_SEPARATORS, pStart[i]) == 0) && (pStart+i != pRightStart)) // not a separator character
  271. i++;
  272. pEnd = pStart + i ;
  273. len = i; // it should be length of WCHAR! not BYTE!!!
  274. if (len >= ulSpaceLeft - ASSEMBLY_NAME_TRIM_INDICATOR_LENGTH) {// because we use ".." if trim happen
  275. pLeftEnd += (ulSpaceLeft - ASSEMBLY_NAME_TRIM_INDICATOR_LENGTH);
  276. break;
  277. }
  278. ulSpaceLeft -= len;
  279. pLeftEnd = pEnd; // "abc.xxxxxxx" pointing to "c"
  280. // right end
  281. qEnd = PureNameEnd;
  282. i = 0 ;
  283. while ((qEnd+i != pLeftEnd) && (wcschr(ASSEMBLY_NAME_VALID_SEPARATORS, qEnd[i]) == 0))
  284. i--;
  285. len = 0 - i;
  286. if (len >= ulSpaceLeft - ASSEMBLY_NAME_TRIM_INDICATOR_LENGTH) {// because we use ".." if trim happen
  287. pRightStart -= ulSpaceLeft - ASSEMBLY_NAME_TRIM_INDICATOR_LENGTH;
  288. break;
  289. }
  290. ulSpaceLeft -= len;
  291. PureNameStart = pLeftEnd + 1;
  292. PureNameEnd = pRightStart - 1;
  293. } // end of while
  294. IFFALSE_EXIT(Buffer->Win32Assign(pszBuffer, pLeftEnd-pszBuffer));
  295. IFFALSE_EXIT(Buffer->Win32Append(ASSEMBLY_NAME_TRIM_INDICATOR, NUMBER_OF(ASSEMBLY_NAME_TRIM_INDICATOR) - 1));
  296. IFFALSE_EXIT(Buffer->Win32Append(pRightStart, ::wcslen(pRightStart))); // till end of the buffer
  297. }
  298. Exit:
  299. return hr;
  300. }
  301. HRESULT
  302. ca_SxspGenerateSxsPath(
  303. IN DWORD Flags,
  304. IN ULONG PathType,
  305. IN const WCHAR *AssemblyRootDirectory OPTIONAL,
  306. IN SIZE_T AssemblyRootDirectoryCch,
  307. IN PCASSEMBLY_IDENTITY pAssemblyIdentity,
  308. IN OUT CBaseStringBuffer &PathBuffer
  309. )
  310. {
  311. HRESULT hr = S_OK;
  312. SIZE_T cch = 0;
  313. PCWSTR pszAssemblyName=NULL, pszVersion=NULL, pszProcessorArchitecture=NULL, pszLanguage=NULL, pszPolicyFileNameWithoutExt = NULL;
  314. PCWSTR pszAssemblyStrongName=NULL;
  315. SIZE_T AssemblyNameCch = 0, AssemblyStrongNameCch=0, VersionCch=0, ProcessorArchitectureCch=0, LanguageCch=0;
  316. SIZE_T PolicyFileNameWithoutExtCch=0;
  317. BOOL fNeedSlashAfterRoot = FALSE;
  318. ULONG IdentityHash;
  319. BOOL fOmitRoot = ((Flags & SXSP_GENERATE_SXS_PATH_FLAG_OMIT_ROOT) != 0);
  320. BOOL fPartialPath = ((Flags & SXSP_GENERATE_SXS_PATH_FLAG_PARTIAL_PATH) != 0);
  321. WCHAR HashBuffer[ULONG_STRING_LENGTH + 1];
  322. SIZE_T HashBufferCch;
  323. CSmallStringBuffer NamePrimeBuffer;
  324. #if DBG_SXS
  325. ::FusionpDbgPrintEx(
  326. FUSION_DBG_LEVEL_INFO,
  327. "SXS.DLL: Entered %s()\n"
  328. " Flags = 0x%08lx\n"
  329. " AssemblyRootDirectory = %p\n"
  330. " AssemblyRootDirectoryCch = %lu\n"
  331. " PathBuffer = %p\n",
  332. __FUNCTION__,
  333. Flags,
  334. AssemblyRootDirectory,
  335. AssemblyRootDirectoryCch,
  336. &PathBuffer);
  337. #endif // DBG_SXS
  338. PARAMETER_CHECK_NTC(
  339. (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_ASSEMBLY) ||
  340. (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST) ||
  341. (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY));
  342. PARAMETER_CHECK_NTC(pAssemblyIdentity != NULL);
  343. PARAMETER_CHECK_NTC((Flags & ~(SXSP_GENERATE_SXS_PATH_FLAG_OMIT_VERSION | SXSP_GENERATE_SXS_PATH_FLAG_OMIT_ROOT | SXSP_GENERATE_SXS_PATH_FLAG_PARTIAL_PATH)) == 0);
  344. // Not supplying the assembly root is only legal if you're asking for it to be left out...
  345. PARAMETER_CHECK_NTC((AssemblyRootDirectoryCch != 0) || (Flags & SXSP_GENERATE_SXS_PATH_FLAG_OMIT_ROOT));
  346. // You can't combine SXSP_GENERATE_SXS_PATH_FLAG_PARTIAL_PATH with anything else...
  347. PARAMETER_CHECK_NTC(
  348. ((Flags & SXSP_GENERATE_SXS_PATH_FLAG_PARTIAL_PATH) == 0) ||
  349. ((Flags & ~(SXSP_GENERATE_SXS_PATH_FLAG_PARTIAL_PATH)) == 0));
  350. // get AssemblyName
  351. IFFALSE_EXIT(::SxspGetAssemblyIdentityAttributeValue(0, pAssemblyIdentity, &s_IdentityAttribute_name, &pszAssemblyName, &AssemblyNameCch));
  352. INTERNAL_ERROR_CHECK_NTC((pszAssemblyName != NULL) && (AssemblyNameCch != 0));
  353. // get AssemblyName' based on AssemblyName
  354. IFFAILED_EXIT(ca_SxspGenerateAssemblyNamePrimeFromName(pszAssemblyName, AssemblyNameCch, &NamePrimeBuffer));
  355. // get Assembly Version
  356. IFFALSE_EXIT(::SxspGetAssemblyIdentityAttributeValue(
  357. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL, // for policy_lookup, no version is used
  358. pAssemblyIdentity,
  359. &s_IdentityAttribute_version,
  360. &pszVersion,
  361. &VersionCch));
  362. if ((Flags & SXSP_GENERATE_SXS_PATH_FLAG_OMIT_VERSION) || (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY))
  363. {
  364. // for policy file, version of the policy file is used as policy filename
  365. pszPolicyFileNameWithoutExt = pszVersion;
  366. PolicyFileNameWithoutExtCch = VersionCch;
  367. pszVersion = NULL;
  368. VersionCch = 0;
  369. }
  370. else
  371. {
  372. PARAMETER_CHECK_NTC((pszVersion != NULL) && (VersionCch != 0));
  373. }
  374. // get Assembly Langage
  375. IFFALSE_EXIT(
  376. ::SxspGetAssemblyIdentityAttributeValue(
  377. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  378. pAssemblyIdentity,
  379. &s_IdentityAttribute_language,
  380. &pszLanguage,
  381. &LanguageCch));
  382. if (pszLanguage == NULL)
  383. {
  384. pszLanguage = SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_LANGUAGE_MISSING_VALUE;
  385. LanguageCch = NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_LANGUAGE_MISSING_VALUE) - 1;
  386. }
  387. // get Assembly ProcessorArchitecture
  388. IFFALSE_EXIT(
  389. ::SxspGetAssemblyIdentityAttributeValue(
  390. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  391. pAssemblyIdentity,
  392. &s_IdentityAttribute_processorArchitecture,
  393. &pszProcessorArchitecture,
  394. &ProcessorArchitectureCch));
  395. if (pszProcessorArchitecture == NULL)
  396. {
  397. pszProcessorArchitecture = L"data";
  398. ProcessorArchitectureCch = 4;
  399. }
  400. // get Assembly StrongName
  401. IFFALSE_EXIT(
  402. ::SxspGetAssemblyIdentityAttributeValue(
  403. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  404. pAssemblyIdentity,
  405. &s_IdentityAttribute_publicKeyToken,
  406. &pszAssemblyStrongName,
  407. &AssemblyStrongNameCch));
  408. if (pszAssemblyStrongName == NULL)
  409. {
  410. pszAssemblyStrongName = SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE;
  411. AssemblyStrongNameCch = NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE) - 1;
  412. }
  413. //get Assembly Hash String
  414. if ((PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY) || (Flags & SXSP_GENERATE_SXS_PATH_FLAG_OMIT_VERSION))
  415. {
  416. IFFALSE_EXIT(::SxspHashAssemblyIdentityForPolicy(0, pAssemblyIdentity, IdentityHash));
  417. }
  418. else
  419. {
  420. IFFALSE_EXIT(::SxsHashAssemblyIdentity(0, pAssemblyIdentity, &IdentityHash));
  421. }
  422. IFFAILED_EXIT(ca_SxspFormatULONG(IdentityHash, NUMBER_OF(HashBuffer), HashBuffer, &HashBufferCch));
  423. INTERNAL_ERROR_CHECK_NTC(HashBufferCch == ULONG_STRING_LENGTH);
  424. if (!fOmitRoot)
  425. {
  426. // If the assembly root was not passed in, get it.
  427. fNeedSlashAfterRoot = (! ::FusionpIsPathSeparator(AssemblyRootDirectory[AssemblyRootDirectoryCch-1]));
  428. }
  429. else
  430. {
  431. // If we don't want to include the root, then don't account for it below...
  432. AssemblyRootDirectoryCch = 0;
  433. fNeedSlashAfterRoot = FALSE;
  434. }
  435. // this computation can be off by one or a few, it's an optimization
  436. // to pregrow a string buffer
  437. cch =
  438. AssemblyRootDirectoryCch + // "C:\WINNT\WinSxS\"
  439. (fNeedSlashAfterRoot ? 1 : 0);
  440. switch (PathType)
  441. {
  442. case SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST:
  443. // Wacky parens and ... - 1) + 1) to reinforce that it's the number of
  444. // characters in the string not including the null and then an extra separator.
  445. cch += (NUMBER_OF(MANIFEST_ROOT_DIRECTORY_NAME) - 1) + 1;
  446. break;
  447. case SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY:
  448. // Wacky parens and ... - 1) + 1) to reinforce that it's the number of
  449. // characters in the string not including the null and then an extra separator.
  450. cch += (NUMBER_OF(POLICY_ROOT_DIRECTORY_NAME) - 1) + 1;
  451. break;
  452. }
  453. cch++;
  454. // fPartialPath means that we don't actually want to take the assembly's identity into
  455. // account; the caller just wants the path to the manifests or policies directories.
  456. if (!fPartialPath)
  457. {
  458. cch +=
  459. ProcessorArchitectureCch + // "x86"
  460. 1 + // "_"
  461. NamePrimeBuffer.Cch() + // "FooBar"
  462. 1 + // "_"
  463. AssemblyStrongNameCch + // StrongName
  464. 1 + // "_"
  465. VersionCch + // "5.6.2900.42"
  466. 1 + // "_"
  467. LanguageCch + // "0409"
  468. 1 + // "_"
  469. HashBufferCch;
  470. if (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST)
  471. {
  472. cch += NUMBER_OF(ASSEMBLY_LONGEST_MANIFEST_FILE_NAME_SUFFIX); // ".manifest\0"
  473. }
  474. else if (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY)
  475. {
  476. // "_" has already reserve space for "\"
  477. cch += PolicyFileNameWithoutExtCch;
  478. cch += NUMBER_OF(ASSEMBLY_POLICY_FILE_NAME_SUFFIX); // ".policy\0"
  479. }
  480. else { // pathType must be SXSP_GENERATE_SXS_PATH_PATHTYPE_ASSEMBLY
  481. // if (!fOmitRoot)
  482. // cch++;
  483. cch++; // trailing null character
  484. }
  485. }
  486. // We try to ensure that the buffer is big enough up front so that we don't have to do any
  487. // dynamic reallocation during the actual process.
  488. IFFALSE_EXIT(PathBuffer.Win32ResizeBuffer(cch, eDoNotPreserveBufferContents));
  489. // Note that since when GENERATE_ASSEMBLY_PATH_OMIT_ROOT is set, we force AssemblyRootDirectoryCch to zero
  490. // and fNeedSlashAfterRoot to FALSE, so the first two entries in this concatenation actually don't
  491. // contribute anything to the string constructed.
  492. if (fPartialPath)
  493. {
  494. IFFALSE_EXIT(PathBuffer.Win32AssignW(5,
  495. AssemblyRootDirectory, static_cast<INT>(AssemblyRootDirectoryCch), // "C:\WINNT\WINSXS"
  496. L"\\", (fNeedSlashAfterRoot ? 1 : 0), // optional '\'
  497. // manifests subdir
  498. MANIFEST_ROOT_DIRECTORY_NAME, ((PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST) ? NUMBER_OF(MANIFEST_ROOT_DIRECTORY_NAME) -1 : 0), // "manifests"
  499. // policies subdir
  500. POLICY_ROOT_DIRECTORY_NAME, ((PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY)? NUMBER_OF(POLICY_ROOT_DIRECTORY_NAME) - 1 : 0), // "policies"
  501. L"\\", (((PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST) || (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY)) ? 1 : 0)
  502. )); // optional '\'
  503. }
  504. else
  505. {
  506. //
  507. // create one of below
  508. // (1) fully-qualified manifest filename,
  509. // eg, [C:\WINNT\WinSxS\]Manifests\X86_DynamicDll_6595b64144ccf1df_2.0.0.0_en-us_2f433926.Manifest
  510. // (2) fully-qualified policy filename,
  511. // eg, [C:\WINNT\WinSxS\]Policies\x86_policy.1.0.DynamicDll_b54bc117ce08a1e8_en-us_d51541cb\1.1.0.0.cat
  512. // (3) fully-qulified assembly name (w. or w/o a version)
  513. // eg, [C:\WINNT\WinSxS\]x86_DynamicDll_6595b64144ccf1df_6.0.0.0_x-ww_ff9986d7
  514. //
  515. IFFALSE_EXIT(
  516. PathBuffer.Win32AssignW(17,
  517. AssemblyRootDirectory, static_cast<INT>(AssemblyRootDirectoryCch), // "C:\WINNT\WINSXS"
  518. L"\\", (fNeedSlashAfterRoot ? 1 : 0), // optional '\'
  519. MANIFEST_ROOT_DIRECTORY_NAME, ((PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST) ? NUMBER_OF(MANIFEST_ROOT_DIRECTORY_NAME) - 1 : 0),
  520. POLICY_ROOT_DIRECTORY_NAME, ((PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY) ? NUMBER_OF(POLICY_ROOT_DIRECTORY_NAME) - 1 : 0),
  521. L"\\", (((PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST) || (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY)) ? 1 : 0), // optional '\'
  522. pszProcessorArchitecture, static_cast<INT>(ProcessorArchitectureCch),
  523. L"_", 1,
  524. static_cast<PCWSTR>(NamePrimeBuffer), static_cast<INT>(NamePrimeBuffer.Cch()),
  525. L"_", 1,
  526. pszAssemblyStrongName, static_cast<INT>(AssemblyStrongNameCch),
  527. L"_", (VersionCch != 0) ? 1 : 0,
  528. pszVersion, static_cast<INT>(VersionCch),
  529. L"_", 1,
  530. pszLanguage, static_cast<INT>(LanguageCch),
  531. L"_", 1,
  532. static_cast<PCWSTR>(HashBuffer), static_cast<INT>(HashBufferCch),
  533. L"\\", ((fOmitRoot ||(PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST)) ? 0 : 1)));
  534. if (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST)
  535. IFFALSE_EXIT(PathBuffer.Win32Append(ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX, NUMBER_OF(ASSEMBLY_MANIFEST_FILE_NAME_SUFFIX) - 1));
  536. else if (PathType == SXSP_GENERATE_SXS_PATH_PATHTYPE_POLICY)
  537. {
  538. if ((pszPolicyFileNameWithoutExt != NULL) && (PolicyFileNameWithoutExtCch >0))
  539. {
  540. IFFALSE_EXIT(PathBuffer.Win32Append(pszPolicyFileNameWithoutExt, PolicyFileNameWithoutExtCch));
  541. IFFALSE_EXIT(PathBuffer.Win32Append(ASSEMBLY_POLICY_FILE_NAME_SUFFIX, NUMBER_OF(ASSEMBLY_POLICY_FILE_NAME_SUFFIX) - 1));
  542. }
  543. }
  544. }
  545. Exit:
  546. return hr;
  547. }
  548. HRESULT
  549. ca_SxspDetermineAssemblyType(
  550. PCASSEMBLY_IDENTITY pAssemblyIdentity,
  551. BOOL &fIsWin32,
  552. BOOL &fIsWin32Policy
  553. )
  554. {
  555. HRESULT hr = S_OK;
  556. PCWSTR pcwszType = NULL;
  557. SIZE_T cchType = 0;
  558. fIsWin32 = FALSE;
  559. fIsWin32Policy = FALSE;
  560. PARAMETER_CHECK_NTC(pAssemblyIdentity != NULL);
  561. IFFALSE_EXIT(
  562. ::SxspGetAssemblyIdentityAttributeValue(
  563. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  564. pAssemblyIdentity,
  565. &s_IdentityAttribute_type,
  566. &pcwszType,
  567. &cchType));
  568. fIsWin32 = (::FusionpCompareStrings(pcwszType, cchType, ASSEMBLY_TYPE_WIN32, ASSEMBLY_TYPE_WIN32_CCH, false) == 0);
  569. if (!fIsWin32)
  570. fIsWin32Policy = (::FusionpCompareStrings(pcwszType, cchType, ASSEMBLY_TYPE_WIN32_POLICY, ASSEMBLY_TYPE_WIN32_POLICY_CCH, false) == 0);
  571. Exit:
  572. return hr;
  573. }