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.

285 lines
8.7 KiB

  1. #include "nt.h"
  2. #include "ntdef.h"
  3. #include "ntrtl.h"
  4. #include "nturtl.h"
  5. #include "stdio.h"
  6. #include "sxs-rtl.h"
  7. #include "fasterxml.h"
  8. #include "skiplist.h"
  9. #include "namespacemanager.h"
  10. #include "xmlstructure.h"
  11. #include "stdlib.h"
  12. #include "xmlassert.h"
  13. #include "manifestinspection.h"
  14. #include "manifestcooked.h"
  15. #include "stringpool.h"
  16. #undef INVALID_HANDLE_VALUE
  17. #include "windows.h"
  18. #include "sha.h"
  19. #include "environment.h"
  20. #include "sha2.h"
  21. #include "assemblygac.h"
  22. ASSEMBLY_CACHE_LISTING s_AssemblyCaches[] = {
  23. { &CDotNetSxsAssemblyCache::CacheIdentifier, CDotNetSxsAssemblyCache::CreateSelf },
  24. { NULL, NULL }
  25. };
  26. LONG
  27. OurFilter(
  28. PEXCEPTION_POINTERS pExceptionPointers
  29. )
  30. {
  31. DbgBreakPoint();
  32. return EXCEPTION_CONTINUE_SEARCH;
  33. }
  34. #define RTL_ANALYZE_MANIFEST_GET_FILES (0x00000001)
  35. #define RTL_ANALYZE_MANIFEST_GET_WINDOW_CLASSES (0x00000002)
  36. #define RTL_ANALYZE_MANIFEST_GET_COM_CLASSES (0x00000004)
  37. #define RTL_ANALYZE_MANIFEST_GET_DEPENDENCIES (0x00000008)
  38. #define RTL_ANALYZE_MANIFEST_GET_SIGNATURES (0x00000010)
  39. #define RTLSXS_INSTALLER_REGION_SIZE (128*1024)
  40. NTSTATUS
  41. RtlAnalyzeManifest(
  42. ULONG ulFlags,
  43. PUNICODE_STRING pusPath,
  44. PMANIFEST_COOKED_DATA *ppusCookedData
  45. )
  46. {
  47. PVOID pvAllocation = NULL;
  48. SIZE_T cbAllocationSize = 0;
  49. LARGE_INTEGER liFileSize;
  50. HANDLE hFile = INVALID_HANDLE_VALUE;
  51. CEnv::StatusCode StatusCode;
  52. SIZE_T cbReadFileSize;
  53. PRTL_MANIFEST_CONTENT_RAW pManifestContent = NULL;
  54. XML_TOKENIZATION_STATE XmlState;
  55. NTSTATUS status;
  56. PMANIFEST_COOKED_DATA pCookedContent = NULL;
  57. SIZE_T cbCookedContent;
  58. ULONG ulGatherFlags = 0;
  59. CEnv::CConstantUnicodeStringPair ManifestPath;
  60. //
  61. // Snag a region of memory to stash the file into
  62. //
  63. StatusCode = CEnv::VirtualAlloc(NULL, RTLSXS_INSTALLER_REGION_SIZE, MEM_RESERVE, PAGE_READWRITE, &pvAllocation);
  64. if (CEnv::DidFail(StatusCode)) {
  65. goto Exit;
  66. }
  67. //
  68. // Convert the input flags into the "gather" flagset
  69. //
  70. if (ulFlags & RTL_ANALYZE_MANIFEST_GET_FILES) ulGatherFlags |= RTLIMS_GATHER_FILES;
  71. if (ulFlags & RTL_ANALYZE_MANIFEST_GET_WINDOW_CLASSES) ulGatherFlags |= RTLIMS_GATHER_WINDOWCLASSES;
  72. if (ulFlags & RTL_ANALYZE_MANIFEST_GET_COM_CLASSES) ulGatherFlags |= RTLIMS_GATHER_COMCLASSES;
  73. if (ulFlags & RTL_ANALYZE_MANIFEST_GET_DEPENDENCIES) ulGatherFlags |= RTLIMS_GATHER_DEPENDENCIES;
  74. if (ulFlags & RTL_ANALYZE_MANIFEST_GET_SIGNATURES) ulGatherFlags |= RTLIMS_GATHER_SIGNATURES;
  75. //
  76. // Acquire a handle on the file, get its size.
  77. //
  78. ManifestPath = CEnv::StringFrom(pusPath);
  79. if (CEnv::DidFail(StatusCode = CEnv::GetFileHandle(&hFile, ManifestPath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING))) {
  80. goto Exit;
  81. }
  82. if (CEnv::DidFail(StatusCode = CEnv::GetFileSize(hFile, &liFileSize))) {
  83. goto Exit;
  84. }
  85. //
  86. // Commit enough space to hold the file contents
  87. //
  88. cbAllocationSize = (SIZE_T)liFileSize.QuadPart;
  89. StatusCode = CEnv::VirtualAlloc(pvAllocation, cbAllocationSize, MEM_COMMIT, PAGE_READWRITE, &pvAllocation);
  90. if (CEnv::DidFail(StatusCode)) {
  91. goto Exit;
  92. }
  93. // Read the file data - in the future, we'll want to respect overlapped
  94. // IO so this can move into the kernel
  95. StatusCode = CEnv::ReadFile(hFile, pvAllocation, cbAllocationSize, cbReadFileSize);
  96. if (CEnv::DidFail(StatusCode)) {
  97. goto Exit;
  98. }
  99. // Initialize our callback stuff. We want to know only about the files that this
  100. // manifest contains - anything else is superflous. Of course, we also want the
  101. // xml signature data contained herein as well.
  102. status = RtlSxsInitializeManifestRawContent(ulGatherFlags, &pManifestContent, NULL, 0);
  103. if (CNtEnvironment::DidFail(status)) {
  104. StatusCode = CNtEnvironment::ConvertStatusToOther<CEnv::StatusCode>(status);
  105. goto Exit;
  106. }
  107. // Now run through the file looking for useful things
  108. status = RtlInspectManifestStream(
  109. ulGatherFlags,
  110. pvAllocation,
  111. cbAllocationSize,
  112. pManifestContent,
  113. &XmlState);
  114. if (CNtEnvironment::DidFail(status)) {
  115. StatusCode = CNtEnvironment::ConvertStatusToOther<CEnv::StatusCode>(status);
  116. goto Exit;
  117. }
  118. //
  119. // Convert the raw content to cooked content that we can use
  120. //
  121. status = RtlConvertRawToCookedContent(pManifestContent, &XmlState.RawTokenState, NULL, 0, &cbCookedContent);
  122. if (CNtEnvironment::DidFail(status) && (status != CNtEnvironment::NotEnoughBuffer)) {
  123. StatusCode = CNtEnvironment::ConvertStatusToOther<CEnv::StatusCode>(status);
  124. goto Exit;
  125. }
  126. //
  127. // Allocate some heap to contain the raw content
  128. //
  129. else if (status == CNtEnvironment::NotEnoughBuffer) {
  130. SIZE_T cbDidWrite;
  131. if (CEnv::DidFail(StatusCode = CEnv::AllocateHeap(cbCookedContent, (PVOID*)&pCookedContent, NULL))) {
  132. goto Exit;
  133. }
  134. status = RtlConvertRawToCookedContent(
  135. pManifestContent,
  136. &XmlState.RawTokenState,
  137. (PVOID)pCookedContent,
  138. cbCookedContent,
  139. &cbDidWrite);
  140. }
  141. *ppusCookedData = pCookedContent;
  142. pCookedContent = NULL;
  143. // Spiffy. We now have converted all the strings that make up the file table -
  144. // let's start installing them!
  145. StatusCode = CEnv::SuccessCode;
  146. Exit:
  147. if (hFile != INVALID_HANDLE_VALUE) {
  148. CEnv::CloseHandle(hFile);
  149. }
  150. if (pvAllocation != NULL) {
  151. CEnv::VirtualFree(pvAllocation, cbAllocationSize, MEM_DECOMMIT);
  152. CEnv::VirtualFree(pvAllocation, 0, MEM_RELEASE);
  153. pvAllocation = NULL;
  154. }
  155. RtlSxsDestroyManifestContent(pManifestContent);
  156. if (pCookedContent != NULL) {
  157. CEnv::FreeHeap(pCookedContent, NULL);
  158. }
  159. return CEnv::DidFail(StatusCode) ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
  160. }
  161. NTSTATUS
  162. InstallAssembly(
  163. PCWSTR pcwszPath,
  164. LPGUID lpgGacIdent
  165. )
  166. {
  167. PMANIFEST_COOKED_DATA pCookedData = NULL;
  168. UNICODE_STRING usManifestFile;
  169. UNICODE_STRING usManifestPath;
  170. CNtEnvironment::StatusCode Result;
  171. COSAssemblyCache *pTargetCache = NULL;
  172. ULONG ul = 0;
  173. RtlInitUnicodeString(&usManifestFile, pcwszPath);
  174. if ((lpgGacIdent == NULL) || (pcwszPath == NULL))
  175. {
  176. return STATUS_INVALID_PARAMETER;
  177. }
  178. for (ul = 0; s_AssemblyCaches[ul].CacheIdent != NULL; ul++)
  179. {
  180. if (*s_AssemblyCaches[ul].CacheIdent == *lpgGacIdent)
  181. {
  182. pTargetCache = s_AssemblyCaches[ul].pfnCreator(0, lpgGacIdent);
  183. if (pTargetCache)
  184. break;
  185. }
  186. }
  187. if (pTargetCache == NULL) {
  188. return STATUS_INVALID_PARAMETER;
  189. }
  190. //
  191. // Gather junk from the manifest
  192. //
  193. Result = RtlAnalyzeManifest(
  194. RTL_ANALYZE_MANIFEST_GET_SIGNATURES | RTL_ANALYZE_MANIFEST_GET_FILES,
  195. &usManifestFile,
  196. &pCookedData);
  197. if (CNtEnvironment::DidFail(Result)) {
  198. goto Exit;
  199. }
  200. usManifestPath = usManifestFile;
  201. while (usManifestPath.Length && (usManifestPath.Buffer[(usManifestPath.Length / sizeof(usManifestPath.Buffer[0])) - 1] != L'\\'))
  202. usManifestPath.Length -= sizeof(usManifestPath.Buffer[0]);
  203. //
  204. // Do the installation. Build the path to the
  205. //
  206. Result = pTargetCache->InstallAssembly(0, pCookedData, CEnv::StringFrom(&usManifestPath));
  207. Exit:
  208. if (pCookedData != NULL) {
  209. CEnv::FreeHeap(pCookedData, NULL);
  210. pCookedData = NULL;
  211. }
  212. if (pTargetCache) {
  213. pTargetCache->~COSAssemblyCache();
  214. CEnv::FreeHeap(pTargetCache, NULL);
  215. }
  216. return Result;
  217. }
  218. int __cdecl wmain(int argc, WCHAR** argv)
  219. {
  220. static int iFrobble = 0;
  221. NTSTATUS status;
  222. UNICODE_STRING usGuid;
  223. GUID gGacGuid;
  224. WCHAR wch[5];
  225. int i = _snwprintf(wch, 5, L"123456");
  226. iFrobble = iFrobble + 1;
  227. __try
  228. {
  229. RtlInitUnicodeString(&usGuid, argv[2]);
  230. if (NT_SUCCESS(status = RtlGUIDFromString(&usGuid, &gGacGuid))) {
  231. status = InstallAssembly(argv[1], &gGacGuid);
  232. }
  233. }
  234. __except(OurFilter(GetExceptionInformation()))
  235. {
  236. }
  237. return (int)status;
  238. }