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.

693 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->ModuleName.Length = ModuleNameString.Length;
  161. LoadedServerDll->ModuleName.MaximumLength = ModuleNameString.MaximumLength;
  162. LoadedServerDll->ModuleName.Buffer = (PCH)(LoadedServerDll+1);
  163. if (ModuleNameString.Length != 0) {
  164. strncpy( LoadedServerDll->ModuleName.Buffer,
  165. ModuleNameString.Buffer,
  166. ModuleNameString.Length
  167. );
  168. }
  169. LoadedServerDll->ServerDllIndex = ServerDllIndex;
  170. LoadedServerDll->ModuleHandle = ModuleHandle;
  171. if (ModuleHandle != NULL) {
  172. RtlInitString(
  173. &ProcedureNameString,
  174. (InitRoutineString == NULL) ? "ServerDllInitialization" : InitRoutineString);
  175. Status = LdrGetProcedureAddress( ModuleHandle,
  176. &ProcedureNameString,
  177. 0,
  178. (PVOID *) &ServerDllInitialization
  179. );
  180. }
  181. else {
  182. ServerDllInitialization = CsrServerDllInitialization;
  183. Status = STATUS_SUCCESS;
  184. }
  185. if (NT_SUCCESS( Status )) {
  186. try {
  187. Status = (*ServerDllInitialization)( LoadedServerDll );
  188. }
  189. except ( CsrUnhandledExceptionFilter( GetExceptionInformation() ) ){
  190. Status = GetExceptionCode();
  191. }
  192. if (NT_SUCCESS( Status )) {
  193. CsrTotalPerProcessDataLength += (ULONG)QUAD_ALIGN(LoadedServerDll->PerProcessDataLength);
  194. CsrLoadedServerDll[ LoadedServerDll->ServerDllIndex ] =
  195. LoadedServerDll;
  196. if ( LoadedServerDll->SharedStaticServerData != CsrSrvSharedSectionHeap ) {
  197. CsrSrvSharedStaticServerData[LoadedServerDll->ServerDllIndex] = LoadedServerDll->SharedStaticServerData;
  198. }
  199. }
  200. else {
  201. if (ModuleHandle != NULL) {
  202. LdrUnloadDll( ModuleHandle );
  203. }
  204. RtlFreeHeap( CsrHeap, 0, LoadedServerDll );
  205. }
  206. }
  207. else {
  208. if (ModuleHandle != NULL) {
  209. LdrUnloadDll( ModuleHandle );
  210. }
  211. RtlFreeHeap( CsrHeap, 0, LoadedServerDll );
  212. }
  213. return( Status );
  214. }
  215. ULONG
  216. CsrSrvClientConnect(
  217. IN OUT PCSR_API_MSG m,
  218. IN OUT PCSR_REPLY_STATUS ReplyStatus
  219. )
  220. {
  221. NTSTATUS Status;
  222. PCSR_CLIENTCONNECT_MSG a = (PCSR_CLIENTCONNECT_MSG)&m->u.ApiMessageData;
  223. PCSR_SERVER_DLL LoadedServerDll;
  224. *ReplyStatus = CsrReplyImmediate;
  225. if (a->ServerDllIndex >= CSR_MAX_SERVER_DLL) {
  226. return( STATUS_TOO_MANY_NAMES );
  227. }
  228. if (CsrLoadedServerDll[ a->ServerDllIndex ] == NULL) {
  229. return( STATUS_INVALID_PARAMETER );
  230. }
  231. if (!CsrValidateMessageBuffer(m, &a->ConnectionInformation, a->ConnectionInformationLength, sizeof(BYTE))) {
  232. return( STATUS_INVALID_PARAMETER );
  233. }
  234. LoadedServerDll = CsrLoadedServerDll[ a->ServerDllIndex ];
  235. if (LoadedServerDll->ConnectRoutine) {
  236. Status = (LoadedServerDll->ConnectRoutine)(
  237. (CSR_SERVER_QUERYCLIENTTHREAD())->Process,
  238. a->ConnectionInformation,
  239. &a->ConnectionInformationLength
  240. );
  241. }
  242. else {
  243. Status = STATUS_SUCCESS;
  244. }
  245. return( Status );
  246. }
  247. NTSTATUS
  248. CsrSrvCreateSharedSection(
  249. IN PCH SizeParameter
  250. )
  251. {
  252. NTSTATUS Status;
  253. LARGE_INTEGER SectionSize;
  254. SIZE_T ViewSize;
  255. ULONG HeapSize;
  256. ULONG AllocationAttributes;
  257. PCH s;
  258. ULONG FirstCsr = (NtCurrentPeb()->SessionId == 0);
  259. #if defined(_WIN64)
  260. PVOID BaseAddress;
  261. SIZE_T RegionSize;
  262. #endif
  263. if (SizeParameter == NULL) {
  264. return STATUS_INVALID_PARAMETER;
  265. }
  266. s = SizeParameter;
  267. while (*s) {
  268. if (*s == ',') {
  269. *s++ = '\0';
  270. break;
  271. }
  272. else {
  273. s++;
  274. }
  275. }
  276. if (!*s) {
  277. return( STATUS_INVALID_PARAMETER );
  278. }
  279. Status = RtlCharToInteger( SizeParameter,
  280. 0,
  281. &HeapSize
  282. );
  283. if (!NT_SUCCESS( Status )) {
  284. return( Status );
  285. }
  286. HeapSize = ROUND_UP_TO_PAGES( HeapSize * 1024 );
  287. CsrSrvSharedSectionSize = HeapSize;
  288. SectionSize.LowPart = CsrSrvSharedSectionSize;
  289. SectionSize.HighPart = 0;
  290. if (FirstCsr) {
  291. AllocationAttributes = SEC_BASED | SEC_RESERVE;
  292. }
  293. else {
  294. AllocationAttributes = SEC_RESERVE;
  295. }
  296. Status = NtCreateSection( &CsrSrvSharedSection,
  297. SECTION_ALL_ACCESS,
  298. (POBJECT_ATTRIBUTES) NULL,
  299. &SectionSize,
  300. PAGE_EXECUTE_READWRITE,
  301. AllocationAttributes,
  302. (HANDLE) NULL
  303. );
  304. if (!NT_SUCCESS( Status )) {
  305. return( Status );
  306. }
  307. ViewSize = 0;
  308. #if defined(_WIN64)
  309. CsrSrvSharedSectionBase = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  310. #else
  311. if (FirstCsr) {
  312. CsrSrvSharedSectionBase = NULL;
  313. }
  314. else {
  315. //
  316. // Retrieve the value of CsrSrvSharedSectionBase from registry
  317. // This is saved by the First CSRSS process and used by others
  318. //
  319. HANDLE hKey;
  320. OBJECT_ATTRIBUTES Obja;
  321. ULONG Attributes;
  322. UNICODE_STRING KeyName;
  323. Attributes = OBJ_CASE_INSENSITIVE;
  324. RtlInitUnicodeString( &KeyName, CSR_BASE_PATH );
  325. InitializeObjectAttributes(&Obja,
  326. &KeyName,
  327. Attributes,
  328. NULL,
  329. NULL);
  330. Status = NtOpenKey(&hKey,
  331. KEY_READ,
  332. &Obja);
  333. if (NT_SUCCESS(Status)) {
  334. ULONG BufferLength;
  335. ULONG ResultLength;
  336. BYTE PrivateKeyValueInformation[ sizeof( KEY_VALUE_PARTIAL_INFORMATION ) +
  337. + sizeof(DWORD) ];
  338. BufferLength = sizeof( PrivateKeyValueInformation );
  339. RtlInitUnicodeString( &KeyName, L"CsrSrvSharedSectionBase" );
  340. if (NT_SUCCESS(Status = NtQueryValueKey( hKey,
  341. &KeyName,
  342. KeyValuePartialInformation,
  343. PrivateKeyValueInformation,
  344. BufferLength,
  345. &ResultLength
  346. ))) {
  347. RtlCopyMemory( &CsrSrvSharedSectionBase,
  348. (( PKEY_VALUE_PARTIAL_INFORMATION )
  349. PrivateKeyValueInformation )->Data,
  350. (( PKEY_VALUE_PARTIAL_INFORMATION )
  351. PrivateKeyValueInformation )->DataLength
  352. );
  353. }
  354. ASSERT(NT_SUCCESS(Status));
  355. NtClose(hKey);
  356. }
  357. if (!NT_SUCCESS(Status)) {
  358. ASSERT(NT_SUCCESS(Status));
  359. return Status;
  360. }
  361. }
  362. #endif
  363. #if defined(_WIN64)
  364. //
  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 exists
  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 occur in DLL_PROCESS_ATTACH
  375. // in kernel32.dll. This code executes when the first thread
  376. // of the process is initialized, and all newly created threads
  377. // are blocked untill this code completes.
  378. //
  379. BaseAddress = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  380. RegionSize = CsrSrvSharedSectionSize;
  381. Status = NtFreeVirtualMemory(NtCurrentProcess(),
  382. &BaseAddress,
  383. &RegionSize,
  384. MEM_RELEASE
  385. );
  386. if (!NT_SUCCESS(Status)) {
  387. NtClose( CsrSrvSharedSection );
  388. return Status;
  389. }
  390. #endif
  391. Status = NtMapViewOfSection( CsrSrvSharedSection,
  392. NtCurrentProcess(),
  393. &CsrSrvSharedSectionBase,
  394. 0, // Zerobits?
  395. 0,
  396. NULL,
  397. &ViewSize,
  398. ViewUnmap,
  399. MEM_TOP_DOWN,
  400. PAGE_EXECUTE_READWRITE
  401. );
  402. if (!NT_SUCCESS( Status )) {
  403. #if defined(_WIN64)
  404. //
  405. // For this code to execute, either the race condition
  406. // described above occured for some unknown reason or
  407. // the memory manager or process is corrupt. With the lack
  408. // of an atomic uncommit and map, the best that can be done is
  409. // try to reallocate the memory. If this fails, everything
  410. // is hopeless.
  411. //
  412. BaseAddress = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  413. RegionSize = CsrSrvSharedSectionSize;
  414. NtAllocateVirtualMemory(NtCurrentProcess(),
  415. &BaseAddress,
  416. 0,
  417. &RegionSize,
  418. MEM_RESERVE,
  419. PAGE_READONLY
  420. );
  421. #endif
  422. NtClose( CsrSrvSharedSection );
  423. return( Status );
  424. }
  425. CsrSrvSharedSectionHeap = CsrSrvSharedSectionBase;
  426. if (IsTerminalServer() && FirstCsr) {
  427. //
  428. //save CsrSrvSharedSectionBase in registry for other csrs
  429. //
  430. HKEY hKey;
  431. OBJECT_ATTRIBUTES Obja;
  432. ULONG Attributes;
  433. UNICODE_STRING KeyName;
  434. DWORD dwDisposition;
  435. Attributes = OBJ_CASE_INSENSITIVE;
  436. RtlInitUnicodeString( &KeyName, CSR_BASE_PATH );
  437. InitializeObjectAttributes(&Obja,
  438. &KeyName,
  439. Attributes,
  440. NULL,
  441. NULL);
  442. Status = NtCreateKey(&hKey,
  443. KEY_WRITE,
  444. &Obja,
  445. 0,
  446. NULL,
  447. REG_OPTION_VOLATILE,
  448. &dwDisposition);
  449. if (NT_SUCCESS(Status)) {
  450. RtlInitUnicodeString( &KeyName, L"CsrSrvSharedSectionBase" );
  451. Status = NtSetValueKey(
  452. hKey,
  453. &KeyName,
  454. 0,
  455. REG_DWORD,
  456. (LPBYTE)&CsrSrvSharedSectionBase,
  457. sizeof(CsrSrvSharedSectionBase)
  458. );
  459. ASSERT(NT_SUCCESS(Status));
  460. NtClose(hKey);
  461. } else {
  462. ASSERT(NT_SUCCESS(Status));
  463. }
  464. }
  465. if (RtlCreateHeap( HEAP_ZERO_MEMORY | HEAP_CLASS_7,
  466. CsrSrvSharedSectionHeap,
  467. HeapSize,
  468. 4*1024,
  469. 0,
  470. 0
  471. ) == NULL
  472. ) {
  473. NtUnmapViewOfSection( NtCurrentProcess(),
  474. CsrSrvSharedSectionBase
  475. );
  476. NtClose( CsrSrvSharedSection );
  477. return( STATUS_NO_MEMORY );
  478. }
  479. CsrSharedBaseTag = RtlCreateTagHeap( CsrSrvSharedSectionHeap,
  480. 0,
  481. L"CSRSHR!",
  482. L"!CSRSHR\0"
  483. L"INIT\0"
  484. );
  485. CsrSrvSharedStaticServerData = (PVOID *)RtlAllocateHeap(
  486. CsrSrvSharedSectionHeap,
  487. MAKE_SHARED_TAG( SHR_INIT_TAG ),
  488. CSR_MAX_SERVER_DLL * sizeof(PVOID)
  489. );
  490. if (CsrSrvSharedStaticServerData == NULL) {
  491. return STATUS_NO_MEMORY;
  492. }
  493. NtCurrentPeb()->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase;
  494. NtCurrentPeb()->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap;
  495. NtCurrentPeb()->ReadOnlyStaticServerData = (PVOID *)CsrSrvSharedStaticServerData;
  496. return( STATUS_SUCCESS );
  497. }
  498. NTSTATUS
  499. CsrSrvAttachSharedSection(
  500. IN PCSR_PROCESS Process OPTIONAL,
  501. OUT PCSR_API_CONNECTINFO p
  502. )
  503. {
  504. NTSTATUS Status;
  505. SIZE_T ViewSize;
  506. #if defined(_WIN64)
  507. PVOID BaseAddress;
  508. SIZE_T RegionSize;
  509. #endif
  510. if (ARGUMENT_PRESENT( Process )) {
  511. #if defined(_WIN64)
  512. BaseAddress = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  513. RegionSize = CsrSrvSharedSectionSize;
  514. Status = NtFreeVirtualMemory(Process->ProcessHandle,
  515. &BaseAddress,
  516. &RegionSize,
  517. MEM_RELEASE
  518. );
  519. if(!NT_SUCCESS(Status)) {
  520. return Status;
  521. }
  522. #endif
  523. ViewSize = 0;
  524. Status = NtMapViewOfSection( CsrSrvSharedSection,
  525. Process->ProcessHandle,
  526. &CsrSrvSharedSectionBase,
  527. 0,
  528. 0,
  529. NULL,
  530. &ViewSize,
  531. ViewUnmap,
  532. SEC_NO_CHANGE,
  533. PAGE_EXECUTE_READ
  534. );
  535. if (!NT_SUCCESS( Status )) {
  536. #if defined(_WIN64)
  537. BaseAddress = (PVOID)CSR_SYSTEM_SHARED_ADDRESS;
  538. RegionSize = CsrSrvSharedSectionSize;
  539. NtAllocateVirtualMemory(Process->ProcessHandle,
  540. &BaseAddress,
  541. 0,
  542. &RegionSize,
  543. MEM_RESERVE,
  544. PAGE_READONLY
  545. );
  546. #endif
  547. return( Status );
  548. }
  549. }
  550. p->SharedSectionBase = CsrSrvSharedSectionBase;
  551. p->SharedSectionHeap = CsrSrvSharedSectionHeap;
  552. p->SharedStaticServerData = CsrSrvSharedStaticServerData;
  553. return( STATUS_SUCCESS );
  554. }