mirror of
https://github.com/reactos/reactos.git
synced 2025-03-09 17:54:55 +00:00
427 lines
13 KiB
C
427 lines
13 KiB
C
/*
|
|
* reactos/subsys/csrss/api/process.c
|
|
*
|
|
* "\windows\ApiPort" port process management functions
|
|
*
|
|
* ReactOS Operating System
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <csrss.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#define LOCK RtlEnterCriticalSection(&ProcessDataLock)
|
|
#define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
static ULONG NrProcess;
|
|
static PCSRSS_PROCESS_DATA ProcessData[256];
|
|
RTL_CRITICAL_SECTION ProcessDataLock;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
VOID WINAPI CsrInitProcessData(VOID)
|
|
{
|
|
RtlZeroMemory (ProcessData, sizeof ProcessData);
|
|
NrProcess = sizeof ProcessData / sizeof ProcessData[0];
|
|
RtlInitializeCriticalSection( &ProcessDataLock );
|
|
}
|
|
|
|
PCSRSS_PROCESS_DATA WINAPI CsrGetProcessData(HANDLE ProcessId)
|
|
{
|
|
ULONG hash;
|
|
PCSRSS_PROCESS_DATA pProcessData;
|
|
|
|
hash = ((ULONG_PTR)ProcessId >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
|
|
|
|
LOCK;
|
|
|
|
pProcessData = ProcessData[hash];
|
|
|
|
while (pProcessData && pProcessData->ProcessId != ProcessId)
|
|
{
|
|
pProcessData = pProcessData->next;
|
|
}
|
|
UNLOCK;
|
|
return pProcessData;
|
|
}
|
|
|
|
PCSRSS_PROCESS_DATA WINAPI CsrCreateProcessData(HANDLE ProcessId)
|
|
{
|
|
ULONG hash;
|
|
PCSRSS_PROCESS_DATA pProcessData;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
CLIENT_ID ClientId;
|
|
NTSTATUS Status;
|
|
|
|
hash = ((ULONG_PTR)ProcessId >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
|
|
|
|
LOCK;
|
|
|
|
pProcessData = ProcessData[hash];
|
|
|
|
while (pProcessData && pProcessData->ProcessId != ProcessId)
|
|
{
|
|
pProcessData = pProcessData->next;
|
|
}
|
|
if (pProcessData == NULL)
|
|
{
|
|
pProcessData = RtlAllocateHeap(CsrssApiHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(CSRSS_PROCESS_DATA));
|
|
if (pProcessData)
|
|
{
|
|
pProcessData->ProcessId = ProcessId;
|
|
pProcessData->next = ProcessData[hash];
|
|
ProcessData[hash] = pProcessData;
|
|
|
|
ClientId.UniqueThread = NULL;
|
|
ClientId.UniqueProcess = pProcessData->ProcessId;
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
|
|
/* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */
|
|
Status = NtOpenProcess(&pProcessData->Process,
|
|
PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION |
|
|
PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | SYNCHRONIZE,
|
|
&ObjectAttributes,
|
|
&ClientId);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ProcessData[hash] = pProcessData->next;
|
|
RtlFreeHeap(CsrssApiHeap, 0, pProcessData);
|
|
pProcessData = NULL;
|
|
}
|
|
else
|
|
{
|
|
RtlInitializeCriticalSection(&pProcessData->HandleTableLock);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("Process data for pid %d already exist\n", ProcessId);
|
|
}
|
|
UNLOCK;
|
|
if (pProcessData == NULL)
|
|
{
|
|
DPRINT1("CsrCreateProcessData() failed\n");
|
|
}
|
|
else
|
|
{
|
|
pProcessData->Terminated = FALSE;
|
|
|
|
/* Set default shutdown parameters */
|
|
pProcessData->ShutdownLevel = 0x280;
|
|
pProcessData->ShutdownFlags = 0;
|
|
}
|
|
return pProcessData;
|
|
}
|
|
|
|
NTSTATUS WINAPI CsrFreeProcessData(HANDLE Pid)
|
|
{
|
|
ULONG hash;
|
|
UINT c;
|
|
PCSRSS_PROCESS_DATA pProcessData, *pPrevLink;
|
|
HANDLE Process;
|
|
|
|
hash = ((ULONG_PTR)Pid >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
|
|
pPrevLink = &ProcessData[hash];
|
|
|
|
LOCK;
|
|
|
|
while ((pProcessData = *pPrevLink) && pProcessData->ProcessId != Pid)
|
|
{
|
|
pPrevLink = &pProcessData->next;
|
|
}
|
|
|
|
if (pProcessData)
|
|
{
|
|
DPRINT("CsrFreeProcessData pid: %d\n", Pid);
|
|
Process = pProcessData->Process;
|
|
if (pProcessData->HandleTable)
|
|
{
|
|
for (c = 0; c < pProcessData->HandleTableSize; c++)
|
|
{
|
|
if (pProcessData->HandleTable[c].Object)
|
|
{
|
|
CsrReleaseObjectByPointer(pProcessData->HandleTable[c].Object);
|
|
}
|
|
}
|
|
RtlFreeHeap(CsrssApiHeap, 0, pProcessData->HandleTable);
|
|
}
|
|
RtlDeleteCriticalSection(&pProcessData->HandleTableLock);
|
|
if (pProcessData->Console)
|
|
{
|
|
RemoveEntryList(&pProcessData->ProcessEntry);
|
|
CsrReleaseObjectByPointer((Object_t *) pProcessData->Console);
|
|
}
|
|
if (pProcessData->CsrSectionViewBase)
|
|
{
|
|
NtUnmapViewOfSection(NtCurrentProcess(), pProcessData->CsrSectionViewBase);
|
|
}
|
|
if (pProcessData->ServerCommunicationPort)
|
|
{
|
|
NtClose(pProcessData->ServerCommunicationPort);
|
|
}
|
|
*pPrevLink = pProcessData->next;
|
|
|
|
RtlFreeHeap(CsrssApiHeap, 0, pProcessData);
|
|
UNLOCK;
|
|
if (Process)
|
|
{
|
|
NtClose(Process);
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
UNLOCK;
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
NTSTATUS WINAPI
|
|
CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc, PVOID Context)
|
|
{
|
|
UINT Hash;
|
|
PCSRSS_PROCESS_DATA pProcessData;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
LOCK;
|
|
|
|
for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
|
|
{
|
|
pProcessData = ProcessData[Hash];
|
|
while (NULL != pProcessData)
|
|
{
|
|
Status = EnumProc(pProcessData, Context);
|
|
if (STATUS_SUCCESS != Status)
|
|
{
|
|
UNLOCK;
|
|
return Status;
|
|
}
|
|
pProcessData = pProcessData->next;
|
|
}
|
|
}
|
|
|
|
UNLOCK;
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* CSRSS API
|
|
*********************************************************************/
|
|
|
|
CSR_API(CsrCreateProcess)
|
|
{
|
|
PCSRSS_PROCESS_DATA NewProcessData;
|
|
NTSTATUS Status;
|
|
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
|
|
NewProcessData = CsrCreateProcessData(Request->Data.CreateProcessRequest.NewProcessId);
|
|
if (NewProcessData == NULL)
|
|
{
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
if (!(Request->Data.CreateProcessRequest.Flags & (CREATE_NEW_CONSOLE|DETACHED_PROCESS)))
|
|
{
|
|
NewProcessData->ParentConsole = ProcessData->Console;
|
|
NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles;
|
|
if (Request->Data.CreateProcessRequest.bInheritHandles)
|
|
{
|
|
Status = CsrDuplicateHandleTable(ProcessData, NewProcessData);
|
|
}
|
|
}
|
|
|
|
if (Request->Data.CreateProcessRequest.Flags & CREATE_NEW_PROCESS_GROUP)
|
|
{
|
|
NewProcessData->ProcessGroup = (DWORD)(ULONG_PTR)NewProcessData->ProcessId;
|
|
}
|
|
else
|
|
{
|
|
NewProcessData->ProcessGroup = ProcessData->ProcessGroup;
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
CSR_API(CsrTerminateProcess)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
ProcessData->Terminated = TRUE;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
CSR_API(CsrConnectProcess)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
CSR_API(CsrGetShutdownParameters)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Request->Data.GetShutdownParametersRequest.Level = ProcessData->ShutdownLevel;
|
|
Request->Data.GetShutdownParametersRequest.Flags = ProcessData->ShutdownFlags;
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
CSR_API(CsrSetShutdownParameters)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
|
|
ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
CSR_API(CsrGetInputHandle)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
if (ProcessData->Console)
|
|
{
|
|
Request->Status = CsrInsertObject(ProcessData,
|
|
&Request->Data.GetInputHandleRequest.InputHandle,
|
|
(Object_t *)ProcessData->Console,
|
|
Request->Data.GetInputHandleRequest.Access,
|
|
Request->Data.GetInputHandleRequest.Inheritable);
|
|
}
|
|
else
|
|
{
|
|
Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
|
|
Request->Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
return Request->Status;
|
|
}
|
|
|
|
CSR_API(CsrGetOutputHandle)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
if (ProcessData->Console)
|
|
{
|
|
RtlEnterCriticalSection(&ProcessDataLock);
|
|
Request->Status = CsrInsertObject(ProcessData,
|
|
&Request->Data.GetOutputHandleRequest.OutputHandle,
|
|
&ProcessData->Console->ActiveBuffer->Header,
|
|
Request->Data.GetOutputHandleRequest.Access,
|
|
Request->Data.GetOutputHandleRequest.Inheritable);
|
|
RtlLeaveCriticalSection(&ProcessDataLock);
|
|
}
|
|
else
|
|
{
|
|
Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
|
|
Request->Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
return Request->Status;
|
|
}
|
|
|
|
CSR_API(CsrCloseHandle)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
return CsrReleaseObject(ProcessData, Request->Data.CloseHandleRequest.Handle);
|
|
}
|
|
|
|
CSR_API(CsrVerifyHandle)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Request->Status = CsrVerifyObject(ProcessData, Request->Data.VerifyHandleRequest.Handle);
|
|
if (!NT_SUCCESS(Request->Status))
|
|
{
|
|
DPRINT("CsrVerifyObject failed, status=%x\n", Request->Status);
|
|
}
|
|
|
|
return Request->Status;
|
|
}
|
|
|
|
CSR_API(CsrDuplicateHandle)
|
|
{
|
|
ULONG_PTR Index;
|
|
PCSRSS_HANDLE Entry;
|
|
DWORD DesiredAccess;
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Index = (ULONG_PTR)Request->Data.DuplicateHandleRequest.Handle >> 2;
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
if (Index >= ProcessData->HandleTableSize
|
|
|| (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
|
|
{
|
|
DPRINT1("Couldn't dup invalid handle %p\n", Request->Data.DuplicateHandleRequest.Handle);
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
if (Request->Data.DuplicateHandleRequest.Options & DUPLICATE_SAME_ACCESS)
|
|
{
|
|
DesiredAccess = Entry->Access;
|
|
}
|
|
else
|
|
{
|
|
DesiredAccess = Request->Data.DuplicateHandleRequest.Access;
|
|
/* Make sure the source handle has all the desired flags */
|
|
if (~Entry->Access & DesiredAccess)
|
|
{
|
|
DPRINT1("Handle %p only has access %X; requested %X\n",
|
|
Request->Data.DuplicateHandleRequest.Handle, Entry->Access, DesiredAccess);
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
Request->Status = CsrInsertObject(ProcessData,
|
|
&Request->Data.DuplicateHandleRequest.Handle,
|
|
Entry->Object,
|
|
DesiredAccess,
|
|
Request->Data.DuplicateHandleRequest.Inheritable);
|
|
if (NT_SUCCESS(Request->Status)
|
|
&& Request->Data.DuplicateHandleRequest.Options & DUPLICATE_CLOSE_SOURCE)
|
|
{
|
|
/* Close the original handle. This cannot drop the count to 0, since a new handle now exists */
|
|
_InterlockedDecrement(&Entry->Object->ReferenceCount);
|
|
Entry->Object = NULL;
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return Request->Status;
|
|
}
|
|
|
|
CSR_API(CsrGetInputWaitHandle)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = ProcessData->ConsoleEvent;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* EOF */
|