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.

1379 lines
44 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. apireqst.c
  5. Abstract:
  6. This module contains the Request thread procedure for the Server side
  7. of the Client-Server Runtime Subsystem.
  8. Author:
  9. Steve Wood (stevewo) 8-Oct-1990
  10. Revision History:
  11. --*/
  12. #include "csrsrv.h"
  13. #include <ntos.h>
  14. NTSTATUS
  15. CsrApiHandleConnectionRequest(
  16. IN PCSR_API_MSG Message
  17. );
  18. EXCEPTION_DISPOSITION
  19. CsrUnhandledExceptionFilter(
  20. struct _EXCEPTION_POINTERS *ExceptionInfo
  21. );
  22. #if DBG
  23. ULONG GetNextTrackIndex(
  24. VOID)
  25. {
  26. ULONG NextIndex;
  27. RtlEnterCriticalSection(&CsrTrackLpcLock);
  28. NextIndex = LpcTrackIndex++ % ARRAY_SIZE(LpcTrackNodes);
  29. RtlLeaveCriticalSection(&CsrTrackLpcLock);
  30. //
  31. // Do some initialization of the slot we're going to be working with.
  32. //
  33. RtlZeroMemory(&LpcTrackNodes[NextIndex], sizeof(LPC_TRACK_NODE));
  34. LpcTrackNodes[NextIndex].Status = (NTSTATUS)-1;
  35. LpcTrackNodes[NextIndex].ClientCid = NtCurrentTeb()->RealClientId;
  36. LpcTrackNodes[NextIndex].ServerCid = NtCurrentTeb()->ClientId;
  37. return NextIndex;
  38. }
  39. #endif
  40. ULONG CsrpDynamicThreadTotal;
  41. ULONG CsrpStaticThreadCount;
  42. PCSR_THREAD CsrConnectToUser(
  43. VOID)
  44. {
  45. static BOOLEAN (*ClientThreadSetupRoutine)(VOID) = NULL;
  46. NTSTATUS Status;
  47. ANSI_STRING DllName;
  48. UNICODE_STRING DllName_U;
  49. STRING ProcedureName;
  50. HANDLE UserClientModuleHandle;
  51. PTEB Teb;
  52. PCSR_THREAD Thread;
  53. BOOLEAN fConnected;
  54. PVOID TempClientThreadSetupRoutine;
  55. if (ClientThreadSetupRoutine == NULL) {
  56. RtlInitAnsiString(&DllName, "user32");
  57. Status = RtlAnsiStringToUnicodeString(&DllName_U, &DllName, TRUE);
  58. if (!NT_SUCCESS(Status)) {
  59. return NULL;
  60. }
  61. Status = LdrGetDllHandle(
  62. UNICODE_NULL,
  63. NULL,
  64. &DllName_U,
  65. (PVOID *)&UserClientModuleHandle
  66. );
  67. RtlFreeUnicodeString(&DllName_U);
  68. if ( NT_SUCCESS(Status) ) {
  69. RtlInitString(&ProcedureName,"ClientThreadSetup");
  70. Status = LdrGetProcedureAddress(
  71. UserClientModuleHandle,
  72. &ProcedureName,
  73. 0L,
  74. &TempClientThreadSetupRoutine
  75. );
  76. if (!NT_SUCCESS(Status)){
  77. return NULL;
  78. }
  79. InterlockedCompareExchangePointer((PVOID *)&ClientThreadSetupRoutine, TempClientThreadSetupRoutine, NULL);
  80. } else {
  81. return NULL;
  82. }
  83. }
  84. try {
  85. fConnected = ClientThreadSetupRoutine();
  86. } except (EXCEPTION_EXECUTE_HANDLER) {
  87. fConnected = FALSE;
  88. }
  89. if (!fConnected) {
  90. IF_DEBUG {
  91. DbgPrint("CSRSS: CsrConnectToUser failed\n");
  92. }
  93. return NULL;
  94. }
  95. /*
  96. * Set up CSR_THREAD pointer in the TEB
  97. */
  98. Teb = NtCurrentTeb();
  99. AcquireProcessStructureLock();
  100. Thread = CsrLocateServerThread(&Teb->ClientId);
  101. ReleaseProcessStructureLock();
  102. if (Thread) {
  103. Teb->CsrClientThread = Thread;
  104. }
  105. return Thread;
  106. }
  107. NTSTATUS
  108. CsrpCheckRequestThreads(VOID)
  109. {
  110. //
  111. // See if we need to create a new thread for api requests.
  112. //
  113. // Don't create a thread if we're in the middle of debugger
  114. // initialization, which would cause the thread to be
  115. // lost to the debugger.
  116. //
  117. // If we are not a dynamic api request thread, then decrement
  118. // the static thread count. If it underflows, then create a temporary
  119. // request thread
  120. //
  121. if (!InterlockedDecrement(&CsrpStaticThreadCount)) {
  122. if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads) {
  123. HANDLE QuickThread;
  124. CLIENT_ID ClientId;
  125. NTSTATUS CreateStatus;
  126. NTSTATUS Status1;
  127. //
  128. // If we are ready to create quick threads, then create one
  129. //
  130. CreateStatus = RtlCreateUserThread(NtCurrentProcess(),
  131. NULL,
  132. TRUE,
  133. 0,
  134. 0,
  135. 0,
  136. CsrApiRequestThread,
  137. NULL,
  138. &QuickThread,
  139. &ClientId);
  140. if (NT_SUCCESS(CreateStatus)) {
  141. InterlockedIncrement(&CsrpStaticThreadCount);
  142. InterlockedIncrement(&CsrpDynamicThreadTotal);
  143. if (CsrAddStaticServerThread(QuickThread, &ClientId, CSR_STATIC_API_THREAD)) {
  144. NtResumeThread(QuickThread, NULL);
  145. } else {
  146. InterlockedDecrement(&CsrpStaticThreadCount);
  147. InterlockedDecrement(&CsrpDynamicThreadTotal);
  148. Status1 = NtTerminateThread (QuickThread, 0);
  149. ASSERT (NT_SUCCESS (Status1));
  150. Status1 = NtWaitForSingleObject (QuickThread, FALSE, NULL);
  151. ASSERT (NT_SUCCESS (Status1));
  152. RtlFreeUserThreadStack (NtCurrentProcess (), QuickThread);
  153. Status1 = NtClose (QuickThread);
  154. ASSERT (NT_SUCCESS (Status1));
  155. return STATUS_UNSUCCESSFUL;
  156. }
  157. }
  158. }
  159. }
  160. return STATUS_SUCCESS;
  161. }
  162. VOID
  163. ReplyToMessage (
  164. IN HANDLE Port,
  165. IN PPORT_MESSAGE m
  166. )
  167. {
  168. NTSTATUS Status;
  169. LARGE_INTEGER DelayTime;
  170. while (1) {
  171. Status = NtReplyPort (CsrApiPort,
  172. (PPORT_MESSAGE)m);
  173. if (Status == STATUS_NO_MEMORY) {
  174. KdPrint (("CSRSS: Failed to reply to calling thread, retrying.\n"));
  175. DelayTime.QuadPart = Int32x32To64 (5000, -10000);
  176. NtDelayExecution (FALSE, &DelayTime);
  177. continue;
  178. }
  179. break;
  180. }
  181. }
  182. typedef struct _QUEUED_HARD_ERROR {
  183. LIST_ENTRY ListEntry;
  184. PCSR_THREAD Thread;
  185. HARDERROR_MSG m;
  186. } QUEUED_HARD_ERROR, *PQUEUED_HARD_ERROR;
  187. #define MAX_CONCURRENT_HARD_ERRORS 3
  188. #define MAX_OUTSTANDING_HARD_ERRORS 100
  189. VOID
  190. QueueHardError (
  191. IN PCSR_THREAD Thread,
  192. IN PHARDERROR_MSG m,
  193. IN ULONG ml
  194. )
  195. {
  196. static LONG OutstandingHardErrors = 0;
  197. static LIST_ENTRY QueuedList = {&QueuedList, &QueuedList};
  198. PQUEUED_HARD_ERROR qm = NULL;
  199. NTSTATUS Status;
  200. LONG OldCount;
  201. ULONG i;
  202. PCSR_SERVER_DLL LoadedServerDll;
  203. //
  204. // Reference the thread if there is one as the hard error routines dereference in an async routine sometimes.
  205. //
  206. if (Thread != NULL) {
  207. CsrReferenceThread (Thread);
  208. }
  209. //
  210. // Mark the message as unhandled
  211. //
  212. m->Response = (ULONG)ResponseNotHandled;
  213. while (1) {
  214. OldCount = OutstandingHardErrors;
  215. //
  216. // If we already have a lot of hard errors active then queue this new one
  217. //
  218. if (OldCount >= MAX_CONCURRENT_HARD_ERRORS) {
  219. if (qm == NULL) {
  220. //
  221. // If too many hard errors are queued already. Drop this one.
  222. // We do this check while not owning a lock but this doesn';t matter.
  223. // We will stopp roughly at this level and it doesn't matter if we are a little off.
  224. //
  225. if (OldCount <= MAX_OUTSTANDING_HARD_ERRORS) {
  226. qm = RtlAllocateHeap (CsrHeap, 0, ml + FIELD_OFFSET (QUEUED_HARD_ERROR, m));
  227. }
  228. if (qm == NULL) {
  229. ReplyToMessage (CsrApiPort, (PPORT_MESSAGE)m);
  230. if (Thread != NULL) {
  231. CsrDereferenceThread (Thread);
  232. }
  233. return;
  234. }
  235. RtlCopyMemory (&qm->m, m, ml);
  236. qm->Thread = Thread;
  237. }
  238. AcquireProcessStructureLock ();
  239. if (InterlockedCompareExchange (&OutstandingHardErrors, OldCount + 1, OldCount) == OldCount) {
  240. InsertTailList (&QueuedList, &qm->ListEntry);
  241. qm = NULL;
  242. }
  243. ReleaseProcessStructureLock ();
  244. if (qm == NULL) {
  245. return;
  246. }
  247. } else if (InterlockedCompareExchange (&OutstandingHardErrors, OldCount + 1, OldCount) == OldCount) {
  248. while (1) {
  249. //
  250. // Only call the handler if there are other
  251. // request threads available to handle
  252. // message processing.
  253. //
  254. CsrpCheckRequestThreads();
  255. if (CsrpStaticThreadCount > 0) {
  256. for (i = 0; i < CSR_MAX_SERVER_DLL; i++) {
  257. LoadedServerDll = CsrLoadedServerDll[i];
  258. if (LoadedServerDll && LoadedServerDll->HardErrorRoutine) {
  259. (*LoadedServerDll->HardErrorRoutine)(Thread, m);
  260. if (m->Response != (ULONG)ResponseNotHandled) {
  261. break;
  262. }
  263. }
  264. }
  265. }
  266. InterlockedIncrement (&CsrpStaticThreadCount);
  267. if (m->Response != (ULONG)-1) {
  268. ReplyToMessage (CsrApiPort, (PPORT_MESSAGE)m);
  269. //
  270. // Release the thread reference if there was one.
  271. //
  272. if (Thread != NULL) {
  273. CsrDereferenceThread (Thread);
  274. }
  275. }
  276. if (qm != NULL) {
  277. RtlFreeHeap (CsrHeap, 0, qm);
  278. qm = NULL;
  279. }
  280. OldCount = InterlockedDecrement (&OutstandingHardErrors);
  281. if (OldCount < MAX_CONCURRENT_HARD_ERRORS) {
  282. return;
  283. }
  284. AcquireProcessStructureLock ();
  285. ASSERT (!IsListEmpty (&QueuedList));
  286. qm = CONTAINING_RECORD (RemoveHeadList (&QueuedList), QUEUED_HARD_ERROR, ListEntry);
  287. ReleaseProcessStructureLock ();
  288. if (qm == NULL) {
  289. return;
  290. }
  291. m = &qm->m;
  292. Thread = qm->Thread;
  293. }
  294. }
  295. }
  296. }
  297. NTSTATUS
  298. CsrApiRequestThread(
  299. IN PVOID Parameter)
  300. {
  301. NTSTATUS Status;
  302. PCSR_PROCESS Process;
  303. PCSR_THREAD Thread;
  304. PCSR_THREAD MyThread;
  305. CSR_API_MSG ReceiveMsg;
  306. PCSR_API_MSG ReplyMsg;
  307. HANDLE ReplyPortHandle;
  308. PCSR_SERVER_DLL LoadedServerDll;
  309. PTEB Teb;
  310. ULONG ServerDllIndex;
  311. ULONG ApiTableIndex;
  312. CSR_REPLY_STATUS ReplyStatus;
  313. ULONG i;
  314. PVOID PortContext;
  315. USHORT MessageType;
  316. ULONG ApiNumber;
  317. PLPC_CLIENT_DIED_MSG CdMsg;
  318. #if DBG
  319. ULONG Index;
  320. #endif
  321. Teb = NtCurrentTeb();
  322. ReplyMsg = NULL;
  323. ReplyPortHandle = CsrApiPort;
  324. //
  325. // Try to connect to USER.
  326. //
  327. while (!CsrConnectToUser()) {
  328. LARGE_INTEGER TimeOut;
  329. //
  330. // The connect failed. The best thing to do is sleep for
  331. // 30 seconds and retry the connect. Clear the
  332. // initialized bit in the TEB so the retry can
  333. // succeed.
  334. //
  335. Teb->Win32ClientInfo[0] = 0;
  336. TimeOut.QuadPart = Int32x32To64(30000, -10000);
  337. NtDelayExecution(FALSE, &TimeOut);
  338. }
  339. MyThread = Teb->CsrClientThread;
  340. if (Parameter) {
  341. Status = NtSetEvent((HANDLE)Parameter, NULL);
  342. ASSERT(NT_SUCCESS(Status));
  343. InterlockedIncrement(&CsrpStaticThreadCount);
  344. InterlockedIncrement(&CsrpDynamicThreadTotal);
  345. }
  346. while (TRUE) {
  347. NtCurrentTeb()->RealClientId = NtCurrentTeb()->ClientId;
  348. ASSERT(NtCurrentTeb()->CountOfOwnedCriticalSections == 0);
  349. while (1) {
  350. Status = NtReplyWaitReceivePort(CsrApiPort,
  351. &PortContext,
  352. (PPORT_MESSAGE)ReplyMsg,
  353. (PPORT_MESSAGE)&ReceiveMsg);
  354. if (Status == STATUS_NO_MEMORY) {
  355. LARGE_INTEGER DelayTime;
  356. if (ReplyMsg != NULL) {
  357. KdPrint (("CSRSS: Failed to reply to calling thread, retrying.\n"));
  358. }
  359. DelayTime.QuadPart = Int32x32To64 (5000, -10000);
  360. NtDelayExecution (FALSE, &DelayTime);
  361. continue;
  362. }
  363. break;
  364. }
  365. if (Status != STATUS_SUCCESS) {
  366. if (NT_SUCCESS(Status)) {
  367. #if DBG
  368. DbgPrint("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status);
  369. #endif
  370. continue; // Try again if alerted or a failure
  371. }
  372. IF_DEBUG {
  373. if (Status == STATUS_INVALID_CID ||
  374. Status == STATUS_UNSUCCESSFUL ||
  375. (Status == STATUS_INVALID_HANDLE &&
  376. ReplyPortHandle != CsrApiPort
  377. )
  378. ) {
  379. }
  380. else {
  381. DbgPrint( "CSRSS: ReceivePort failed - Status == %X\n", Status );
  382. DbgPrint( "CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPortHandle, CsrApiPort );
  383. }
  384. }
  385. //
  386. // Ignore if client went away.
  387. //
  388. ReplyMsg = NULL;
  389. ReplyPortHandle = CsrApiPort;
  390. continue;
  391. }
  392. ASSERT(ReceiveMsg.h.u1.s1.TotalLength >= sizeof (PORT_MESSAGE));
  393. ASSERT(sizeof (ReceiveMsg) > ReceiveMsg.h.u1.s1.TotalLength);
  394. RtlZeroMemory (((PUCHAR)&ReceiveMsg) + ReceiveMsg.h.u1.s1.TotalLength, sizeof (ReceiveMsg) - ReceiveMsg.h.u1.s1.TotalLength);
  395. NtCurrentTeb()->RealClientId = ReceiveMsg.h.ClientId;
  396. MessageType = ReceiveMsg.h.u2.s2.Type;
  397. #if DBG
  398. Index = GetNextTrackIndex();
  399. LpcTrackNodes[Index].MessageType = MessageType;
  400. LpcTrackNodes[Index].ClientCid = ReceiveMsg.h.ClientId;
  401. LpcTrackNodes[Index].Message = ReceiveMsg.h;
  402. #endif
  403. //
  404. // Check to see if this is a connection request and handle.
  405. //
  406. if (MessageType == LPC_CONNECTION_REQUEST) {
  407. NTSTATUS ConnectionStatus;
  408. ConnectionStatus = CsrApiHandleConnectionRequest(&ReceiveMsg);
  409. #if DBG
  410. LpcTrackNodes[Index].Status = ConnectionStatus;
  411. #endif
  412. ReplyPortHandle = CsrApiPort;
  413. ReplyMsg = NULL;
  414. continue;
  415. }
  416. //
  417. // Lookup the client thread structure using the client id
  418. //
  419. AcquireProcessStructureLock();
  420. Thread = CsrLocateThreadByClientId(&Process, &ReceiveMsg.h.ClientId);
  421. if (!Thread) {
  422. ReleaseProcessStructureLock();
  423. if (MessageType == LPC_EXCEPTION) {
  424. ReplyMsg = &ReceiveMsg;
  425. ReplyPortHandle = CsrApiPort;
  426. ReplyMsg->ReturnValue = DBG_CONTINUE;
  427. } else if (MessageType == LPC_CLIENT_DIED ||
  428. MessageType == LPC_PORT_CLOSED) {
  429. ReplyPortHandle = CsrApiPort;
  430. ReplyMsg = NULL;
  431. } else {
  432. //
  433. // This must be a non-csr thread calling us. Tell it to get
  434. // lost (unless this is a hard error).
  435. //
  436. if (MessageType == LPC_ERROR_EVENT) {
  437. PHARDERROR_MSG m;
  438. m = (PHARDERROR_MSG)&ReceiveMsg;
  439. QueueHardError (NULL, m, sizeof (ReceiveMsg));
  440. ReplyPortHandle = CsrApiPort;
  441. ReplyMsg = NULL;
  442. continue;
  443. } else {
  444. ReplyPortHandle = CsrApiPort;
  445. if (MessageType == LPC_REQUEST) {
  446. ReplyMsg = &ReceiveMsg;
  447. ReplyMsg->ReturnValue = STATUS_ILLEGAL_FUNCTION;
  448. } else if (MessageType == LPC_DATAGRAM) {
  449. //
  450. // If this is a datagram, make the api call
  451. //
  452. //
  453. // There is no thread so there can't be a mapped section for it.
  454. // Make sure the capture stuff is off.
  455. //
  456. ReceiveMsg.CaptureBuffer = NULL;
  457. ApiNumber = ReceiveMsg.ApiNumber;
  458. ServerDllIndex =
  459. CSR_APINUMBER_TO_SERVERDLLINDEX(ApiNumber);
  460. if (ServerDllIndex >= CSR_MAX_SERVER_DLL ||
  461. (LoadedServerDll = CsrLoadedServerDll[ServerDllIndex]) == NULL) {
  462. IF_DEBUG {
  463. DbgPrint( "CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
  464. ServerDllIndex, LoadedServerDll
  465. );
  466. DbgBreakPoint();
  467. }
  468. ReplyPortHandle = CsrApiPort;
  469. ReplyMsg = NULL;
  470. continue;
  471. } else {
  472. ApiTableIndex =
  473. CSR_APINUMBER_TO_APITABLEINDEX( ApiNumber ) -
  474. LoadedServerDll->ApiNumberBase;
  475. if (ApiTableIndex >= LoadedServerDll->MaxApiNumber - LoadedServerDll->ApiNumberBase) {
  476. IF_DEBUG {
  477. DbgPrint( "CSRSS: %lx is invalid ApiTableIndex for %Z\n",
  478. LoadedServerDll->ApiNumberBase + ApiTableIndex,
  479. &LoadedServerDll->ModuleName
  480. );
  481. }
  482. ReplyPortHandle = CsrApiPort;
  483. ReplyMsg = NULL;
  484. continue;
  485. }
  486. }
  487. #if DBG
  488. IF_CSR_DEBUG( LPC ) {
  489. DbgPrint( "[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
  490. NtCurrentTeb()->ClientId.UniqueThread,
  491. ReceiveMsg.h.ClientId.UniqueProcess,
  492. ReceiveMsg.h.ClientId.UniqueThread,
  493. LoadedServerDll->ApiNameTable[ ApiTableIndex ],
  494. Thread
  495. );
  496. }
  497. #endif
  498. ReceiveMsg.ReturnValue = STATUS_SUCCESS;
  499. CsrpCheckRequestThreads();
  500. ReplyPortHandle = CsrApiPort;
  501. ReplyMsg = NULL;
  502. try {
  503. (*(LoadedServerDll->ApiDispatchTable[ApiTableIndex]))(
  504. &ReceiveMsg,
  505. &ReplyStatus);
  506. } except (CsrUnhandledExceptionFilter(GetExceptionInformation())) {
  507. }
  508. InterlockedIncrement(&CsrpStaticThreadCount);
  509. } else {
  510. ReplyMsg = NULL;
  511. }
  512. }
  513. }
  514. continue;
  515. }
  516. //
  517. // See if this is a client died message. If so,
  518. // callout and then teardown thread/process structures.
  519. // this is how ExitThread is seen by CSR.
  520. //
  521. // LPC_CLIENT_DIED is caused by ExitProcess. ExitProcess
  522. // calls TerminateProcess, which terminates all of the process's
  523. // threads except the caller. this termination generates
  524. // LPC_CLIENT_DIED.
  525. //
  526. ReplyPortHandle = CsrApiPort;
  527. if (MessageType != LPC_REQUEST) {
  528. if (MessageType == LPC_CLIENT_DIED) {
  529. CdMsg = (PLPC_CLIENT_DIED_MSG)&ReceiveMsg;
  530. if (CdMsg->CreateTime.QuadPart == Thread->CreateTime.QuadPart) {
  531. ReplyPortHandle = Thread->Process->ClientPort;
  532. CsrLockedReferenceThread(Thread);
  533. Status = CsrDestroyThread(&ReceiveMsg.h.ClientId);
  534. //
  535. // if this thread is it, then we also need to dereference
  536. // the process since it will not be going through the
  537. // normal destroy process path.
  538. //
  539. if (Process->ThreadCount == 1) {
  540. CsrDestroyProcess(&Thread->ClientId, 0);
  541. }
  542. CsrLockedDereferenceThread(Thread);
  543. }
  544. ReleaseProcessStructureLock();
  545. ReplyPortHandle = CsrApiPort;
  546. ReplyMsg = NULL;
  547. continue;
  548. }
  549. CsrLockedReferenceThread(Thread);
  550. ReleaseProcessStructureLock();
  551. //
  552. // If this is an exception message, terminate the process.
  553. //
  554. if (MessageType == LPC_EXCEPTION) {
  555. PDBGKM_APIMSG m;
  556. NtTerminateProcess(Process->ProcessHandle, STATUS_ABANDONED);
  557. Status = CsrDestroyProcess(&ReceiveMsg.h.ClientId, STATUS_ABANDONED);
  558. m = (PDBGKM_APIMSG)&ReceiveMsg;
  559. m->ReturnedStatus = DBG_CONTINUE;
  560. ReplyPortHandle = CsrApiPort;
  561. ReplyMsg = &ReceiveMsg;
  562. CsrDereferenceThread(Thread);
  563. continue;
  564. }
  565. //
  566. // If this is a hard error message, return to caller.
  567. //
  568. if (MessageType == LPC_ERROR_EVENT) {
  569. PHARDERROR_MSG m;
  570. m = (PHARDERROR_MSG)&ReceiveMsg;
  571. QueueHardError (Thread, m, sizeof (ReceiveMsg));
  572. }
  573. CsrDereferenceThread (Thread);
  574. ReplyPortHandle = CsrApiPort;
  575. ReplyMsg = NULL;
  576. continue;
  577. }
  578. CsrLockedReferenceThread(Thread);
  579. ReleaseProcessStructureLock();
  580. ApiNumber = ReceiveMsg.ApiNumber;
  581. ServerDllIndex =
  582. CSR_APINUMBER_TO_SERVERDLLINDEX( ApiNumber );
  583. if (ServerDllIndex >= CSR_MAX_SERVER_DLL ||
  584. (LoadedServerDll = CsrLoadedServerDll[ ServerDllIndex ]) == NULL
  585. ) {
  586. IF_DEBUG {
  587. DbgPrint( "CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
  588. ServerDllIndex, LoadedServerDll
  589. );
  590. SafeBreakPoint();
  591. }
  592. ReplyMsg = &ReceiveMsg;
  593. ReplyPortHandle = CsrApiPort;
  594. ReplyMsg->ReturnValue = STATUS_ILLEGAL_FUNCTION;
  595. CsrDereferenceThread(Thread);
  596. continue;
  597. } else {
  598. ApiTableIndex =
  599. CSR_APINUMBER_TO_APITABLEINDEX( ApiNumber ) -
  600. LoadedServerDll->ApiNumberBase;
  601. if (ApiTableIndex >= LoadedServerDll->MaxApiNumber - LoadedServerDll->ApiNumberBase) {
  602. IF_DEBUG {
  603. DbgPrint( "CSRSS: %lx is invalid ApiTableIndex for %Z\n",
  604. LoadedServerDll->ApiNumberBase + ApiTableIndex,
  605. &LoadedServerDll->ModuleName
  606. );
  607. SafeBreakPoint();
  608. }
  609. ReplyMsg = &ReceiveMsg;
  610. ReplyPortHandle = CsrApiPort;
  611. ReplyMsg->ReturnValue = STATUS_ILLEGAL_FUNCTION;
  612. CsrDereferenceThread(Thread);
  613. continue;
  614. }
  615. }
  616. #if DBG
  617. IF_CSR_DEBUG( LPC ) {
  618. DbgPrint( "[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
  619. NtCurrentTeb()->ClientId.UniqueThread,
  620. ReceiveMsg.h.ClientId.UniqueProcess,
  621. ReceiveMsg.h.ClientId.UniqueThread,
  622. LoadedServerDll->ApiNameTable[ ApiTableIndex ],
  623. Thread
  624. );
  625. }
  626. #endif
  627. ReplyMsg = &ReceiveMsg;
  628. ReplyPortHandle = Thread->Process->ClientPort;
  629. ReceiveMsg.ReturnValue = STATUS_SUCCESS;
  630. if (ReceiveMsg.CaptureBuffer != NULL) {
  631. if (!CsrCaptureArguments( Thread, &ReceiveMsg )) {
  632. CsrDereferenceThread(Thread);
  633. goto failit;
  634. }
  635. }
  636. Teb->CsrClientThread = (PVOID)Thread;
  637. ReplyStatus = CsrReplyImmediate;
  638. CsrpCheckRequestThreads ();
  639. try {
  640. ReplyMsg->ReturnValue =
  641. (*(LoadedServerDll->ApiDispatchTable[ ApiTableIndex ]))(&ReceiveMsg,
  642. &ReplyStatus);
  643. } except (CsrUnhandledExceptionFilter (GetExceptionInformation ())){
  644. //
  645. // We don't get here as the filter makes this a fatal error
  646. //
  647. }
  648. InterlockedIncrement (&CsrpStaticThreadCount);
  649. Teb->CsrClientThread = (PVOID)MyThread;
  650. if (ReplyStatus == CsrReplyImmediate) {
  651. //
  652. // free captured arguments if a capture buffer was allocated
  653. // AND we're replying to the message now (no wait block has
  654. // been created).
  655. //
  656. if (ReplyMsg && ReceiveMsg.CaptureBuffer != NULL) {
  657. CsrReleaseCapturedArguments( &ReceiveMsg );
  658. }
  659. CsrDereferenceThread(Thread);
  660. } else if (ReplyStatus == CsrClientDied) {
  661. NTSTATUS Status;
  662. while (1) {
  663. Status = NtReplyPort (ReplyPortHandle,
  664. (PPORT_MESSAGE)ReplyMsg);
  665. if (Status == STATUS_NO_MEMORY) {
  666. LARGE_INTEGER DelayTime;
  667. KdPrint (("CSRSS: Failed to reply to calling thread, retrying.\n"));
  668. DelayTime.QuadPart = Int32x32To64 (5000, -10000);
  669. NtDelayExecution (FALSE, &DelayTime);
  670. continue;
  671. }
  672. break;
  673. }
  674. ReplyPortHandle = CsrApiPort;
  675. ReplyMsg = NULL;
  676. CsrDereferenceThread(Thread);
  677. } else if (ReplyStatus == CsrReplyPending) {
  678. ReplyPortHandle = CsrApiPort;
  679. ReplyMsg = NULL;
  680. } else if (ReplyStatus == CsrServerReplied) {
  681. if (ReplyMsg && ReceiveMsg.CaptureBuffer != NULL) {
  682. CsrReleaseCapturedArguments( &ReceiveMsg );
  683. }
  684. ReplyPortHandle = CsrApiPort;
  685. ReplyMsg = NULL;
  686. CsrDereferenceThread(Thread);
  687. } else {
  688. if (ReplyMsg && ReceiveMsg.CaptureBuffer != NULL) {
  689. CsrReleaseCapturedArguments( &ReceiveMsg );
  690. }
  691. CsrDereferenceThread(Thread);
  692. }
  693. failit:;
  694. }
  695. NtTerminateThread(NtCurrentThread(), Status);
  696. return Status;
  697. }
  698. NTSTATUS
  699. CsrCallServerFromServer(
  700. PCSR_API_MSG ReceiveMsg,
  701. PCSR_API_MSG ReplyMsg
  702. )
  703. /*++
  704. Routine Description:
  705. This function dispatches an API call the same way CsrApiRequestThread
  706. does, but it does it as a direct call, not an LPC connect. It is used
  707. by the csr dll when the server is calling a dll function. We don't
  708. worry about process serialization here because none of the process APIs
  709. can be called from the server.
  710. Arguments:
  711. ReceiveMessage - Pointer to the API request message received.
  712. ReplyMessage - Pointer to the API request message to return.
  713. Return Value:
  714. Status Code
  715. --*/
  716. {
  717. ULONG ServerDllIndex;
  718. ULONG ApiTableIndex;
  719. PCSR_SERVER_DLL LoadedServerDll;
  720. CSR_REPLY_STATUS ReplyStatus;
  721. ServerDllIndex =
  722. CSR_APINUMBER_TO_SERVERDLLINDEX( ReceiveMsg->ApiNumber );
  723. if (ServerDllIndex >= CSR_MAX_SERVER_DLL ||
  724. (LoadedServerDll = CsrLoadedServerDll[ ServerDllIndex ]) == NULL
  725. ) {
  726. IF_DEBUG {
  727. DbgPrint( "CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
  728. ServerDllIndex, LoadedServerDll
  729. );
  730. // DbgBreakPoint();
  731. }
  732. ReplyMsg->ReturnValue = STATUS_ILLEGAL_FUNCTION;
  733. return STATUS_ILLEGAL_FUNCTION;
  734. }
  735. else {
  736. ApiTableIndex =
  737. CSR_APINUMBER_TO_APITABLEINDEX( ReceiveMsg->ApiNumber ) -
  738. LoadedServerDll->ApiNumberBase;
  739. if (ApiTableIndex >= LoadedServerDll->MaxApiNumber - LoadedServerDll->ApiNumberBase ||
  740. (LoadedServerDll->ApiServerValidTable &&
  741. !LoadedServerDll->ApiServerValidTable[ ApiTableIndex ])) {
  742. #if DBG
  743. IF_DEBUG {
  744. DbgPrint( "CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an invalid API to call from the server.\n",
  745. LoadedServerDll->ApiNumberBase + ApiTableIndex,
  746. (LoadedServerDll->ApiNameTable &&
  747. LoadedServerDll->ApiNameTable[ ApiTableIndex ]
  748. ) ? LoadedServerDll->ApiNameTable[ ApiTableIndex ]
  749. : "*** UNKNOWN ***",
  750. &LoadedServerDll->ModuleName
  751. );
  752. DbgBreakPoint();
  753. }
  754. #endif
  755. ReplyMsg->ReturnValue = STATUS_ILLEGAL_FUNCTION;
  756. return STATUS_ILLEGAL_FUNCTION;
  757. }
  758. }
  759. #if DBG
  760. IF_CSR_DEBUG( LPC ) {
  761. DbgPrint( "CSRSS: %s Api Request received from server process\n",
  762. LoadedServerDll->ApiNameTable[ ApiTableIndex ]
  763. );
  764. }
  765. #endif
  766. try {
  767. ReplyMsg->ReturnValue =
  768. (*(LoadedServerDll->ApiDispatchTable[ ApiTableIndex ]))(
  769. ReceiveMsg,
  770. &ReplyStatus
  771. );
  772. } except( EXCEPTION_EXECUTE_HANDLER ) {
  773. ReplyMsg->ReturnValue = STATUS_ACCESS_VIOLATION;
  774. }
  775. return STATUS_SUCCESS;
  776. }
  777. BOOLEAN
  778. CsrCaptureArguments(
  779. IN PCSR_THREAD t,
  780. IN PCSR_API_MSG m
  781. )
  782. {
  783. PCSR_CAPTURE_HEADER ClientCaptureBuffer;
  784. PCSR_CAPTURE_HEADER ServerCaptureBuffer = NULL;
  785. PULONG_PTR PointerOffsets;
  786. ULONG Length, CountPointers;
  787. ULONG_PTR PointerDelta, Pointer;
  788. ULONG i;
  789. ClientCaptureBuffer = m->CaptureBuffer;
  790. m->ReturnValue = STATUS_SUCCESS;
  791. if ((PCH)ClientCaptureBuffer < t->Process->ClientViewBase ||
  792. (PCH)ClientCaptureBuffer > (t->Process->ClientViewBounds - FIELD_OFFSET(CSR_CAPTURE_HEADER,MessagePointerOffsets))) {
  793. IF_DEBUG {
  794. DbgPrint( "*** CSRSS: CaptureBuffer outside of ClientView 1\n" );
  795. SafeBreakPoint();
  796. }
  797. m->ReturnValue = STATUS_INVALID_PARAMETER;
  798. return FALSE;
  799. }
  800. try {
  801. Length = ClientCaptureBuffer->Length;
  802. if (((PCH)ClientCaptureBuffer + Length) < (PCH)ClientCaptureBuffer ||
  803. ((PCH)ClientCaptureBuffer + Length) > t->Process->ClientViewBounds) {
  804. IF_DEBUG {
  805. DbgPrint( "*** CSRSS: CaptureBuffer outside of ClientView 2\n" );
  806. SafeBreakPoint();
  807. }
  808. m->ReturnValue = STATUS_INVALID_PARAMETER;
  809. return FALSE;
  810. }
  811. CountPointers = ClientCaptureBuffer->CountMessagePointers;
  812. if (Length < FIELD_OFFSET(CSR_CAPTURE_HEADER, MessagePointerOffsets) + CountPointers * sizeof(PVOID) ||
  813. CountPointers > MAXUSHORT) {
  814. IF_DEBUG {
  815. DbgPrint( "*** CSRSS: CaptureBuffer %p has bad length\n", ClientCaptureBuffer );
  816. SafeBreakPoint();
  817. }
  818. m->ReturnValue = STATUS_INVALID_PARAMETER;
  819. return FALSE;
  820. }
  821. ServerCaptureBuffer = RtlAllocateHeap (CsrHeap, MAKE_TAG (CAPTURE_TAG), Length);
  822. if (ServerCaptureBuffer == NULL) {
  823. m->ReturnValue = STATUS_NO_MEMORY;
  824. return FALSE;
  825. }
  826. RtlCopyMemory (ServerCaptureBuffer, ClientCaptureBuffer, Length);
  827. } except (EXCEPTION_EXECUTE_HANDLER) {
  828. IF_DEBUG {
  829. DbgPrint( "*** CSRSS: Took exception during capture %x\n", GetExceptionCode ());
  830. SafeBreakPoint();
  831. }
  832. if (ServerCaptureBuffer != NULL) {
  833. RtlFreeHeap (CsrHeap, 0, ServerCaptureBuffer);
  834. }
  835. m->ReturnValue = STATUS_INVALID_PARAMETER;
  836. return FALSE;
  837. }
  838. ServerCaptureBuffer->Length = Length;
  839. ServerCaptureBuffer->CountMessagePointers = CountPointers;
  840. PointerDelta = (ULONG_PTR)ServerCaptureBuffer - (ULONG_PTR)ClientCaptureBuffer;
  841. PointerOffsets = ServerCaptureBuffer->MessagePointerOffsets;
  842. for (i = CountPointers; i > 0; i--) {
  843. Pointer = *PointerOffsets++;
  844. if (Pointer != 0) {
  845. //
  846. // If the pointer is outside the LPC message or before the message data reject it.
  847. // Reject unaligned pointers within the message also.
  848. //
  849. if ((ULONG_PTR)Pointer > sizeof (CSR_API_MSG) - sizeof (PVOID) ||
  850. (ULONG_PTR)Pointer < FIELD_OFFSET (CSR_API_MSG, u) ||
  851. (((ULONG_PTR)Pointer&(sizeof (PVOID)-1))) != 0) {
  852. m->ReturnValue = STATUS_INVALID_PARAMETER;
  853. IF_DEBUG {
  854. DbgPrint( "*** CSRSS: CaptureBuffer MessagePointer outside of message\n" );
  855. SafeBreakPoint();
  856. }
  857. break;
  858. }
  859. //
  860. // The strings are captured as well as the pointers so make sure they were within the captured range.
  861. //
  862. Pointer += (ULONG_PTR)m;
  863. if ((PCH)*(PULONG_PTR)Pointer >= (PCH)&ClientCaptureBuffer->MessagePointerOffsets[CountPointers] &&
  864. (PCH)*(PULONG_PTR)Pointer <= (PCH)ClientCaptureBuffer + Length - sizeof (PVOID)) {
  865. *(PULONG_PTR)Pointer += PointerDelta;
  866. } else {
  867. IF_DEBUG {
  868. DbgPrint( "*** CSRSS: CaptureBuffer MessagePointer outside of ClientView\n" );
  869. SafeBreakPoint();
  870. }
  871. m->ReturnValue = STATUS_INVALID_PARAMETER;
  872. break;
  873. }
  874. }
  875. }
  876. if (m->ReturnValue != STATUS_SUCCESS) {
  877. RtlFreeHeap (CsrHeap, 0, ServerCaptureBuffer);
  878. return FALSE ;
  879. } else {
  880. ServerCaptureBuffer->RelatedCaptureBuffer = ClientCaptureBuffer;
  881. m->CaptureBuffer = ServerCaptureBuffer;
  882. return TRUE;
  883. }
  884. }
  885. VOID
  886. CsrReleaseCapturedArguments(
  887. IN PCSR_API_MSG m
  888. )
  889. {
  890. PCSR_CAPTURE_HEADER ClientCaptureBuffer;
  891. PCSR_CAPTURE_HEADER ServerCaptureBuffer;
  892. PULONG_PTR PointerOffsets;
  893. ULONG CountPointers;
  894. ULONG_PTR PointerDelta, Pointer;
  895. ServerCaptureBuffer = m->CaptureBuffer;
  896. ClientCaptureBuffer = ServerCaptureBuffer->RelatedCaptureBuffer;
  897. if (ServerCaptureBuffer == NULL) {
  898. return;
  899. }
  900. ServerCaptureBuffer->RelatedCaptureBuffer = NULL;
  901. PointerDelta = (ULONG_PTR)ClientCaptureBuffer - (ULONG_PTR)ServerCaptureBuffer;
  902. PointerOffsets = ServerCaptureBuffer->MessagePointerOffsets;
  903. CountPointers = ServerCaptureBuffer->CountMessagePointers;
  904. while (CountPointers--) {
  905. Pointer = *PointerOffsets++;
  906. if (Pointer != 0) {
  907. Pointer += (ULONG_PTR)m;
  908. *(PULONG_PTR)Pointer += PointerDelta;
  909. }
  910. }
  911. try {
  912. RtlCopyMemory (ClientCaptureBuffer,
  913. ServerCaptureBuffer,
  914. ServerCaptureBuffer->Length);
  915. } except (EXCEPTION_EXECUTE_HANDLER) {
  916. SafeBreakPoint();
  917. m->ReturnValue = GetExceptionCode ();
  918. }
  919. RtlFreeHeap( CsrHeap, 0, ServerCaptureBuffer );
  920. }
  921. BOOLEAN
  922. CsrValidateMessageBuffer(
  923. IN CONST CSR_API_MSG* m,
  924. IN VOID CONST * CONST * Buffer,
  925. IN ULONG Count,
  926. IN ULONG Size
  927. )
  928. /*++
  929. Routine Description:
  930. This routine validates the given message buffer within the capture
  931. buffer of the CSR_API_MSG structure. The message buffer must be valid
  932. and of the correct size. This function should be called to validate
  933. any buffer allocated through CsrCaptureMessageBuffer.
  934. Arguments:
  935. m - Pointer to CSR_API_MSG.
  936. Buffer - Pointer to message buffer.
  937. Count - number of elements in buffer.
  938. Size - size of each element in buffer.
  939. Return Value:
  940. TRUE - if message buffer is valid and of correct size.
  941. FALSE - otherwise.
  942. --*/
  943. {
  944. ULONG i;
  945. ULONG_PTR Length;
  946. ULONG_PTR EndOfBuffer;
  947. ULONG_PTR Offset;
  948. PCSR_CAPTURE_HEADER CaptureBuffer = m->CaptureBuffer;
  949. //
  950. // Check for buffer length overflow. Also, Size should not be 0.
  951. //
  952. if (Size && Count <= MAXULONG / Size) {
  953. //
  954. // If buffer is empty, we're done
  955. //
  956. Length = Count * Size;
  957. if (*Buffer == NULL && Length == 0) {
  958. return TRUE;
  959. }
  960. //
  961. // Make sure we have a capture area
  962. //
  963. if (CaptureBuffer) {
  964. //
  965. // Check for buffer length exceeding capture area size
  966. //
  967. EndOfBuffer = (ULONG_PTR)CaptureBuffer + CaptureBuffer->Length;
  968. if (Length <= (EndOfBuffer - (ULONG_PTR)(*Buffer))) {
  969. //
  970. // Search for buffer in capture area
  971. //
  972. Offset = (ULONG_PTR)Buffer - (ULONG_PTR)m;
  973. for (i = 0; i < CaptureBuffer->CountMessagePointers; i++) {
  974. if (CaptureBuffer->MessagePointerOffsets[i] == Offset) {
  975. return TRUE;
  976. }
  977. }
  978. }
  979. } else {
  980. //
  981. // If this is called from the CSRSS process vis CsrCallServerFromServer,
  982. // then CaptureBuffer is NULL. Verify that the caller is the CSRSS process.
  983. //
  984. if (m->h.ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess) {
  985. return TRUE;
  986. }
  987. }
  988. }
  989. IF_DEBUG {
  990. DbgPrint("CSRSRV: Bad message buffer %p\n", m);
  991. SafeBreakPoint();
  992. }
  993. return FALSE;
  994. }
  995. BOOLEAN
  996. CsrValidateMessageString(
  997. IN CONST CSR_API_MSG* m,
  998. IN CONST PCWSTR *Buffer
  999. ) {
  1000. PCSR_CAPTURE_HEADER CaptureBuffer = m->CaptureBuffer;
  1001. ULONG_PTR EndOfBuffer;
  1002. ULONG_PTR Offset;
  1003. ULONG i;
  1004. PWCHAR cp;
  1005. //
  1006. // Make sure we have a capture area
  1007. //
  1008. cp = (PWCHAR)*Buffer;
  1009. if (cp == NULL) {
  1010. return TRUE;
  1011. }
  1012. if (CaptureBuffer) {
  1013. //
  1014. // Search for buffer in capture area
  1015. //
  1016. Offset = (ULONG_PTR)Buffer - (ULONG_PTR)m;
  1017. for (i = 0; i < CaptureBuffer->CountMessagePointers; i++) {
  1018. if (CaptureBuffer->MessagePointerOffsets[i] == Offset) {
  1019. break;
  1020. }
  1021. }
  1022. if (i >= CaptureBuffer->CountMessagePointers) {
  1023. SafeBreakPoint();
  1024. return FALSE;
  1025. }
  1026. //
  1027. // Check unicode alignment.
  1028. //
  1029. if (((ULONG_PTR)cp & (sizeof (WCHAR) - 1)) != 0) {
  1030. SafeBreakPoint();
  1031. return FALSE;
  1032. }
  1033. //
  1034. // Check for buffer length exceeding capture area size
  1035. //
  1036. EndOfBuffer = (ULONG_PTR)CaptureBuffer + CaptureBuffer->Length;
  1037. //
  1038. // The buffer is valid if we see a null before the end of the buffer
  1039. //
  1040. while (1) {
  1041. if (cp < (PWCHAR)EndOfBuffer) {
  1042. if (*cp == L'\0') {
  1043. return TRUE;
  1044. }
  1045. } else {
  1046. SafeBreakPoint();
  1047. return FALSE;
  1048. }
  1049. cp++;
  1050. }
  1051. } else {
  1052. //
  1053. // If this is called from the CSRSS process vis CsrCallServerFromServer,
  1054. // then CaptureBuffer is NULL. Verify that the caller is the CSRSS process.
  1055. //
  1056. if (m->h.ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess) {
  1057. return TRUE;
  1058. }
  1059. }
  1060. KdPrint(("CSRSRV: Bad message string %p\n", m));
  1061. ASSERT(FALSE);
  1062. return FALSE;
  1063. }
  1064. NTSTATUS
  1065. CsrApiHandleConnectionRequest(
  1066. IN PCSR_API_MSG Message)
  1067. {
  1068. NTSTATUS Status;
  1069. REMOTE_PORT_VIEW ClientView;
  1070. BOOLEAN AcceptConnection;
  1071. HANDLE PortHandle;
  1072. PCSR_PROCESS Process = NULL;
  1073. PCSR_THREAD Thread;
  1074. PCSR_API_CONNECTINFO ConnectionInformation;
  1075. ConnectionInformation = &Message->ConnectionRequest;
  1076. AcceptConnection = FALSE;
  1077. AcquireProcessStructureLock();
  1078. Thread = CsrLocateThreadByClientId(NULL, &Message->h.ClientId);
  1079. if (Thread != NULL && (Process = Thread->Process) != NULL) {
  1080. CsrLockedReferenceProcess(Process);
  1081. Status = CsrSrvAttachSharedSection(Process, ConnectionInformation);
  1082. if (NT_SUCCESS(Status)) {
  1083. #if DBG
  1084. ConnectionInformation->DebugFlags = CsrDebug;
  1085. #endif
  1086. AcceptConnection = TRUE;
  1087. }
  1088. }
  1089. ReleaseProcessStructureLock();
  1090. ClientView.Length = sizeof(ClientView);
  1091. ClientView.ViewSize = 0;
  1092. ClientView.ViewBase = 0;
  1093. ConnectionInformation->ServerProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
  1094. Status = NtAcceptConnectPort(&PortHandle,
  1095. AcceptConnection ? (PVOID)UlongToPtr(Process->SequenceNumber) : 0,
  1096. &Message->h,
  1097. AcceptConnection,
  1098. NULL,
  1099. &ClientView);
  1100. if (NT_SUCCESS(Status) && AcceptConnection) {
  1101. IF_CSR_DEBUG(LPC) {
  1102. DbgPrint("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
  1103. Message->h.ClientId.UniqueProcess,
  1104. Message->h.ClientId.UniqueThread,
  1105. ClientView.ViewBase,
  1106. ClientView.ViewSize);
  1107. }
  1108. Process->ClientPort = PortHandle;
  1109. Process->ClientViewBase = (PCH)ClientView.ViewBase;
  1110. Process->ClientViewBounds = (PCH)ClientView.ViewBase + ClientView.ViewSize;
  1111. Status = NtCompleteConnectPort(PortHandle);
  1112. if (!NT_SUCCESS(Status)) {
  1113. #if DBG
  1114. DbgPrint("CSRSS: NtCompleteConnectPort - failed. Status == %X\n",
  1115. Status);
  1116. #endif
  1117. }
  1118. } else {
  1119. if (!NT_SUCCESS(Status)) {
  1120. #if DBG
  1121. DbgPrint("CSRSS: NtAcceptConnectPort - failed. Status == %X\n",
  1122. Status);
  1123. #endif
  1124. } else {
  1125. #if DBG
  1126. DbgPrint("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
  1127. Message->h.ClientId.UniqueProcess,
  1128. Message->h.ClientId.UniqueThread);
  1129. #endif
  1130. }
  1131. }
  1132. #if DBG
  1133. {
  1134. ULONG Index = GetNextTrackIndex();
  1135. LpcTrackNodes[Index].Status = Status;
  1136. }
  1137. #endif
  1138. if (Process != NULL) {
  1139. CsrDereferenceProcess(Process);
  1140. }
  1141. return Status;
  1142. }