Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenapi.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS CSR Sub System 00004 * FILE: subsys/csr/csrsrv/api.c 00005 * PURPOSE: CSR Server DLL API LPC Implementation 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include "srv.h" 00012 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* DATA **********************************************************************/ 00017 BOOLEAN (*CsrClientThreadSetup)(VOID) = NULL; 00018 ULONG CsrMaxApiRequestThreads; 00019 UNICODE_STRING CsrSbApiPortName; 00020 UNICODE_STRING CsrApiPortName; 00021 HANDLE CsrSbApiPort; 00022 HANDLE CsrApiPort; 00023 PCSR_THREAD CsrSbApiRequestThreadPtr; 00024 volatile LONG CsrpStaticThreadCount; 00025 volatile LONG CsrpDynamicThreadTotal; 00026 00027 /* PRIVATE FUNCTIONS *********************************************************/ 00028 00029 /*++ 00030 * @name CsrpCheckRequestThreads 00031 * 00032 * The CsrpCheckRequestThreads routine checks if there are no more threads 00033 * to handle CSR API Requests, and creates a new thread if possible, to 00034 * avoid starvation. 00035 * 00036 * @param None. 00037 * 00038 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL 00039 * if a new thread couldn't be created. 00040 * 00041 * @remarks None. 00042 * 00043 *--*/ 00044 NTSTATUS 00045 NTAPI 00046 CsrpCheckRequestThreads(VOID) 00047 { 00048 HANDLE hThread; 00049 CLIENT_ID ClientId; 00050 NTSTATUS Status; 00051 00052 /* Decrease the count, and see if we're out */ 00053 if (!(_InterlockedDecrement(&CsrpStaticThreadCount))) 00054 { 00055 /* Check if we've still got space for a Dynamic Thread */ 00056 if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads) 00057 { 00058 /* Create a new dynamic thread */ 00059 Status = RtlCreateUserThread(NtCurrentProcess(), 00060 NULL, 00061 TRUE, 00062 0, 00063 0, 00064 0, 00065 (PVOID)CsrApiRequestThread, 00066 NULL, 00067 &hThread, 00068 &ClientId); 00069 /* Check success */ 00070 if (NT_SUCCESS(Status)) 00071 { 00072 /* Increase the thread counts */ 00073 _InterlockedIncrement(&CsrpStaticThreadCount); 00074 _InterlockedIncrement(&CsrpDynamicThreadTotal); 00075 00076 /* Add a new server thread */ 00077 if (CsrAddStaticServerThread(hThread, 00078 &ClientId, 00079 CsrThreadIsServerThread)) 00080 { 00081 /* Activate it */ 00082 NtResumeThread(hThread,NULL); 00083 } 00084 else 00085 { 00086 /* Failed to create a new static thread */ 00087 _InterlockedDecrement(&CsrpStaticThreadCount); 00088 _InterlockedDecrement(&CsrpDynamicThreadTotal); 00089 00090 /* Terminate it */ 00091 NtTerminateThread(hThread,0); 00092 NtClose(hThread); 00093 00094 /* Return */ 00095 return STATUS_UNSUCCESSFUL; 00096 } 00097 } 00098 } 00099 } 00100 00101 /* Success */ 00102 return STATUS_SUCCESS; 00103 } 00104 00105 /*++ 00106 * @name CsrSbApiPortInitialize 00107 * 00108 * The CsrSbApiPortInitialize routine initializes the LPC Port used for 00109 * communications with the Session Manager (SM) and initializes the static 00110 * thread that will handle connection requests and APIs. 00111 * 00112 * @param None 00113 * 00114 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL 00115 * othwerwise. 00116 * 00117 * @remarks None. 00118 * 00119 *--*/ 00120 NTSTATUS 00121 NTAPI 00122 CsrSbApiPortInitialize(VOID) 00123 { 00124 ULONG Size; 00125 PSECURITY_DESCRIPTOR PortSd; 00126 OBJECT_ATTRIBUTES ObjectAttributes; 00127 NTSTATUS Status; 00128 HANDLE hRequestThread; 00129 CLIENT_ID ClientId; 00130 00131 /* Calculate how much space we'll need for the Port Name */ 00132 Size = CsrDirectoryName.Length + sizeof(SB_PORT_NAME) + sizeof(WCHAR); 00133 00134 /* Create the buffer for it */ 00135 CsrSbApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size); 00136 if (!CsrSbApiPortName.Buffer) return STATUS_NO_MEMORY; 00137 00138 /* Setup the rest of the empty string */ 00139 CsrSbApiPortName.Length = 0; 00140 CsrSbApiPortName.MaximumLength = (USHORT)Size; 00141 00142 /* Now append the full port name */ 00143 RtlAppendUnicodeStringToString(&CsrSbApiPortName, &CsrDirectoryName); 00144 RtlAppendUnicodeToString(&CsrSbApiPortName, UNICODE_PATH_SEP); 00145 RtlAppendUnicodeToString(&CsrSbApiPortName, SB_PORT_NAME); 00146 if (CsrDebug & 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName); 00147 00148 /* Create Security Descriptor for this Port */ 00149 Status = CsrCreateLocalSystemSD(&PortSd); 00150 if (!NT_SUCCESS(Status)) return Status; 00151 00152 /* Initialize the Attributes */ 00153 InitializeObjectAttributes(&ObjectAttributes, 00154 &CsrSbApiPortName, 00155 0, 00156 NULL, 00157 PortSd); 00158 00159 /* Create the Port Object */ 00160 Status = NtCreatePort(&CsrSbApiPort, 00161 &ObjectAttributes, 00162 sizeof(SB_CONNECTION_INFO), 00163 sizeof(SB_API_MSG), 00164 32 * sizeof(SB_API_MSG)); 00165 if (PortSd) RtlFreeHeap(CsrHeap, 0, PortSd); 00166 00167 if (NT_SUCCESS(Status)) 00168 { 00169 /* Create the Thread to handle the API Requests */ 00170 Status = RtlCreateUserThread(NtCurrentProcess(), 00171 NULL, 00172 TRUE, 00173 0, 00174 0, 00175 0, 00176 (PVOID)CsrSbApiRequestThread, 00177 NULL, 00178 &hRequestThread, 00179 &ClientId); 00180 if (NT_SUCCESS(Status)) 00181 { 00182 /* Add it as a Static Server Thread */ 00183 CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(hRequestThread, 00184 &ClientId, 00185 0); 00186 00187 /* Activate it */ 00188 Status = NtResumeThread(hRequestThread, NULL); 00189 } 00190 } 00191 00192 return Status; 00193 } 00194 00195 /*++ 00196 * @name CsrApiPortInitialize 00197 * 00198 * The CsrApiPortInitialize routine initializes the LPC Port used for 00199 * communications with the Client/Server Runtime (CSR) and initializes the 00200 * static thread that will handle connection requests and APIs. 00201 * 00202 * @param None 00203 * 00204 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL 00205 * othwerwise. 00206 * 00207 * @remarks None. 00208 * 00209 *--*/ 00210 NTSTATUS 00211 NTAPI 00212 CsrApiPortInitialize(VOID) 00213 { 00214 ULONG Size; 00215 OBJECT_ATTRIBUTES ObjectAttributes; 00216 NTSTATUS Status; 00217 HANDLE hRequestEvent, hThread; 00218 CLIENT_ID ClientId; 00219 PLIST_ENTRY ListHead, NextEntry; 00220 PCSR_THREAD ServerThread; 00221 00222 /* Calculate how much space we'll need for the Port Name */ 00223 Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR); 00224 00225 /* Create the buffer for it */ 00226 CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size); 00227 if (!CsrApiPortName.Buffer) return STATUS_NO_MEMORY; 00228 00229 /* Setup the rest of the empty string */ 00230 CsrApiPortName.Length = 0; 00231 CsrApiPortName.MaximumLength = (USHORT)Size; 00232 RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName); 00233 RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP); 00234 RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME); 00235 if (CsrDebug & 1) 00236 { 00237 DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName); 00238 DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n", 00239 sizeof(CSR_CONNECTION_INFO), sizeof(CSR_API_MESSAGE)); 00240 } 00241 00242 /* FIXME: Create a Security Descriptor */ 00243 00244 /* Initialize the Attributes */ 00245 InitializeObjectAttributes(&ObjectAttributes, 00246 &CsrApiPortName, 00247 0, 00248 NULL, 00249 NULL /* FIXME*/); 00250 00251 /* Create the Port Object */ 00252 Status = NtCreatePort(&CsrApiPort, 00253 &ObjectAttributes, 00254 sizeof(CSR_CONNECTION_INFO), 00255 sizeof(CSR_API_MESSAGE), 00256 16 * PAGE_SIZE); 00257 if (NT_SUCCESS(Status)) 00258 { 00259 /* Create the event the Port Thread will use */ 00260 Status = NtCreateEvent(&hRequestEvent, 00261 EVENT_ALL_ACCESS, 00262 NULL, 00263 SynchronizationEvent, 00264 FALSE); 00265 if (NT_SUCCESS(Status)) 00266 { 00267 /* Create the Request Thread */ 00268 Status = RtlCreateUserThread(NtCurrentProcess(), 00269 NULL, 00270 TRUE, 00271 0, 00272 0, 00273 0, 00274 (PVOID)CsrApiRequestThread, 00275 (PVOID)hRequestEvent, 00276 &hThread, 00277 &ClientId); 00278 if (NT_SUCCESS(Status)) 00279 { 00280 /* Add this as a static thread to CSRSRV */ 00281 CsrAddStaticServerThread(hThread, &ClientId, CsrThreadIsServerThread); 00282 00283 /* Get the Thread List Pointers */ 00284 ListHead = &CsrRootProcess->ThreadList; 00285 NextEntry = ListHead->Flink; 00286 00287 /* Start looping the list */ 00288 while (NextEntry != ListHead) 00289 { 00290 /* Get the Thread */ 00291 ServerThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link); 00292 00293 /* Start it up */ 00294 Status = NtResumeThread(ServerThread->ThreadHandle, NULL); 00295 00296 /* Is this a Server Thread? */ 00297 if (ServerThread->Flags & CsrThreadIsServerThread) 00298 { 00299 /* If so, then wait for it to initialize */ 00300 Status = NtWaitForSingleObject(hRequestEvent, FALSE, NULL); 00301 ASSERT(NT_SUCCESS(Status)); 00302 } 00303 00304 /* Next thread */ 00305 NextEntry = NextEntry->Flink; 00306 } 00307 00308 /* We don't need this anymore */ 00309 NtClose(hRequestEvent); 00310 } 00311 } 00312 } 00313 00314 /* Return */ 00315 return Status; 00316 } 00317 00318 /*++ 00319 * @name CsrApiRequestThread 00320 * 00321 * The CsrApiRequestThread routine handles incoming messages or connection 00322 * requests on the CSR API LPC Port. 00323 * 00324 * @param Parameter 00325 * System-default user-defined parameter. Unused. 00326 * 00327 * @return The thread exit code, if the thread is terminated. 00328 * 00329 * @remarks Before listening on the port, the routine will first attempt 00330 * to connect to the user subsystem. 00331 * 00332 *--*/ 00333 NTSTATUS 00334 NTAPI 00335 CsrApiRequestThread(IN PVOID Parameter) 00336 { 00337 PTEB Teb = NtCurrentTeb(); 00338 LARGE_INTEGER TimeOut; 00339 PCSR_THREAD CurrentThread, CsrThread; 00340 NTSTATUS Status; 00341 PCSR_API_MESSAGE ReplyMsg; 00342 CSR_API_MESSAGE ReceiveMsg; 00343 PCSR_PROCESS CsrProcess; 00344 PHARDERROR_MSG HardErrorMsg; 00345 PVOID PortContext; 00346 PCSR_SERVER_DLL ServerDll; 00347 PCLIENT_DIED_MSG ClientDiedMsg; 00348 PDBGKM_MSG DebugMessage; 00349 ULONG ServerId, ApiId, Reply, MessageType, i; 00350 HANDLE ReplyPort; 00351 00352 /* Setup LPC loop port and message */ 00353 ReplyMsg = NULL; 00354 ReplyPort = CsrApiPort; 00355 00356 /* Connect to user32 */ 00357 while (!CsrConnectToUser()) 00358 { 00359 /* Set up the timeout for the connect (30 seconds) */ 00360 TimeOut.QuadPart = -30 * 1000 * 1000 * 10; 00361 00362 /* Keep trying until we get a response */ 00363 Teb->Win32ClientInfo[0] = 0; 00364 NtDelayExecution(FALSE, &TimeOut); 00365 } 00366 00367 /* Get our thread */ 00368 CurrentThread = Teb->CsrClientThread; 00369 00370 /* If we got an event... */ 00371 if (Parameter) 00372 { 00373 /* Set it, to let stuff waiting on us load */ 00374 Status = NtSetEvent((HANDLE)Parameter, NULL); 00375 ASSERT(NT_SUCCESS(Status)); 00376 00377 /* Increase the Thread Counts */ 00378 _InterlockedIncrement(&CsrpStaticThreadCount); 00379 _InterlockedIncrement(&CsrpDynamicThreadTotal); 00380 } 00381 00382 /* Now start the loop */ 00383 while (TRUE) 00384 { 00385 /* Make sure the real CID is set */ 00386 Teb->RealClientId = Teb->ClientId; 00387 00388 /* Debug check */ 00389 if (Teb->CountOfOwnedCriticalSections) 00390 { 00391 DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n", 00392 Teb->CountOfOwnedCriticalSections); 00393 DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n", 00394 &ReceiveMsg, ReplyMsg); 00395 DbgBreakPoint(); 00396 } 00397 00398 /* Wait for a message to come through */ 00399 Status = NtReplyWaitReceivePort(ReplyPort, 00400 &PortContext, 00401 &ReplyMsg->Header, 00402 &ReceiveMsg.Header); 00403 00404 /* Check if we didn't get success */ 00405 if (Status != STATUS_SUCCESS) 00406 { 00407 /* Was it a failure or another success code? */ 00408 if (!NT_SUCCESS(Status)) 00409 { 00410 /* Check for specific status cases */ 00411 if ((Status != STATUS_INVALID_CID) && 00412 (Status != STATUS_UNSUCCESSFUL) && 00413 ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort))) 00414 { 00415 /* Notify the debugger */ 00416 DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status); 00417 DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort); 00418 } 00419 00420 /* We failed big time, so start out fresh */ 00421 ReplyMsg = NULL; 00422 ReplyPort = CsrApiPort; 00423 continue; 00424 } 00425 else 00426 { 00427 /* A bizare "success" code, just try again */ 00428 DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status); 00429 continue; 00430 } 00431 } 00432 00433 /* Use whatever Client ID we got */ 00434 Teb->RealClientId = ReceiveMsg.Header.ClientId; 00435 00436 /* Get the Message Type */ 00437 MessageType = ReceiveMsg.Header.u2.s2.Type; 00438 00439 /* Handle connection requests */ 00440 if (MessageType == LPC_CONNECTION_REQUEST) 00441 { 00442 /* Handle the Connection Request */ 00443 CsrApiHandleConnectionRequest(&ReceiveMsg); 00444 ReplyPort = CsrApiPort; 00445 ReplyMsg = NULL; 00446 continue; 00447 } 00448 00449 /* It's some other kind of request. Get the lock for the lookup */ 00450 CsrAcquireProcessLock(); 00451 00452 /* Now do the lookup to get the CSR_THREAD */ 00453 CsrThread = CsrLocateThreadByClientId(&CsrProcess, 00454 &ReceiveMsg.Header.ClientId); 00455 00456 /* Did we find a thread? */ 00457 if (!CsrThread) 00458 { 00459 /* This wasn't a CSR Thread, release lock */ 00460 CsrReleaseProcessLock(); 00461 00462 /* If this was an exception, handle it */ 00463 if (MessageType == LPC_EXCEPTION) 00464 { 00465 ReplyMsg = &ReceiveMsg; 00466 ReplyPort = CsrApiPort; 00467 ReplyMsg->Status = DBG_CONTINUE; 00468 } 00469 else if (MessageType == LPC_PORT_CLOSED || 00470 MessageType == LPC_CLIENT_DIED) 00471 { 00472 /* The Client or Port are gone, loop again */ 00473 ReplyMsg = NULL; 00474 ReplyPort = CsrApiPort; 00475 } 00476 else if (MessageType == LPC_ERROR_EVENT) 00477 { 00478 /* If it's a hard error, handle this too */ 00479 HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg; 00480 00481 /* Default it to unhandled */ 00482 HardErrorMsg->Response = ResponseNotHandled; 00483 00484 /* Check if there are free api threads */ 00485 CsrpCheckRequestThreads(); 00486 if (CsrpStaticThreadCount) 00487 { 00488 /* Loop every Server DLL */ 00489 for (i = 0; i < CSR_SERVER_DLL_MAX; i++) 00490 { 00491 /* Get the Server DLL */ 00492 ServerDll = CsrLoadedServerDll[i]; 00493 00494 /* Check if it's valid and if it has a Hard Error Callback */ 00495 if ((ServerDll) && (ServerDll->HardErrorCallback)) 00496 { 00497 /* Call it */ 00498 ServerDll->HardErrorCallback(NULL, HardErrorMsg); 00499 00500 /* If it's handled, get out of here */ 00501 if (HardErrorMsg->Response != ResponseNotHandled) break; 00502 } 00503 } 00504 } 00505 00506 /* Increase the thread count */ 00507 _InterlockedIncrement(&CsrpStaticThreadCount); 00508 00509 /* If the response was 0xFFFFFFFF, we'll ignore it */ 00510 if (HardErrorMsg->Response == 0xFFFFFFFF) 00511 { 00512 ReplyMsg = NULL; 00513 ReplyPort = CsrApiPort; 00514 } 00515 else 00516 { 00517 ReplyMsg = &ReceiveMsg; 00518 } 00519 } 00520 else if (MessageType == LPC_REQUEST) 00521 { 00522 /* This is an API Message coming from a non-CSR Thread */ 00523 ReplyMsg = &ReceiveMsg; 00524 ReplyPort = CsrApiPort; 00525 ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION; 00526 } 00527 else if (MessageType == LPC_DATAGRAM) 00528 { 00529 /* This is an API call, get the Server ID */ 00530 ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg.Opcode); 00531 00532 /* Make sure that the ID is within limits, and the Server DLL loaded */ 00533 ServerDll = NULL; 00534 if ((ServerId >= CSR_SERVER_DLL_MAX) || 00535 (!(ServerDll = CsrLoadedServerDll[ServerId]))) 00536 { 00537 /* We are beyond the Maximum Server ID */ 00538 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", 00539 ServerId, ServerDll); 00540 DbgBreakPoint(); 00541 ReplyPort = CsrApiPort; 00542 ReplyMsg = NULL; 00543 continue; 00544 } 00545 00546 /* Get the API ID */ 00547 ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode); 00548 00549 /* Normalize it with our Base ID */ 00550 ApiId -= ServerDll->ApiBase; 00551 00552 /* Make sure that the ID is within limits, and the entry exists */ 00553 if (ApiId >= ServerDll->HighestApiSupported) 00554 { 00555 /* We are beyond the Maximum API ID, or it doesn't exist */ 00556 DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n", 00557 CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode), 00558 &ServerDll->Name); 00559 ReplyPort = CsrApiPort; 00560 ReplyMsg = NULL; 00561 continue; 00562 } 00563 00564 if (CsrDebug & 2) 00565 { 00566 DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n", 00567 Teb->ClientId.UniqueThread, 00568 ReceiveMsg.Header.ClientId.UniqueProcess, 00569 ReceiveMsg.Header.ClientId.UniqueThread, 00570 ServerDll->NameTable[ApiId], 00571 NULL); 00572 } 00573 00574 /* Assume success */ 00575 ReceiveMsg.Status = STATUS_SUCCESS; 00576 00577 /* Validation complete, start SEH */ 00578 _SEH2_TRY 00579 { 00580 /* Make sure we have enough threads */ 00581 CsrpCheckRequestThreads(); 00582 00583 /* Call the API and get the result */ 00584 ReplyMsg = NULL; 00585 ReplyPort = CsrApiPort; 00586 ServerDll->DispatchTable[ApiId](&ReceiveMsg, &Reply); 00587 00588 /* Increase the static thread count */ 00589 _InterlockedIncrement(&CsrpStaticThreadCount); 00590 } 00591 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation())) 00592 { 00593 ReplyMsg = NULL; 00594 ReplyPort = CsrApiPort; 00595 } 00596 _SEH2_END; 00597 } 00598 else 00599 { 00600 /* Some other ignored message type */ 00601 ReplyMsg = NULL; 00602 ReplyPort = CsrApiPort; 00603 } 00604 00605 /* Keep going */ 00606 continue; 00607 } 00608 00609 /* We have a valid thread, was this an LPC Request? */ 00610 if (MessageType != LPC_REQUEST) 00611 { 00612 /* It's not an API, check if the client died */ 00613 if (MessageType == LPC_CLIENT_DIED) 00614 { 00615 /* Get the information and check if it matches our thread */ 00616 ClientDiedMsg = (PCLIENT_DIED_MSG)&ReceiveMsg; 00617 if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart) 00618 { 00619 /* Reference the thread */ 00620 CsrLockedReferenceThread(CsrThread); 00621 00622 /* Destroy the thread in the API Message */ 00623 CsrDestroyThread(&ReceiveMsg.Header.ClientId); 00624 00625 /* Check if the thread was actually ourselves */ 00626 if (CsrProcess->ThreadCount == 1) 00627 { 00628 /* Kill the process manually here */ 00629 CsrDestroyProcess(&CsrThread->ClientId, 0); 00630 } 00631 00632 /* Remove our extra reference */ 00633 CsrLockedDereferenceThread(CsrThread); 00634 } 00635 00636 /* Release the lock and keep looping */ 00637 CsrReleaseProcessLock(); 00638 ReplyMsg = NULL; 00639 ReplyPort = CsrApiPort; 00640 continue; 00641 } 00642 00643 /* Reference the thread and release the lock */ 00644 CsrLockedReferenceThread(CsrThread); 00645 CsrReleaseProcessLock(); 00646 00647 /* Check if this was an exception */ 00648 if (MessageType == LPC_EXCEPTION) 00649 { 00650 /* Kill the process */ 00651 NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED); 00652 00653 /* Destroy it from CSR */ 00654 CsrDestroyProcess(&ReceiveMsg.Header.ClientId, STATUS_ABANDONED); 00655 00656 /* Return a Debug Message */ 00657 DebugMessage = (PDBGKM_MSG)&ReceiveMsg; 00658 DebugMessage->ReturnedStatus = DBG_CONTINUE; 00659 ReplyMsg = &ReceiveMsg; 00660 ReplyPort = CsrApiPort; 00661 00662 /* Remove our extra reference */ 00663 CsrDereferenceThread(CsrThread); 00664 } 00665 else if (MessageType == LPC_ERROR_EVENT) 00666 { 00667 /* If it's a hard error, handle this too */ 00668 HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg; 00669 00670 /* Default it to unhandled */ 00671 HardErrorMsg->Response = ResponseNotHandled; 00672 00673 /* Check if there are free api threads */ 00674 CsrpCheckRequestThreads(); 00675 if (CsrpStaticThreadCount) 00676 { 00677 /* Loop every Server DLL */ 00678 for (i = 0; i < CSR_SERVER_DLL_MAX; i++) 00679 { 00680 /* Get the Server DLL */ 00681 ServerDll = CsrLoadedServerDll[i]; 00682 00683 /* Check if it's valid and if it has a Hard Error Callback */ 00684 if ((ServerDll) && (ServerDll->HardErrorCallback)) 00685 { 00686 /* Call it */ 00687 ServerDll->HardErrorCallback(CsrThread, HardErrorMsg); 00688 00689 /* If it's handled, get out of here */ 00690 if (HardErrorMsg->Response != ResponseNotHandled) break; 00691 } 00692 } 00693 } 00694 00695 /* Increase the thread count */ 00696 _InterlockedIncrement(&CsrpStaticThreadCount); 00697 00698 /* If the response was 0xFFFFFFFF, we'll ignore it */ 00699 if (HardErrorMsg->Response == 0xFFFFFFFF) 00700 { 00701 ReplyMsg = NULL; 00702 ReplyPort = CsrApiPort; 00703 } 00704 else 00705 { 00706 CsrDereferenceThread(CsrThread); 00707 ReplyMsg = &ReceiveMsg; 00708 ReplyPort = CsrApiPort; 00709 } 00710 } 00711 else 00712 { 00713 /* Something else */ 00714 CsrDereferenceThread(CsrThread); 00715 ReplyMsg = NULL; 00716 } 00717 00718 /* Keep looping */ 00719 continue; 00720 } 00721 00722 /* We got an API Request */ 00723 CsrLockedReferenceThread(CsrThread); 00724 CsrReleaseProcessLock(); 00725 00726 /* This is an API call, get the Server ID */ 00727 ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg.Opcode); 00728 00729 /* Make sure that the ID is within limits, and the Server DLL loaded */ 00730 ServerDll = NULL; 00731 if ((ServerId >= CSR_SERVER_DLL_MAX) || 00732 (!(ServerDll = CsrLoadedServerDll[ServerId]))) 00733 { 00734 /* We are beyond the Maximum Server ID */ 00735 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", 00736 ServerId, ServerDll); 00737 DbgBreakPoint(); 00738 00739 ReplyPort = CsrApiPort; 00740 ReplyMsg = &ReceiveMsg; 00741 ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION; 00742 CsrDereferenceThread(CsrThread); 00743 continue; 00744 } 00745 00746 /* Get the API ID */ 00747 ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode); 00748 00749 /* Normalize it with our Base ID */ 00750 ApiId -= ServerDll->ApiBase; 00751 00752 /* Make sure that the ID is within limits, and the entry exists */ 00753 if (ApiId >= ServerDll->HighestApiSupported) 00754 { 00755 /* We are beyond the Maximum API ID, or it doesn't exist */ 00756 DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n", 00757 CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode), 00758 &ServerDll->Name); 00759 00760 ReplyPort = CsrApiPort; 00761 ReplyMsg = &ReceiveMsg; 00762 ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION; 00763 CsrDereferenceThread(CsrThread); 00764 continue; 00765 } 00766 00767 if (CsrDebug & 2) 00768 { 00769 DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n", 00770 Teb->ClientId.UniqueThread, 00771 ReceiveMsg.Header.ClientId.UniqueProcess, 00772 ReceiveMsg.Header.ClientId.UniqueThread, 00773 ServerDll->NameTable[ApiId], 00774 CsrThread); 00775 } 00776 00777 /* Assume success */ 00778 ReplyMsg = &ReceiveMsg; 00779 ReceiveMsg.Status = STATUS_SUCCESS; 00780 00781 /* Now we reply to a particular client */ 00782 ReplyPort = CsrThread->Process->ClientPort; 00783 00784 /* Check if there's a capture buffer */ 00785 if (ReceiveMsg.CsrCaptureData) 00786 { 00787 /* Capture the arguments */ 00788 if (!CsrCaptureArguments(CsrThread, &ReceiveMsg)) 00789 { 00790 /* Ignore this message if we failed to get the arguments */ 00791 CsrDereferenceThread(CsrThread); 00792 continue; 00793 } 00794 } 00795 00796 /* Validation complete, start SEH */ 00797 _SEH2_TRY 00798 { 00799 /* Make sure we have enough threads */ 00800 CsrpCheckRequestThreads(); 00801 00802 Teb->CsrClientThread = CsrThread; 00803 00804 /* Call the API and get the result */ 00805 Reply = 0; 00806 ServerDll->DispatchTable[ApiId](&ReceiveMsg, &Reply); 00807 00808 /* Increase the static thread count */ 00809 _InterlockedIncrement(&CsrpStaticThreadCount); 00810 00811 Teb->CsrClientThread = CurrentThread; 00812 00813 if (Reply == 3) 00814 { 00815 ReplyMsg = NULL; 00816 if (ReceiveMsg.CsrCaptureData) 00817 { 00818 CsrReleaseCapturedArguments(&ReceiveMsg); 00819 } 00820 CsrDereferenceThread(CsrThread); 00821 ReplyPort = CsrApiPort; 00822 } 00823 else if (Reply == 2) 00824 { 00825 NtReplyPort(ReplyPort, &ReplyMsg->Header); 00826 ReplyPort = CsrApiPort; 00827 ReplyMsg = NULL; 00828 CsrDereferenceThread(CsrThread); 00829 } 00830 else if (Reply == 1) 00831 { 00832 ReplyPort = CsrApiPort; 00833 ReplyMsg = NULL; 00834 } 00835 else 00836 { 00837 if (ReceiveMsg.CsrCaptureData) 00838 { 00839 CsrReleaseCapturedArguments(&ReceiveMsg); 00840 } 00841 CsrDereferenceThread(CsrThread); 00842 } 00843 } 00844 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation())) 00845 { 00846 ReplyMsg = NULL; 00847 ReplyPort = CsrApiPort; 00848 } 00849 _SEH2_END; 00850 } 00851 00852 /* We're out of the loop for some reason, terminate! */ 00853 NtTerminateThread(NtCurrentThread(), Status); 00854 return Status; 00855 } 00856 00857 /*++ 00858 * @name CsrApiHandleConnectionRequest 00859 * 00860 * The CsrApiHandleConnectionRequest routine handles and accepts a new 00861 * connection request to the CSR API LPC Port. 00862 * 00863 * @param ApiMessage 00864 * Pointer to the incoming CSR API Message which contains the 00865 * connection request. 00866 * 00867 * @return STATUS_SUCCESS in case of success, or status code which caused 00868 * the routine to error. 00869 * 00870 * @remarks This routine is responsible for attaching the Shared Section to 00871 * new clients connecting to CSR. 00872 * 00873 *--*/ 00874 NTSTATUS 00875 NTAPI 00876 CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage) 00877 { 00878 PCSR_THREAD CsrThread = NULL; 00879 PCSR_PROCESS CsrProcess = NULL; 00880 NTSTATUS Status = STATUS_SUCCESS; 00881 PCSR_CONNECTION_INFO ConnectInfo = &ApiMessage->ConnectionInfo; 00882 BOOLEAN AllowConnection = FALSE; 00883 REMOTE_PORT_VIEW RemotePortView; 00884 HANDLE hPort; 00885 00886 /* Acquire the Process Lock */ 00887 CsrAcquireProcessLock(); 00888 00889 /* Lookup the CSR Thread */ 00890 CsrThread = CsrLocateThreadByClientId(NULL, &ApiMessage->Header.ClientId); 00891 00892 /* Check if we have a thread */ 00893 if (CsrThread) 00894 { 00895 /* Get the Process */ 00896 CsrProcess = CsrThread->Process; 00897 00898 /* Make sure we have a Process as well */ 00899 if (CsrProcess) 00900 { 00901 /* Reference the Process */ 00902 CsrLockedReferenceProcess(CsrThread->Process); 00903 00904 /* Release the lock */ 00905 CsrReleaseProcessLock(); 00906 00907 /* Duplicate the Object Directory */ 00908 Status = NtDuplicateObject(NtCurrentProcess(), 00909 CsrObjectDirectory, 00910 CsrProcess->ProcessHandle, 00911 &ConnectInfo->ObjectDirectory, 00912 0, 00913 0, 00914 DUPLICATE_SAME_ACCESS | 00915 DUPLICATE_SAME_ATTRIBUTES); 00916 00917 /* Acquire the lock */ 00918 CsrAcquireProcessLock(); 00919 00920 /* Check for success */ 00921 if (NT_SUCCESS(Status)) 00922 { 00923 /* Attach the Shared Section */ 00924 Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo); 00925 00926 /* Check how this went */ 00927 if (NT_SUCCESS(Status)) AllowConnection = TRUE; 00928 } 00929 00930 /* Dereference the project */ 00931 CsrLockedDereferenceProcess(CsrProcess); 00932 } 00933 } 00934 00935 /* Release the lock */ 00936 CsrReleaseProcessLock(); 00937 00938 /* Setup the Port View Structure */ 00939 RemotePortView.Length = sizeof(REMOTE_PORT_VIEW); 00940 RemotePortView.ViewSize = 0; 00941 RemotePortView.ViewBase = NULL; 00942 00943 /* Save the Process ID */ 00944 ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess; 00945 00946 /* Accept the Connection */ 00947 Status = NtAcceptConnectPort(&hPort, 00948 AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0, 00949 &ApiMessage->Header, 00950 AllowConnection, 00951 NULL, 00952 &RemotePortView); 00953 if (!NT_SUCCESS(Status)) 00954 { 00955 DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status); 00956 } 00957 else if (AllowConnection) 00958 { 00959 if (CsrDebug & 2) 00960 { 00961 DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n", 00962 ApiMessage->Header.ClientId.UniqueProcess, 00963 ApiMessage->Header.ClientId.UniqueThread, 00964 RemotePortView.ViewBase, 00965 RemotePortView.ViewSize); 00966 } 00967 00968 /* Set some Port Data in the Process */ 00969 CsrProcess->ClientPort = hPort; 00970 CsrProcess->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase; 00971 CsrProcess->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase + 00972 (ULONG_PTR)RemotePortView.ViewSize); 00973 00974 /* Complete the connection */ 00975 Status = NtCompleteConnectPort(hPort); 00976 if (!NT_SUCCESS(Status)) 00977 { 00978 DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status); 00979 } 00980 } 00981 else 00982 { 00983 DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n", 00984 ApiMessage->Header.ClientId.UniqueProcess, 00985 ApiMessage->Header.ClientId.UniqueThread); 00986 } 00987 00988 /* Return status to caller */ 00989 return Status; 00990 } 00991 00992 /*++ 00993 * @name CsrSbApiRequestThread 00994 * 00995 * The CsrSbApiRequestThread routine handles incoming messages or connection 00996 * requests on the SM API LPC Port. 00997 * 00998 * @param Parameter 00999 * System-default user-defined parameter. Unused. 01000 * 01001 * @return The thread exit code, if the thread is terminated. 01002 * 01003 * @remarks Before listening on the port, the routine will first attempt 01004 * to connect to the user subsystem. 01005 * 01006 *--*/ 01007 VOID 01008 NTAPI 01009 CsrSbApiRequestThread(IN PVOID Parameter) 01010 { 01011 NTSTATUS Status; 01012 SB_API_MSG ReceiveMsg; 01013 PSB_API_MSG ReplyMsg = NULL; 01014 PVOID PortContext; 01015 ULONG MessageType; 01016 01017 /* Start the loop */ 01018 while (TRUE) 01019 { 01020 /* Wait for a message to come in */ 01021 Status = NtReplyWaitReceivePort(CsrSbApiPort, 01022 &PortContext, 01023 &ReplyMsg->h, 01024 &ReceiveMsg.h); 01025 01026 /* Check if we didn't get success */ 01027 if (Status != STATUS_SUCCESS) 01028 { 01029 /* If we only got a warning, keep going */ 01030 if (NT_SUCCESS(Status)) continue; 01031 01032 /* We failed big time, so start out fresh */ 01033 ReplyMsg = NULL; 01034 DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status); 01035 continue; 01036 } 01037 01038 /* Save the message type */ 01039 MessageType = ReceiveMsg.h.u2.s2.Type; 01040 01041 /* Check if this is a connection request */ 01042 if (MessageType == LPC_CONNECTION_REQUEST) 01043 { 01044 /* Handle connection request */ 01045 CsrSbApiHandleConnectionRequest(&ReceiveMsg); 01046 01047 /* Start over */ 01048 ReplyMsg = NULL; 01049 continue; 01050 } 01051 01052 /* Check if the port died */ 01053 if (MessageType == LPC_PORT_CLOSED) 01054 { 01055 /* Close the handle if we have one */ 01056 if (PortContext) NtClose((HANDLE)PortContext); 01057 01058 /* Client died, start over */ 01059 ReplyMsg = NULL; 01060 continue; 01061 } 01062 else if (MessageType == LPC_CLIENT_DIED) 01063 { 01064 /* Client died, start over */ 01065 ReplyMsg = NULL; 01066 continue; 01067 } 01068 01069 /* 01070 * It's an API Message, check if it's within limits. If it's not, the 01071 * NT Behaviour is to set this to the Maximum API. 01072 */ 01073 if (ReceiveMsg.ApiNumber > SbpMaxApiNumber) 01074 { 01075 ReceiveMsg.ApiNumber = SbpMaxApiNumber; 01076 DPRINT1("CSRSS: %lx is invalid Sb ApiNumber\n", ReceiveMsg.ApiNumber); 01077 } 01078 01079 /* Reuse the message */ 01080 ReplyMsg = &ReceiveMsg; 01081 01082 /* Make sure that the message is supported */ 01083 if (ReceiveMsg.ApiNumber < SbpMaxApiNumber) 01084 { 01085 /* Call the API */ 01086 if (!CsrServerSbApiDispatch[ReceiveMsg.ApiNumber](&ReceiveMsg)) 01087 { 01088 /* It failed, so return nothing */ 01089 ReplyMsg = NULL; 01090 } 01091 } 01092 else 01093 { 01094 /* We don't support this API Number */ 01095 ReplyMsg->ReturnValue = STATUS_NOT_IMPLEMENTED; 01096 } 01097 } 01098 } 01099 01100 /*++ 01101 * @name CsrSbApiHandleConnectionRequest 01102 * 01103 * The CsrSbApiHandleConnectionRequest routine handles and accepts a new 01104 * connection request to the SM API LPC Port. 01105 * 01106 * @param ApiMessage 01107 * Pointer to the incoming CSR API Message which contains the 01108 * connection request. 01109 * 01110 * @return STATUS_SUCCESS in case of success, or status code which caused 01111 * the routine to error. 01112 * 01113 * @remarks None. 01114 * 01115 *--*/ 01116 NTSTATUS 01117 NTAPI 01118 CsrSbApiHandleConnectionRequest(IN PSB_API_MSG Message) 01119 { 01120 NTSTATUS Status; 01121 REMOTE_PORT_VIEW RemotePortView; 01122 HANDLE hPort; 01123 01124 /* Set the Port View Structure Length */ 01125 RemotePortView.Length = sizeof(REMOTE_PORT_VIEW); 01126 01127 /* Accept the connection */ 01128 Status = NtAcceptConnectPort(&hPort, 01129 NULL, 01130 (PPORT_MESSAGE)Message, 01131 TRUE, 01132 NULL, 01133 &RemotePortView); 01134 if (!NT_SUCCESS(Status)) 01135 { 01136 DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status); 01137 return Status; 01138 } 01139 01140 /* Complete the Connection */ 01141 Status = NtCompleteConnectPort(hPort); 01142 if (!NT_SUCCESS(Status)) 01143 { 01144 DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status); 01145 } 01146 01147 /* Return status */ 01148 return Status; 01149 } 01150 01151 /* PUBLIC FUNCTIONS **********************************************************/ 01152 01153 /*++ 01154 * @name CsrCallServerFromServer 01155 * @implemented NT4 01156 * 01157 * The CsrCallServerFromServer routine calls a CSR API from within a server. 01158 * It avoids using LPC messages since the request isn't coming from a client. 01159 * 01160 * @param ReceiveMsg 01161 * Pointer to the CSR API Message to send to the server. 01162 * 01163 * @param ReplyMsg 01164 * Pointer to the CSR API Message to receive from the server. 01165 * 01166 * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION 01167 * if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there 01168 * was a problem executing the API. 01169 * 01170 * @remarks None. 01171 * 01172 *--*/ 01173 NTSTATUS 01174 NTAPI 01175 CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg, 01176 PCSR_API_MESSAGE ReplyMsg) 01177 { 01178 ULONG ServerId; 01179 PCSR_SERVER_DLL ServerDll; 01180 ULONG ApiId; 01181 ULONG Reply; 01182 NTSTATUS Status; 01183 01184 /* Get the Server ID */ 01185 ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg->Opcode); 01186 01187 /* Make sure that the ID is within limits, and the Server DLL loaded */ 01188 if ((ServerId >= CSR_SERVER_DLL_MAX) || 01189 (!(ServerDll = CsrLoadedServerDll[ServerId]))) 01190 { 01191 /* We are beyond the Maximum Server ID */ 01192 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll); 01193 ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION; 01194 return STATUS_ILLEGAL_FUNCTION; 01195 } 01196 else 01197 { 01198 /* Get the API ID */ 01199 ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg->Opcode); 01200 01201 /* Normalize it with our Base ID */ 01202 ApiId -= ServerDll->ApiBase; 01203 01204 /* Make sure that the ID is within limits, and the entry exists */ 01205 if ((ApiId >= ServerDll->HighestApiSupported) || 01206 ((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId]))) 01207 { 01208 /* We are beyond the Maximum API ID, or it doesn't exist */ 01209 DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an " 01210 "invalid API to call from the server.\n", 01211 ServerDll->ValidTable[ApiId], 01212 ((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ? 01213 ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name); 01214 DbgBreakPoint(); 01215 ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION; 01216 return STATUS_ILLEGAL_FUNCTION; 01217 } 01218 } 01219 01220 if (CsrDebug & 2) 01221 { 01222 DPRINT1("CSRSS: %s Api Request received from server process\n", 01223 ServerDll->NameTable[ApiId]); 01224 } 01225 01226 /* Validation complete, start SEH */ 01227 _SEH2_TRY 01228 { 01229 /* Call the API and get the result */ 01230 Status = ServerDll->DispatchTable[ApiId](ReceiveMsg, &Reply); 01231 01232 /* Return the result, no matter what it is */ 01233 ReplyMsg->Status = Status; 01234 } 01235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01236 { 01237 /* If we got an exception, return access violation */ 01238 ReplyMsg->Status = STATUS_ACCESS_VIOLATION; 01239 } 01240 _SEH2_END; 01241 01242 /* Return success */ 01243 return STATUS_SUCCESS; 01244 } 01245 01246 /*++ 01247 * @name CsrConnectToUser 01248 * @implemented NT4 01249 * 01250 * The CsrConnectToUser connects to the User subsystem. 01251 * 01252 * @param None 01253 * 01254 * @return A pointer to the CSR Thread 01255 * 01256 * @remarks None. 01257 * 01258 *--*/ 01259 PCSR_THREAD 01260 NTAPI 01261 CsrConnectToUser(VOID) 01262 { 01263 NTSTATUS Status; 01264 ANSI_STRING DllName; 01265 UNICODE_STRING TempName; 01266 HANDLE hUser32; 01267 STRING StartupName; 01268 PTEB Teb = NtCurrentTeb(); 01269 PCSR_THREAD CsrThread; 01270 BOOLEAN Connected; 01271 01272 /* Check if we didn't already find it */ 01273 if (!CsrClientThreadSetup) 01274 { 01275 /* Get the DLL Handle for user32.dll */ 01276 RtlInitAnsiString(&DllName, "user32"); 01277 RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE); 01278 Status = LdrGetDllHandle(NULL, 01279 NULL, 01280 &TempName, 01281 &hUser32); 01282 RtlFreeUnicodeString(&TempName); 01283 01284 /* If we got teh handle, get the Client Thread Startup Entrypoint */ 01285 if (NT_SUCCESS(Status)) 01286 { 01287 RtlInitAnsiString(&StartupName,"ClientThreadSetup"); 01288 Status = LdrGetProcedureAddress(hUser32, 01289 &StartupName, 01290 0, 01291 (PVOID)&CsrClientThreadSetup); 01292 } 01293 } 01294 01295 /* Connect to user32 */ 01296 _SEH2_TRY 01297 { 01298 Connected = CsrClientThreadSetup(); 01299 } 01300 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01301 { 01302 Connected = FALSE; 01303 } _SEH2_END; 01304 01305 if (!Connected) 01306 { 01307 DPRINT1("CSRSS: CsrConnectToUser failed\n"); 01308 return NULL; 01309 } 01310 01311 /* Save pointer to this thread in TEB */ 01312 CsrAcquireProcessLock(); 01313 CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId); 01314 CsrReleaseProcessLock(); 01315 if (CsrThread) Teb->CsrClientThread = CsrThread; 01316 01317 /* Return it */ 01318 return CsrThread; 01319 } 01320 01321 /*++ 01322 * @name CsrQueryApiPort 01323 * @implemented NT4 01324 * 01325 * The CsrQueryApiPort routine returns a handle to the CSR API LPC port. 01326 * 01327 * @param None. 01328 * 01329 * @return A handle to the port. 01330 * 01331 * @remarks None. 01332 * 01333 *--*/ 01334 HANDLE 01335 NTAPI 01336 CsrQueryApiPort(VOID) 01337 { 01338 DPRINT("CSRSRV: %s called\n", __FUNCTION__); 01339 return CsrApiPort; 01340 } 01341 01342 /*++ 01343 * @name CsrCaptureArguments 01344 * @implemented NT5.1 01345 * 01346 * The CsrCaptureArguments routine validates a CSR Capture Buffer and 01347 * re-captures it into a server CSR Capture Buffer. 01348 * 01349 * @param CsrThread 01350 * Pointer to the CSR Thread performing the validation. 01351 * 01352 * @param ApiMessage 01353 * Pointer to the CSR API Message containing the Capture Buffer 01354 * that needs to be validated. 01355 * 01356 * @return TRUE if validation succeeded, FALSE otherwise. 01357 * 01358 * @remarks None. 01359 * 01360 *--*/ 01361 BOOLEAN 01362 NTAPI 01363 CsrCaptureArguments(IN PCSR_THREAD CsrThread, 01364 IN PCSR_API_MESSAGE ApiMessage) 01365 { 01366 PCSR_CAPTURE_BUFFER LocalCaptureBuffer = NULL, RemoteCaptureBuffer = NULL; 01367 ULONG LocalLength = 0, PointerCount = 0; 01368 SIZE_T BufferDistance = 0; 01369 ULONG_PTR **PointerOffsets = NULL, *CurrentPointer = NULL; 01370 01371 /* Use SEH to make sure this is valid */ 01372 _SEH2_TRY 01373 { 01374 /* Get the buffer we got from whoever called NTDLL */ 01375 LocalCaptureBuffer = ApiMessage->CsrCaptureData; 01376 LocalLength = LocalCaptureBuffer->Size; 01377 01378 /* Now check if the buffer is inside our mapped section */ 01379 if (((ULONG_PTR)LocalCaptureBuffer < CsrThread->Process->ClientViewBase) || 01380 (((ULONG_PTR)LocalCaptureBuffer + LocalLength) >= CsrThread->Process->ClientViewBounds)) 01381 { 01382 /* Return failure */ 01383 DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView\n"); 01384 ApiMessage->Status = STATUS_INVALID_PARAMETER; 01385 _SEH2_YIELD(return FALSE); 01386 } 01387 01388 /* Check if the Length is valid */ 01389 if (((LocalCaptureBuffer->PointerCount * 4 + sizeof(CSR_CAPTURE_BUFFER)) > 01390 LocalLength) ||(LocalLength > MAXWORD)) 01391 { 01392 /* Return failure */ 01393 DPRINT1("*** CSRSS: CaptureBuffer %p has bad length\n", LocalCaptureBuffer); 01394 DbgBreakPoint(); 01395 ApiMessage->Status = STATUS_INVALID_PARAMETER; 01396 _SEH2_YIELD(return FALSE); 01397 } 01398 } 01399 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01400 { 01401 /* Return failure */ 01402 ApiMessage->Status = STATUS_INVALID_PARAMETER; 01403 _SEH2_YIELD(return FALSE); 01404 } _SEH2_END; 01405 01406 /* We validated the incoming buffer, now allocate the remote one */ 01407 RemoteCaptureBuffer = RtlAllocateHeap(CsrHeap, 0, LocalLength); 01408 if (!RemoteCaptureBuffer) 01409 { 01410 /* We're out of memory */ 01411 ApiMessage->Status = STATUS_NO_MEMORY; 01412 return FALSE; 01413 } 01414 01415 /* Copy the client's buffer */ 01416 RtlMoveMemory(RemoteCaptureBuffer, LocalCaptureBuffer, LocalLength); 01417 01418 /* Copy the length */ 01419 RemoteCaptureBuffer->Size = LocalLength; 01420 01421 /* Calculate the difference between our buffer and the client's */ 01422 BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer; 01423 01424 /* Save the pointer count and offset pointer */ 01425 PointerCount = RemoteCaptureBuffer->PointerCount; 01426 PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1); 01427 01428 /* Start the loop */ 01429 while (PointerCount) 01430 { 01431 /* Get the current pointer */ 01432 if ((CurrentPointer = *PointerOffsets++)) 01433 { 01434 /* Add it to the CSR Message structure */ 01435 CurrentPointer += (ULONG_PTR)ApiMessage; 01436 01437 /* Validate the bounds of the current pointer */ 01438 if ((*CurrentPointer >= CsrThread->Process->ClientViewBase) && 01439 (*CurrentPointer < CsrThread->Process->ClientViewBounds)) 01440 { 01441 /* Modify the pointer to take into account its new position */ 01442 *CurrentPointer += BufferDistance; 01443 } 01444 else 01445 { 01446 /* Invalid pointer, fail */ 01447 DPRINT1("*** CSRSS: CaptureBuffer MessagePointer outside of ClientView\n"); 01448 DbgBreakPoint(); 01449 ApiMessage->Status = STATUS_INVALID_PARAMETER; 01450 } 01451 } 01452 01453 /* Move to the next Pointer */ 01454 PointerCount--; 01455 } 01456 01457 /* Check if we got success */ 01458 if (ApiMessage->Status != STATUS_SUCCESS) 01459 { 01460 /* Failure. Free the buffer and return*/ 01461 RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer); 01462 return FALSE; 01463 } 01464 else 01465 { 01466 /* Success, save the previous buffer */ 01467 RemoteCaptureBuffer->PreviousCaptureBuffer = LocalCaptureBuffer; 01468 ApiMessage->CsrCaptureData = RemoteCaptureBuffer; 01469 } 01470 01471 /* Success */ 01472 return TRUE; 01473 } 01474 01475 /*++ 01476 * @name CsrReleaseCapturedArguments 01477 * @implemented NT5.1 01478 * 01479 * The CsrReleaseCapturedArguments routine releases a Capture Buffer 01480 * that was previously captured with CsrCaptureArguments. 01481 * 01482 * @param ApiMessage 01483 * Pointer to the CSR API Message containing the Capture Buffer 01484 * that needs to be released. 01485 * 01486 * @return None. 01487 * 01488 * @remarks None. 01489 * 01490 *--*/ 01491 VOID 01492 NTAPI 01493 CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage) 01494 { 01495 PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer; 01496 SIZE_T BufferDistance; 01497 ULONG PointerCount; 01498 ULONG_PTR **PointerOffsets, *CurrentPointer; 01499 01500 /* Get the capture buffers */ 01501 RemoteCaptureBuffer = ApiMessage->CsrCaptureData; 01502 LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer; 01503 01504 /* Free the previous one */ 01505 RemoteCaptureBuffer->PreviousCaptureBuffer = NULL; 01506 01507 /* Find out the difference between the two buffers */ 01508 BufferDistance = (ULONG_PTR)LocalCaptureBuffer - (ULONG_PTR)RemoteCaptureBuffer; 01509 01510 /* Save the pointer count and offset pointer */ 01511 PointerCount = RemoteCaptureBuffer->PointerCount; 01512 PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1); 01513 01514 /* Start the loop */ 01515 while (PointerCount) 01516 { 01517 /* Get the current pointer */ 01518 CurrentPointer = *PointerOffsets++; 01519 if (CurrentPointer) 01520 { 01521 /* Add it to the CSR Message structure */ 01522 CurrentPointer += (ULONG_PTR)ApiMessage; 01523 01524 /* Modify the pointer to take into account its new position */ 01525 *CurrentPointer += BufferDistance; 01526 } 01527 01528 /* Move to the next Pointer */ 01529 PointerCount--; 01530 } 01531 01532 /* Copy the data back */ 01533 RtlMoveMemory(LocalCaptureBuffer, RemoteCaptureBuffer, RemoteCaptureBuffer->Size); 01534 01535 /* Free our allocated buffer */ 01536 RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer); 01537 } 01538 01539 /*++ 01540 * @name CsrValidateMessageBuffer 01541 * @implemented NT5.1 01542 * 01543 * The CsrValidateMessageBuffer routine validates a captured message buffer 01544 * present in the CSR Api Message 01545 * 01546 * @param ApiMessage 01547 * Pointer to the CSR API Message containing the CSR Capture Buffer. 01548 * 01549 * @param Buffer 01550 * Pointer to the message buffer to validate. 01551 * 01552 * @param ArgumentSize 01553 * Size of the message to check. 01554 * 01555 * @param ArgumentCount 01556 * Number of messages to check. 01557 * 01558 * @return TRUE if validation suceeded, FALSE otherwise. 01559 * 01560 * @remarks None. 01561 * 01562 *--*/ 01563 BOOLEAN 01564 NTAPI 01565 CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage, 01566 IN PVOID *Buffer, 01567 IN ULONG ArgumentSize, 01568 IN ULONG ArgumentCount) 01569 { 01570 PCSR_CAPTURE_BUFFER CaptureBuffer = ApiMessage->CsrCaptureData; 01571 SIZE_T BufferDistance; 01572 ULONG PointerCount, i; 01573 ULONG_PTR **PointerOffsets, *CurrentPointer; 01574 01575 /* Make sure there are some arguments */ 01576 if (!ArgumentCount) return FALSE; 01577 01578 /* Check if didn't get a buffer and there aren't any arguments to check */ 01579 if (!(*Buffer) && (!(ArgumentCount * ArgumentSize))) return TRUE; 01580 01581 /* Check if we have no capture buffer */ 01582 if (!CaptureBuffer) 01583 { 01584 /* In this case, check only the Process ID */ 01585 if (NtCurrentTeb()->ClientId.UniqueProcess == 01586 ApiMessage->Header.ClientId.UniqueProcess) 01587 { 01588 /* There is a match, validation succeeded */ 01589 return TRUE; 01590 } 01591 } 01592 else 01593 { 01594 /* Make sure that there is still space left in the buffer */ 01595 if ((CaptureBuffer->Size - (ULONG_PTR)*Buffer + (ULONG_PTR)CaptureBuffer) < 01596 (ArgumentCount * ArgumentSize)) 01597 { 01598 /* Find out the difference between the two buffers */ 01599 BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage; 01600 01601 /* Save the pointer count */ 01602 PointerCount = CaptureBuffer->PointerCount; 01603 PointerOffsets = (ULONG_PTR**)(CaptureBuffer + 1); 01604 01605 /* Start the loop */ 01606 for (i = 0; i < PointerCount; i++) 01607 { 01608 /* Get the current pointer */ 01609 CurrentPointer = *PointerOffsets++; 01610 01611 /* Check if its' equal to the difference */ 01612 if (*CurrentPointer == BufferDistance) return TRUE; 01613 } 01614 } 01615 } 01616 01617 /* Failure */ 01618 DbgPrint("CSRSRV: Bad message buffer %p\n", ApiMessage); 01619 DbgBreakPoint(); 01620 return FALSE; 01621 } 01622 01623 /*++ 01624 * @name CsrValidateMessageString 01625 * @implemented NT5.1 01626 * 01627 * The CsrValidateMessageString validates a captured Wide-Character String 01628 * present in a CSR API Message. 01629 * 01630 * @param ApiMessage 01631 * Pointer to the CSR API Message containing the CSR Capture Buffer. 01632 * 01633 * @param MessageString 01634 * Pointer to the buffer containing the string to validate. 01635 * 01636 * @return TRUE if validation suceeded, FALSE otherwise. 01637 * 01638 * @remarks None. 01639 * 01640 *--*/ 01641 BOOLEAN 01642 NTAPI 01643 CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage, 01644 IN LPWSTR *MessageString) 01645 { 01646 DPRINT1("CSRSRV: %s called\n", __FUNCTION__); 01647 return FALSE; 01648 } 01649 01650 /* EOF */ Generated on Sun May 27 2012 04:22:34 for ReactOS by
1.7.6.1
|