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.

690 lines
21 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. srvloadr.c
  5. Abstract:
  6. This is the server DLL loader module for the Server side of the Client
  7. Server Runtime Subsystem (CSRSS)
  8. Author:
  9. Steve Wood (stevewo) 08-Oct-1990
  10. Environment:
  11. User Mode Only
  12. Revision History:
  13. --*/
  14. #include "csrsrv.h"
  15. #include "windows.h"
  16. #ifdef _IA64_
  17. #include <ntia64.h>
  18. #endif // _IA64_
  19. EXCEPTION_DISPOSITION
  20. CsrUnhandledExceptionFilter(
  21. struct _EXCEPTION_POINTERS *ExceptionInfo
  22. )
  23. {
  24. UNICODE_STRING UnicodeParameter;
  25. ULONG_PTR Parameters[ 4 ];
  26. ULONG Response;
  27. BOOLEAN WasEnabled;
  28. NTSTATUS Status;
  29. LONG lReturn = EXCEPTION_EXECUTE_HANDLER;
  30. SYSTEM_KERNEL_DEBUGGER_INFORMATION KernelDebuggerInfo;
  31. //
  32. // Terminating will cause sm's wait to sense that we crashed. This will
  33. // result in a clean shutdown due to sm's hard error logic
  34. //
  35. Status = NtQuerySystemInformation( SystemKernelDebuggerInformation,
  36. &KernelDebuggerInfo,
  37. sizeof(KernelDebuggerInfo),
  38. NULL
  39. );
  40. //
  41. // Under Hydra, we don't want to shutdown the system just
  42. // because the Win32 subsystem is going away. In case of non-console CSRSS,
  43. // causing the process to terminate is sufficient.
  44. //
  45. if ((NtCurrentPeb()->SessionId == 0) ||
  46. (NT_SUCCESS(Status) && KernelDebuggerInfo.KernelDebuggerEnabled)) {
  47. lReturn = RtlUnhandledExceptionFilter(ExceptionInfo);
  48. if (lReturn != EXCEPTION_CONTINUE_EXECUTION)
  49. {
  50. //
  51. // We are hosed, so raise a fatal system error to shutdown the system.
  52. // (Basically a user mode KeBugCheck).
  53. //
  54. Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
  55. (BOOLEAN)TRUE,
  56. TRUE,
  57. &WasEnabled
  58. );
  59. if (Status == STATUS_NO_TOKEN) {
  60. //
  61. // No thread token, use the process token
  62. //
  63. Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
  64. (BOOLEAN)TRUE,
  65. FALSE,
  66. &WasEnabled
  67. );
  68. }
  69. RtlInitUnicodeString( &UnicodeParameter, L"Windows SubSystem" );
  70. Parameters[ 0 ] = (ULONG_PTR)&UnicodeParameter;
  71. Parameters[ 1 ] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionCode;
  72. Parameters[ 2 ] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
  73. Parameters[ 3 ] = (ULONG_PTR)ExceptionInfo->ContextRecord;
  74. Status = NtRaiseHardError( STATUS_SYSTEM_PROCESS_TERMINATED,
  75. 4,
  76. 1,
  77. Parameters,
  78. OptionShutdownSystem,
  79. &Response
  80. );
  81. }
  82. }
  83. if (lReturn != EXCEPTION_CONTINUE_EXECUTION)
  84. {
  85. //
  86. // If this returns, giveup
  87. //
  88. NtTerminateProcess(NtCurrentProcess(),ExceptionInfo->ExceptionRecord->ExceptionCode);
  89. }
  90. return lReturn;
  91. }
  92. NTSTATUS
  93. CsrLoadServerDll(
  94. IN PCH ModuleName,
  95. IN PCH InitRoutineString,
  96. IN ULONG ServerDllIndex
  97. )
  98. {
  99. NTSTATUS Status;
  100. ANSI_STRING ModuleNameString;
  101. UNICODE_STRING ModuleNameString_U;
  102. HANDLE ModuleHandle;
  103. PCSR_SERVER_DLL LoadedServerDll;
  104. STRING ProcedureNameString;
  105. PCSR_SERVER_DLL_INIT_ROUTINE ServerDllInitialization;
  106. ULONG n;
  107. if (ServerDllIndex >= CSR_MAX_SERVER_DLL) {
  108. return( STATUS_TOO_MANY_NAMES );
  109. }
  110. if (CsrLoadedServerDll[ ServerDllIndex ] != NULL) {
  111. return( STATUS_INVALID_PARAMETER );
  112. }
  113. ASSERT( ModuleName != NULL );
  114. RtlInitAnsiString( &ModuleNameString, ModuleName );
  115. if (ServerDllIndex != CSRSRV_SERVERDLL_INDEX) {
  116. Status = RtlAnsiStringToUnicodeString(&ModuleNameString_U, &ModuleNameString, TRUE);
  117. if (!NT_SUCCESS(Status)) {
  118. return Status;
  119. }
  120. Status = LdrLoadDll( UNICODE_NULL, NULL, &ModuleNameString_U, &ModuleHandle );
  121. if ( !NT_SUCCESS(Status) ) {
  122. PUNICODE_STRING ErrorStrings[2];
  123. UNICODE_STRING ErrorDllPath;
  124. ULONG ErrorResponse;
  125. NTSTATUS ErrorStatus;
  126. ErrorStrings[0] = &ModuleNameString_U;
  127. ErrorStrings[1] = &ErrorDllPath;
  128. RtlInitUnicodeString(&ErrorDllPath,L"Default Load Path");
  129. //
  130. // need to get image name
  131. //
  132. ErrorStatus = NtRaiseHardError(
  133. (NTSTATUS)STATUS_DLL_NOT_FOUND,
  134. 2,
  135. 0x00000003,
  136. (PULONG_PTR)ErrorStrings,
  137. OptionOk,
  138. &ErrorResponse
  139. );
  140. }
  141. RtlFreeUnicodeString(&ModuleNameString_U);
  142. if (!NT_SUCCESS( Status )) {
  143. return( Status );
  144. }
  145. }
  146. else {
  147. ModuleHandle = NULL;
  148. }
  149. n = sizeof( *LoadedServerDll ) + ModuleNameString.MaximumLength;
  150. LoadedServerDll = RtlAllocateHeap( CsrHeap, MAKE_TAG( INIT_TAG ), n );
  151. if (LoadedServerDll == NULL) {
  152. if (ModuleHandle != NULL) {
  153. LdrUnloadDll( ModuleHandle );
  154. }
  155. return( STATUS_NO_MEMORY );
  156. }
  157. RtlZeroMemory( LoadedServerDll, n );
  158. LoadedServerDll->SharedStaticServerData = CsrSrvSharedSectionHeap;
  159. LoadedServerDll->Length = n;
  160. LoadedServerDll->CsrInitializationEvent = CsrInitializationEvent;
  161. LoadedServerDll->ModuleName.Length = ModuleNameString.Length;
  162. LoadedServerDll->ModuleName.MaximumLength = ModuleNameString.MaximumLength;
  163. LoadedServerDll->ModuleName.Buffer = (PCH)(LoadedServerDll+1);
  164. if (ModuleNameString.Length != 0) {
  165. strncpy( LoadedServerDll->ModuleName.Buffer,
  166. ModuleNameString.Buffer,
  167. ModuleNameString.Length
  168. );
  169. }
  170. LoadedServerDll->ServerDllIndex = ServerDllIndex;
  171. LoadedServerDll->ModuleHandle = ModuleHandle;
  172. if (ModuleHandle != NULL) {
  173. RtlInitString(
  174. &ProcedureNameString,
  175. (InitRoutineString == NULL) ? "ServerDllInitialization" : InitRoutineString);
  176. Status = LdrGetProcedureAddress( ModuleHandle,
  177. &ProcedureNameString,
  178. 0,
  179. (PVOID *) &ServerDllInitialization
  180. );
  181. }
  182. else {
  183. ServerDllInitialization = CsrServerDllInitialization;
  184. Status = STATUS_SUCCESS;
  185. }
  186. if (NT_SUCCESS( Status )) {
  187. try {
  188. Status = (*ServerDllInitialization)( LoadedServerDll );
  189. }
  190. except ( CsrUnhandledExceptionFilter( GetExceptionInformation() ) ){
  191. Status = GetExceptionCode();
  192. }
  193. if (NT_SUCCESS( Status )) {
  194. CsrTotalPerProcessDataLength += (ULONG)QUAD_ALIGN(LoadedServerDll->PerProcessDataLength);
  195. CsrLoadedServerDll[ LoadedServerDll->ServerDllIndex ] =
  196. LoadedServerDll;
  197. if ( LoadedServerDll->SharedStaticServerData != CsrSrvSharedSectionHeap ) {
  198. CsrSrvSharedStaticServerData[LoadedServerDll->ServerDllIndex] = LoadedServerDll->SharedStaticServerData;
  199. }
  200. }
  201. else {
  202. if (ModuleHandle != NULL) {
  203. LdrUnloadDll( ModuleHandle );
  204. }
  205. RtlFreeHeap( CsrHeap, 0, LoadedServerDll );
  206. }
  207. }
  208. else {
  209. if (ModuleHandle != NULL) {
  210. LdrUnloadDll( ModuleHandle );
  211. }
  212. RtlFreeHeap( CsrHeap, 0, LoadedServerDll );
  213. }
  214. return( Status );
  215. }
  216. ULONG
  217. CsrSrvClientConnect(
  218. IN OUT PCSR_API_MSG m,
  219. IN OUT PCSR_REPLY_STATUS ReplyStatus
  220. )
  221. {
  222. NTSTATUS Status;
  223. PCSR_CLIENTCONNECT_MSG a = (PCSR_CLIENTCONNECT_MSG)&m->u.ApiMessageData;
  224. PCSR_SERVER_DLL LoadedServerDll;
  225. *ReplyStatus = CsrReplyImmediate;
  226. if (a->ServerDllIndex >= CSR_MAX_SERVER_DLL) {
  227. return( (ULONG)STATUS_TOO_MANY_NAMES );
  228. }
  229. if (CsrLoadedServerDll[ a->ServerDllIndex ] == NULL) {
  230. return( (ULONG)STATUS_INVALID_PARAMETER );
  231. }
  232. if (!CsrValidateMessageBuffer(m, &a->ConnectionInformation, a->ConnectionInformationLength, sizeof(BYTE))) {
  233. return( (ULONG)STATUS_INVALID_PARAMETER );
  234. }
  235. LoadedServerDll = CsrLoadedServerDll[ a->ServerDllIndex ];
  236. if (LoadedServerDll->ConnectRoutine) {
  237. Status = (LoadedServerDll->ConnectRoutine)(
  238. (CSR_SERVER_QUERYCLIENTTHREAD())->Process,
  239. a->ConnectionInformation,
  240. &a->ConnectionInformationLength
  241. );
  242. }
  243. else {
  244. Status = STATUS_SUCCESS;
  245. }
  246. return( (ULONG)Status );
  247. }
  248. NTSTATUS
  249. CsrSrvCreateSharedSection(
  250. IN PCH SizeParameter
  251. )
  252. {
  253. NTSTATUS Status;
  254. LARGE_INTEGER SectionSize;
  255. SIZE_T ViewSize;
  256. ULONG HeapSize;
  257. ULONG AllocationAttributes;
  258. PCH s;
  259. ULONG FirstCsr = (NtCurrentPeb()->SessionId == 0);
  260. #if defined(_WIN64)
  261. PVOID BaseAddress;
  262. SIZE_T RegionSize;
  263. #endif
  264. if (SizeParameter == NULL) {
  265. return STATUS_INVALID_PARAMETER;
  266. }
  267. s = SizeParameter;
  268. while (*s) {
  269. if (*s == ',') {
  270. *s++ = '\0';
  271. break;
  272. }
  273. else {
  274. s++;
  275. }
  276. }
  277. if (!*s) {
  278. return( STATUS_INVALID_PARAMETER );
  279. }
  280. Status = RtlCharToInteger( SizeParameter,
  281. 0,
  282. &HeapSize
  283. );
  284. if (!NT_SUCCESS( Status )) {
  285. return( Status );
  286. }
  287. HeapSize = ROUND_UP_TO_PAGES( HeapSize * 1024 );
  288. CsrSrvSharedSectionSize = HeapSize;
  289. SectionSize.LowPart = CsrSrvSharedSectionSize;
  290. SectionSize.HighPart = 0;
  291. if (FirstCsr) {
  292. AllocationAttributes = SEC_BASED | SEC_RESERVE;
  293. }
  294. else {
  295. AllocationAttributes = SEC_RESERVE;
  296. }
  297. Status = NtCreateSection( &CsrSrvSharedSection,
  298. SECTION_ALL_ACCESS,
  299. (POBJECT_ATTRIBUTES) NULL,
  300. &SectionSize,
  301. PAGE_EXECUTE_READWRITE,
  302. AllocationAttributes,
  303. (HANDLE) NULL
  304. );
  305. if (!NT_SUCCESS( Status )) {
  306. return( Status );
  307. }
  308. ViewSize = 0;
  309. #if defined(_WIN64)
  310. CsrSrvSharedSectionBase = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  311. #else
  312. if (FirstCsr) {
  313. CsrSrvSharedSectionBase = NULL;
  314. }
  315. else {
  316. //
  317. // Retrieve the value of CsrSrvSharedSectionBase from registry
  318. // This is saved by the First CSRSS process and used by others
  319. //
  320. HANDLE hKey;
  321. OBJECT_ATTRIBUTES Obja;
  322. ULONG Attributes;
  323. UNICODE_STRING KeyName;
  324. Attributes = OBJ_CASE_INSENSITIVE;
  325. RtlInitUnicodeString( &KeyName, CSR_BASE_PATH );
  326. InitializeObjectAttributes(&Obja,
  327. &KeyName,
  328. Attributes,
  329. NULL,
  330. NULL);
  331. Status = NtOpenKey(&hKey,
  332. KEY_READ,
  333. &Obja);
  334. if (NT_SUCCESS(Status)) {
  335. ULONG BufferLength;
  336. ULONG ResultLength;
  337. BYTE PrivateKeyValueInformation[ sizeof( KEY_VALUE_PARTIAL_INFORMATION ) +
  338. + sizeof(DWORD) ];
  339. BufferLength = sizeof( PrivateKeyValueInformation );
  340. RtlInitUnicodeString( &KeyName, L"CsrSrvSharedSectionBase" );
  341. if (NT_SUCCESS(Status = NtQueryValueKey( hKey,
  342. &KeyName,
  343. KeyValuePartialInformation,
  344. PrivateKeyValueInformation,
  345. BufferLength,
  346. &ResultLength
  347. ))) {
  348. RtlMoveMemory( &CsrSrvSharedSectionBase,
  349. (( PKEY_VALUE_PARTIAL_INFORMATION )
  350. PrivateKeyValueInformation )->Data,
  351. (( PKEY_VALUE_PARTIAL_INFORMATION )
  352. PrivateKeyValueInformation )->DataLength
  353. );
  354. }
  355. ASSERT(NT_SUCCESS(Status));
  356. NtClose(hKey);
  357. }
  358. if (!NT_SUCCESS(Status)) {
  359. ASSERT(NT_SUCCESS(Status));
  360. return Status;
  361. }
  362. }
  363. #endif
  364. #if defined(_WIN64)
  365. // For compatibility reasons, on Win64 the csrss shared section
  366. // needs to be at an address below 2GB. Since it is difficult to
  367. // find an address in the middle of the address space that is
  368. // guaranteed to be available in all processes, the memory
  369. // manager reserves an address at the top of the 2GB range.
  370. // To use this memory, CSRSS first unreserves the memory and
  371. // then maps in the section. A possible race condition exits
  372. // if another thread tries to allocate the memory at the same
  373. // time, but this is highly unlikely since in the current NT
  374. // code the mapping and unmapping will always occure in DLL_PROCESS_ATTACH
  375. // in kernel32.dll. This code executely when the first thread
  376. // of the process is initialized, and all newly created threads
  377. // are blocked untill this code completes.
  378. BaseAddress = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  379. RegionSize = CsrSrvSharedSectionSize;
  380. Status = NtFreeVirtualMemory(NtCurrentProcess(),
  381. &BaseAddress,
  382. &RegionSize,
  383. MEM_RELEASE
  384. );
  385. if (!NT_SUCCESS(Status)) {
  386. NtClose( CsrSrvSharedSection );
  387. return Status;
  388. }
  389. #endif
  390. Status = NtMapViewOfSection( CsrSrvSharedSection,
  391. NtCurrentProcess(),
  392. &CsrSrvSharedSectionBase,
  393. 0, // Zerobits?
  394. 0,
  395. NULL,
  396. &ViewSize,
  397. ViewUnmap,
  398. MEM_TOP_DOWN,
  399. PAGE_EXECUTE_READWRITE
  400. );
  401. if (!NT_SUCCESS( Status )) {
  402. #if defined(_WIN64)
  403. // For this code to execute, either the race condition
  404. // described above occured for some unknown reason or
  405. // the memory manager or process is corrupt. With the lack
  406. // of an atom uncommit and map, the best that can be done is
  407. // try to reallocate the memory. If this fails, everything
  408. // is hopeless.
  409. BaseAddress = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  410. RegionSize = CsrSrvSharedSectionSize;
  411. NtAllocateVirtualMemory(NtCurrentProcess(),
  412. &BaseAddress,
  413. 0,
  414. &RegionSize,
  415. MEM_RESERVE,
  416. PAGE_READONLY
  417. );
  418. #endif
  419. NtClose( CsrSrvSharedSection );
  420. return( Status );
  421. }
  422. CsrSrvSharedSectionHeap = CsrSrvSharedSectionBase;
  423. if (IsTerminalServer() && FirstCsr) {
  424. //
  425. //save CsrSrvSharedSectionBase in registry for other csrs
  426. //
  427. HKEY hKey;
  428. OBJECT_ATTRIBUTES Obja;
  429. ULONG Attributes;
  430. UNICODE_STRING KeyName;
  431. DWORD dwDisposition;
  432. Attributes = OBJ_CASE_INSENSITIVE;
  433. RtlInitUnicodeString( &KeyName, CSR_BASE_PATH );
  434. InitializeObjectAttributes(&Obja,
  435. &KeyName,
  436. Attributes,
  437. NULL,
  438. NULL);
  439. Status = NtCreateKey(&hKey,
  440. KEY_WRITE,
  441. &Obja,
  442. 0,
  443. NULL,
  444. REG_OPTION_VOLATILE,
  445. &dwDisposition);
  446. if (NT_SUCCESS(Status)) {
  447. RtlInitUnicodeString( &KeyName, L"CsrSrvSharedSectionBase" );
  448. Status = NtSetValueKey(
  449. hKey,
  450. &KeyName,
  451. 0,
  452. REG_DWORD,
  453. (LPBYTE)&CsrSrvSharedSectionBase,
  454. sizeof(CsrSrvSharedSectionBase)
  455. );
  456. ASSERT(NT_SUCCESS(Status));
  457. NtClose(hKey);
  458. } else {
  459. ASSERT(NT_SUCCESS(Status));
  460. }
  461. }
  462. if (RtlCreateHeap( HEAP_ZERO_MEMORY | HEAP_CLASS_7,
  463. CsrSrvSharedSectionHeap,
  464. HeapSize,
  465. 4*1024,
  466. 0,
  467. 0
  468. ) == NULL
  469. ) {
  470. NtUnmapViewOfSection( NtCurrentProcess(),
  471. CsrSrvSharedSectionBase
  472. );
  473. NtClose( CsrSrvSharedSection );
  474. return( STATUS_NO_MEMORY );
  475. }
  476. CsrSharedBaseTag = RtlCreateTagHeap( CsrSrvSharedSectionHeap,
  477. 0,
  478. L"CSRSHR!",
  479. L"!CSRSHR\0"
  480. L"INIT\0"
  481. );
  482. CsrSrvSharedStaticServerData = (PVOID *)RtlAllocateHeap(
  483. CsrSrvSharedSectionHeap,
  484. MAKE_SHARED_TAG( SHR_INIT_TAG ),
  485. CSR_MAX_SERVER_DLL * sizeof(PVOID)
  486. );
  487. if (CsrSrvSharedStaticServerData == NULL) {
  488. return STATUS_NO_MEMORY;
  489. }
  490. NtCurrentPeb()->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase;
  491. NtCurrentPeb()->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap;
  492. NtCurrentPeb()->ReadOnlyStaticServerData = (PVOID *)CsrSrvSharedStaticServerData;
  493. return( STATUS_SUCCESS );
  494. }
  495. NTSTATUS
  496. CsrSrvAttachSharedSection(
  497. IN PCSR_PROCESS Process OPTIONAL,
  498. OUT PCSR_API_CONNECTINFO p
  499. )
  500. {
  501. NTSTATUS Status;
  502. SIZE_T ViewSize;
  503. #if defined(_WIN64)
  504. PVOID BaseAddress;
  505. SIZE_T RegionSize;
  506. #endif
  507. if (ARGUMENT_PRESENT( Process )) {
  508. #if defined(_WIN64)
  509. BaseAddress = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  510. RegionSize = CsrSrvSharedSectionSize;
  511. Status = NtFreeVirtualMemory(Process->ProcessHandle,
  512. &BaseAddress,
  513. &RegionSize,
  514. MEM_RELEASE
  515. );
  516. if(!NT_SUCCESS(Status)) {
  517. return Status;
  518. }
  519. #endif
  520. ViewSize = 0;
  521. Status = NtMapViewOfSection( CsrSrvSharedSection,
  522. Process->ProcessHandle,
  523. &CsrSrvSharedSectionBase,
  524. 0,
  525. 0,
  526. NULL,
  527. &ViewSize,
  528. ViewUnmap,
  529. SEC_NO_CHANGE,
  530. PAGE_EXECUTE_READ
  531. );
  532. if (!NT_SUCCESS( Status )) {
  533. #if defined(_WIN64)
  534. BaseAddress = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  535. RegionSize = CsrSrvSharedSectionSize;
  536. NtAllocateVirtualMemory(Process->ProcessHandle,
  537. &BaseAddress,
  538. 0,
  539. &RegionSize,
  540. MEM_RESERVE,
  541. PAGE_READONLY
  542. );
  543. #endif
  544. return( Status );
  545. }
  546. }
  547. p->SharedSectionBase = CsrSrvSharedSectionBase;
  548. p->SharedSectionHeap = CsrSrvSharedSectionHeap;
  549. p->SharedStaticServerData = CsrSrvSharedStaticServerData;
  550. return( STATUS_SUCCESS );
  551. }