reactos/subsystems/win32/csrss/api/process.c
Timo Kreuzer 9ea495ba33 Create a branch for header work.
svn path=/branches/header-work/; revision=45691
2010-02-26 22:57:55 +00:00

428 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 */