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.

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