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.

1655 lines
57 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. srvsxs.c
  5. Abstract:
  6. Support for side-by-side (fusion) in the win32 base server.
  7. Author:
  8. Michael J. Grier (MGrier) 23-Feb-2000
  9. Revision History:
  10. Jay Krell (a-JayK) July 2000 moved file opening from csr/sxs to kernel32
  11. marshal over large CreateProcess message with manifest, policy, and assembly path
  12. pass IStreams to sxs
  13. Jay Krell (a-JayK) September 2000
  14. moved (assembly directory computation from manifest) from basesrv to kernel32
  15. Jay Krell (a-JayK) October 2000 System Default Activation Context
  16. (aka System Compatible Activation Context)
  17. --*/
  18. #include "basesrv.h"
  19. #include "SxsApi.h"
  20. #include "ntldr.h"
  21. #include "nturtl.h"
  22. #include "mmapstm.h"
  23. #include <limits.h>
  24. #if defined(_WIN64)
  25. #include "wow64t.h"
  26. #endif // defined(_WIN64)
  27. #if !defined(BASE_SRV_SXS_HRESULT_FROM_STATUS)
  28. #if defined(RTLP_HRESULT_FROM_STATUS)
  29. #define BASE_SRV_SXS_HRESULT_FROM_STATUS(x) RTLP_HRESULT_FROM_STATUS(x)
  30. #else
  31. #define BASE_SRV_SXS_HRESULT_FROM_STATUS(x) HRESULT_FROM_WIN32(RtlNtStatusToDosErrorNoTeb(x))
  32. //#define BASE_SRV_SXS_HRESULT_FROM_STATUS(x) HRESULT_FROM_WIN32(RtlNtStatusToDosError(x))
  33. //#define BASE_SRV_SXS_HRESULT_FROM_STATUS(x) HRESULT_FROM_NT(x)
  34. #endif
  35. #endif
  36. #if DBG
  37. BOOLEAN DebugFilter_SxsTrace;
  38. #endif
  39. #define DPFLTR_LEVEL_STATUS(x) ((NT_SUCCESS(x) \
  40. || (x) == STATUS_NO_SUCH_FILE \
  41. || (x) == STATUS_OBJECT_NAME_NOT_FOUND \
  42. || (x) == STATUS_OBJECT_PATH_NOT_FOUND \
  43. || (x) == STATUS_RESOURCE_DATA_NOT_FOUND \
  44. || (x) == STATUS_RESOURCE_LANG_NOT_FOUND \
  45. || (x) == STATUS_RESOURCE_NAME_NOT_FOUND \
  46. || (x) == STATUS_RESOURCE_TYPE_NOT_FOUND \
  47. || (x) == STATUS_SXS_CANT_GEN_ACTCTX \
  48. || (x) == STATUS_SXS_ASSEMBLY_NOT_FOUND \
  49. || (x) == STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY \
  50. ) \
  51. ? DPFLTR_TRACE_LEVEL : DPFLTR_ERROR_LEVEL)
  52. #define DPFLTR_LEVEL_WIN32(x) ((x) ? DPFLTR_TRACE_LEVEL : DPFLTR_ERROR_LEVEL)
  53. typedef union _BASE_SRV_SXS_STREAM_UNION_WITH_VTABLE {
  54. BASE_SRV_MEMORY_MAPPED_STREAM_WITH_VTABLE Mmap;
  55. RTL_OUT_OF_PROCESS_MEMORY_STREAM_WITH_VTABLE OutOfProcess;
  56. } BASE_SRV_SXS_STREAM_UNION_WITH_VTABLE, *PBASE_SRV_SXS_STREAM_UNION_WITH_VTABLE;
  57. #if BASESRV_UNLOAD_SXS_DLL
  58. PVOID SxsDllHandle;
  59. RTL_CRITICAL_SECTION BaseSrvSxsCritSec;
  60. LONG SxsDllHandleRefCount;
  61. #endif
  62. LONG BaseSrvSxsGetActCtxGenCount;
  63. PSXS_GENERATE_ACTIVATION_CONTEXT_FUNCTION SxsActivationContextGenerationFunction;
  64. ULONG PinnedMsvcrtDll; // ULONG instead of BOOLEAN for atomicity of store?
  65. const UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
  66. RTL_CRITICAL_SECTION BaseSrvSxsSystemDefaultActivationContextCriticalSection;
  67. BASE_SRV_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT SxsSystemDefaultActivationContexts[] =
  68. {
  69. #ifdef _WIN64
  70. { NULL, RTL_CONSTANT_STRING(L"x86"), PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 },
  71. #else
  72. { NULL, RTL_CONSTANT_STRING(L"x86"), PROCESSOR_ARCHITECTURE_INTEL },
  73. #endif
  74. { NULL, RTL_CONSTANT_STRING(L"ia64"), PROCESSOR_ARCHITECTURE_IA64 },
  75. { NULL, RTL_CONSTANT_STRING(L"amd64"), PROCESSOR_ARCHITECTURE_AMD64 }
  76. };
  77. #define STRING(x) #x
  78. #define IF_NOT_SUCCESS_TRACE_AND_EXIT(subfunction) \
  79. do { \
  80. if (!NT_SUCCESS(Status)) { \
  81. KdPrintEx((DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() " STRING(subfunction) " failed 0x%08lx\n", __FUNCTION__, Status)); \
  82. goto Exit; \
  83. } \
  84. } while(0)
  85. #define ASSERT_UNICODE_STRING_IS_NUL_TERMINATED(ustr) \
  86. ASSERT((ustr)->MaximumLength >= ((ustr)->Length + sizeof(WCHAR))); \
  87. ASSERT((ustr)->Buffer[(ustr)->Length / sizeof(WCHAR)] == 0);
  88. #define IMPERSONATE_ENTIRE_SXS_CALL 1
  89. #if !IMPERSONATE_ENTIRE_SXS_CALL
  90. typedef struct _ACTIVATION_CONTEXT_GENERATION_IMPERSONATION_CONTEXT {
  91. BOOL SuccessfulImpersonation;
  92. } ACTIVATION_CONTEXT_GENERATION_IMPERSONATION_CONTEXT, *PACTIVATION_CONTEXT_GENERATION_IMPERSONATION_CONTEXT;
  93. BOOL
  94. __stdcall
  95. BaseSrvpSxsActivationContextGenerationImpersonationCallback(
  96. PVOID ContextIn,
  97. BOOL Impersonate
  98. )
  99. /*++
  100. Routine Description:
  101. This function is called back by the sxs.dll API to create an activation
  102. context when it needs to impersonate or unimpersonate the client of the
  103. CSR message.
  104. Arguments:
  105. ContextIn - PACTIVATION_CONTEXT_GENERATION_IMPERSONATION_CONTEXT
  106. passed in to the create activation context API returned back
  107. as a PVOID. We use it to track whether the previous impersonate
  108. call succeeded.
  109. Impersonate - nonzero (TRUE) if this function should impersonate the
  110. client, zero (FALSE) if the function should revert to the normal
  111. csrss identity.
  112. Return Value:
  113. // the old comment
  114. TRUE on success; FALSE on failure. The last error state is as
  115. CsrImpersonateClient() leaves it.
  116. // a more accurate comment?
  117. TRUE on successful impersonation, FALSE upon no successful impersonation
  118. the last error status is defined
  119. --*/
  120. {
  121. BOOL Success = FALSE;
  122. PACTIVATION_CONTEXT_GENERATION_IMPERSONATION_CONTEXT Context =
  123. (PACTIVATION_CONTEXT_GENERATION_IMPERSONATION_CONTEXT) ContextIn;
  124. if (Impersonate) {
  125. Context->SuccessfulImpersonation = CsrImpersonateClient(NULL);
  126. if you enable this function, you must revisit its error handling
  127. if (!Context->SuccessfulImpersonation)
  128. goto Exit;
  129. } else {
  130. if (Context->SuccessfulImpersonation) {
  131. CsrRevertToSelf();
  132. Context->SuccessfulImpersonation = FALSE;
  133. } else
  134. goto Exit;
  135. }
  136. Success = TRUE;
  137. Exit:
  138. return Success;
  139. }
  140. #endif
  141. //#define TRACE_AND_EXECUTE(x) do { DbgPrint("%s\n", #x); x ; } while(0)
  142. #define TRACE_AND_EXECUTE(x) x
  143. NTSTATUS
  144. BaseSrvSxsInvalidateSystemDefaultActivationContextCache(
  145. VOID
  146. )
  147. {
  148. ULONG i;
  149. HANDLE LocalSystemDefaultActivationContextSections[RTL_NUMBER_OF(SxsSystemDefaultActivationContexts)];
  150. HANDLE SectionHandle;
  151. RtlEnterCriticalSection(&BaseSrvSxsSystemDefaultActivationContextCriticalSection);
  152. __try {
  153. //
  154. // First copy to locals to minimize time in the critical section.
  155. //
  156. for (i = 0 ; i != RTL_NUMBER_OF(SxsSystemDefaultActivationContexts) ; ++i) {
  157. LocalSystemDefaultActivationContextSections[i] = SxsSystemDefaultActivationContexts[i].Section;
  158. SxsSystemDefaultActivationContexts[i].Section = NULL;
  159. }
  160. } __finally {
  161. RtlLeaveCriticalSection(&BaseSrvSxsSystemDefaultActivationContextCriticalSection);
  162. }
  163. //
  164. // Then iterate over locals, closing.
  165. //
  166. for (i = 0 ; i != RTL_NUMBER_OF(LocalSystemDefaultActivationContextSections) ; ++i) {
  167. SectionHandle = LocalSystemDefaultActivationContextSections[i];
  168. if (SectionHandle != NULL) {
  169. NTSTATUS Status1 = STATUS_SUCCESS;
  170. RTL_SOFT_VERIFY(NT_SUCCESS(Status1 = NtClose(SectionHandle)));
  171. }
  172. }
  173. return STATUS_SUCCESS;
  174. }
  175. NTSTATUS
  176. BaseSrvSxsInit(
  177. VOID
  178. )
  179. /*++
  180. Routine Description:
  181. Function called during csr/basesrv.dll initialization which
  182. creates a critical section we use to guard loading and
  183. unloading sxs.dll. We use a critical section rather
  184. then just relying on the peb loader lock to manage the
  185. reference count because we want to be able to call a
  186. one-time initialization function on load and a one-time
  187. uninitialization function on unload.
  188. Arguments:
  189. Return Value:
  190. NTSTATUS indicating the disposition of the function.
  191. --*/
  192. {
  193. NTSTATUS Status;
  194. Status = RtlInitializeCriticalSection(&BaseSrvSxsSystemDefaultActivationContextCriticalSection);
  195. if (!NT_SUCCESS(Status))
  196. goto Exit;
  197. #if BASESRV_UNLOAD_SXS_DLL
  198. Status = RtlInitializeCriticalSection(&BaseSrvSxsCritSec);
  199. if (!NT_SUCCESS(Status))
  200. goto Exit;
  201. ASSERT(SxsDllHandle == NULL);
  202. ASSERT(SxsActivationContextGenerationFunction == NULL);
  203. ASSERT(SxsDllHandleRefCount == 0);
  204. #endif
  205. ASSERT(BaseSrvSxsGetActCtxGenCount == 0);
  206. Status = STATUS_SUCCESS;
  207. Exit:
  208. return Status;
  209. }
  210. NTSTATUS
  211. BaseSrvSxsMapViewOfSection(
  212. OUT PVOID* Address,
  213. IN HANDLE Process,
  214. IN HANDLE Section,
  215. IN ULONGLONG Offset,
  216. IN SIZE_T Size,
  217. IN ULONG Protect,
  218. IN ULONG AllocationType
  219. )
  220. /*++
  221. Routine Description:
  222. pare down the NtMapViewOfSection parameter list to the parameters
  223. that actually ever vary in common use
  224. allow for unaligned mappings, both in the offset and the size
  225. the memory manager wants both aligned to 64k
  226. change the parameters that aren't needed to be inout to only in
  227. the out-ness of the native parameters doesn't seem useful,
  228. esp. because the mm will not align your parameters and
  229. return the aligned values
  230. deprecate LARGE_INTEGER, use LONGLONG instead
  231. Arguments:
  232. Subset of NtMapViewOfSection, but can be unaligned
  233. Return Value:
  234. NTSTATUS
  235. Note:
  236. It is tempting to pare down the parameter list since many of them
  237. are always the same: ZeroBits, CommitSize, InheritDisposition, AllocationType.
  238. It is also tempting to move this to Rtl.
  239. --*/
  240. {
  241. LARGE_INTEGER LargeIntegerOffset;
  242. NTSTATUS Status = STATUS_SUCCESS;
  243. SIZE_T OffsetRemainder;
  244. SIZE_T SizeRemainder;
  245. #define SIXTY_FOUR_K (1UL << 16)
  246. #define VIEW_OFFSET_ALIGNMENT SIXTY_FOUR_K
  247. #define VIEW_SIZE_ALIGNMENT SIXTY_FOUR_K
  248. #if DBG
  249. if (DebugFilter_SxsTrace) {
  250. DbgPrintEx(
  251. DPFLTR_SXS_ID,
  252. DPFLTR_TRACE_LEVEL,
  253. "SRVSXS: %s(\n"
  254. "SRVSXS: Process %p\n"
  255. "SRVSXS: Section %p\n"
  256. "SRVSXS: Offset 0x%I64x\n"
  257. "SRVSXS: Size 0x%Ix\n"
  258. "SRVSXS: ) beginning\n",
  259. __FUNCTION__,
  260. Process,
  261. Section,
  262. Offset,
  263. Size
  264. );
  265. }
  266. #endif
  267. ASSERT(Address != NULL);
  268. *Address = NULL;
  269. //
  270. // round down offset, round up size
  271. // must round offset first, since rounding it alters size
  272. //
  273. #if 1 // Mm comments allow this, but the code does not.
  274. OffsetRemainder = (((SIZE_T)Offset) % VIEW_OFFSET_ALIGNMENT);
  275. if (OffsetRemainder != 0) {
  276. Offset -= OffsetRemainder;
  277. if (Size != 0) {
  278. Size += OffsetRemainder;
  279. }
  280. }
  281. #endif
  282. #if 0 // Mm allows this.
  283. SizeRemainder = Size % VIEW_SIZE_ALIGNMENT;
  284. if (SizeRemainder != 0) {
  285. Size = Size + (VIEW_SIZE_ALIGNMENT - SizeRemainder);
  286. }
  287. #endif
  288. LargeIntegerOffset.QuadPart = Offset;
  289. Status =
  290. NtMapViewOfSection(
  291. Section,
  292. Process,
  293. Address,
  294. 0, // ZeroBits
  295. 0, // CommitSize
  296. &LargeIntegerOffset,
  297. &Size,
  298. ViewShare, // InheritDisposition
  299. AllocationType, // AllocationType
  300. Protect);
  301. if (!NT_SUCCESS(Status)) {
  302. goto Exit;
  303. }
  304. *Address = ((PUCHAR)*Address) + OffsetRemainder;
  305. Exit:
  306. //
  307. // If the Memory Manager returns STATUS_MAPPED_ALIGNMENT,
  308. // then we have failed at our task.
  309. //
  310. ASSERT(Status != STATUS_MAPPED_ALIGNMENT);
  311. #if DBG
  312. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  313. #endif
  314. return Status;
  315. }
  316. NTSTATUS
  317. BaseSrvSxsCreateActivationContextFromStruct(
  318. HANDLE CsrClientProcess,
  319. HANDLE SxsClientProcess,
  320. PBASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG Struct,
  321. OUT HANDLE* OutSection
  322. )
  323. /*++
  324. Routine Description:
  325. This function handles the CSR message both for CreateActCtx
  326. and CreateProcess. Pointers in the "Struct" are trusted (vs.
  327. pointers in a "message").
  328. Arguments:
  329. CsrClientProcess - the process that called CreateProcess or CreateActCtx
  330. or NtCurrentProcess for creating system default activation context (csr)
  331. SxsClientProcess - CreateProcess: the new process
  332. CreateActCtx: the calling process (csr client process)
  333. System default: NtCurrentProcess (csr)
  334. Struct - the parameters marshaled from the csr client process
  335. OutSection - for creating the system default context that gets mapped repeatedly
  336. Return Value:
  337. NTSTATUS
  338. --*/
  339. {
  340. ASSERT(Struct != NULL);
  341. if (Struct == NULL) {
  342. return STATUS_INVALID_PARAMETER;
  343. }
  344. #define BASE_MSG_SXS_MINIMAL_FLAGS \
  345. ( BASE_MSG_SXS_MANIFEST_PRESENT \
  346. | BASE_MSG_SXS_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY_PRESENT \
  347. | BASE_MSG_SXS_TEXTUAL_ASSEMBLY_IDENTITY_PRESENT \
  348. )
  349. ASSERT(Struct->Flags & BASE_MSG_SXS_MINIMAL_FLAGS);
  350. if ((Struct->Flags & BASE_MSG_SXS_MINIMAL_FLAGS) == 0) {
  351. return STATUS_SUCCESS;
  352. } else {
  353. NTSTATUS Status = STATUS_SUCCESS;
  354. PVOID ViewBase = NULL;
  355. SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS SxsDllParameters = {0};
  356. BASE_SRV_SXS_STREAM_UNION_WITH_VTABLE ManifestStream;
  357. BASE_SRV_SXS_STREAM_UNION_WITH_VTABLE PolicyStream;
  358. DWORD_PTR Cookie = 0;
  359. BOOLEAN ReleaseCtxFunction = FALSE;
  360. PSXS_GENERATE_ACTIVATION_CONTEXT_FUNCTION FunctionPointer = NULL;
  361. LARGE_INTEGER SectionOffset = {0};
  362. HRESULT Hr = NOERROR;
  363. BOOL SxsFunctionSuccess = FALSE;
  364. NTSTATUS Status1 = STATUS_SUCCESS;
  365. #if IMPERSONATE_ENTIRE_SXS_CALL
  366. BOOLEAN SuccessfulImpersonation = FALSE;
  367. #else
  368. ACTIVATION_CONTEXT_GENERATION_IMPERSONATION_CONTEXT ImpersonationContext = {0};
  369. #endif
  370. #if DBG
  371. if (DebugFilter_SxsTrace) {
  372. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() beginning\n", __FUNCTION__);
  373. }
  374. #endif
  375. ASSERT(Struct != NULL);
  376. ASSERT(Struct != NULL && Struct->Manifest.Path.Buffer != NULL);
  377. if ( Struct->Flags & BASE_MSG_SXS_MANIFEST_PRESENT)
  378. {
  379. // because these are unions, " = {0}" won't necessarily clear them completely
  380. RtlZeroMemory(&ManifestStream, sizeof(ManifestStream));
  381. RtlZeroMemory(&PolicyStream, sizeof(PolicyStream));
  382. Status = BaseSrvSxsCreateMemoryStream(
  383. CsrClientProcess,
  384. &Struct->Manifest,
  385. &ManifestStream,
  386. &IID_ISequentialStream,
  387. (PVOID*)&SxsDllParameters.Manifest.Stream
  388. );
  389. IF_NOT_SUCCESS_TRACE_AND_EXIT(BaseSrvSxsCreateMemoryStream(manifest));
  390. SxsDllParameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
  391. if (Struct->Flags & BASE_MSG_SXS_POLICY_PRESENT) {
  392. Status = BaseSrvSxsCreateMemoryStream(
  393. CsrClientProcess,
  394. &Struct->Policy,
  395. &PolicyStream,
  396. &IID_ISequentialStream,
  397. (PVOID*)&SxsDllParameters.Policy.Stream
  398. );
  399. IF_NOT_SUCCESS_TRACE_AND_EXIT(BaseSrvSxsCreateMemoryStream(policy));
  400. if (Struct->Policy.PathType != BASE_MSG_PATHTYPE_NONE
  401. && Struct->Policy.Path.Length != 0
  402. && Struct->Policy.Path.Buffer != NULL
  403. ) {
  404. ASSERT_UNICODE_STRING_IS_NUL_TERMINATED(&Struct->Policy.Path);
  405. SxsDllParameters.Policy.Path = Struct->Policy.Path.Buffer;
  406. switch (Struct->Policy.PathType) {
  407. case BASE_MSG_PATHTYPE_FILE:
  408. SxsDllParameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  409. break;
  410. case BASE_MSG_PATHTYPE_URL:
  411. SxsDllParameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_URL;
  412. break;
  413. }
  414. }
  415. }
  416. }
  417. else // Textual AssemblyIdentity
  418. {
  419. SxsDllParameters.Flags |= SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY;
  420. if ( Struct->Flags & BASE_MSG_SXS_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY_PRESENT)
  421. {
  422. SxsDllParameters.Flags |= SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY;
  423. }
  424. SxsDllParameters.TextualAssemblyIdentity = Struct->TextualAssemblyIdentity.Buffer;
  425. ASSERT_UNICODE_STRING_IS_NUL_TERMINATED(&Struct->TextualAssemblyIdentity);
  426. }
  427. if ( Struct->Flags & BASE_MSG_SXS_APP_RUNNING_IN_SAFEMODE)
  428. SxsDllParameters.Flags |= SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_APP_RUNNING_IN_SAFEMODE;
  429. SxsDllParameters.ProcessorArchitecture = Struct->ProcessorArchitecture;
  430. SxsDllParameters.LangId = Struct->LangId;
  431. SxsDllParameters.AssemblyDirectory = Struct->AssemblyDirectory.Buffer;
  432. ASSERT_UNICODE_STRING_IS_NUL_TERMINATED(&Struct->AssemblyDirectory);
  433. Status = BaseSrvSxsGetActivationContextGenerationFunction(&FunctionPointer, &Cookie);
  434. if (Status == STATUS_DLL_NOT_FOUND) {
  435. // This happens under stress.
  436. // We will probably propagate STATUS_NO_MEMORY post beta1 here,
  437. // if RtlAllocateHeap on a small amount fails.
  438. // In Blackcomb we will maybe fix RtlSearchPath/LdrLoadDll to propagate
  439. // accurate status.
  440. DbgPrintEx(
  441. DPFLTR_SXS_ID,
  442. DPFLTR_ERROR_LEVEL,
  443. "SXS: BaseSrvSxsGetActivationContextGenerationFunction() returned STATUS_DLL_NOT_FOUND, propagating.\n"
  444. );
  445. //
  446. // Old bogus code actually returned a STATUS_SUCCESS when it was a genuine failure.
  447. // Instead, we should return the actual status that is being generated. The other
  448. // option is to return STATUS_NO_MEMORY, the generic "oops" error code. Our clients
  449. // do the Smart Thing with an NT_SUCCESS() check, so returning STATUS_DLL_NOT_FOUND
  450. // is just dandy. This if block just prints that fact, relying on the following
  451. // IF_NOT_SUCCESS_TRACE_AND_EXIT to quit out.
  452. //
  453. }
  454. IF_NOT_SUCCESS_TRACE_AND_EXIT(BaseSrvSxsGetActivationContextGenerationFunction);
  455. // If we fail before we explicitly clean up, release the refcount on the sxs dll
  456. // in the failure path.
  457. ReleaseCtxFunction = TRUE;
  458. if (Struct->Manifest.PathType != BASE_MSG_PATHTYPE_NONE
  459. && Struct->Manifest.Path.Length != 0
  460. && Struct->Manifest.Path.Buffer != NULL
  461. ) {
  462. ASSERT(Struct->Manifest.Path.Buffer[Struct->Manifest.Path.Length / sizeof(WCHAR)] == 0);
  463. SxsDllParameters.Manifest.Path = Struct->Manifest.Path.Buffer;
  464. switch (Struct->Manifest.PathType) {
  465. case BASE_MSG_PATHTYPE_FILE:
  466. SxsDllParameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  467. break;
  468. case BASE_MSG_PATHTYPE_URL:
  469. SxsDllParameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_URL;
  470. break;
  471. }
  472. }
  473. #if IMPERSONATE_ENTIRE_SXS_CALL
  474. SuccessfulImpersonation = CsrImpersonateClient(NULL);
  475. if (!SuccessfulImpersonation) {
  476. //
  477. // if we could not impersonate then exit
  478. //
  479. // DbgPrintEx(...);
  480. Status = STATUS_BAD_IMPERSONATION_LEVEL;
  481. goto Exit;
  482. }
  483. SxsDllParameters.ImpersonationCallback = NULL;
  484. SxsDllParameters.ImpersonationContext = NULL;
  485. #else
  486. SxsDllParameters.ImpersonationCallback = BaseSrvpSxsActivationContextGenerationImpersonationCallback;
  487. SxsDllParameters.ImpersonationContext = &ImpersonationContext;
  488. #endif
  489. SxsFunctionSuccess = (*FunctionPointer)(&SxsDllParameters);
  490. if (SxsFunctionSuccess) // succeed but if for system default, we need check the status
  491. {
  492. if (Struct->Flags & BASE_MSG_SXS_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY_PRESENT)
  493. {
  494. //
  495. // For System Default, there are two ignorable cases when ActCtx is failed.
  496. // case 1: that there is no system defult
  497. // case 2: The dependency of system default has not been installed.
  498. // Status is set to be STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY under this situation which would be ignored
  499. // by BaseSrvCreateProcess, xiaoyuw@11/30/2000
  500. //
  501. if ((SxsDllParameters.SystemDefaultActCxtGenerationResult & BASESRV_SXS_RETURN_RESULT_SYSTEM_DEFAULT_NOT_FOUND) ||
  502. (SxsDllParameters.SystemDefaultActCxtGenerationResult & BASESRV_SXS_RETURN_RESULT_SYSTEM_DEFAULT_DEPENDENCY_ASSEMBLY_NOT_FOUND))
  503. {
  504. Status = STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY; // ActCtx of system default is not generated
  505. goto Exit;
  506. }
  507. }
  508. }
  509. if (!SxsFunctionSuccess) {
  510. DbgPrintEx(
  511. DPFLTR_SXS_ID,
  512. DPFLTR_INFO_LEVEL,
  513. "SXS: Activation Context generation function failed.\n");
  514. Status = STATUS_SXS_CANT_GEN_ACTCTX;
  515. goto Exit;
  516. }
  517. if (SxsDllParameters.SectionObjectHandle != NULL) {
  518. if (Struct->ActivationContextData != NULL) {
  519. // Now let's map the section read-only into the target process...
  520. Status =
  521. BaseSrvSxsMapViewOfSection(
  522. &ViewBase,
  523. SxsClientProcess,
  524. SxsDllParameters.SectionObjectHandle,
  525. 0, // offset
  526. 0, // size
  527. PAGE_READONLY,
  528. SEC_NO_CHANGE);
  529. IF_NOT_SUCCESS_TRACE_AND_EXIT(BaseSrvSxsMapViewOfSection);
  530. //
  531. // And now push that duplicated handle into the process's PEB
  532. //
  533. // On 64bit we are writing into a 64bit PEB that then is copied
  534. // into a 32bit PEB if the process is 32bit.
  535. //
  536. // Or we are writing into a CreateActCtx local, but again 64bit,
  537. // and copied back to 32bit for 32bit processes.
  538. //
  539. Status =
  540. NtWriteVirtualMemory(
  541. SxsClientProcess,
  542. Struct->ActivationContextData,
  543. &ViewBase,
  544. sizeof(ViewBase),
  545. NULL);
  546. IF_NOT_SUCCESS_TRACE_AND_EXIT(NtWriteVirtualMemory);
  547. }
  548. if (OutSection != NULL) {
  549. *OutSection = SxsDllParameters.SectionObjectHandle;
  550. SxsDllParameters.SectionObjectHandle = NULL;
  551. } else {
  552. Status = NtClose(SxsDllParameters.SectionObjectHandle);
  553. SxsDllParameters.SectionObjectHandle = NULL;
  554. IF_NOT_SUCCESS_TRACE_AND_EXIT(NtClose);
  555. }
  556. }
  557. Status = BaseSrvSxsReleaseActivationContextGenerationFunction(Cookie);
  558. ReleaseCtxFunction = FALSE;
  559. IF_NOT_SUCCESS_TRACE_AND_EXIT(BaseSrvSxsReleaseActivationContextGenerationFunction);
  560. Status = STATUS_SUCCESS;
  561. ViewBase = NULL;
  562. Exit:
  563. RTL_SOFT_VERIFY(NT_SUCCESS(Status1 = RTL_UNMAP_VIEW_OF_SECTION2(SxsClientProcess, ViewBase)));
  564. RTL_SOFT_VERIFY(NT_SUCCESS(Status1 = RTL_CLOSE_HANDLE(SxsDllParameters.SectionObjectHandle)));
  565. if (ReleaseCtxFunction) {
  566. Status1 = BaseSrvSxsReleaseActivationContextGenerationFunction(Cookie);
  567. RTL_SOFT_ASSERT(NT_SUCCESS(Status1));
  568. }
  569. #if IMPERSONATE_ENTIRE_SXS_CALL
  570. if (SuccessfulImpersonation) {
  571. CsrRevertToSelf();
  572. }
  573. #endif
  574. if ( Struct->Flags & BASE_MSG_SXS_MANIFEST_PRESENT)
  575. {
  576. RTL_RELEASE(SxsDllParameters.Manifest.Stream);
  577. RTL_RELEASE(SxsDllParameters.Policy.Stream);
  578. #if DBG
  579. if (ManifestStream.Mmap.MemStream.Data.ReferenceCount != 0) {
  580. DbgPrintEx(
  581. DPFLTR_SXS_ID,
  582. DPFLTR_ERROR_LEVEL,
  583. "SRVSXS: ManifestStream.Mmap.MemStream.Data.ReferenceCount: %ld\n",
  584. ManifestStream.Mmap.MemStream.Data.ReferenceCount);
  585. }
  586. if (PolicyStream.Mmap.MemStream.Data.ReferenceCount != 0) {
  587. DbgPrintEx(
  588. DPFLTR_SXS_ID,
  589. DPFLTR_ERROR_LEVEL,
  590. "SRVSXS: PolicyStream.Mmap.MemStream.Data.ReferenceCount: %ld\n",
  591. PolicyStream.Mmap.MemStream.Data.ReferenceCount );
  592. }
  593. ASSERT(ManifestStream.Mmap.MemStream.Data.ReferenceCount == 0
  594. && PolicyStream.Mmap.MemStream.Data.ReferenceCount == 0);
  595. #endif
  596. }
  597. #if DBG
  598. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  599. #endif
  600. return Status;
  601. }}
  602. NTSTATUS
  603. BaseSrvSxsValidateMessageStrings(
  604. IN CONST CSR_API_MSG* Message,
  605. IN ULONG NumberOfStrings,
  606. IN CONST PCUNICODE_STRING* Strings
  607. )
  608. {
  609. ULONG i = 0;
  610. NTSTATUS Status = STATUS_SUCCESS;
  611. for (i = 0 ; i != NumberOfStrings ; ++i) {
  612. if (Strings[i] != NULL && Strings[i]->Buffer != NULL) {
  613. if (!CsrValidateMessageBuffer(
  614. Message,
  615. &Strings[i]->Buffer,
  616. Strings[i]->Length + sizeof(WCHAR),
  617. sizeof(BYTE))) {
  618. DbgPrintEx(
  619. DPFLTR_SXS_ID,
  620. DPFLTR_ERROR_LEVEL,
  621. "SXS: Validation of message buffer 0x%lx failed.\n"
  622. " Message:%p\n"
  623. " String %p{Length:0x%x, MaximumLength:0x%x, Buffer:%p}\n",
  624. i,
  625. Message,
  626. Strings[i],
  627. Strings[i]->Length,
  628. Strings[i]->MaximumLength,
  629. Strings[i]->Buffer
  630. );
  631. Status = STATUS_INVALID_PARAMETER;
  632. goto Exit;
  633. }
  634. }
  635. }
  636. Status = STATUS_SUCCESS;
  637. Exit:
  638. #if DBG
  639. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  640. #endif
  641. return Status;
  642. }
  643. ULONG
  644. BaseSrvSxsCreateActivationContextFromMessage(
  645. IN OUT PCSR_API_MSG m,
  646. IN OUT PCSR_REPLY_STATUS ReplyStatus
  647. )
  648. /*++
  649. Routine Description:
  650. This function handles the CSR message requesting that an activation
  651. context be created.
  652. It loads sxs.dll if it is not loaded, calls the sxs.dll api to
  653. create an activation context, maps the activation context into the
  654. client API and sets the address of the created activation context
  655. into the client's address space.
  656. Arguments:
  657. m - the message sent to csr from the win32 client
  658. ReplyStatus - an indicator of the status of the reply
  659. Return Value:
  660. ULONG return value to the win32 client; in this case we return
  661. the NTSTATUS disposition of the function's execution.
  662. --*/
  663. {
  664. PBASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG Message =
  665. (PBASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG) &m->u.ApiMessageData;
  666. NTSTATUS Status = STATUS_SUCCESS;
  667. HANDLE CsrClientProcess = NULL;
  668. PCUNICODE_STRING StringsInMessageToValidate[4];
  669. ULONG i = 0;
  670. #if DBG
  671. BOOLEAN StringsOk = FALSE;
  672. #endif
  673. #if DBG
  674. DebugFilter_SxsTrace = (NtQueryDebugFilterState(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL) == TRUE);
  675. if (DebugFilter_SxsTrace) {
  676. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() beginning\n", __FUNCTION__);
  677. }
  678. #endif
  679. StringsInMessageToValidate[0] = &Message->Manifest.Path;
  680. StringsInMessageToValidate[1] = &Message->Policy.Path;
  681. StringsInMessageToValidate[2] = &Message->AssemblyDirectory;
  682. StringsInMessageToValidate[3] = &Message->TextualAssemblyIdentity;
  683. Status = BaseSrvSxsValidateMessageStrings(m, RTL_NUMBER_OF(StringsInMessageToValidate), StringsInMessageToValidate);
  684. if (!NT_SUCCESS(Status)) {
  685. goto Exit;
  686. }
  687. #if DBG
  688. StringsOk = TRUE;
  689. #endif
  690. #if DBG
  691. if (DebugFilter_SxsTrace) {
  692. DbgPrintEx(
  693. DPFLTR_SXS_ID,
  694. DPFLTR_TRACE_LEVEL,
  695. "SXS: %s() Manifest=%wZ; Policy=%wZ; TextualAssemblyIdentity=%wZ\n",
  696. __FUNCTION__,
  697. &Message->Manifest.Path,
  698. &Message->Policy.Path,
  699. &Message->TextualAssemblyIdentity
  700. );
  701. }
  702. #endif
  703. CsrClientProcess = CSR_SERVER_QUERYCLIENTTHREAD()->Process->ProcessHandle;
  704. Status = BaseSrvSxsCreateActivationContextFromStruct(CsrClientProcess, CsrClientProcess, Message, NULL);
  705. if (!NT_SUCCESS(Status)) {
  706. goto Exit;
  707. }
  708. Status = STATUS_SUCCESS;
  709. Exit:
  710. #if DBG
  711. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  712. if (StringsOk && DPFLTR_LEVEL_STATUS(Status) == DPFLTR_ERROR_LEVEL) {
  713. DbgPrintEx(
  714. DPFLTR_SXS_ID,
  715. DPFLTR_ERROR_LEVEL,
  716. "SXS: %s() Manifest=%wZ; Policy=%wZ; TextualAssemblyIdentity=%wZ\n",
  717. __FUNCTION__,
  718. &Message->Manifest.Path,
  719. &Message->Policy.Path,
  720. &Message->TextualAssemblyIdentity
  721. );
  722. }
  723. #endif
  724. return Status;
  725. }
  726. ULONG
  727. BaseSrvSxsCreateActivationContext(
  728. IN OUT PCSR_API_MSG m,
  729. IN OUT PCSR_REPLY_STATUS ReplyStatus
  730. )
  731. {
  732. return BaseSrvSxsCreateActivationContextFromMessage(m, ReplyStatus);
  733. }
  734. NTSTATUS
  735. BaseSrvSxsGetActivationContextGenerationFunction(
  736. PSXS_GENERATE_ACTIVATION_CONTEXT_FUNCTION* FunctionPointer,
  737. PDWORD_PTR Cookie
  738. )
  739. /*++
  740. Routine Description:
  741. This function loads sxs.dll if it is not loaded and returns a pointer
  742. to the function to call to generate an activation context.
  743. Arguments:
  744. FunctionPointer - pointer to activation context generation function pointer
  745. returned.
  746. Cookie - returned DWORD_PTR value which must later be passed in
  747. to BaseSrvSxsReleaseActivationContextGenerationFunction() to
  748. lower the refcount on sxs.dll.
  749. Return Value:
  750. NTSTATUS indicating the disposition of the function's execution.
  751. --*/
  752. {
  753. static STRING SxsProcedureName = RTL_CONSTANT_STRING( "SxsGenerateActivationContext" );
  754. NTSTATUS Status = STATUS_SUCCESS;
  755. BOOLEAN FreeDll = FALSE;
  756. DWORD_PTR NewCookie = 0;
  757. NTSTATUS Status1 = STATUS_SUCCESS;
  758. #if BASESRV_UNLOAD_SXS_DLL
  759. BOOLEAN CritSecLocked = FALSE;
  760. #else
  761. PVOID SxsDllHandle = NULL;
  762. #endif
  763. #if BASESRV_UNLOAD_SXS_DLL
  764. __try
  765. #endif
  766. {
  767. #if DBG
  768. if (DebugFilter_SxsTrace) {
  769. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() beginning\n", __FUNCTION__);
  770. }
  771. #endif
  772. if (!(ARGUMENT_PRESENT(FunctionPointer) && ARGUMENT_PRESENT(Cookie))) {
  773. Status = STATUS_INVALID_PARAMETER;
  774. goto Exit;
  775. }
  776. #if BASESRV_UNLOAD_SXS_DLL
  777. //
  778. // It's tempting to want to optimize away locking the critical section
  779. // when looking at the pointer, because we know if it's not NULL, we can
  780. // just use it, but we're keeping a reference count on the SXS.DLL
  781. // so that we can unload it, so to avoid this race, we need to lock the
  782. // critical section.
  783. //
  784. Status = RtlEnterCriticalSection(&BaseSrvSxsCritSec);
  785. if (!NT_SUCCESS(Status))
  786. goto Exit;
  787. CritSecLocked = TRUE;
  788. #endif
  789. if (SxsActivationContextGenerationFunction == NULL) {
  790. Status = LdrLoadDll(
  791. NULL,
  792. NULL,
  793. &BaseSrvSxsDllPath,
  794. &SxsDllHandle);
  795. if (!NT_SUCCESS(Status)) {
  796. DbgPrintEx(
  797. DPFLTR_SXS_ID,
  798. DPFLTR_LEVEL_STATUS(Status),
  799. "SXS: %s: LdrLoadDll(%wZ) failed 0x%08lx\n",
  800. __FUNCTION__,
  801. &BaseSrvSxsDllPath,
  802. Status
  803. );
  804. if (Status == STATUS_DLL_NOT_FOUND) {
  805. PVOID p = RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(L"c:\\windows\\system32\\sxs.dll"));
  806. RtlFreeHeap(RtlProcessHeap(), 0, p);
  807. if (p == NULL) {
  808. DbgPrintEx(
  809. DPFLTR_SXS_ID,
  810. DPFLTR_LEVEL_STATUS(Status),
  811. "SXS: %s: LdrLoadDll(%wZ) actually probably out of memory in RtlSearchPath (RtlAllocateHeap failure)\n",
  812. __FUNCTION__,
  813. &BaseSrvSxsDllPath
  814. );
  815. }
  816. }
  817. goto Exit;
  818. }
  819. FreeDll = TRUE;
  820. Status = LdrGetProcedureAddress(SxsDllHandle, &SxsProcedureName, 0, (PVOID *) &SxsActivationContextGenerationFunction);
  821. if (!NT_SUCCESS(Status)) {
  822. DbgPrintEx(
  823. DPFLTR_SXS_ID,
  824. DPFLTR_LEVEL_STATUS(Status),
  825. "SXS: %s: LdrGetProcedureAddress(%wZ:%Z) failed 0x%08lx\n",
  826. __FUNCTION__,
  827. &BaseSrvSxsDllPath,
  828. &SxsProcedureName,
  829. Status
  830. );
  831. goto Exit;
  832. }
  833. FreeDll = FALSE;
  834. }
  835. NewCookie = BaseSrvSxsGetActCtxGenCount++;
  836. #if BASESRV_UNLOAD_SXS_DLL
  837. SxsDllHandleRefCount++;
  838. RtlLeaveCriticalSection(&BaseSrvSxsCritSec);
  839. CritSecLocked = FALSE;
  840. #endif
  841. *FunctionPointer = SxsActivationContextGenerationFunction;
  842. *Cookie = NewCookie;
  843. Status = STATUS_SUCCESS;
  844. Exit:
  845. if (FreeDll) {
  846. #if BASESRV_UNLOAD_SXS_DLL
  847. ASSERT(CritSecLocked);
  848. ASSERT(SxsDllHandle != NULL);
  849. ASSERT(SxsActivationContextGenerationFunction == NULL);
  850. #endif
  851. SxsActivationContextGenerationFunction = NULL;
  852. Status1 = LdrUnloadDll(SxsDllHandle);
  853. RTL_SOFT_ASSERT(NT_SUCCESS(Status1));
  854. SxsDllHandle = NULL;
  855. }
  856. #if DBG
  857. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  858. #endif
  859. }
  860. #if BASESRV_UNLOAD_SXS_DLL
  861. __finally
  862. {
  863. if (CritSecLocked)
  864. RtlLeaveCriticalSection(&BaseSrvSxsCritSec);
  865. }
  866. #endif
  867. return Status;
  868. }
  869. NTSTATUS
  870. BaseSrvSxsReleaseActivationContextGenerationFunction(
  871. DWORD_PTR Cookie
  872. )
  873. /*++
  874. Routine Description:
  875. This function decrements the reference count on sxs.dll and unloads it
  876. if the reference count is zero.
  877. Arguments:
  878. Cookie - value returned by BaseSrvSxsGetActivationContextGenerationFunction
  879. Return Value:
  880. NTSTATUS indicating the disposition of the function's execution.
  881. --*/
  882. {
  883. NTSTATUS Status = STATUS_SUCCESS;
  884. #if BASESRV_UNLOAD_SXS_DLL
  885. BOOLEAN CritSecLocked = FALSE;
  886. __try {
  887. #if DBG
  888. if (DebugFilter_SxsTrace) {
  889. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() beginning\n", __FUNCTION__);
  890. }
  891. #endif
  892. (Cookie); // maybe someday we'll actively track this in debug builds...
  893. Status = RtlEnterCriticalSection(&BaseSrvSxsCritSec);
  894. if (!NT_SUCCESS(Status))
  895. goto Exit;
  896. CritSecLocked = TRUE;
  897. // We shouldn't have gotten here if the DLL wasn't loaded - someone either
  898. // released more than once or called release without having called
  899. // get previously.
  900. ASSERT(SxsDllHandle != NULL);
  901. ASSERT(SxsDllHandleRefCount != 0);
  902. --SxsDllHandleRefCount;
  903. if (SxsDllHandleRefCount == 0) {
  904. #if DBG
  905. Status = LdrUnloadDll(SxsDllHandle);
  906. SxsDllHandle = NULL;
  907. SxsActivationContextGenerationFunction = NULL;
  908. if (!NT_SUCCESS(Status))
  909. goto Exit;
  910. #endif // DBG
  911. }
  912. RtlLeaveCriticalSection(&BaseSrvSxsCritSec);
  913. CritSecLocked = FALSE;
  914. Status = STATUS_SUCCESS;
  915. Exit:
  916. #if DBG
  917. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  918. #endif
  919. } __finally {
  920. if (CritSecLocked)
  921. RtlLeaveCriticalSection(&BaseSrvSxsCritSec);
  922. }
  923. #endif // BASESRV_UNLOAD_SXS_DLL
  924. return Status;
  925. }
  926. NTSTATUS
  927. BaseSrvSxsDuplicateObject(
  928. HANDLE FromProcess,
  929. HANDLE FromHandle,
  930. HANDLE* ToHandle
  931. )
  932. /*++
  933. Routine Description:
  934. Shrink the parameter list of NtDuplicateObject to a smaller common case.
  935. Arguments:
  936. FromProcess -
  937. FromHandle -
  938. ToHandle -
  939. Return Value:
  940. NTSTATUS from NtDuplicateObject
  941. --*/
  942. {
  943. NTSTATUS Status = STATUS_SUCCESS;
  944. Status =
  945. NtDuplicateObject(
  946. FromProcess,
  947. FromHandle,
  948. NtCurrentProcess(),
  949. ToHandle,
  950. 0,
  951. 0,
  952. DUPLICATE_SAME_ACCESS
  953. );
  954. return Status;
  955. }
  956. NTSTATUS
  957. BaseSrvSxsCreateMemoryStream(
  958. HANDLE CsrClientProcess,
  959. IN PCBASE_MSG_SXS_STREAM MsgStream,
  960. OUT PBASE_SRV_SXS_STREAM_UNION_WITH_VTABLE StreamUnion,
  961. IN const IID* IIDStream,
  962. OUT PVOID* OutIStream
  963. )
  964. /*++
  965. Routine Description:
  966. Based on MsgStream->HandleType, this initializes the correct
  967. union member of StreamUnion and returns an IStream* to it.
  968. Arguments:
  969. CsrClientProcess - the process MsgStream->Handle is valid in,
  970. and the value of the handle if MsgStream->HandleType == BASE_MSG_HANDLETYPE_CLIENT_PROCESS
  971. MsgStream - a description of an IStream that is easily remoted across to csrss.exe
  972. StreamUnion - a union of all our IStream implementations
  973. OutIStream - resulting IStream*
  974. Return Value:
  975. NTSTATUS indicating the disposition of the function.
  976. Note:
  977. All the handles in MsgStream are valid in CsrClientProcess.
  978. Therefore, we don't close them. We duplicate them, and close the duplicates.
  979. --*/
  980. {
  981. HANDLE Handle = NULL;
  982. HANDLE FileHandle = NULL;
  983. NTSTATUS Status = STATUS_SUCCESS;
  984. HRESULT Hr = NOERROR;
  985. PVOID ViewBase = NULL;
  986. NTSTATUS Status1 = STATUS_SUCCESS;
  987. ULONG i = 0;
  988. #if DBG
  989. if (DebugFilter_SxsTrace) {
  990. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SRVSXS: %s() beginning\n", __FUNCTION__);
  991. }
  992. #endif
  993. ASSERT(CsrClientProcess != NULL);
  994. ASSERT(MsgStream != NULL);
  995. ASSERT(StreamUnion != NULL);
  996. ASSERT(IIDStream != NULL);
  997. ASSERT(OutIStream != NULL);
  998. // If the manifest is actually just a VA region in the client process, dup the client process
  999. // handle from our own address space to our own address space; otherwise, it's a handle
  1000. // in the client address space so we need to dup it from the client space to ours.
  1001. if (MsgStream->HandleType == BASE_MSG_HANDLETYPE_CLIENT_PROCESS) {
  1002. Status = BaseSrvSxsDuplicateObject(NtCurrentProcess(), CsrClientProcess, &Handle);
  1003. } else {
  1004. Status = BaseSrvSxsDuplicateObject(CsrClientProcess, MsgStream->Handle, &Handle);
  1005. }
  1006. if (!NT_SUCCESS(Status)) {
  1007. Handle = NULL;
  1008. #if DBG
  1009. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SRVSXS: %s(): NtDuplicateObject failed; Status = %08lx\n", __FUNCTION__, Status);
  1010. #if 1 /* temporary */
  1011. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SRVSXS: MsgStream->HandleType 0x%lx\n", MsgStream->HandleType);
  1012. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SRVSXS: BASE_MSG_HANDLETYPE_CLIENT_PROCESS 0x%lx\n", BASE_MSG_HANDLETYPE_CLIENT_PROCESS);
  1013. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SRVSXS: CsrClientProcess %p\n", CsrClientProcess);
  1014. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SRVSXS: MsgStream->Handle %p\n", MsgStream->Handle);
  1015. #endif
  1016. #endif
  1017. goto Exit;
  1018. }
  1019. if (MsgStream->FileHandle != NULL) {
  1020. Status = BaseSrvSxsDuplicateObject(CsrClientProcess, MsgStream->FileHandle, &FileHandle);
  1021. if (!NT_SUCCESS(Status)) {
  1022. #if DBG
  1023. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SRVSXS: %s(): NtDuplicateObject(FileHandle) failed.\n", __FUNCTION__);
  1024. #endif
  1025. goto Exit;
  1026. }
  1027. }
  1028. switch (MsgStream->HandleType) {
  1029. default:
  1030. ASSERTMSG("Bad HandleType", FALSE);
  1031. Status = STATUS_INVALID_PARAMETER;
  1032. goto Exit;
  1033. case BASE_MSG_HANDLETYPE_CLIENT_PROCESS:
  1034. case BASE_MSG_HANDLETYPE_PROCESS:
  1035. // This is the app-compat case.
  1036. //
  1037. // REVIEW: if Offset happens to be in a section in the process
  1038. // (you can find out with NtQuerySection(SectionBasicInformation)),
  1039. // we should instead map it. That would be more efficient.
  1040. //
  1041. // That logic could just as well be in kernel32 though, and for
  1042. // the sake of minimizing csr code and time, that's where we'd do it.
  1043. //
  1044. RtlInitOutOfProcessMemoryStream(&StreamUnion->OutOfProcess);
  1045. StreamUnion->OutOfProcess.Data.Process = Handle;
  1046. Handle = NULL; // the stream owns it now
  1047. StreamUnion->OutOfProcess.Data.Begin = (PUCHAR)MsgStream->Offset;
  1048. StreamUnion->OutOfProcess.Data.Current = StreamUnion->OutOfProcess.Data.Begin;
  1049. StreamUnion->OutOfProcess.Data.End = StreamUnion->OutOfProcess.Data.Begin + MsgStream->Size;
  1050. break;
  1051. case BASE_MSG_HANDLETYPE_SECTION: {
  1052. Status =
  1053. BaseSrvSxsMapViewOfSection(
  1054. &ViewBase,
  1055. NtCurrentProcess(),
  1056. Handle,
  1057. MsgStream->Offset,
  1058. MsgStream->Size,
  1059. PAGE_READONLY,
  1060. SEC_NO_CHANGE
  1061. );
  1062. if (!NT_SUCCESS(Status)) {
  1063. goto Exit;
  1064. }
  1065. BaseSrvInitMemoryMappedStream(&StreamUnion->Mmap);
  1066. StreamUnion->Mmap.MemStream.Data.Begin = (PUCHAR)ViewBase;
  1067. ViewBase = NULL; // the stream owns it now
  1068. StreamUnion->Mmap.MemStream.Data.Current = StreamUnion->Mmap.MemStream.Data.Begin;
  1069. StreamUnion->Mmap.MemStream.Data.End = StreamUnion->Mmap.MemStream.Data.Begin + MsgStream->Size;
  1070. StreamUnion->Mmap.FileHandle = FileHandle;
  1071. FileHandle = NULL; // the stream owns it now
  1072. break;
  1073. }
  1074. }
  1075. // it does not matter here which member of the union we use, we are only using
  1076. // members of the members that are at the same offset
  1077. Hr = StreamUnion->Mmap.MemStream.StreamVTable->QueryInterface(
  1078. (IStream*)&StreamUnion->Mmap.MemStream,
  1079. IIDStream,
  1080. OutIStream);
  1081. ASSERT(SUCCEEDED(Hr));
  1082. Status = STATUS_SUCCESS;
  1083. Exit:
  1084. RTL_SOFT_VERIFY(NT_SUCCESS(RTL_CLOSE_HANDLE(FileHandle)));
  1085. RTL_SOFT_VERIFY(NT_SUCCESS(RTL_CLOSE_HANDLE(Handle)));
  1086. RTL_SOFT_VERIFY(NT_SUCCESS(RTL_UNMAP_VIEW_OF_SECTION1(ViewBase)));
  1087. #if DBG
  1088. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  1089. #endif
  1090. return Status;
  1091. }
  1092. NTSTATUS
  1093. BaseSrvSxsCreateProcess(
  1094. HANDLE CsrClientProcess,
  1095. HANDLE NewProcess,
  1096. IN OUT PCSR_API_MSG CsrMessage,
  1097. PPEB NewProcessPeb
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. Runs during kernel32.dll::CreateProcessW's calls to csrss.exe.
  1102. Munges the csr message into something more Win32-ish (IStreams) and calls into sxs.dll to
  1103. create the processes default activation context.
  1104. Munges the create process message to look like a CreateActCtx message, which isn't much work,
  1105. and then delegates to code common with CreateActCtx.
  1106. Arguments:
  1107. Process - the csr client process, the "old" process, the "parent" process that called
  1108. CreateProcess
  1109. Message - a bunch of parameters
  1110. Return Value:
  1111. NTSTATUS indicating the disposition of the function.
  1112. --*/
  1113. {
  1114. PROCESS_BASIC_INFORMATION ProcessBasicInfo;
  1115. BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG Struct = {0};
  1116. PCUNICODE_STRING StringsInMessageToValidate[3];
  1117. NTSTATUS Status = STATUS_SUCCESS;
  1118. PBASE_CREATEPROCESS_MSG CreateProcessMessage = (PBASE_CREATEPROCESS_MSG)&CsrMessage->u.ApiMessageData;
  1119. PBASE_SXS_CREATEPROCESS_MSG SxsMessage = &CreateProcessMessage->Sxs;
  1120. ASSERT(CsrMessage != NULL);
  1121. if ((SxsMessage->Flags & BASE_MSG_SXS_MANIFEST_PRESENT) == 0) {
  1122. Status = STATUS_SUCCESS;
  1123. goto Exit;
  1124. }
  1125. #if DBG
  1126. DebugFilter_SxsTrace = (NtQueryDebugFilterState(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL) == TRUE);
  1127. if (DebugFilter_SxsTrace) {
  1128. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_TRACE_LEVEL, "SXS: %s() beginning\n", __FUNCTION__);
  1129. }
  1130. #endif
  1131. StringsInMessageToValidate[0] = &SxsMessage->Manifest.Path;
  1132. StringsInMessageToValidate[1] = &SxsMessage->Policy.Path;
  1133. StringsInMessageToValidate[2] = &SxsMessage->AssemblyDirectory;
  1134. Status = BaseSrvSxsValidateMessageStrings(CsrMessage, RTL_NUMBER_OF(StringsInMessageToValidate), StringsInMessageToValidate);
  1135. if (!NT_SUCCESS(Status)) {
  1136. goto Exit;
  1137. }
  1138. #if DBG
  1139. if (DebugFilter_SxsTrace) {
  1140. DbgPrintEx(
  1141. DPFLTR_SXS_ID,
  1142. DPFLTR_TRACE_LEVEL,
  1143. "SXS: %s() Manifest=%wZ; Policy=%wZ, AssemblyDirectory=%wZ\n",
  1144. __FUNCTION__,
  1145. &SxsMessage->Manifest.Path,
  1146. &SxsMessage->Policy.Path,
  1147. &SxsMessage->AssemblyDirectory
  1148. );
  1149. }
  1150. #endif
  1151. if (CsrImpersonateClient(NULL)) {
  1152. __try {
  1153. Status = NtQueryDefaultUILanguage(&Struct.LangId);
  1154. } __finally {
  1155. CsrRevertToSelf();
  1156. }
  1157. } else {
  1158. Status = NtQueryInstallUILanguage(&Struct.LangId);
  1159. }
  1160. if (!NT_SUCCESS(Status))
  1161. goto Exit;
  1162. Struct.Flags = SxsMessage->Flags;
  1163. Struct.Manifest = SxsMessage->Manifest;
  1164. Struct.Policy = SxsMessage->Policy;
  1165. Struct.AssemblyDirectory = SxsMessage->AssemblyDirectory;
  1166. Struct.ActivationContextData = (PVOID)&NewProcessPeb->ActivationContextData;
  1167. Struct.ProcessorArchitecture = CreateProcessMessage->ProcessorArchitecture;
  1168. Status = BaseSrvSxsCreateActivationContextFromStruct(CsrClientProcess, NewProcess, &Struct, NULL);
  1169. if (!NT_SUCCESS(Status)) {
  1170. goto Exit;
  1171. }
  1172. Status = STATUS_SUCCESS;
  1173. Exit:
  1174. #if DBG
  1175. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  1176. #endif
  1177. return Status;
  1178. }
  1179. NTSTATUS
  1180. BaseSrvSxsGetCachedSystemDefaultActivationContext(
  1181. IN USHORT ProcessorArchitecture,
  1182. OUT PBASE_SRV_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT *SystemDefaultActivationContext
  1183. )
  1184. /*++
  1185. if (SystemDefaultActivationContext != NULL)
  1186. then the caller must take the BaseSrvSxsSystemDefaultActivationContextCriticalSection.
  1187. --*/
  1188. {
  1189. NTSTATUS Status = STATUS_SUCCESS;
  1190. ULONG i;
  1191. for (i = 0 ; i != RTL_NUMBER_OF(SxsSystemDefaultActivationContexts) ; ++i) {
  1192. if (SxsSystemDefaultActivationContexts[i].ProcessorArchitecture == ProcessorArchitecture) {
  1193. *SystemDefaultActivationContext = &SxsSystemDefaultActivationContexts[i];
  1194. break;
  1195. }
  1196. }
  1197. if (*SystemDefaultActivationContext == NULL) {
  1198. ASSERTMSG("Unknown Processor Architecture", FALSE);
  1199. Status = STATUS_UNSUCCESSFUL;
  1200. goto Exit;
  1201. }
  1202. Status = STATUS_SUCCESS;
  1203. Exit:
  1204. return Status;
  1205. }
  1206. NTSTATUS
  1207. BaseSrvSxsDoSystemDefaultActivationContext(
  1208. USHORT ProcessorArchitecture,
  1209. HANDLE NewProcess,
  1210. PPEB NewPeb
  1211. )
  1212. /*++
  1213. Routine Description:
  1214. Runs during kernel32.dll::CreateProcessW's calls to csrss.exe.
  1215. FOR ALL PROCESSES (except the special first few, system, idle, smss, csrss),
  1216. on demand create the default activation context, and write it into
  1217. the new process's peb.
  1218. Within this function, the textual-assembly-identity string for System Default is created
  1219. and passed to BaseSrvSxsCreateActivationContextFromStruct, which would pass this string to
  1220. SXS.dll, where manifest file would be located using this textual-string.
  1221. Arguments:
  1222. LangID - user's ui language for the new process
  1223. ProcessorArchitecture - the ProcessorArchitecture for the new process
  1224. NewProcess -
  1225. NewPeb -
  1226. Return Value:
  1227. NTSTATUS indicating the disposition of the function.
  1228. --*/
  1229. {
  1230. NTSTATUS Status = STATUS_SUCCESS;
  1231. HANDLE ActivationContextSection = NULL;
  1232. PBASE_SRV_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT SystemDefaultActivationContext = NULL;
  1233. LANGID LangId = 0;
  1234. BOOLEAN RevertToSelfNeeded = FALSE;
  1235. BASE_SXS_CREATE_ACTIVATION_CONTEXT_MSG Struct = {0};
  1236. RTL_UNICODE_STRING_BUFFER SystemDefaultAssemblyDirectoryBuffer = {0};
  1237. // The size of the following buffer is only heuristic, we will grow via the heap if necessary.
  1238. UCHAR SystemDefaultAssemblyDirectoryStaticBuffer[sizeof(L"c:\\windows8.123\\winsxs")];
  1239. UNICODE_STRING SystemRoot;
  1240. USHORT AssemblyDirectoryLength = 0;
  1241. const UNICODE_STRING SystemDefaultContextString = RTL_CONSTANT_STRING(L"System Default Context");
  1242. RTL_UNICODE_STRING_BUFFER SystemDefaultTextualAssemblyIdentityBuffer = {0};
  1243. UCHAR SystemDefaultTextualAssemblyIdentityStaticBuffer[
  1244. sizeof(LSYSTEM_COMPATIBLE_ASSEMBLY_NAME L",version=\"65535.65535.65535.65535\",type=\"win32\",publicKeyToken=\"6595b64144ccf1df\",processorArchitecture=\"alpha\"...padding...")
  1245. ];
  1246. PVOID ViewBase = NULL;
  1247. BOOLEAN Locked = FALSE;
  1248. __try
  1249. {
  1250. Status = BaseSrvSxsGetCachedSystemDefaultActivationContext(ProcessorArchitecture, &SystemDefaultActivationContext);
  1251. if (!NT_SUCCESS(Status) && SystemDefaultActivationContext == NULL) {
  1252. goto Exit;
  1253. }
  1254. //
  1255. // Enter the critical section to read the Section member data.
  1256. //
  1257. RtlEnterCriticalSection(&BaseSrvSxsSystemDefaultActivationContextCriticalSection);
  1258. Locked = TRUE;
  1259. if (SystemDefaultActivationContext->Section != NULL) {
  1260. goto GotActivationContext;
  1261. }
  1262. //
  1263. // Leave the critical section a while, in order to reduce stress failure.
  1264. //
  1265. RtlLeaveCriticalSection(&BaseSrvSxsSystemDefaultActivationContextCriticalSection);
  1266. Locked = FALSE;
  1267. if (CsrImpersonateClient(NULL)) {
  1268. __try {
  1269. Status = NtQueryDefaultUILanguage(&LangId);
  1270. } __finally {
  1271. CsrRevertToSelf();
  1272. }
  1273. } else {
  1274. Status = NtQueryInstallUILanguage(&LangId);
  1275. }
  1276. if (!NT_SUCCESS(Status)) {
  1277. #if DBG
  1278. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SRVSXS: %s(): NtQueryDefaultUILanguage failed; status = 0x%08lx.\n", __FUNCTION__, Status);
  1279. #endif
  1280. goto Exit;
  1281. }
  1282. RtlInitUnicodeStringBuffer(&SystemDefaultAssemblyDirectoryBuffer, SystemDefaultAssemblyDirectoryStaticBuffer, sizeof(SystemDefaultAssemblyDirectoryStaticBuffer));
  1283. SystemRoot = BaseSrvWindowsDirectory;
  1284. RtlRemoveTrailingPathSeperators(0, &SystemRoot);
  1285. {
  1286. #define X(x) { (x).Length, (x).MaximumLength, (x).Buffer }
  1287. /*static*/ const UNICODE_STRING Strings1[] =
  1288. {
  1289. X(SystemRoot),
  1290. RTL_CONSTANT_STRING(L"\\WinSxs")
  1291. };
  1292. #undef X
  1293. Status = RtlMultiAppendUnicodeStringBuffer(&SystemDefaultAssemblyDirectoryBuffer, RTL_NUMBER_OF(Strings1), Strings1);
  1294. IF_NOT_SUCCESS_TRACE_AND_EXIT(RtlMultiAppendUnicodeStringBuffer#1);
  1295. AssemblyDirectoryLength = SystemDefaultAssemblyDirectoryBuffer.String.Length; // AssemblyDirectory = "x:\winnt\winsxs\manifests"
  1296. }
  1297. RtlInitUnicodeStringBuffer(&SystemDefaultTextualAssemblyIdentityBuffer,
  1298. SystemDefaultTextualAssemblyIdentityStaticBuffer, sizeof(SystemDefaultTextualAssemblyIdentityStaticBuffer));
  1299. {
  1300. #define X(x) { (x).Length, (x).MaximumLength, (x).Buffer }
  1301. /*static*/ const UNICODE_STRING Strings1[] =
  1302. {
  1303. RTL_CONSTANT_STRING(
  1304. LSYSTEM_COMPATIBLE_ASSEMBLY_NAME
  1305. L",version=\""
  1306. SYSTEM_COMPATIBLE_ASSEMBLY_FULL_VERSION_STRING_W
  1307. L"\",type=\"win32\",publicKeyToken=\"6595b64144ccf1df\",processorArchitecture=\""
  1308. ),
  1309. X(SystemDefaultActivationContext->ProcessorArchitectureString),
  1310. RTL_CONSTANT_STRING(L"\"")
  1311. };
  1312. #undef X
  1313. Status = RtlMultiAppendUnicodeStringBuffer(&SystemDefaultTextualAssemblyIdentityBuffer, RTL_NUMBER_OF(Strings1), Strings1);
  1314. IF_NOT_SUCCESS_TRACE_AND_EXIT(RtlMultiAppendUnicodeStringBuffer#3);
  1315. ASSERT_UNICODE_STRING_IS_NUL_TERMINATED(&SystemDefaultTextualAssemblyIdentityBuffer.String);
  1316. }
  1317. Struct.Flags = BASE_MSG_SXS_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY_PRESENT;
  1318. Struct.Flags |= BASE_MSG_SXS_TEXTUAL_ASSEMBLY_IDENTITY_PRESENT;
  1319. Struct.TextualAssemblyIdentity.Buffer = SystemDefaultTextualAssemblyIdentityBuffer.String.Buffer;
  1320. Struct.TextualAssemblyIdentity.Length = SystemDefaultTextualAssemblyIdentityBuffer.String.Length;
  1321. Struct.TextualAssemblyIdentity.MaximumLength = SystemDefaultTextualAssemblyIdentityBuffer.String.MaximumLength;
  1322. Struct.AssemblyDirectory = SystemDefaultAssemblyDirectoryBuffer.String;
  1323. Struct.AssemblyDirectory.Length = AssemblyDirectoryLength;
  1324. Struct.AssemblyDirectory.Buffer[Struct.AssemblyDirectory.Length / sizeof(WCHAR)] = 0;
  1325. Struct.Manifest.PathType = BASE_MSG_PATHTYPE_FILE;
  1326. Struct.Manifest.Path = SystemDefaultContextString;
  1327. Struct.LangId = LangId;
  1328. Struct.ProcessorArchitecture = ProcessorArchitecture;
  1329. //
  1330. // BaseSrvSxsCreateActivationContextFromStruct would return STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY
  1331. // if the failure from ActCtx generation is ignorable.
  1332. //
  1333. Status =
  1334. BaseSrvSxsCreateActivationContextFromStruct(
  1335. NtCurrentProcess(),
  1336. NtCurrentProcess(),
  1337. &Struct,
  1338. &ActivationContextSection
  1339. );
  1340. IF_NOT_SUCCESS_TRACE_AND_EXIT(BaseSrvSxsCreateActivationContextFromStruct);
  1341. RtlEnterCriticalSection(&BaseSrvSxsSystemDefaultActivationContextCriticalSection);
  1342. Locked = TRUE;
  1343. if (SystemDefaultActivationContext->Section == NULL) {
  1344. SystemDefaultActivationContext->Section = ActivationContextSection;
  1345. } else {
  1346. NtClose(ActivationContextSection);
  1347. }
  1348. ActivationContextSection = NULL;
  1349. GotActivationContext:
  1350. //
  1351. // Hold the critical section until we
  1352. // finish with SystemDefaultActivationContext->Section.
  1353. //
  1354. ASSERT(ActivationContextSection == NULL);
  1355. ASSERT(SystemDefaultActivationContext != NULL
  1356. && SystemDefaultActivationContext->Section != NULL);
  1357. ASSERT(Locked);
  1358. Status =
  1359. BaseSrvSxsMapViewOfSection(
  1360. &ViewBase,
  1361. NewProcess,
  1362. SystemDefaultActivationContext->Section,
  1363. 0, // offset
  1364. 0, // size
  1365. PAGE_READONLY,
  1366. SEC_NO_CHANGE);
  1367. RtlLeaveCriticalSection(&BaseSrvSxsSystemDefaultActivationContextCriticalSection);
  1368. Locked = FALSE;
  1369. IF_NOT_SUCCESS_TRACE_AND_EXIT(BaseSrvSxsMapViewOfSection);
  1370. Status =
  1371. NtWriteVirtualMemory(
  1372. NewProcess,
  1373. (PVOID)&NewPeb->SystemDefaultActivationContextData,
  1374. &ViewBase,
  1375. (ProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) ? sizeof(ULONG) : sizeof(ViewBase),
  1376. NULL);
  1377. IF_NOT_SUCCESS_TRACE_AND_EXIT(NtWriteVirtualMemory);
  1378. Status = STATUS_SUCCESS;
  1379. ViewBase = NULL;
  1380. Exit:
  1381. ;
  1382. } __finally {
  1383. //
  1384. // do the critical section first because
  1385. // 1) it doesn't guard any of the others, they are all local
  1386. // 2) to keep the critical section held shorter
  1387. // 3) in case we exception out from any of the others
  1388. //
  1389. if (Locked) {
  1390. RtlLeaveCriticalSection(&BaseSrvSxsSystemDefaultActivationContextCriticalSection);
  1391. Locked = FALSE;
  1392. }
  1393. RtlFreeUnicodeStringBuffer(&SystemDefaultAssemblyDirectoryBuffer);
  1394. RtlFreeUnicodeStringBuffer(&SystemDefaultTextualAssemblyIdentityBuffer);
  1395. if (AbnormalTermination()) {
  1396. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "Abnormal termination in " __FUNCTION__ ".\n");
  1397. }
  1398. RTL_UNMAP_VIEW_OF_SECTION2(NewProcess, ViewBase);
  1399. if (RevertToSelfNeeded) {
  1400. CsrRevertToSelf(); // This unstacks client contexts
  1401. }
  1402. }
  1403. #if DBG
  1404. DbgPrintEx(DPFLTR_SXS_ID, DPFLTR_LEVEL_STATUS(Status), "SXS: %s() exiting 0x%08lx\n", __FUNCTION__, Status);
  1405. #endif
  1406. return Status;
  1407. }