/*++ * @name CsrAllocateProcess * @implemented NT4 * * The CsrAllocateProcess routine allocates a new CSR Process object. * * @return Pointer to the newly allocated CSR Process. * * @remarks None. * *--*/ PCSR_PROCESS NTAPI CsrAllocateProcess(VOID) { PCSR_PROCESS CsrProcess; ULONG TotalSize; /* Calculate the amount of memory this should take */ TotalSize = sizeof(CSR_PROCESS) + (CSR_SERVER_DLL_MAX * sizeof(PVOID)) + CsrTotalPerProcessDataLength; /* Allocate a Process */ CsrProcess = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, TotalSize); if (!CsrProcess) return NULL; /* Handle the Sequence Number and protect against overflow */ CsrProcess->SequenceNumber = CsrProcessSequenceCount++; if (CsrProcessSequenceCount < 5) CsrProcessSequenceCount = 5; /* Increase the reference count */ CsrLockedReferenceProcess(CsrProcess); /* Initialize the Thread List */ InitializeListHead(&CsrProcess->ThreadList); /* Return the Process */ return CsrProcess; }
/*++ * @name CsrLockProcessByClientId * @implemented NT4 * * The CsrLockProcessByClientId routine locks the CSR Process corresponding * to the given Process ID and optionally returns it. * * @param Pid * Process ID corresponding to the CSR Process which will be locked. * * @param CsrProcess * Optional pointer to a CSR Process pointer which will hold the * CSR Process corresponding to the given Process ID. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks Locking a CSR Process is defined as acquiring an extra * reference to it and returning with the Process Lock held. * *--*/ NTSTATUS NTAPI CsrLockProcessByClientId(IN HANDLE Pid, OUT PCSR_PROCESS *CsrProcess) { PLIST_ENTRY NextEntry; PCSR_PROCESS CurrentProcess = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; /* Acquire the lock */ CsrAcquireProcessLock(); /* Assume failure */ ASSERT(CsrProcess != NULL); *CsrProcess = NULL; /* Setup the List Pointers */ NextEntry = &CsrRootProcess->ListLink; do { /* Get the Process */ CurrentProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink); /* Check for PID Match */ if (CurrentProcess->ClientId.UniqueProcess == Pid) { Status = STATUS_SUCCESS; break; } /* Move to the next entry */ NextEntry = NextEntry->Flink; } while (NextEntry != &CsrRootProcess->ListLink); /* Check if we didn't find it in the list */ if (!NT_SUCCESS(Status)) { /* Nothing found, release the lock */ CsrReleaseProcessLock(); } else { /* Lock the found process and return it */ CsrLockedReferenceProcess(CurrentProcess); *CsrProcess = CurrentProcess; } /* Return the result */ return Status; }
/*++ * @name CsrAllocateThread * * The CsrAllocateThread routine allocates a new CSR Thread object. * * @param CsrProcess * Pointer to the CSR Process which will contain this CSR Thread. * * @return Pointer to the newly allocated CSR Thread. * * @remarks None. * *--*/ PCSR_THREAD NTAPI CsrAllocateThread(IN PCSR_PROCESS CsrProcess) { PCSR_THREAD CsrThread; /* Allocate the structure */ CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD)); if (!CsrThread) return NULL; /* Reference the Thread and Process */ CsrLockedReferenceThread(CsrThread); CsrLockedReferenceProcess(CsrProcess); /* Set the Parent Process */ CsrThread->Process = CsrProcess; /* Return Thread */ return CsrThread; }
/*++ * @name CsrShutdownProcesses * @implemented NT4 * * The CsrShutdownProcesses routine shuts down every CSR Process possible * and calls each Server DLL's shutdown notification. * * @param CallerLuid * Pointer to the LUID of the CSR Process that is ordering the * shutdown. * * @param Flags * Flags to send to the shutdown notification routine. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrShutdownProcesses(IN PLUID CallerLuid, IN ULONG Flags) { PLIST_ENTRY NextEntry; PCSR_PROCESS CsrProcess; NTSTATUS Status; BOOLEAN FirstTry; ULONG i; PCSR_SERVER_DLL ServerDll; ULONG Result = 0; /* Acquire process lock */ CsrAcquireProcessLock(); /* Add shutdown flag */ CsrRootProcess->ShutdownFlags |= CsrShutdownSystem; /* Get the list pointers */ NextEntry = CsrRootProcess->ListLink.Flink; while (NextEntry != &CsrRootProcess->ListLink) { /* Get the Process */ CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink); /* Move to the next entry */ NextEntry = NextEntry->Flink; /* Remove the skip flag, set shutdown flags to 0 */ CsrProcess->Flags &= ~CsrProcessSkipShutdown; CsrProcess->ShutdownFlags = 0; } /* Set shutdown Priority */ CsrSetToShutdownPriority(); /* Start looping */ while (TRUE) { /* Find the next process to shutdown */ CsrProcess = FindProcessForShutdown(CallerLuid); if (!CsrProcess) break; /* Increase reference to process */ CsrLockedReferenceProcess(CsrProcess); FirstTry = TRUE; while (TRUE) { /* Loop all the servers */ for (i = 0; i < CSR_SERVER_DLL_MAX; i++) { /* Get the current server */ ServerDll = CsrLoadedServerDll[i]; /* Check if it's valid and if it has a Shutdown Process Callback */ if (ServerDll && ServerDll->ShutdownProcessCallback) { /* Release the lock, make the callback, and acquire it back */ CsrReleaseProcessLock(); Result = ServerDll->ShutdownProcessCallback(CsrProcess, Flags, FirstTry); CsrAcquireProcessLock(); /* Check the result */ if (Result == CsrShutdownCsrProcess) { /* The callback unlocked the process */ break; } else if (Result == CsrShutdownCancelled) { /* Check if this was a forced shutdown */ if (Flags & EWX_FORCE) { DPRINT1("Process %x cancelled forced shutdown (Dll = %d)\n", CsrProcess->ClientId.UniqueProcess, i); DbgBreakPoint(); } /* Shutdown was cancelled, unlock and exit */ CsrReleaseProcessLock(); Status = STATUS_CANCELLED; goto Quickie; } } } /* No matches during the first try, so loop again */ if (FirstTry && (Result == CsrShutdownNonCsrProcess)) { FirstTry = FALSE; continue; } /* Second try, break out */ break; } /* We've reached the final loop here, so dereference */ if (i == CSR_SERVER_DLL_MAX) CsrLockedDereferenceProcess(CsrProcess); } /* Success path */ CsrReleaseProcessLock(); Status = STATUS_SUCCESS; Quickie: /* Return to normal priority */ CsrSetToNormalPriority(); return Status; }
/*++ * @name CsrApiHandleConnectionRequest * * The CsrApiHandleConnectionRequest routine handles and accepts a new * connection request to the CSR API LPC Port. * * @param ApiMessage * Pointer to the incoming CSR API Message which contains the * connection request. * * @return STATUS_SUCCESS in case of success, or status code which caused * the routine to error. * * @remarks This routine is responsible for attaching the Shared Section to * new clients connecting to CSR. * *--*/ NTSTATUS NTAPI CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage) { PCSR_THREAD CsrThread = NULL; PCSR_PROCESS CsrProcess = NULL; NTSTATUS Status = STATUS_SUCCESS; PCSR_API_CONNECTINFO ConnectInfo = &ApiMessage->ConnectionInfo; BOOLEAN AllowConnection = FALSE; REMOTE_PORT_VIEW RemotePortView; HANDLE ServerPort; /* Acquire the Process Lock */ CsrAcquireProcessLock(); /* Lookup the CSR Thread */ CsrThread = CsrLocateThreadByClientId(NULL, &ApiMessage->Header.ClientId); /* Check if we have a thread */ if (CsrThread) { /* Get the Process */ CsrProcess = CsrThread->Process; /* Make sure we have a Process as well */ if (CsrProcess) { /* Reference the Process */ CsrLockedReferenceProcess(CsrProcess); /* Release the lock */ CsrReleaseProcessLock(); /* Duplicate the Object Directory */ Status = NtDuplicateObject(NtCurrentProcess(), CsrObjectDirectory, CsrProcess->ProcessHandle, &ConnectInfo->ObjectDirectory, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); /* Acquire the lock */ CsrAcquireProcessLock(); /* Check for success */ if (NT_SUCCESS(Status)) { /* Attach the Shared Section */ Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo); /* Check how this went */ if (NT_SUCCESS(Status)) { /* Allow the connection, and return debugging flag */ ConnectInfo->DebugFlags = CsrDebug; AllowConnection = TRUE; } } /* Dereference the project */ CsrLockedDereferenceProcess(CsrProcess); } } /* Release the lock */ CsrReleaseProcessLock(); /* Setup the Port View Structure */ RemotePortView.Length = sizeof(REMOTE_PORT_VIEW); RemotePortView.ViewSize = 0; RemotePortView.ViewBase = NULL; /* Save the Process ID */ ConnectInfo->ServerProcessId = NtCurrentTeb()->ClientId.UniqueProcess; /* Accept the Connection */ Status = NtAcceptConnectPort(&ServerPort, AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0, &ApiMessage->Header, AllowConnection, NULL, &RemotePortView); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status); } else if (AllowConnection) { if (CsrDebug & 2) { DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n", ApiMessage->Header.ClientId.UniqueProcess, ApiMessage->Header.ClientId.UniqueThread, RemotePortView.ViewBase, RemotePortView.ViewSize); } /* Set some Port Data in the Process */ CsrProcess->ClientPort = ServerPort; CsrProcess->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase; CsrProcess->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase + (ULONG_PTR)RemotePortView.ViewSize); /* Complete the connection */ Status = NtCompleteConnectPort(ServerPort); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status); } } else { DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n", ApiMessage->Header.ClientId.UniqueProcess, ApiMessage->Header.ClientId.UniqueThread); } /* Return status to caller */ return Status; }