Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwapi.c
Go to the documentation of this file.
00001 /* $Id: wapi.c 55722 2012-02-19 20:16:36Z ion $ 00002 * 00003 * subsystems/win32/csrss/csrsrv/api/wapi.c 00004 * 00005 * CSRSS port message processing 00006 * 00007 * ReactOS Operating System 00008 * 00009 */ 00010 00011 /* INCLUDES ******************************************************************/ 00012 00013 #include <srv.h> 00014 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 /* GLOBALS *******************************************************************/ 00019 00020 static unsigned ApiDefinitionsCount = 0; 00021 static PCSRSS_API_DEFINITION ApiDefinitions = NULL; 00022 UNICODE_STRING CsrApiPortName; 00023 volatile LONG CsrpStaticThreadCount; 00024 volatile LONG CsrpDynamicThreadTotal; 00025 ULONG CsrMaxApiRequestThreads; 00026 00027 /* FUNCTIONS *****************************************************************/ 00028 00029 NTSTATUS FASTCALL 00030 CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions) 00031 { 00032 unsigned NewCount; 00033 PCSRSS_API_DEFINITION Scan; 00034 PCSRSS_API_DEFINITION New; 00035 00036 DPRINT("CSR: %s called\n", __FUNCTION__); 00037 00038 NewCount = 0; 00039 for (Scan = NewDefinitions; 0 != Scan->Handler; Scan++) 00040 { 00041 NewCount++; 00042 } 00043 00044 New = RtlAllocateHeap(CsrHeap, 0, 00045 (ApiDefinitionsCount + NewCount) 00046 * sizeof(CSRSS_API_DEFINITION)); 00047 if (NULL == New) 00048 { 00049 DPRINT1("Unable to allocate memory\n"); 00050 return STATUS_NO_MEMORY; 00051 } 00052 if (0 != ApiDefinitionsCount) 00053 { 00054 RtlCopyMemory(New, ApiDefinitions, 00055 ApiDefinitionsCount * sizeof(CSRSS_API_DEFINITION)); 00056 RtlFreeHeap(CsrHeap, 0, ApiDefinitions); 00057 } 00058 RtlCopyMemory(New + ApiDefinitionsCount, NewDefinitions, 00059 NewCount * sizeof(CSRSS_API_DEFINITION)); 00060 ApiDefinitions = New; 00061 ApiDefinitionsCount += NewCount; 00062 00063 return STATUS_SUCCESS; 00064 } 00065 00066 VOID 00067 FASTCALL 00068 CsrApiCallHandler(PCSR_PROCESS ProcessData, 00069 PCSR_API_MESSAGE Request) 00070 { 00071 unsigned DefIndex; 00072 ULONG Type; 00073 00074 DPRINT("CSR: Calling handler for type: %x.\n", Request->Type); 00075 Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */ 00076 DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16); 00077 00078 /* FIXME: Extract DefIndex instead of looping */ 00079 for (DefIndex = 0; DefIndex < ApiDefinitionsCount; DefIndex++) 00080 { 00081 if (ApiDefinitions[DefIndex].Type == Type) 00082 { 00083 if (Request->Header.u1.s1.DataLength < ApiDefinitions[DefIndex].MinRequestSize) 00084 { 00085 DPRINT1("Request type %d min request size %d actual %d\n", 00086 Type, ApiDefinitions[DefIndex].MinRequestSize, 00087 Request->Header.u1.s1.DataLength); 00088 Request->Status = STATUS_INVALID_PARAMETER; 00089 } 00090 else 00091 { 00092 Request->Status = (ApiDefinitions[DefIndex].Handler)(ProcessData, Request); 00093 } 00094 return; 00095 } 00096 } 00097 DPRINT1("CSR: Unknown request type 0x%x\n", Request->Type); 00098 Request->Status = STATUS_INVALID_SYSTEM_SERVICE; 00099 } 00100 00101 VOID 00102 CallHardError(IN PCSR_THREAD ThreadData, 00103 IN PHARDERROR_MSG HardErrorMessage); 00104 00105 static 00106 VOID 00107 NTAPI 00108 CsrHandleHardError(IN PCSR_THREAD ThreadData, 00109 IN OUT PHARDERROR_MSG Message) 00110 { 00111 DPRINT1("CSR: received hard error %lx\n", Message->Status); 00112 00113 /* Call the hard error handler in win32csr */ 00114 CallHardError(ThreadData, Message); 00115 } 00116 00117 /*++ 00118 * @name CsrCallServerFromServer 00119 * @implemented NT4 00120 * 00121 * The CsrCallServerFromServer routine calls a CSR API from within a server. 00122 * It avoids using LPC messages since the request isn't coming from a client. 00123 * 00124 * @param ReceiveMsg 00125 * Pointer to the CSR API Message to send to the server. 00126 * 00127 * @param ReplyMsg 00128 * Pointer to the CSR API Message to receive from the server. 00129 * 00130 * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION 00131 * if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there 00132 * was a problem executing the API. 00133 * 00134 * @remarks None. 00135 * 00136 *--*/ 00137 NTSTATUS 00138 NTAPI 00139 CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg, 00140 PCSR_API_MESSAGE ReplyMsg) 00141 { 00142 #if 0 // real code 00143 ULONG ServerId; 00144 PCSR_SERVER_DLL ServerDll; 00145 ULONG ApiId; 00146 ULONG Reply; 00147 NTSTATUS Status; 00148 00149 /* Get the Server ID */ 00150 ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg->Opcode); 00151 00152 /* Make sure that the ID is within limits, and the Server DLL loaded */ 00153 if ((ServerId >= CSR_SERVER_DLL_MAX) || 00154 (!(ServerDll = CsrLoadedServerDll[ServerId]))) 00155 { 00156 /* We are beyond the Maximum Server ID */ 00157 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll); 00158 ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION; 00159 return STATUS_ILLEGAL_FUNCTION; 00160 } 00161 else 00162 { 00163 /* Get the API ID */ 00164 ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg->Opcode); 00165 00166 /* Normalize it with our Base ID */ 00167 ApiId -= ServerDll->ApiBase; 00168 00169 /* Make sure that the ID is within limits, and the entry exists */ 00170 if ((ApiId >= ServerDll->HighestApiSupported) || 00171 ((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId]))) 00172 { 00173 /* We are beyond the Maximum API ID, or it doesn't exist */ 00174 DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an " 00175 "invalid API to call from the server.\n", 00176 ServerDll->ValidTable[ApiId], 00177 ((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ? 00178 ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name); 00179 DbgBreakPoint(); 00180 ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION; 00181 return STATUS_ILLEGAL_FUNCTION; 00182 } 00183 } 00184 00185 if (CsrDebug & 2) 00186 { 00187 DPRINT1("CSRSS: %s Api Request received from server process\n", 00188 ServerDll->NameTable[ApiId]); 00189 } 00190 00191 /* Validation complete, start SEH */ 00192 _SEH2_TRY 00193 { 00194 /* Call the API and get the result */ 00195 Status = (ServerDll->DispatchTable[ApiId])(ReceiveMsg, &Reply); 00196 00197 /* Return the result, no matter what it is */ 00198 ReplyMsg->Status = Status; 00199 } 00200 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00201 { 00202 /* If we got an exception, return access violation */ 00203 ReplyMsg->Status = STATUS_ACCESS_VIOLATION; 00204 } 00205 _SEH2_END; 00206 00207 /* Return success */ 00208 return STATUS_SUCCESS; 00209 #else // Hacky reactos code 00210 PCSR_PROCESS ProcessData; 00211 00212 /* Get the Process Data */ 00213 CsrLockProcessByClientId(&ReceiveMsg->Header.ClientId.UniqueProcess, &ProcessData); 00214 if (!ProcessData) 00215 { 00216 DPRINT1("Message: Unable to find data for process 0x%x\n", 00217 ReceiveMsg->Header.ClientId.UniqueProcess); 00218 return STATUS_NOT_SUPPORTED; 00219 } 00220 00221 /* Validation complete, start SEH */ 00222 _SEH2_TRY 00223 { 00224 /* Call the API and get the result */ 00225 CsrApiCallHandler(ProcessData, ReplyMsg); 00226 } 00227 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00228 { 00229 /* If we got an exception, return access violation */ 00230 ReplyMsg->Status = STATUS_ACCESS_VIOLATION; 00231 } 00232 _SEH2_END; 00233 00234 /* Release the process reference */ 00235 CsrUnlockProcess(ProcessData); 00236 00237 /* Return success */ 00238 return STATUS_SUCCESS; 00239 #endif 00240 } 00241 00242 /*++ 00243 * @name CsrApiPortInitialize 00244 * 00245 * The CsrApiPortInitialize routine initializes the LPC Port used for 00246 * communications with the Client/Server Runtime (CSR) and initializes the 00247 * static thread that will handle connection requests and APIs. 00248 * 00249 * @param None 00250 * 00251 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL 00252 * othwerwise. 00253 * 00254 * @remarks None. 00255 * 00256 *--*/ 00257 NTSTATUS 00258 NTAPI 00259 CsrApiPortInitialize(VOID) 00260 { 00261 ULONG Size; 00262 OBJECT_ATTRIBUTES ObjectAttributes; 00263 NTSTATUS Status; 00264 HANDLE hRequestEvent, hThread; 00265 CLIENT_ID ClientId; 00266 PLIST_ENTRY ListHead, NextEntry; 00267 PCSR_THREAD ServerThread; 00268 00269 /* Calculate how much space we'll need for the Port Name */ 00270 Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR); 00271 00272 /* Create the buffer for it */ 00273 CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size); 00274 if (!CsrApiPortName.Buffer) return STATUS_NO_MEMORY; 00275 00276 /* Setup the rest of the empty string */ 00277 CsrApiPortName.Length = 0; 00278 CsrApiPortName.MaximumLength = (USHORT)Size; 00279 RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName); 00280 RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP); 00281 RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME); 00282 if (CsrDebug & 1) 00283 { 00284 DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName); 00285 DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n", 00286 sizeof(CSR_CONNECTION_INFO), sizeof(CSR_API_MESSAGE)); 00287 } 00288 00289 /* FIXME: Create a Security Descriptor */ 00290 00291 /* Initialize the Attributes */ 00292 InitializeObjectAttributes(&ObjectAttributes, 00293 &CsrApiPortName, 00294 0, 00295 NULL, 00296 NULL /* FIXME*/); 00297 00298 /* Create the Port Object */ 00299 Status = NtCreatePort(&CsrApiPort, 00300 &ObjectAttributes, 00301 LPC_MAX_DATA_LENGTH, // hack 00302 LPC_MAX_MESSAGE_LENGTH, // hack 00303 16 * PAGE_SIZE); 00304 if (NT_SUCCESS(Status)) 00305 { 00306 /* Create the event the Port Thread will use */ 00307 Status = NtCreateEvent(&hRequestEvent, 00308 EVENT_ALL_ACCESS, 00309 NULL, 00310 SynchronizationEvent, 00311 FALSE); 00312 if (NT_SUCCESS(Status)) 00313 { 00314 /* Create the Request Thread */ 00315 Status = RtlCreateUserThread(NtCurrentProcess(), 00316 NULL, 00317 TRUE, 00318 0, 00319 0, 00320 0, 00321 (PVOID)ClientConnectionThread,//CsrApiRequestThread, 00322 (PVOID)hRequestEvent, 00323 &hThread, 00324 &ClientId); 00325 if (NT_SUCCESS(Status)) 00326 { 00327 /* Add this as a static thread to CSRSRV */ 00328 CsrAddStaticServerThread(hThread, &ClientId, CsrThreadIsServerThread); 00329 00330 /* Get the Thread List Pointers */ 00331 ListHead = &CsrRootProcess->ThreadList; 00332 NextEntry = ListHead->Flink; 00333 00334 /* Start looping the list */ 00335 while (NextEntry != ListHead) 00336 { 00337 /* Get the Thread */ 00338 ServerThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link); 00339 00340 /* Start it up */ 00341 Status = NtResumeThread(ServerThread->ThreadHandle, NULL); 00342 00343 /* Is this a Server Thread? */ 00344 if (ServerThread->Flags & CsrThreadIsServerThread) 00345 { 00346 /* If so, then wait for it to initialize */ 00347 Status = NtWaitForSingleObject(hRequestEvent, FALSE, NULL); 00348 ASSERT(NT_SUCCESS(Status)); 00349 } 00350 00351 /* Next thread */ 00352 NextEntry = NextEntry->Flink; 00353 } 00354 00355 /* We don't need this anymore */ 00356 NtClose(hRequestEvent); 00357 } 00358 } 00359 } 00360 00361 /* Return */ 00362 return Status; 00363 } 00364 00365 PBASE_STATIC_SERVER_DATA BaseStaticServerData; 00366 00367 NTSTATUS 00368 NTAPI 00369 CreateBaseAcls(OUT PACL* Dacl, 00370 OUT PACL* RestrictedDacl) 00371 { 00372 PSID SystemSid, WorldSid, RestrictedSid; 00373 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; 00374 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; 00375 NTSTATUS Status; 00376 UCHAR KeyValueBuffer[0x40]; 00377 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo; 00378 UNICODE_STRING KeyName; 00379 ULONG ProtectionMode = 0; 00380 ULONG AclLength, ResultLength; 00381 HANDLE hKey; 00382 OBJECT_ATTRIBUTES ObjectAttributes; 00383 00384 /* Open the Session Manager Key */ 00385 RtlInitUnicodeString(&KeyName, SM_REG_KEY); 00386 InitializeObjectAttributes(&ObjectAttributes, 00387 &KeyName, 00388 OBJ_CASE_INSENSITIVE, 00389 NULL, 00390 NULL); 00391 Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes); 00392 if (NT_SUCCESS(Status)) 00393 { 00394 /* Read the key value */ 00395 RtlInitUnicodeString(&KeyName, L"ProtectionMode"); 00396 Status = NtQueryValueKey(hKey, 00397 &KeyName, 00398 KeyValuePartialInformation, 00399 KeyValueBuffer, 00400 sizeof(KeyValueBuffer), 00401 &ResultLength); 00402 00403 /* Make sure it's what we expect it to be */ 00404 KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer; 00405 if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) && 00406 (*(PULONG)KeyValuePartialInfo->Data)) 00407 { 00408 /* Save the Protection Mode */ 00409 ProtectionMode = *(PULONG)KeyValuePartialInfo->Data; 00410 } 00411 00412 /* Close the handle */ 00413 NtClose(hKey); 00414 } 00415 00416 /* Allocate the System SID */ 00417 Status = RtlAllocateAndInitializeSid(&NtAuthority, 00418 1, SECURITY_LOCAL_SYSTEM_RID, 00419 0, 0, 0, 0, 0, 0, 0, 00420 &SystemSid); 00421 ASSERT(NT_SUCCESS(Status)); 00422 00423 /* Allocate the World SID */ 00424 Status = RtlAllocateAndInitializeSid(&WorldAuthority, 00425 1, SECURITY_WORLD_RID, 00426 0, 0, 0, 0, 0, 0, 0, 00427 &WorldSid); 00428 ASSERT(NT_SUCCESS(Status)); 00429 00430 /* Allocate the restricted SID */ 00431 Status = RtlAllocateAndInitializeSid(&NtAuthority, 00432 1, SECURITY_RESTRICTED_CODE_RID, 00433 0, 0, 0, 0, 0, 0, 0, 00434 &RestrictedSid); 00435 ASSERT(NT_SUCCESS(Status)); 00436 00437 /* Allocate one ACL with 3 ACEs each for one SID */ 00438 AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + 00439 RtlLengthSid(SystemSid) + 00440 RtlLengthSid(RestrictedSid) + 00441 RtlLengthSid(WorldSid); 00442 *Dacl = RtlAllocateHeap(CsrHeap, 0, AclLength); 00443 ASSERT(*Dacl != NULL); 00444 00445 /* Set the correct header fields */ 00446 Status = RtlCreateAcl(*Dacl, AclLength, ACL_REVISION2); 00447 ASSERT(NT_SUCCESS(Status)); 00448 00449 /* Give the appropriate rights to each SID */ 00450 /* FIXME: Should check SessionId/ProtectionMode */ 00451 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid); 00452 ASSERT(NT_SUCCESS(Status)); 00453 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid); 00454 ASSERT(NT_SUCCESS(Status)); 00455 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid); 00456 ASSERT(NT_SUCCESS(Status)); 00457 00458 /* Now allocate the restricted DACL */ 00459 *RestrictedDacl = RtlAllocateHeap(CsrHeap, 0, AclLength); 00460 ASSERT(*RestrictedDacl != NULL); 00461 00462 /* Initialize it */ 00463 Status = RtlCreateAcl(*RestrictedDacl, AclLength, ACL_REVISION2); 00464 ASSERT(NT_SUCCESS(Status)); 00465 00466 /* And add the same ACEs as before */ 00467 /* FIXME: Not really fully correct */ 00468 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid); 00469 ASSERT(NT_SUCCESS(Status)); 00470 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid); 00471 ASSERT(NT_SUCCESS(Status)); 00472 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid); 00473 ASSERT(NT_SUCCESS(Status)); 00474 00475 /* The SIDs are captured, can free them now */ 00476 RtlFreeHeap(CsrHeap, 0, SystemSid); 00477 RtlFreeHeap(CsrHeap, 0, WorldSid); 00478 RtlFreeHeap(CsrHeap, 0, RestrictedSid); 00479 return Status; 00480 } 00481 00482 VOID 00483 WINAPI 00484 BasepFakeStaticServerData(VOID) 00485 { 00486 NTSTATUS Status; 00487 WCHAR Buffer[MAX_PATH]; 00488 PWCHAR HeapBuffer; 00489 UNICODE_STRING SystemRootString; 00490 UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%"); 00491 UNICODE_STRING BaseSrvCSDString; 00492 UNICODE_STRING BaseSrvWindowsDirectory; 00493 UNICODE_STRING BaseSrvWindowsSystemDirectory; 00494 UNICODE_STRING BnoString; 00495 OBJECT_ATTRIBUTES ObjectAttributes; 00496 ULONG SessionId; 00497 HANDLE BaseSrvNamedObjectDirectory; 00498 HANDLE BaseSrvRestrictedObjectDirectory; 00499 PACL BnoDacl, BnoRestrictedDacl; 00500 PSECURITY_DESCRIPTOR BnoSd; 00501 HANDLE SymHandle; 00502 UNICODE_STRING DirectoryName, SymlinkName; 00503 BOOLEAN LuidEnabled; 00504 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] = 00505 { 00506 { 00507 NULL, 00508 RTL_QUERY_REGISTRY_DIRECT, 00509 L"CSDVersion", 00510 &BaseSrvCSDString 00511 }, 00512 {0} 00513 }; 00514 00515 /* Get the session ID */ 00516 SessionId = NtCurrentPeb()->SessionId; 00517 00518 /* Get the Windows directory */ 00519 RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer)); 00520 Status = RtlExpandEnvironmentStrings_U(NULL, 00521 &UnexpandedSystemRootString, 00522 &SystemRootString, 00523 NULL); 00524 ASSERT(NT_SUCCESS(Status)); 00525 00526 /* Create the base directory */ 00527 Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL; 00528 Status = RtlCreateUnicodeString(&BaseSrvWindowsDirectory, 00529 SystemRootString.Buffer); 00530 ASSERT(NT_SUCCESS(Status)); 00531 00532 /* Create the system directory */ 00533 wcscat(SystemRootString.Buffer, L"\\system32"); 00534 Status = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory, 00535 SystemRootString.Buffer); 00536 ASSERT(NT_SUCCESS(Status)); 00537 00538 /* FIXME: Check Session ID */ 00539 wcscpy(Buffer, L"\\BaseNamedObjects"); 00540 RtlInitUnicodeString(&BnoString, Buffer); 00541 00542 /* Allocate the server data */ 00543 BaseStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap, 00544 HEAP_ZERO_MEMORY, 00545 sizeof(BASE_STATIC_SERVER_DATA)); 00546 ASSERT(BaseStaticServerData != NULL); 00547 00548 /* Process timezone information */ 00549 BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID; 00550 BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0; 00551 Status = NtQuerySystemInformation(SystemTimeOfDayInformation, 00552 &BaseStaticServerData->TimeOfDay, 00553 sizeof(BaseStaticServerData->TimeOfDay), 00554 NULL); 00555 ASSERT(NT_SUCCESS(Status)); 00556 00557 /* Make a shared heap copy of the Windows directory */ 00558 BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory; 00559 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap, 00560 0, 00561 BaseSrvWindowsDirectory.MaximumLength); 00562 ASSERT(HeapBuffer); 00563 RtlCopyMemory(HeapBuffer, 00564 BaseStaticServerData->WindowsDirectory.Buffer, 00565 BaseSrvWindowsDirectory.MaximumLength); 00566 BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer; 00567 00568 /* Make a shared heap copy of the System directory */ 00569 BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory; 00570 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap, 00571 0, 00572 BaseSrvWindowsSystemDirectory.MaximumLength); 00573 ASSERT(HeapBuffer); 00574 RtlCopyMemory(HeapBuffer, 00575 BaseStaticServerData->WindowsSystemDirectory.Buffer, 00576 BaseSrvWindowsSystemDirectory.MaximumLength); 00577 BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer; 00578 00579 /* This string is not used */ 00580 RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory, 00581 NULL, 00582 0); 00583 00584 /* Make a shared heap copy of the BNO directory */ 00585 BaseStaticServerData->NamedObjectDirectory = BnoString; 00586 BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length + 00587 sizeof(UNICODE_NULL); 00588 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap, 00589 0, 00590 BaseStaticServerData->NamedObjectDirectory.MaximumLength); 00591 ASSERT(HeapBuffer); 00592 RtlCopyMemory(HeapBuffer, 00593 BaseStaticServerData->NamedObjectDirectory.Buffer, 00594 BaseStaticServerData->NamedObjectDirectory.MaximumLength); 00595 BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer; 00596 00597 /* 00598 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length 00599 * and MaximumLength of the CSD String, since the same UNICODE_STRING is 00600 * being queried twice, the first time as a ULONG! 00601 * 00602 * Somehow, in Windows this doesn't cause a buffer overflow, but it might 00603 * in ReactOS, so this code is disabled until someone figures out WTF. 00604 */ 00605 BaseStaticServerData->CSDNumber = 0; 00606 BaseStaticServerData->RCNumber = 0; 00607 00608 /* Initialize the CSD string and query its value from the registry */ 00609 RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer)); 00610 Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT, 00611 L"", 00612 BaseServerRegistryConfigurationTable, 00613 NULL, 00614 NULL); 00615 if (NT_SUCCESS(Status)) 00616 { 00617 /* Copy into the shared buffer */ 00618 wcsncpy(BaseStaticServerData->CSDVersion, 00619 BaseSrvCSDString.Buffer, 00620 BaseSrvCSDString.Length / sizeof(WCHAR)); 00621 } 00622 else 00623 { 00624 /* NULL-terminate to indicate nothing is there */ 00625 BaseStaticServerData->CSDVersion[0] = UNICODE_NULL; 00626 } 00627 00628 /* Cache the system information */ 00629 Status = NtQuerySystemInformation(SystemBasicInformation, 00630 &BaseStaticServerData->SysInfo, 00631 sizeof(BaseStaticServerData->SysInfo), 00632 NULL); 00633 ASSERT(NT_SUCCESS(Status)); 00634 00635 /* FIXME: Should query the registry for these */ 00636 BaseStaticServerData->DefaultSeparateVDM = FALSE; 00637 BaseStaticServerData->IsWowTaskReady = FALSE; 00638 00639 /* Allocate a security descriptor and create it */ 00640 BnoSd = RtlAllocateHeap(CsrHeap, 0, 1024); 00641 ASSERT(BnoSd); 00642 Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION); 00643 ASSERT(NT_SUCCESS(Status)); 00644 00645 /* Create the BNO and \Restricted DACLs */ 00646 Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl); 00647 ASSERT(NT_SUCCESS(Status)); 00648 00649 /* Set the BNO DACL as active for now */ 00650 Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE); 00651 ASSERT(NT_SUCCESS(Status)); 00652 00653 /* Create the BNO directory */ 00654 RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects"); 00655 InitializeObjectAttributes(&ObjectAttributes, 00656 &BnoString, 00657 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 00658 NULL, 00659 BnoSd); 00660 Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory, 00661 DIRECTORY_ALL_ACCESS, 00662 &ObjectAttributes); 00663 ASSERT(NT_SUCCESS(Status)); 00664 00665 /* Check if we are session 0 */ 00666 if (!SessionId) 00667 { 00668 /* Mark this as a session 0 directory */ 00669 Status = NtSetInformationObject(BaseSrvNamedObjectDirectory, 00670 ObjectSessionInformation, 00671 NULL, 00672 0); 00673 ASSERT(NT_SUCCESS(Status)); 00674 } 00675 00676 /* Check if LUID device maps are enabled */ 00677 NtQueryInformationProcess(NtCurrentProcess(), 00678 ProcessLUIDDeviceMapsEnabled, 00679 &LuidEnabled, 00680 sizeof(LuidEnabled), 00681 NULL); 00682 BaseStaticServerData->LUIDDeviceMapsEnabled = LuidEnabled; 00683 if (!BaseStaticServerData->LUIDDeviceMapsEnabled) 00684 { 00685 /* Make Global point back to BNO */ 00686 RtlInitUnicodeString(&DirectoryName, L"Global"); 00687 RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects"); 00688 InitializeObjectAttributes(&ObjectAttributes, 00689 &DirectoryName, 00690 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 00691 BaseSrvNamedObjectDirectory, 00692 BnoSd); 00693 Status = NtCreateSymbolicLinkObject(&SymHandle, 00694 SYMBOLIC_LINK_ALL_ACCESS, 00695 &ObjectAttributes, 00696 &SymlinkName); 00697 if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle); 00698 00699 /* Make local point back to \Sessions\x\BNO */ 00700 RtlInitUnicodeString(&DirectoryName, L"Local"); 00701 ASSERT(SessionId == 0); 00702 InitializeObjectAttributes(&ObjectAttributes, 00703 &DirectoryName, 00704 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 00705 BaseSrvNamedObjectDirectory, 00706 BnoSd); 00707 Status = NtCreateSymbolicLinkObject(&SymHandle, 00708 SYMBOLIC_LINK_ALL_ACCESS, 00709 &ObjectAttributes, 00710 &SymlinkName); 00711 if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle); 00712 00713 /* Make Session point back to BNOLINKS */ 00714 RtlInitUnicodeString(&DirectoryName, L"Session"); 00715 RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS"); 00716 InitializeObjectAttributes(&ObjectAttributes, 00717 &DirectoryName, 00718 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 00719 BaseSrvNamedObjectDirectory, 00720 BnoSd); 00721 Status = NtCreateSymbolicLinkObject(&SymHandle, 00722 SYMBOLIC_LINK_ALL_ACCESS, 00723 &ObjectAttributes, 00724 &SymlinkName); 00725 if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle); 00726 00727 /* Create the BNO\Restricted directory and set the restricted DACL */ 00728 RtlInitUnicodeString(&DirectoryName, L"Restricted"); 00729 Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoRestrictedDacl, FALSE); 00730 ASSERT(NT_SUCCESS(Status)); 00731 InitializeObjectAttributes(&ObjectAttributes, 00732 &DirectoryName, 00733 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 00734 BaseSrvNamedObjectDirectory, 00735 BnoSd); 00736 Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory, 00737 DIRECTORY_ALL_ACCESS, 00738 &ObjectAttributes); 00739 ASSERT(NT_SUCCESS(Status)); 00740 } 00741 00742 /* Finally, set the pointer */ 00743 CsrSrvSharedStaticServerData[CSR_CONSOLE] = BaseStaticServerData; 00744 } 00745 00746 NTSTATUS WINAPI 00747 CsrpHandleConnectionRequest (PPORT_MESSAGE Request) 00748 { 00749 NTSTATUS Status; 00750 HANDLE ServerPort = NULL;//, ServerThread = NULL; 00751 PCSR_PROCESS ProcessData = NULL; 00752 REMOTE_PORT_VIEW RemotePortView; 00753 // CLIENT_ID ClientId; 00754 BOOLEAN AllowConnection = FALSE; 00755 PCSR_CONNECTION_INFO ConnectInfo; 00756 ServerPort = NULL; 00757 00758 DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request); 00759 00760 ConnectInfo = (PCSR_CONNECTION_INFO)(Request + 1); 00761 00762 /* Save the process ID */ 00763 RtlZeroMemory(ConnectInfo, sizeof(CSR_CONNECTION_INFO)); 00764 00765 CsrLockProcessByClientId(Request->ClientId.UniqueProcess, &ProcessData); 00766 if (!ProcessData) 00767 { 00768 DPRINT1("CSRSRV: Unknown process: %lx. Will be rejecting connection\n", 00769 Request->ClientId.UniqueProcess); 00770 } 00771 00772 if ((ProcessData) && (ProcessData != CsrRootProcess)) 00773 { 00774 /* Attach the Shared Section */ 00775 Status = CsrSrvAttachSharedSection(ProcessData, ConnectInfo); 00776 if (NT_SUCCESS(Status)) 00777 { 00778 DPRINT("Connection ok\n"); 00779 AllowConnection = TRUE; 00780 } 00781 else 00782 { 00783 DPRINT1("Shared section map failed: %lx\n", Status); 00784 } 00785 } 00786 else if (ProcessData == CsrRootProcess) 00787 { 00788 AllowConnection = TRUE; 00789 } 00790 00791 /* Release the process */ 00792 if (ProcessData) CsrUnlockProcess(ProcessData); 00793 00794 /* Setup the Port View Structure */ 00795 RemotePortView.Length = sizeof(REMOTE_PORT_VIEW); 00796 RemotePortView.ViewSize = 0; 00797 RemotePortView.ViewBase = NULL; 00798 00799 /* Save the Process ID */ 00800 ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess; 00801 00802 Status = NtAcceptConnectPort(&ServerPort, 00803 AllowConnection ? UlongToPtr(ProcessData->SequenceNumber) : 0, 00804 Request, 00805 AllowConnection, 00806 NULL, 00807 &RemotePortView); 00808 if (!NT_SUCCESS(Status)) 00809 { 00810 DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status); 00811 } 00812 else if (AllowConnection) 00813 { 00814 if (CsrDebug & 2) 00815 { 00816 DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n", 00817 Request->ClientId.UniqueProcess, 00818 Request->ClientId.UniqueThread, 00819 RemotePortView.ViewBase, 00820 RemotePortView.ViewSize); 00821 } 00822 00823 /* Set some Port Data in the Process */ 00824 ProcessData->ClientPort = ServerPort; 00825 ProcessData->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase; 00826 ProcessData->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase + 00827 (ULONG_PTR)RemotePortView.ViewSize); 00828 00829 /* Complete the connection */ 00830 Status = NtCompleteConnectPort(ServerPort); 00831 if (!NT_SUCCESS(Status)) 00832 { 00833 DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status); 00834 } 00835 } 00836 else 00837 { 00838 DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n", 00839 Request->ClientId.UniqueProcess, 00840 Request->ClientId.UniqueThread); 00841 } 00842 00843 return Status; 00844 } 00845 00846 PCSR_THREAD 00847 NTAPI 00848 CsrConnectToUser(VOID) 00849 { 00850 PTEB Teb = NtCurrentTeb(); 00851 PCSR_THREAD CsrThread; 00852 #if 0 00853 NTSTATUS Status; 00854 ANSI_STRING DllName; 00855 UNICODE_STRING TempName; 00856 HANDLE hUser32; 00857 STRING StartupName; 00858 00859 /* Check if we didn't already find it */ 00860 if (!CsrClientThreadSetup) 00861 { 00862 /* Get the DLL Handle for user32.dll */ 00863 RtlInitAnsiString(&DllName, "user32"); 00864 RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE); 00865 Status = LdrGetDllHandle(NULL, 00866 NULL, 00867 &TempName, 00868 &hUser32); 00869 RtlFreeUnicodeString(&TempName); 00870 00871 /* If we got teh handle, get the Client Thread Startup Entrypoint */ 00872 if (NT_SUCCESS(Status)) 00873 { 00874 RtlInitAnsiString(&StartupName,"ClientThreadSetup"); 00875 Status = LdrGetProcedureAddress(hUser32, 00876 &StartupName, 00877 0, 00878 (PVOID)&CsrClientThreadSetup); 00879 } 00880 } 00881 00882 /* Connect to user32 */ 00883 CsrClientThreadSetup(); 00884 #endif 00885 /* Save pointer to this thread in TEB */ 00886 CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId); 00887 if (CsrThread) Teb->CsrClientThread = CsrThread; 00888 00889 /* Return it */ 00890 return CsrThread; 00891 } 00892 00893 /*++ 00894 * @name CsrpCheckRequestThreads 00895 * 00896 * The CsrpCheckRequestThreads routine checks if there are no more threads 00897 * to handle CSR API Requests, and creates a new thread if possible, to 00898 * avoid starvation. 00899 * 00900 * @param None. 00901 * 00902 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL 00903 * if a new thread couldn't be created. 00904 * 00905 * @remarks None. 00906 * 00907 *--*/ 00908 NTSTATUS 00909 NTAPI 00910 CsrpCheckRequestThreads(VOID) 00911 { 00912 HANDLE hThread; 00913 CLIENT_ID ClientId; 00914 NTSTATUS Status; 00915 00916 /* Decrease the count, and see if we're out */ 00917 if (!(_InterlockedDecrement(&CsrpStaticThreadCount))) 00918 { 00919 /* Check if we've still got space for a Dynamic Thread */ 00920 if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads) 00921 { 00922 /* Create a new dynamic thread */ 00923 Status = RtlCreateUserThread(NtCurrentProcess(), 00924 NULL, 00925 TRUE, 00926 0, 00927 0, 00928 0, 00929 (PVOID)ClientConnectionThread,//CsrApiRequestThread, 00930 NULL, 00931 &hThread, 00932 &ClientId); 00933 /* Check success */ 00934 if (NT_SUCCESS(Status)) 00935 { 00936 /* Increase the thread counts */ 00937 _InterlockedIncrement(&CsrpStaticThreadCount); 00938 _InterlockedIncrement(&CsrpDynamicThreadTotal); 00939 00940 /* Add a new server thread */ 00941 if (CsrAddStaticServerThread(hThread, 00942 &ClientId, 00943 CsrThreadIsServerThread)) 00944 { 00945 /* Activate it */ 00946 NtResumeThread(hThread, NULL); 00947 } 00948 else 00949 { 00950 /* Failed to create a new static thread */ 00951 _InterlockedDecrement(&CsrpStaticThreadCount); 00952 _InterlockedDecrement(&CsrpDynamicThreadTotal); 00953 00954 /* Terminate it */ 00955 DPRINT1("Failing\n"); 00956 NtTerminateThread(hThread, 0); 00957 NtClose(hThread); 00958 00959 /* Return */ 00960 return STATUS_UNSUCCESSFUL; 00961 } 00962 } 00963 } 00964 } 00965 00966 /* Success */ 00967 return STATUS_SUCCESS; 00968 } 00969 00970 VOID 00971 WINAPI 00972 ClientConnectionThread(IN PVOID Parameter) 00973 { 00974 PTEB Teb = NtCurrentTeb(); 00975 LARGE_INTEGER TimeOut; 00976 NTSTATUS Status; 00977 BYTE RawRequest[LPC_MAX_DATA_LENGTH]; 00978 PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest; 00979 PCSR_API_MESSAGE Reply; 00980 PCSR_PROCESS CsrProcess; 00981 PCSR_THREAD ServerThread, CsrThread; 00982 ULONG MessageType; 00983 HANDLE ReplyPort; 00984 PDBGKM_MSG DebugMessage; 00985 PHARDERROR_MSG HardErrorMsg; 00986 PCLIENT_DIED_MSG ClientDiedMsg; 00987 DPRINT("CSR: %s called\n", __FUNCTION__); 00988 00989 /* Setup LPC loop port and message */ 00990 Reply = NULL; 00991 ReplyPort = CsrApiPort; 00992 00993 /* Connect to user32 */ 00994 while (!CsrConnectToUser()) 00995 { 00996 /* Set up the timeout for the connect (30 seconds) */ 00997 TimeOut.QuadPart = -30 * 1000 * 1000 * 10; 00998 00999 /* Keep trying until we get a response */ 01000 Teb->Win32ClientInfo[0] = 0; 01001 NtDelayExecution(FALSE, &TimeOut); 01002 } 01003 01004 /* Get our thread */ 01005 ServerThread = Teb->CsrClientThread; 01006 01007 /* If we got an event... */ 01008 if (Parameter) 01009 { 01010 /* Set it, to let stuff waiting on us load */ 01011 Status = NtSetEvent((HANDLE)Parameter, NULL); 01012 ASSERT(NT_SUCCESS(Status)); 01013 01014 /* Increase the Thread Counts */ 01015 _InterlockedIncrement(&CsrpStaticThreadCount); 01016 _InterlockedIncrement(&CsrpDynamicThreadTotal); 01017 } 01018 01019 /* Now start the loop */ 01020 while (TRUE) 01021 { 01022 /* Make sure the real CID is set */ 01023 Teb->RealClientId = Teb->ClientId; 01024 01025 /* Debug check */ 01026 if (Teb->CountOfOwnedCriticalSections) 01027 { 01028 DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n", 01029 Teb->CountOfOwnedCriticalSections); 01030 DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n", 01031 Request, Reply); 01032 DbgBreakPoint(); 01033 } 01034 01035 /* Send the reply and wait for a new request */ 01036 DPRINT("Replying to: %lx (%lx)\n", ReplyPort, CsrApiPort); 01037 Status = NtReplyWaitReceivePort(ReplyPort, 01038 0, 01039 &Reply->Header, 01040 &Request->Header); 01041 /* Check if we didn't get success */ 01042 if (Status != STATUS_SUCCESS) 01043 { 01044 /* Was it a failure or another success code? */ 01045 if (!NT_SUCCESS(Status)) 01046 { 01047 /* Check for specific status cases */ 01048 if ((Status != STATUS_INVALID_CID) && 01049 (Status != STATUS_UNSUCCESSFUL) && 01050 ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort))) 01051 { 01052 /* Notify the debugger */ 01053 DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status); 01054 DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort); 01055 } 01056 01057 /* We failed big time, so start out fresh */ 01058 Reply = NULL; 01059 ReplyPort = CsrApiPort; 01060 DPRINT1("failed: %lx\n", Status); 01061 continue; 01062 } 01063 else 01064 { 01065 /* A bizare "success" code, just try again */ 01066 DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status); 01067 continue; 01068 } 01069 } 01070 01071 /* Use whatever Client ID we got */ 01072 Teb->RealClientId = Request->Header.ClientId; 01073 01074 /* Get the Message Type */ 01075 MessageType = Request->Header.u2.s2.Type; 01076 01077 /* Handle connection requests */ 01078 if (MessageType == LPC_CONNECTION_REQUEST) 01079 { 01080 /* Handle the Connection Request */ 01081 DPRINT("Accepting new connection\n"); 01082 CsrpHandleConnectionRequest((PPORT_MESSAGE)Request); 01083 Reply = NULL; 01084 ReplyPort = CsrApiPort; 01085 continue; 01086 } 01087 01088 /* It's some other kind of request. Get the lock for the lookup */ 01089 CsrAcquireProcessLock(); 01090 01091 /* Now do the lookup to get the CSR_THREAD */ 01092 CsrThread = CsrLocateThreadByClientId(&CsrProcess, 01093 &Request->Header.ClientId); 01094 01095 /* Did we find a thread? */ 01096 if (!CsrThread) 01097 { 01098 /* This wasn't a CSR Thread, release lock */ 01099 CsrReleaseProcessLock(); 01100 01101 /* If this was an exception, handle it */ 01102 if (MessageType == LPC_EXCEPTION) 01103 { 01104 DPRINT1("Exception from unknown thread, just continue\n"); 01105 Reply = Request; 01106 ReplyPort = CsrApiPort; 01107 Reply->Status = DBG_CONTINUE; 01108 } 01109 else if (MessageType == LPC_PORT_CLOSED || 01110 MessageType == LPC_CLIENT_DIED) 01111 { 01112 /* The Client or Port are gone, loop again */ 01113 DPRINT1("Death from unknown thread, just continue\n"); 01114 Reply = NULL; 01115 ReplyPort = CsrApiPort; 01116 } 01117 else if (MessageType == LPC_ERROR_EVENT) 01118 { 01119 /* If it's a hard error, handle this too */ 01120 DPRINT1("Hard error from unknown thread, call handlers\n"); 01121 HandleHardError: 01122 HardErrorMsg = (PHARDERROR_MSG)Request; 01123 01124 /* Default it to unhandled */ 01125 HardErrorMsg->Response = ResponseNotHandled; 01126 01127 /* Check if there are free api threads */ 01128 CsrpCheckRequestThreads(); 01129 if (CsrpStaticThreadCount) 01130 { 01131 CsrHandleHardError(CsrThread, (PHARDERROR_MSG)Request); 01132 } 01133 01134 /* If the response was 0xFFFFFFFF, we'll ignore it */ 01135 if (HardErrorMsg->Response == 0xFFFFFFFF) 01136 { 01137 Reply = NULL; 01138 ReplyPort = CsrApiPort; 01139 } 01140 else 01141 { 01142 if (CsrThread) CsrDereferenceThread(CsrThread); 01143 Reply = Request; 01144 ReplyPort = CsrApiPort; 01145 } 01146 } 01147 else if (MessageType == LPC_REQUEST) 01148 { 01149 /* This is an API Message coming from a non-CSR Thread */ 01150 DPRINT1("No thread found for request %lx and clientID %lx.%lx\n", 01151 Request->Type & 0xFFFF, 01152 Request->Header.ClientId.UniqueProcess, 01153 Request->Header.ClientId.UniqueThread); 01154 Reply = Request; 01155 ReplyPort = CsrApiPort; 01156 Reply->Status = STATUS_ILLEGAL_FUNCTION; 01157 } 01158 else if (MessageType == LPC_DATAGRAM) 01159 { 01160 DPRINT1("Kernel datagram: not yet supported\n"); 01161 Reply = NULL; 01162 ReplyPort = CsrApiPort; 01163 } 01164 else 01165 { 01166 /* Some other ignored message type */ 01167 Reply = NULL; 01168 ReplyPort = CsrApiPort; 01169 } 01170 01171 /* Keep going */ 01172 continue; 01173 } 01174 01175 /* We have a valid thread, was this an LPC Request? */ 01176 if (MessageType != LPC_REQUEST) 01177 { 01178 /* It's not an API, check if the client died */ 01179 if (MessageType == LPC_CLIENT_DIED) 01180 { 01181 /* Get the information and check if it matches our thread */ 01182 ClientDiedMsg = (PCLIENT_DIED_MSG)Request; 01183 if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart) 01184 { 01185 /* Reference the thread */ 01186 CsrLockedReferenceThread(CsrThread); 01187 01188 /* Destroy the thread in the API Message */ 01189 CsrDestroyThread(&Request->Header.ClientId); 01190 01191 /* Check if the thread was actually ourselves */ 01192 if (CsrProcess->ThreadCount == 1) 01193 { 01194 /* Kill the process manually here */ 01195 DPRINT1("Last thread\n"); 01196 CsrDestroyProcess(&CsrThread->ClientId, 0); 01197 } 01198 01199 /* Remove our extra reference */ 01200 CsrLockedDereferenceThread(CsrThread); 01201 } 01202 01203 /* Release the lock and keep looping */ 01204 CsrReleaseProcessLock(); 01205 Reply = NULL; 01206 ReplyPort = CsrApiPort; 01207 continue; 01208 } 01209 01210 /* Reference the thread and release the lock */ 01211 CsrLockedReferenceThread(CsrThread); 01212 CsrReleaseProcessLock(); 01213 01214 /* If this was an exception, handle it */ 01215 if (MessageType == LPC_EXCEPTION) 01216 { 01217 /* Kill the process */ 01218 DPRINT1("Exception in %lx.%lx. Killing...\n", 01219 Request->Header.ClientId.UniqueProcess, 01220 Request->Header.ClientId.UniqueThread); 01221 NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED); 01222 01223 /* Destroy it from CSR */ 01224 CsrDestroyProcess(&Request->Header.ClientId, STATUS_ABANDONED); 01225 01226 /* Return a Debug Message */ 01227 DebugMessage = (PDBGKM_MSG)Request; 01228 DebugMessage->ReturnedStatus = DBG_CONTINUE; 01229 Reply = Request; 01230 ReplyPort = CsrApiPort; 01231 01232 /* Remove our extra reference */ 01233 CsrDereferenceThread(CsrThread); 01234 } 01235 else if (MessageType == LPC_ERROR_EVENT) 01236 { 01237 DPRINT1("Hard error from known CSR thread... handling\n"); 01238 goto HandleHardError; 01239 } 01240 else 01241 { 01242 /* Something else */ 01243 DPRINT1("Unhandled message type: %lx\n", MessageType); 01244 CsrDereferenceThread(CsrThread); 01245 Reply = NULL; 01246 } 01247 01248 /* Keep looping */ 01249 continue; 01250 } 01251 01252 /* We got an API Request */ 01253 CsrLockedReferenceThread(CsrThread); 01254 CsrReleaseProcessLock(); 01255 01256 /* Assume success */ 01257 Reply = Request; 01258 Request->Status = STATUS_SUCCESS; 01259 01260 /* Now we reply to a particular client */ 01261 ReplyPort = CsrThread->Process->ClientPort; 01262 01263 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n", 01264 Request->Type, 01265 Request->Header.ClientId.UniqueThread); 01266 01267 /* Validation complete, start SEH */ 01268 _SEH2_TRY 01269 { 01270 /* Make sure we have enough threads */ 01271 CsrpCheckRequestThreads(); 01272 01273 /* Set the client thread pointer */ 01274 NtCurrentTeb()->CsrClientThread = CsrThread; 01275 01276 /* Call the Handler */ 01277 CsrApiCallHandler(CsrThread->Process, Request); 01278 01279 /* Increase the static thread count */ 01280 _InterlockedIncrement(&CsrpStaticThreadCount); 01281 01282 /* Restore the server thread */ 01283 NtCurrentTeb()->CsrClientThread = ServerThread; 01284 01285 /* Check if this is a dead client now */ 01286 if (Request->Type == 0xBABE) 01287 { 01288 /* Reply to the death message */ 01289 NtReplyPort(ReplyPort, &Reply->Header); 01290 01291 /* Reply back to the API port now */ 01292 ReplyPort = CsrApiPort; 01293 Reply = NULL; 01294 01295 /* Drop the reference */ 01296 CsrDereferenceThread(CsrThread); 01297 } 01298 else 01299 { 01300 /* Drop the reference */ 01301 CsrDereferenceThread(CsrThread); 01302 } 01303 } 01304 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation())) 01305 { 01306 Reply = NULL; 01307 ReplyPort = CsrApiPort; 01308 } 01309 _SEH2_END; 01310 } 01311 01312 /* Close the port and exit the thread */ 01313 // NtClose(ServerPort); 01314 01315 DPRINT1("CSR: %s done\n", __FUNCTION__); 01316 /* We're out of the loop for some reason, terminate! */ 01317 NtTerminateThread(NtCurrentThread(), Status); 01318 //return Status; 01319 } 01320 01321 /*++ 01322 * @name CsrReleaseCapturedArguments 01323 * @implemented NT5.1 01324 * 01325 * The CsrReleaseCapturedArguments routine releases a Capture Buffer 01326 * that was previously captured with CsrCaptureArguments. 01327 * 01328 * @param ApiMessage 01329 * Pointer to the CSR API Message containing the Capture Buffer 01330 * that needs to be released. 01331 * 01332 * @return None. 01333 * 01334 * @remarks None. 01335 * 01336 *--*/ 01337 VOID 01338 NTAPI 01339 CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage) 01340 { 01341 PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer; 01342 SIZE_T BufferDistance; 01343 ULONG PointerCount; 01344 ULONG_PTR **PointerOffsets, *CurrentPointer; 01345 01346 /* Get the capture buffers */ 01347 RemoteCaptureBuffer = ApiMessage->CsrCaptureData; 01348 LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer; 01349 01350 /* Free the previous one */ 01351 RemoteCaptureBuffer->PreviousCaptureBuffer = NULL; 01352 01353 /* Find out the difference between the two buffers */ 01354 BufferDistance = (ULONG_PTR)LocalCaptureBuffer - (ULONG_PTR)RemoteCaptureBuffer; 01355 01356 /* Save the pointer count and offset pointer */ 01357 PointerCount = RemoteCaptureBuffer->PointerCount; 01358 PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1); 01359 01360 /* Start the loop */ 01361 while (PointerCount) 01362 { 01363 /* Get the current pointer */ 01364 CurrentPointer = *PointerOffsets++; 01365 if (CurrentPointer) 01366 { 01367 /* Add it to the CSR Message structure */ 01368 CurrentPointer += (ULONG_PTR)ApiMessage; 01369 01370 /* Modify the pointer to take into account its new position */ 01371 *CurrentPointer += BufferDistance; 01372 } 01373 01374 /* Move to the next Pointer */ 01375 PointerCount--; 01376 } 01377 01378 /* Copy the data back */ 01379 RtlMoveMemory(LocalCaptureBuffer, RemoteCaptureBuffer, RemoteCaptureBuffer->Size); 01380 01381 /* Free our allocated buffer */ 01382 RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer); 01383 } 01384 01385 /* EOF */ Generated on Mon May 28 2012 04:37:43 for ReactOS by
1.7.6.1
|