ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

wapi.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.