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

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

Generated on Sun May 27 2012 04:22:34 for ReactOS by doxygen 1.7.6.1

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