Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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